// 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.zookeeper.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);
    }
  }
}
