// 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.capture;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;

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.gerrit.server.util.TimeUtil;
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.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 SchemaFactory<ReviewDb> schemaFactory;
  private SubmoduleSubscriptionAccess subscriptions;
  private ReviewDb schema;
  private Provider<String> urlProvider;
  private GitRepositoryManager repoManager;
  private GitReferenceUpdated gitRefUpdated;

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

    schemaFactory = createStrictMock(SchemaFactory.class);
    schema = createStrictMock(ReviewDb.class);
    subscriptions = createStrictMock(SubmoduleSubscriptionAccess.class);
    urlProvider = createStrictMock(Provider.class);
    repoManager = createStrictMock(GitRepositoryManager.class);
    gitRefUpdated = createStrictMock(GitReferenceUpdated.class);
  }

  private void doReplay() {
    replay(schemaFactory, schema, subscriptions, urlProvider, repoManager,
        gitRefUpdated);
  }

  private void doVerify() {
    verify(schemaFactory, schema, subscriptions, urlProvider, repoManager,
        gitRefUpdated);
  }

  /**
   * 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);

    final Repository realDb = createWorkRepository();
    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<SubmoduleSubscription>(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);

    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");

    final List<SubmoduleSubscription> subscriptionsToInsert =
        new ArrayList<SubmoduleSubscription>();
    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");

    final List<SubmoduleSubscription> subscriptionsToInsert =
        new ArrayList<SubmoduleSubscription>();
    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");

    final List<SubmoduleSubscription> subscriptionsToInsert =
        new ArrayList<SubmoduleSubscription>();
    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");

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

    final List<SubmoduleSubscription> oldOnesToMergedBranch =
        new ArrayList<SubmoduleSubscription>();
    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");

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

    final List<SubmoduleSubscription> oldOnesToMergedBranch =
        new ArrayList<SubmoduleSubscription>();
    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");

    final List<SubmoduleSubscription> extractedsubscriptions =
        new ArrayList<SubmoduleSubscription>();

    final List<SubmoduleSubscription> oldOnesToMergedBranch =
        new ArrayList<SubmoduleSubscription>();
    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);

    final Repository sourceRepository = createWorkRepository();
    final Git sourceGit = new Git(sourceRepository);

    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());
    codeReviewCommit.change = submittedChange;

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

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

    final Repository targetRepository = createWorkRepository();
    final Git targetGit = new Git(targetRepository);

    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<SubmoduleSubscription>(Collections
            .singletonList(new SubmoduleSubscription(targetBranchNameKey,
                sourceBranchNameKey, "source-project")));
    expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn(
        subscribers);

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

    Capture<RefUpdate> ruCapture = new Capture<RefUpdate>();
    gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()),
        capture(ruCapture));

    expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
    final ResultSet<SubmoduleSubscription> emptySubscriptions =
        new ListResultSet<SubmoduleSubscription>(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);

    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);

    final Repository sourceRepository = createWorkRepository();
    final Git sourceGit = new Git(sourceRepository);

    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());
    codeReviewCommit.change = submittedChange;

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

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

    final Repository targetRepository = createWorkRepository();
    final Git targetGit = new Git(targetRepository);

    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<SubmoduleSubscription>(Collections
            .singletonList(new SubmoduleSubscription(targetBranchNameKey,
                sourceBranchNameKey, "source-project")));
    expect(subscriptions.bySubmodule(sourceBranchNameKey)).andReturn(
        subscribers);

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

    Capture<RefUpdate> ruCapture = new Capture<RefUpdate>();
    gitRefUpdated.fire(eq(targetBranchNameKey.getParentKey()),
        capture(ruCapture));

    expect(schema.submoduleSubscriptions()).andReturn(subscriptions);
    final ResultSet<SubmoduleSubscription> incorrectSubscriptions =
        new ListResultSet<SubmoduleSubscription>(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);

    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");

    final List<SubmoduleSubscription> subscriptionsToInsert =
        new ArrayList<SubmoduleSubscription>();
    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</code> 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 {@link 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</code> 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 {@link 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</code>
   *        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);

    final Repository realDb = createWorkRepository();
    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<SubmoduleSubscription>(previousSubscriptions));

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

    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<SubmoduleSubscription>();
    for (SubmoduleSubscription s : extractedSubscriptions) {
      if (previousSubscriptions.contains(s)) {
        alreadySubscribeds.add(s);
      }
    }

    final Set<SubmoduleSubscription> subscriptionsToRemove =
        new HashSet<SubmoduleSubscription>(previousSubscriptions);
    final List<SubmoduleSubscription> subscriptionsToInsert =
        new ArrayList<SubmoduleSubscription>(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<SubmoduleSubscription>(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);

    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;
  }
}
