// Copyright (C) 2011 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.git;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.capture;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;

import com.google.gerrit.common.ChangeHooks;
import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.SubmoduleSubscriptionAccess;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gwtorm.client.KeyUtil;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.ResultSet;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.StandardKeyEncoder;
import com.google.inject.Provider;

import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IMocksControl;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

public class SubmoduleOpTest extends LocalDiskRepositoryTestCase {
  static {
    KeyUtil.setEncoderImpl(new StandardKeyEncoder());
  }

  private static final String newLine = System.getProperty("line.separator");

  private IMocksControl mockMaker;
  private SchemaFactory<ReviewDb> schemaFactory;
  private SubmoduleSubscriptionAccess subscriptions;
  private ReviewDb schema;
  private Provider<String> urlProvider;
  private GitRepositoryManager repoManager;
  private GitReferenceUpdated gitRefUpdated;
  private ChangeHooks changeHooks;

  @SuppressWarnings("unchecked")
  @Override
  @Before
  public void setUp() throws Exception {
    super.setUp();

    mockMaker = EasyMock.createStrictControl();
    schemaFactory = mockMaker.createMock(SchemaFactory.class);
    schema = mockMaker.createMock(ReviewDb.class);
    subscriptions = mockMaker.createMock(SubmoduleSubscriptionAccess.class);
    urlProvider = mockMaker.createMock(Provider.class);
    repoManager = mockMaker.createMock(GitRepositoryManager.class);
    gitRefUpdated = mockMaker.createMock(GitReferenceUpdated.class);
    changeHooks = mockMaker.createMock(ChangeHooks.class);
  }

  private void doReplay() {
    mockMaker.replay();
  }

  private void doVerify() {
    mockMaker.verify();
  }

  /**
   * It tests Submodule.update in the scenario a merged commit is an empty one
   * (it does not have a .gitmodules file) and the project the commit was merged
   * is not a submodule of other project.
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testEmptyCommit() throws Exception {
    expect(schemaFactory.open()).andReturn(schema);

    try (Repository realDb = createWorkRepository()) {
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git git = new Git(realDb);

      final RevCommit mergeTip = git.commit().setMessage("test").call();

      final Branch.NameKey branchNameKey =
          new Branch.NameKey(new Project.NameKey("test-project"), "test-branch");

      expect(urlProvider.get()).andReturn("http://localhost:8080");

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      final ResultSet<SubmoduleSubscription> emptySubscriptions =
          new ListResultSet<>(new ArrayList<SubmoduleSubscription>());
      expect(subscriptions.bySubmodule(branchNameKey)).andReturn(
          emptySubscriptions);

      schema.close();

      doReplay();

      final SubmoduleOp submoduleOp =
          new SubmoduleOp(branchNameKey, mergeTip, new RevWalk(realDb), urlProvider,
              schemaFactory, realDb, null, new ArrayList<Change>(), null, null,
              null, null, null, null);

      submoduleOp.update();

      doVerify();
    }
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project"</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source"]
   *       path = source
   *       url = http://localhost:8080/source
   *       branch = .
   * </pre>
   * <p>
   * It expects to insert a new row in subscriptions table. The row inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "a" on branch "refs/heads/master"</li>
   * <li>path "a"</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionToDotBranchValue() throws Exception {
    doOneSubscriptionInsert(buildSubmoduleSection("source", "source",
        "http://localhost:8080/source", ".").toString(), "refs/heads/master");

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project"</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source"]
   *       path = source
   *       url = http://localhost:8080/source
   *       branch = refs/heads/master
   * </pre>
   *
   * <p>
   * It expects to insert a new row in subscriptions table. The row inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source" on branch "refs/heads/master"</li>
   * <li>path "source"</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionToSameBranch() throws Exception {
    doOneSubscriptionInsert(buildSubmoduleSection("source", "source",
        "http://localhost:8080/source", "refs/heads/master").toString(),
        "refs/heads/master");

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project"</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source"]
   *       path = source
   *       url = http://localhost:8080/source
   *       branch = refs/heads/test
   * </pre>
   * <p>
   * It expects to insert a new row in subscriptions table. The row inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source" on branch "refs/heads/test"</li>
   * <li>path "source"</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionToDifferentBranch() throws Exception {
    doOneSubscriptionInsert(buildSubmoduleSection("source", "source",
        "http://localhost:8080/source", "refs/heads/test").toString(),
        "refs/heads/test");

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project" in "refs/heads/master" branch</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source-a"]
   *       path = source-a
   *       url = http://localhost:8080/source-a
   *       branch = .
   *
   *     [submodule "source-b"]
   *       path = source-b
   *       url = http://localhost:8080/source-b
   *       branch = .
   * </pre>
   * <p>
   * It expects to insert new rows in subscriptions table. The rows inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source-a" on branch "refs/heads/master" with "source-a" path</li>
   * <li>source "source-b" on branch "refs/heads/master" with "source-b" path</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionsWithDotBranchValue() throws Exception {
    final StringBuilder sb =
        buildSubmoduleSection("source-a", "source-a",
            "http://localhost:8080/source-a", ".");
    sb.append(buildSubmoduleSection("source-b", "source-b",
        "http://localhost:8080/source-b", "."));

    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> subscriptionsToInsert = new ArrayList<>();
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-a"), "refs/heads/master"), "source-a"));
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-b"), "refs/heads/master"), "source-b"));

    doOnlySubscriptionInserts(sb.toString(), mergedBranch,
        subscriptionsToInsert);

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project" in "refs/heads/master" branch</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source-a"]
   *       path = source-a
   *       url = http://localhost:8080/source-a
   *       branch = .
   *
   *     [submodule "source-b"]
   *       path = source-b
   *       url = http://localhost:8080/source-b
   *       branch = refs/heads/master
   * </pre>
   * <p>
   * It expects to insert new rows in subscriptions table. The rows inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source-a" on branch "refs/heads/master" with "source-a" path</li>
   * <li>source "source-b" on branch "refs/heads/master" with "source-b" path</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionsDotAndSameBranchValues() throws Exception {
    final StringBuilder sb =
        buildSubmoduleSection("source-a", "source-a",
            "http://localhost:8080/source-a", ".");
    sb.append(buildSubmoduleSection("source-b", "source-b",
        "http://localhost:8080/source-b", "refs/heads/master"));

    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> subscriptionsToInsert = new ArrayList<>();
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-a"), "refs/heads/master"), "source-a"));
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-b"), "refs/heads/master"), "source-b"));

    doOnlySubscriptionInserts(sb.toString(), mergedBranch,
        subscriptionsToInsert);

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>no subscriptions existing to destination project</li>
   * <li>a commit is merged to "dest-project" in "refs/heads/master" branch</li>
   * <li>commit contains .gitmodules file with content</li>
   *
   * <pre>
   *     [submodule "source-a"]
   *       path = source-a
   *       url = http://localhost:8080/source-a
   *       branch = refs/heads/test-a
   *
   *     [submodule "source-b"]
   *       path = source-b
   *       url = http://localhost:8080/source-b
   *       branch = refs/heads/test-b
   * </pre>
   *
   * <p>
   * It expects to insert new rows in subscriptions table. The rows inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source-a" on branch "refs/heads/test-a" with "source-a" path</li>
   * <li>source "source-b" on branch "refs/heads/test-b" with "source-b" path</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testNewSubscriptionsSpecificBranchValues() throws Exception {
    final StringBuilder sb =
        buildSubmoduleSection("source-a", "source-a",
            "http://localhost:8080/source-a", "refs/heads/test-a");
    sb.append(buildSubmoduleSection("source-b", "source-b",
        "http://localhost:8080/source-b", "refs/heads/test-b"));

    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> subscriptionsToInsert = new ArrayList<>();
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-a"), "refs/heads/test-a"), "source-a"));
    subscriptionsToInsert
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-b"), "refs/heads/test-b"), "source-b"));

    doOnlySubscriptionInserts(sb.toString(), mergedBranch,
        subscriptionsToInsert);

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>one subscription existing to destination project/branch</li>
   * <li>a commit is merged to "dest-project" in "refs/heads/master" branch</li>
   * <li>commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "source"]
   *       path = source
   *       url = http://localhost:8080/source
   *       branch = refs/heads/master
   * </pre>
   * <p>
   * It expects to insert a new row in subscriptions table. The rows inserted
   * specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "source" on branch "refs/heads/master" with "source" path</li>
   * </ul>
   * </p>
   * <p>
   * It also expects to remove the row in subscriptions table specifying another
   * project/branch subscribed to merged branch. This one to be removed is:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "old-source" on branch "refs/heads/master" with "old-source"
   * path</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testSubscriptionsInsertOneRemoveOne() throws Exception {
    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> subscriptionsToInsert = new ArrayList<>();
    subscriptionsToInsert.add(new SubmoduleSubscription(mergedBranch,
        new Branch.NameKey(new Project.NameKey("source"), "refs/heads/master"),
        "source"));

    List<SubmoduleSubscription> oldOnesToMergedBranch = new ArrayList<>();
    oldOnesToMergedBranch.add(new SubmoduleSubscription(mergedBranch,
        new Branch.NameKey(new Project.NameKey("old-source"),
            "refs/heads/master"), "old-source"));

    doOnlySubscriptionTableOperations(buildSubmoduleSection("source", "source",
        "http://localhost:8080/source", "refs/heads/master").toString(),
        mergedBranch, subscriptionsToInsert, oldOnesToMergedBranch);

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering:
   * <ul>
   * <li>one subscription existing to destination project/branch with a source
   * called old on refs/heads/master branch</li>
   * <li>a commit is merged to "dest-project" in "refs/heads/master" branch</li>
   * <li>
   * commit contains .gitmodules file with content</li>
   * </ul>
   *
   * <pre>
   *     [submodule "new"]
   *       path = new
   *       url = http://localhost:8080/new
   *       branch = refs/heads/master
   *
   *     [submodule "old"]
   *       path = old
   *       url = http://localhost:8080/old
   *       branch = refs/heads/master
   * </pre>
   * <p>
   * It expects to insert a new row in subscriptions table. It should not remove
   * any row. The rows inserted specifies:
   * <ul>
   * <li>target "dest-project" on branch "refs/heads/master"</li>
   * <li>source "new" on branch "refs/heads/master" with "new" path</li>
   * </ul>
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testSubscriptionAddedAndMantainPreviousOne() throws Exception {
    final StringBuilder sb =
        buildSubmoduleSection("new", "new", "http://localhost:8080/new",
            "refs/heads/master");
    sb.append(buildSubmoduleSection("old", "old", "http://localhost:8080/old",
        "refs/heads/master"));

    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    final SubmoduleSubscription old =
        new SubmoduleSubscription(mergedBranch, new Branch.NameKey(new Project.NameKey(
            "old"), "refs/heads/master"), "old");

    List<SubmoduleSubscription> extractedsubscriptions = new ArrayList<>();
    extractedsubscriptions.add(new SubmoduleSubscription(mergedBranch,
        new Branch.NameKey(new Project.NameKey("new"), "refs/heads/master"),
        "new"));
    extractedsubscriptions.add(old);

    List<SubmoduleSubscription> oldOnesToMergedBranch = new ArrayList<>();
    oldOnesToMergedBranch.add(old);

    doOnlySubscriptionTableOperations(sb.toString(), mergedBranch,
        extractedsubscriptions, oldOnesToMergedBranch);

    doVerify();
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering an empty .gitmodules
   * file is part of a commit to a destination project/branch having two sources
   * subscribed.
   * <p>
   * It expects to remove the subscriptions to destination project/branch.
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testRemoveSubscriptions() throws Exception {
    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> extractedsubscriptions = new ArrayList<>();
    List<SubmoduleSubscription> oldOnesToMergedBranch = new ArrayList<>();
    oldOnesToMergedBranch
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-a"), "refs/heads/master"), "source-a"));
    oldOnesToMergedBranch
        .add(new SubmoduleSubscription(mergedBranch, new Branch.NameKey(
            new Project.NameKey("source-b"), "refs/heads/master"), "source-b"));

    doOnlySubscriptionTableOperations("", mergedBranch, extractedsubscriptions,
        oldOnesToMergedBranch);
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering no .gitmodules file
   * in a merged commit to a destination project/branch that is a source one to
   * one called "target-project".
   * <p>
   * It expects to update the git link called "source-project" to be in target
   * repository.
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testOneSubscriberToUpdate() throws Exception {
    expect(schemaFactory.open()).andReturn(schema);

    try (Repository sourceRepository = createWorkRepository();
        Repository targetRepository = createWorkRepository()) {
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git sourceGit = new Git(sourceRepository);
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git targetGit = new Git(targetRepository);

      addRegularFileToIndex("file.txt", "test content", sourceRepository);

      final RevCommit sourceMergeTip =
          sourceGit.commit().setMessage("test").call();

      final Branch.NameKey sourceBranchNameKey =
          new Branch.NameKey(new Project.NameKey("source-project"),
              "refs/heads/master");

      final CodeReviewCommit codeReviewCommit =
          new CodeReviewCommit(sourceMergeTip.toObjectId());
      final Change submittedChange = new Change(
          new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1),
          new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs());

      final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>();
      mergedCommits.put(submittedChange.getId(), codeReviewCommit);

      final List<Change> submitted = new ArrayList<>();
      submitted.add(submittedChange);

      addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository);

      targetGit.commit().setMessage("test").call();

      final Branch.NameKey targetBranchNameKey =
          new Branch.NameKey(new Project.NameKey("target-project"),
              sourceBranchNameKey.get());

      expect(urlProvider.get()).andReturn("http://localhost:8080");

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      final ResultSet<SubmoduleSubscription> subscribers =
          new ListResultSet<>(Collections
              .singletonList(new SubmoduleSubscription(targetBranchNameKey,
                  sourceBranchNameKey, "source-project")));
      expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn(
          subscribers);

      expect(repoManager.openRepository(targetBranchNameKey.getParentKey()))
          .andReturn(targetRepository).anyTimes();

      Capture<RefUpdate> ruCapture = new Capture<>();
      gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()),
          capture(ruCapture));
      changeHooks.doRefUpdatedHook(eq(targetBranchNameKey),
          anyObject(RefUpdate.class), EasyMock.<Account>isNull());

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      final ResultSet<SubmoduleSubscription> emptySubscriptions =
          new ListResultSet<>(new ArrayList<SubmoduleSubscription>());
      expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn(
          emptySubscriptions);

      schema.close();

      final PersonIdent myIdent =
          new PersonIdent("test-user", "test-user@email.com");

      doReplay();

      final SubmoduleOp submoduleOp =
          new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk(
              sourceRepository), urlProvider, schemaFactory, sourceRepository,
              new Project(sourceBranchNameKey.getParentKey()), submitted,
              mergedCommits, myIdent, repoManager, gitRefUpdated, null,
              changeHooks);

      submoduleOp.update();

      doVerify();
      RefUpdate ru = ruCapture.getValue();
      assertEquals(ru.getName(), targetBranchNameKey.get());
    }
  }

  /**
   * It tests SubmoduleOp.update in a scenario considering established circular
   * reference in submodule_subscriptions table.
   * <p>
   * In the tested scenario there is no .gitmodules file in a merged commit to a
   * destination project/branch that is a source one to one called
   * "target-project".
   * <p>
   * submodule_subscriptions table will be incorrect due source appearing as a
   * subscriber or target-project: according to database target-project has as
   * source the source-project, and source-project has as source the
   * target-project.
   * <p>
   * It expects to update the git link called "source-project" to be in target
   * repository and ignoring the incorrect row in database establishing the
   * circular reference.
   * </p>
   *
   * @throws Exception If an exception occurs.
   */
  @Test
  public void testAvoidingCircularReference() throws Exception {
    expect(schemaFactory.open()).andReturn(schema);

    try (Repository sourceRepository = createWorkRepository();
        Repository targetRepository = createWorkRepository()) {
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git sourceGit = new Git(sourceRepository);
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git targetGit = new Git(targetRepository);

      addRegularFileToIndex("file.txt", "test content", sourceRepository);

      final RevCommit sourceMergeTip =
          sourceGit.commit().setMessage("test").call();

      final Branch.NameKey sourceBranchNameKey =
          new Branch.NameKey(new Project.NameKey("source-project"),
              "refs/heads/master");

      final CodeReviewCommit codeReviewCommit =
          new CodeReviewCommit(sourceMergeTip.toObjectId());
      final Change submittedChange = new Change(
          new Change.Key(sourceMergeTip.toObjectId().getName()), new Change.Id(1),
          new Account.Id(1), sourceBranchNameKey, TimeUtil.nowTs());

      final Map<Change.Id, CodeReviewCommit> mergedCommits = new HashMap<>();
      mergedCommits.put(submittedChange.getId(), codeReviewCommit);

      final List<Change> submitted = new ArrayList<>();
      submitted.add(submittedChange);

      addGitLinkToIndex("a", sourceMergeTip.copy(), targetRepository);

      targetGit.commit().setMessage("test").call();

      final Branch.NameKey targetBranchNameKey =
          new Branch.NameKey(new Project.NameKey("target-project"),
              sourceBranchNameKey.get());

      expect(urlProvider.get()).andReturn("http://localhost:8080");

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      final ResultSet<SubmoduleSubscription> subscribers =
          new ListResultSet<>(Collections
              .singletonList(new SubmoduleSubscription(targetBranchNameKey,
                  sourceBranchNameKey, "source-project")));
      expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn(
          subscribers);

      expect(repoManager.openRepository(targetBranchNameKey.getParentKey()))
          .andReturn(targetRepository).anyTimes();

      Capture<RefUpdate> ruCapture = new Capture<>();
      gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()),
          capture(ruCapture));
      changeHooks.doRefUpdatedHook(eq(targetBranchNameKey),
            anyObject(RefUpdate.class), EasyMock.<Account>isNull());

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      final ResultSet<SubmoduleSubscription> incorrectSubscriptions =
          new ListResultSet<>(Collections
              .singletonList(new SubmoduleSubscription(sourceBranchNameKey,
                  targetBranchNameKey, "target-project")));
      expect(subscriptions.bySubmodule(targetBranchNameKey)).andReturn(
          incorrectSubscriptions);

      schema.close();

      final PersonIdent myIdent =
          new PersonIdent("test-user", "test-user@email.com");

      doReplay();

      final SubmoduleOp submoduleOp =
          new SubmoduleOp(sourceBranchNameKey, sourceMergeTip, new RevWalk(
              sourceRepository), urlProvider, schemaFactory, sourceRepository,
              new Project(sourceBranchNameKey.getParentKey()), submitted,
              mergedCommits, myIdent, repoManager, gitRefUpdated, null, changeHooks);

      submoduleOp.update();

      doVerify();
      RefUpdate ru = ruCapture.getValue();
      assertEquals(ru.getName(), targetBranchNameKey.get());
    }
  }

  /**
   * It calls SubmoduleOp.update considering only one insert on Subscriptions
   * table.
   * <p>
   * It considers a commit containing a .gitmodules file was merged in
   * refs/heads/master of a dest-project.
   * </p>
   * <p>
   * The .gitmodules file content should indicate a source project called
   * "source".
   * </p>
   *
   * @param gitModulesFileContent The .gitmodules file content. During the test
   *        this file is created, so the commit containing it.
   * @param sourceBranchName The branch name of source project "pointed by"
   *        .gitmodules file.
   * @throws Exception If an exception occurs.
   */
  private void doOneSubscriptionInsert(final String gitModulesFileContent,
      final String sourceBranchName) throws Exception {
    final Branch.NameKey mergedBranch =
        new Branch.NameKey(new Project.NameKey("dest-project"),
            "refs/heads/master");

    List<SubmoduleSubscription> subscriptionsToInsert = new ArrayList<>();
    subscriptionsToInsert.add(new SubmoduleSubscription(mergedBranch,
        new Branch.NameKey(new Project.NameKey("source"), sourceBranchName),
        "source"));

    doOnlySubscriptionInserts(gitModulesFileContent, mergedBranch,
        subscriptionsToInsert);
  }

  /**
   * It calls SubmoduleOp.update method considering scenario only inserting new
   * subscriptions.
   * <p>
   * In this test a commit is created and considered merged to
   * {@code mergedBranch} branch.
   * </p>
   * <p>
   * The destination project the commit was merged is not considered to be a
   * source of another project (no subscribers found to this project).
   * </p>
   *
   * @param gitModulesFileContent The .gitmodules file content.
   * @param mergedBranch The {@code Branch.NameKey} instance representing the
   *        project/branch the commit was merged.
   * @param extractedSubscriptions The subscription rows extracted from
   *        gitmodules file.
   * @throws Exception If an exception occurs.
   */
  private void doOnlySubscriptionInserts(final String gitModulesFileContent,
      final Branch.NameKey mergedBranch,
      final List<SubmoduleSubscription> extractedSubscriptions) throws Exception {
    doOnlySubscriptionTableOperations(gitModulesFileContent, mergedBranch,
        extractedSubscriptions, new ArrayList<SubmoduleSubscription>());
  }

  /**
   * It calls SubmoduleOp.update method considering scenario only updating
   * Subscriptions table.
   * <p>
   * In this test a commit is created and considered merged to
   * {@code mergedBranch} branch.
   * </p>
   * <p>
   * The destination project the commit was merged is not considered to be a
   * source of another project (no subscribers found to this project).
   * </p>
   *
   * @param gitModulesFileContent The .gitmodules file content.
   * @param mergedBranch The {@code Branch.NameKey} instance representing the
   *        project/branch the commit was merged.
   * @param extractedSubscriptions The subscription rows extracted from
   *        gitmodules file.
   * @param previousSubscriptions The subscription rows to be considering as
   *        existing and pointing as target to the {@code mergedBranch}
   *        before updating the table.
   * @throws Exception If an exception occurs.
   */
  private void doOnlySubscriptionTableOperations(
      final String gitModulesFileContent, final Branch.NameKey mergedBranch,
      final List<SubmoduleSubscription> extractedSubscriptions,
      final List<SubmoduleSubscription> previousSubscriptions) throws Exception {
    expect(schemaFactory.open()).andReturn(schema);

    try (Repository realDb = createWorkRepository()) {
      // TODO(dborowitz): Use try/finally when this doesn't double-close the repo.
      @SuppressWarnings("resource")
      final Git git = new Git(realDb);

      addRegularFileToIndex(".gitmodules", gitModulesFileContent, realDb);

      final RevCommit mergeTip = git.commit().setMessage("test").call();

      expect(urlProvider.get()).andReturn("http://localhost:8080").times(2);

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      expect(subscriptions.bySuperProject(mergedBranch)).andReturn(
          new ListResultSet<>(previousSubscriptions));

      SortedSet<Project.NameKey> existingProjects = new TreeSet<>();

      for (SubmoduleSubscription extracted : extractedSubscriptions) {
        existingProjects.add(extracted.getSubmodule().getParentKey());
      }

      for (int index = 0; index < extractedSubscriptions.size(); index++) {
        expect(repoManager.list()).andReturn(existingProjects);
      }

      final Set<SubmoduleSubscription> alreadySubscribeds = new HashSet<>();
      for (SubmoduleSubscription s : extractedSubscriptions) {
        if (previousSubscriptions.contains(s)) {
          alreadySubscribeds.add(s);
        }
      }

      final Set<SubmoduleSubscription> subscriptionsToRemove =
          new HashSet<>(previousSubscriptions);
      final List<SubmoduleSubscription> subscriptionsToInsert =
          new ArrayList<>(extractedSubscriptions);

      subscriptionsToRemove.removeAll(subscriptionsToInsert);
      subscriptionsToInsert.removeAll(alreadySubscribeds);

      if (!subscriptionsToRemove.isEmpty()) {
        expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
        subscriptions.delete(subscriptionsToRemove);
      }

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      subscriptions.insert(subscriptionsToInsert);

      expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
      expect(subscriptions.bySubmodule(mergedBranch)).andReturn(
          new ListResultSet<>(new ArrayList<SubmoduleSubscription>()));

      schema.close();

      doReplay();

      final SubmoduleOp submoduleOp =
          new SubmoduleOp(mergedBranch, mergeTip, new RevWalk(realDb),
              urlProvider, schemaFactory, realDb, new Project(mergedBranch
                  .getParentKey()), new ArrayList<Change>(), null, null,
              repoManager, null, null, null);

      submoduleOp.update();
    }
  }

  /**
   * It creates and adds a regular file to git index of a repository.
   *
   * @param fileName The file name.
   * @param content File content.
   * @param repository The Repository instance.
   * @throws IOException If an I/O exception occurs.
   */
  private void addRegularFileToIndex(final String fileName,
      final String content, final Repository repository) throws IOException {
    final ObjectInserter oi = repository.newObjectInserter();
    AnyObjectId objectId =
        oi.insert(Constants.OBJ_BLOB, Constants.encode(content));
    oi.flush();
    addEntryToIndex(fileName, FileMode.REGULAR_FILE, objectId, repository);
  }

  /**
   * It creates and adds a git link to git index of a repository.
   *
   * @param fileName The file name.
   * @param objectId The sha-1 value of git link.
   * @param repository The Repository instance.
   * @throws IOException If an I/O exception occurs.
   */
  private void addGitLinkToIndex(final String fileName,
      final AnyObjectId objectId, final Repository repository)
      throws IOException {
    addEntryToIndex(fileName, FileMode.GITLINK, objectId, repository);
  }

  /**
   * It adds an entry to index.
   *
   * @param path The entry path.
   * @param fileMode The entry file mode.
   * @param objectId The ObjectId value of the entry.
   * @param repository The repository instance.
   * @throws IOException If an I/O exception occurs.
   */
  private void addEntryToIndex(final String path, final FileMode fileMode,
      final AnyObjectId objectId, final Repository repository)
      throws IOException {
    final DirCacheEntry e = new DirCacheEntry(path);
    e.setFileMode(fileMode);
    e.setObjectId(objectId);

    final DirCacheBuilder dirCacheBuilder = repository.lockDirCache().builder();
    dirCacheBuilder.add(e);
    dirCacheBuilder.commit();
  }

  private static StringBuilder buildSubmoduleSection(final String name,
      final String path, final String url, final String branch) {
    final StringBuilder sb = new StringBuilder();

    sb.append("[submodule \"");
    sb.append(name);
    sb.append("\"]");
    sb.append(newLine);

    sb.append("\tpath = ");
    sb.append(path);
    sb.append(newLine);

    sb.append("\turl = ");
    sb.append(url);
    sb.append(newLine);

    sb.append("\tbranch = ");
    sb.append(branch);
    sb.append(newLine);

    return sb;
  }
}
