// Copyright (C) 2020 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 com.googlesource.gerrit.plugins.multisite.validation.ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF;
import static com.googlesource.gerrit.plugins.multisite.validation.ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.isNull;
import static org.mockito.Mockito.atMost;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;

import com.gerritforge.gerrit.globalrefdb.validation.ProjectsFilter;
import com.gerritforge.gerrit.globalrefdb.validation.SharedRefDatabaseWrapper;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.server.events.Event;
import com.google.gerrit.server.events.RefUpdatedEvent;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import com.google.gerrit.testing.InMemoryTestEnvironment;
import com.google.inject.Inject;
import com.googlesource.gerrit.plugins.multisite.ProjectVersionLogger;
import com.googlesource.gerrit.plugins.multisite.validation.dfsrefdb.RefFixture;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import org.eclipse.jgit.errors.LargeObjectException;
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

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

  private static final String DEFAULT_INSTANCE_ID = "instance-id";

  @Rule public InMemoryTestEnvironment testEnvironment = new InMemoryTestEnvironment();

  @Mock RefUpdatedEvent refUpdatedEvent;
  @Mock SharedRefDatabaseWrapper sharedRefDb;
  @Mock GitReferenceUpdated gitReferenceUpdated;
  @Mock ProjectVersionLogger verLogger;
  @Mock ProjectsFilter projectsFilter;

  @Inject private ProjectConfig.Factory projectConfigFactory;
  @Inject private InMemoryRepositoryManager repoManager;
  private TestRepository<InMemoryRepository> repo;
  private ProjectConfig project;
  private RevCommit masterCommit;

  @Before
  public void setUp() throws Exception {
    when(projectsFilter.matches(any(Event.class))).thenReturn(true);
    refUpdatedEvent.instanceId = DEFAULT_INSTANCE_ID;
    InMemoryRepository inMemoryRepo = repoManager.createRepository(A_TEST_PROJECT_NAME_KEY);
    project = projectConfigFactory.create(A_TEST_PROJECT_NAME_KEY);
    project.load(inMemoryRepo);
    repo = new TestRepository<>(inMemoryRepo);
    masterCommit = repo.branch("master").commit().create();
  }

  @Test
  public void producerShouldUpdateProjectVersionUponRefUpdatedEvent() throws IOException {
    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
            String.class))
        .thenReturn(Optional.of("26f7ee61bf0e470e8393c884526eec8a9b943a63"));
    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
            String.class))
        .thenReturn(Optional.of("" + (masterCommit.getCommitTime() - 1)));
    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
        .thenReturn(true);
    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(String.class), any(), any()))
        .thenReturn(true);
    when(refUpdatedEvent.getProjectNameKey()).thenReturn(A_TEST_PROJECT_NAME_KEY);
    when(refUpdatedEvent.getRefName()).thenReturn(A_TEST_REF_NAME);

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);

    verify(sharedRefDb, atMost(1))
        .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));

    assertThat(ref).isNotNull();

    ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
    long storedVersion = readLongObject(loader);
    assertThat(storedVersion).isGreaterThan((long) masterCommit.getCommitTime());

    verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
  }

  @Test
  public void producerShouldUpdateProjectVersionUponForcedPushRefUpdatedEvent() throws Exception {
    Thread.sleep(1000L);
    RevCommit masterPlusOneCommit = repo.branch("master").commit().create();

    Thread.sleep(1000L);
    repo.branch("master").update(masterCommit);

    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
            String.class))
        .thenReturn(Optional.of("26f7ee61bf0e470e8393c884526eec8a9b943a63"));
    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
            String.class))
        .thenReturn(Optional.of("" + (masterCommit.getCommitTime() - 1)));
    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
        .thenReturn(true);
    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(String.class), any(), any()))
        .thenReturn(true);
    when(refUpdatedEvent.getProjectNameKey()).thenReturn(A_TEST_PROJECT_NAME_KEY);
    when(refUpdatedEvent.getRefName()).thenReturn(A_TEST_REF_NAME);

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);

    verify(sharedRefDb, atMost(1))
        .compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class));

    assertThat(ref).isNotNull();

    ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
    long storedVersion = readLongObject(loader);
    assertThat(storedVersion).isGreaterThan((long) masterPlusOneCommit.getCommitTime());

    verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
  }

  @Test
  public void producerShouldCreateNewProjectVersionWhenMissingUponRefUpdatedEvent()
      throws IOException {
    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_REF,
            String.class))
        .thenReturn(Optional.empty());
    when(sharedRefDb.get(
            A_TEST_PROJECT_NAME_KEY,
            ProjectVersionRefUpdate.MULTI_SITE_VERSIONING_VALUE_REF,
            String.class))
        .thenReturn(Optional.empty());

    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(Ref.class), any(ObjectId.class)))
        .thenReturn(true);
    when(sharedRefDb.compareAndPut(any(Project.NameKey.class), any(String.class), any(), any()))
        .thenReturn(true);
    when(refUpdatedEvent.getProjectNameKey()).thenReturn(A_TEST_PROJECT_NAME_KEY);
    when(refUpdatedEvent.getRefName()).thenReturn(A_TEST_REF_NAME);

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);

    verify(sharedRefDb, atMost(1))
        .compareAndPut(any(Project.NameKey.class), isNull(), any(ObjectId.class));

    assertThat(ref).isNotNull();

    ObjectLoader loader = repo.getRepository().open(ref.getObjectId());
    long storedVersion = readLongObject(loader);
    assertThat(storedVersion).isGreaterThan((long) masterCommit.getCommitTime());

    verify(verLogger).log(A_TEST_PROJECT_NAME_KEY, storedVersion, 0);
  }

  @Test
  public void producerShouldNotUpdateProjectVersionUponSequenceRefUpdatedEvent() throws Exception {
    producerShouldNotUpdateProjectVersionUponMagicRefUpdatedEvent(RefNames.REFS_SEQUENCES);
  }

  @Test
  public void producerShouldNotUpdateProjectVersionUponStarredChangesRefUpdatedEvent()
      throws Exception {
    producerShouldNotUpdateProjectVersionUponMagicRefUpdatedEvent(RefNames.REFS_STARRED_CHANGES);
  }

  private long readLongObject(ObjectLoader loader)
      throws LargeObjectException, UnsupportedEncodingException {
    String boutString = new String(loader.getBytes(), StandardCharsets.UTF_8.name());
    return Long.parseLong(boutString);
  }

  private void producerShouldNotUpdateProjectVersionUponMagicRefUpdatedEvent(String magicRefPrefix)
      throws Exception {
    String magicRefName = magicRefPrefix + "/foo";
    when(refUpdatedEvent.getProjectNameKey()).thenReturn(A_TEST_PROJECT_NAME_KEY);
    when(refUpdatedEvent.getRefName()).thenReturn(magicRefName);
    repo.branch(magicRefName).commit().create();

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);
    assertThat(ref).isNull();

    verifyZeroInteractions(verLogger);
  }

  @Test
  public void producerShouldNotUpdateProjectVersionUponForwardedRefUpdatedEvent()
      throws IOException {
    refUpdatedEvent.instanceId = "instance-id-2";

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);
    assertThat(ref).isNull();

    verifyZeroInteractions(verLogger);
  }

  @Test
  public void shouldNotUpdateProjectVersionWhenProjectDoesntExist() throws IOException {
    when(refUpdatedEvent.getProjectNameKey()).thenReturn(Project.nameKey("aNonExistentProject"));
    when(refUpdatedEvent.getRefName()).thenReturn(A_TEST_REF_NAME);

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);
    assertThat(ref).isNull();

    verifyZeroInteractions(verLogger);
  }

  @Test
  public void shouldNotUpdateProjectVersionWhenProjectFilteredOut() throws Exception {
    when(projectsFilter.matches(any(Event.class))).thenReturn(false);

    Thread.sleep(1000L);
    repo.branch("master").commit().create();

    Thread.sleep(1000L);
    repo.branch("master").update(masterCommit);

    new ProjectVersionRefUpdate(
            repoManager,
            sharedRefDb,
            gitReferenceUpdated,
            verLogger,
            projectsFilter,
            DEFAULT_INSTANCE_ID)
        .onEvent(refUpdatedEvent);

    Ref ref = repo.getRepository().findRef(MULTI_SITE_VERSIONING_REF);
    assertThat(ref).isNull();

    verifyZeroInteractions(verLogger);
  }

  @Test
  public void getRemoteProjectVersionShouldReturnCorrectValue() {
    when(sharedRefDb.get(A_TEST_PROJECT_NAME_KEY, MULTI_SITE_VERSIONING_VALUE_REF, String.class))
        .thenReturn(Optional.of("123"));

    Optional<Long> version =
        new ProjectVersionRefUpdate(
                repoManager,
                sharedRefDb,
                gitReferenceUpdated,
                verLogger,
                projectsFilter,
                DEFAULT_INSTANCE_ID)
            .getProjectRemoteVersion(A_TEST_PROJECT_NAME);

    assertThat(version.isPresent()).isTrue();
    assertThat(version.get()).isEqualTo(123L);
  }
}
