// Copyright (C) 2019 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package com.googlesource.gerrit.plugins.multisite.validation;

import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.verify;

import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import java.io.IOException;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class MultiSiteRepositoryTest implements RefFixture {

  @Mock MultiSiteRefDatabase.Factory multiSiteRefDbFactory;
  @Mock MultiSiteRefDatabase multiSiteRefDb;
  @Mock RefDatabase genericRefDb;

  @Mock MultiSiteRefUpdate multiSiteRefUpdate;

  @Mock Repository repository;

  private final String PROJECT_NAME = "ProjectName";
  private final String REFS_HEADS_MASTER = "refs/heads/master";

  @Override
  public String testBranch() {
    return null;
  }

  private void setMockitoCommon() {
    doReturn(genericRefDb).when(repository).getRefDatabase();
    doReturn(multiSiteRefDb).when(multiSiteRefDbFactory).create(PROJECT_NAME, genericRefDb);
  }

  @Test
  public void shouldInvokeMultiSiteRefDbFactoryCreate() {
    setMockitoCommon();
    try (MultiSiteRepository multiSiteRepository =
        new MultiSiteRepository(multiSiteRefDbFactory, PROJECT_NAME, repository)) {

      multiSiteRepository.getRefDatabase();
      verify(multiSiteRefDbFactory).create(PROJECT_NAME, genericRefDb);
    }
  }

  @Test
  public void shouldInvokeNewUpdateInMultiSiteRefDatabase() throws IOException {
    setMockitoCommon();
    try (MultiSiteRepository multiSiteRepository =
        new MultiSiteRepository(multiSiteRefDbFactory, PROJECT_NAME, repository)) {
      multiSiteRepository.getRefDatabase().newUpdate(REFS_HEADS_MASTER, false);

      verify(multiSiteRefDb).newUpdate(REFS_HEADS_MASTER, false);
    }
  }

  @Test
  public void shouldInvokeUpdateInMultiSiteRefUpdate() throws IOException {
    setMockitoCommon();
    doReturn(Result.NEW).when(multiSiteRefUpdate).update();
    doReturn(multiSiteRefUpdate).when(multiSiteRefDb).newUpdate(REFS_HEADS_MASTER, false);

    try (MultiSiteRepository multiSiteRepository =
        new MultiSiteRepository(multiSiteRefDbFactory, PROJECT_NAME, repository)) {

      Result updateResult =
          multiSiteRepository.getRefDatabase().newUpdate(REFS_HEADS_MASTER, false).update();

      verify(multiSiteRefUpdate).update();
      assertThat(updateResult).isEqualTo(Result.NEW);
    }
  }
}
