// 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.google.gerrit.server.submit;

import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.testing.GerritJUnit.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.gerrit.entities.BranchNameKey;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.SubmoduleSubscription;
import com.google.gerrit.entities.SubscribeSection;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.submit.SubscriptionGraph.DefaultFactory;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;

@RunWith(MockitoJUnitRunner.class)
public class SubscriptionGraphTest {
  private static final String TEST_PATH = "test/path";
  private static final Project.NameKey SUPER_PROJECT = Project.nameKey("Superproject");
  private static final Project.NameKey SUB_PROJECT = Project.nameKey("Subproject");
  private static final BranchNameKey SUPER_BRANCH =
      BranchNameKey.create(SUPER_PROJECT, "refs/heads/one");
  private static final BranchNameKey SUB_BRANCH =
      BranchNameKey.create(SUB_PROJECT, "refs/heads/one");
  private InMemoryRepositoryManager repoManager = new InMemoryRepositoryManager();
  private MergeOpRepoManager mergeOpRepoManager;

  @Mock GitModules.Factory mockGitModulesFactory;
  @Mock ProjectCache mockProjectCache;
  @Mock ProjectState mockProjectState;

  @Before
  public void setUp() throws Exception {
    when(mockProjectCache.get(any())).thenReturn(Optional.of(mockProjectState));
    mergeOpRepoManager = new MergeOpRepoManager(repoManager, mockProjectCache, null, null);

    GitModules emptyMockGitModules = mock(GitModules.class);
    when(mockGitModulesFactory.create(any(), any())).thenReturn(emptyMockGitModules);

    TestRepository<Repository> superProject = createRepo(SUPER_PROJECT);
    TestRepository<Repository> submoduleProject = createRepo(SUB_PROJECT);

    // Make sure that SUPER_BRANCH and SUB_BRANCH can be subscribed.
    allowSubscription(SUPER_BRANCH);
    allowSubscription(SUB_BRANCH);

    setSubscription(SUB_BRANCH, ImmutableList.of(SUPER_BRANCH));
    setSubscription(SUPER_BRANCH, ImmutableList.of());
    createBranch(
        superProject, SUPER_BRANCH, superProject.commit().message("Initial commit").create());
    createBranch(
        submoduleProject, SUB_BRANCH, submoduleProject.commit().message("Initial commit").create());
  }

  @Test
  public void oneSuperprojectOneSubmodule() throws Exception {
    SubscriptionGraph.Factory factory = new DefaultFactory(mockGitModulesFactory, mockProjectCache);
    SubscriptionGraph subscriptionGraph =
        factory.compute(ImmutableSet.of(SUB_BRANCH), mergeOpRepoManager);

    assertThat(subscriptionGraph.getAffectedSuperProjects()).containsExactly(SUPER_PROJECT);
    assertThat(subscriptionGraph.getAffectedSuperBranches(SUPER_PROJECT))
        .containsExactly(SUPER_BRANCH);
    assertThat(subscriptionGraph.getSubscriptions(SUPER_BRANCH))
        .containsExactly(new SubmoduleSubscription(SUPER_BRANCH, SUB_BRANCH, TEST_PATH));
    assertThat(subscriptionGraph.hasSuperproject(SUB_BRANCH)).isTrue();
    assertThat(subscriptionGraph.getSortedSuperprojectAndSubmoduleBranches())
        .containsExactly(SUB_BRANCH, SUPER_BRANCH)
        .inOrder();
  }

  @Test
  public void circularSubscription() throws Exception {
    SubscriptionGraph.Factory factory = new DefaultFactory(mockGitModulesFactory, mockProjectCache);
    setSubscription(SUPER_BRANCH, ImmutableList.of(SUB_BRANCH));
    SubmoduleConflictException e =
        assertThrows(
            SubmoduleConflictException.class,
            () -> factory.compute(ImmutableSet.of(SUB_BRANCH), mergeOpRepoManager));

    String expectedErrorMessage =
        "Subproject,refs/heads/one->Superproject,refs/heads/one->Subproject,refs/heads/one";
    assertThat(e).hasMessageThat().contains(expectedErrorMessage);
  }

  @Test
  public void multipleSuperprojectsToMultipleSubmodules() throws Exception {
    // Create superprojects and subprojects.
    Project.NameKey superProject1 = Project.nameKey("superproject1");
    Project.NameKey superProject2 = Project.nameKey("superproject2");
    Project.NameKey subProject1 = Project.nameKey("subproject1");
    Project.NameKey subProject2 = Project.nameKey("subproject2");
    TestRepository<Repository> superProjectRepo1 = createRepo(superProject1);
    TestRepository<Repository> superProjectRepo2 = createRepo(superProject2);
    TestRepository<Repository> submoduleRepo1 = createRepo(subProject1);
    TestRepository<Repository> submoduleRepo2 = createRepo(subProject2);

    // Initialize super branches.
    BranchNameKey superBranch1 = BranchNameKey.create(superProject1, "refs/heads/one");
    BranchNameKey superBranch2 = BranchNameKey.create(superProject2, "refs/heads/one");
    createBranch(
        superProjectRepo1,
        superBranch1,
        superProjectRepo1.commit().message("Initial commit").create());
    createBranch(
        superProjectRepo2,
        superBranch2,
        superProjectRepo2.commit().message("Initial commit").create());

    // Initialize sub branches.
    BranchNameKey submoduleBranch1 = BranchNameKey.create(subProject1, "refs/heads/one");
    BranchNameKey submoduleBranch2 = BranchNameKey.create(subProject1, "refs/heads/two");
    BranchNameKey submoduleBranch3 = BranchNameKey.create(subProject2, "refs/heads/one");
    createBranch(
        submoduleRepo1, submoduleBranch1, submoduleRepo1.commit().message("Commit1").create());
    createBranch(
        submoduleRepo1, submoduleBranch2, submoduleRepo1.commit().message("Commit2").create());
    createBranch(
        submoduleRepo2, submoduleBranch3, submoduleRepo2.commit().message("Commit1").create());

    allowSubscription(submoduleBranch1);
    allowSubscription(submoduleBranch2);
    allowSubscription(submoduleBranch3);

    // Initialize subscriptions.
    setSubscription(submoduleBranch1, ImmutableList.of(superBranch1, superBranch2));
    setSubscription(submoduleBranch2, ImmutableList.of(superBranch1));
    setSubscription(submoduleBranch3, ImmutableList.of(superBranch1, superBranch2));

    SubscriptionGraph.Factory factory = new DefaultFactory(mockGitModulesFactory, mockProjectCache);
    SubscriptionGraph subscriptionGraph =
        factory.compute(ImmutableSet.of(submoduleBranch1, submoduleBranch2), mergeOpRepoManager);

    assertThat(subscriptionGraph.getAffectedSuperProjects())
        .containsExactly(superProject1, superProject2);
    assertThat(subscriptionGraph.getAffectedSuperBranches(superProject1))
        .containsExactly(superBranch1);
    assertThat(subscriptionGraph.getAffectedSuperBranches(superProject2))
        .containsExactly(superBranch2);

    assertThat(subscriptionGraph.getSubscriptions(superBranch1))
        .containsExactly(
            new SubmoduleSubscription(superBranch1, submoduleBranch1, TEST_PATH),
            new SubmoduleSubscription(superBranch1, submoduleBranch2, TEST_PATH));
    assertThat(subscriptionGraph.getSubscriptions(superBranch2))
        .containsExactly(new SubmoduleSubscription(superBranch2, submoduleBranch1, TEST_PATH));

    assertThat(subscriptionGraph.hasSuperproject(submoduleBranch1)).isTrue();
    assertThat(subscriptionGraph.hasSuperproject(submoduleBranch2)).isTrue();
    assertThat(subscriptionGraph.hasSuperproject(submoduleBranch3)).isFalse();

    assertThat(subscriptionGraph.getSortedSuperprojectAndSubmoduleBranches())
        .containsExactly(submoduleBranch2, submoduleBranch1, superBranch2, superBranch1)
        .inOrder();
  }

  private TestRepository<Repository> createRepo(Project.NameKey project) throws Exception {
    Repository repo = repoManager.createRepository(project);
    return new TestRepository<>(repo);
  }

  private void createBranch(TestRepository<Repository> repo, BranchNameKey branch, RevCommit commit)
      throws Exception {
    repo.update(branch.branch(), commit);
  }

  private void allowSubscription(BranchNameKey branch) {
    SubscribeSection.Builder s = SubscribeSection.builder(branch.project());
    s.addMultiMatchRefSpec("refs/heads/*:refs/heads/*");
    when(mockProjectState.getSubscribeSections(branch)).thenReturn(ImmutableSet.of(s.build()));
  }

  private void setSubscription(
      BranchNameKey submoduleBranch, List<BranchNameKey> superprojectBranches) {
    List<SubmoduleSubscription> subscriptions =
        superprojectBranches.stream()
            .map(
                (targetBranch) ->
                    new SubmoduleSubscription(targetBranch, submoduleBranch, TEST_PATH))
            .collect(Collectors.toList());
    GitModules mockGitModules = mock(GitModules.class);
    when(mockGitModules.subscribedTo(submoduleBranch)).thenReturn(subscriptions);
    when(mockGitModulesFactory.create(submoduleBranch, mergeOpRepoManager))
        .thenReturn(mockGitModules);
  }
}
