Merge "Adapt to new core package layout"
diff --git a/BUILD b/BUILD
index 1c3873a..c6741d3 100644
--- a/BUILD
+++ b/BUILD
@@ -16,12 +16,21 @@
     ],
 )
 
+java_library(
+    name = "automerger_test_helpers",
+    srcs = glob(["src/test/java/**/helpers/*.java"]),
+)
+
 junit_tests(
     name = "automerger_tests",
-    srcs = glob(["src/test/java/**/*.java"]),
+    srcs = glob([
+        "src/test/java/**/*Test.java",
+        "src/test/java/**/*IT.java",
+    ]),
     resources = glob(["src/test/resources/**/*"]),
     tags = ["automerger"],
     deps = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
+        ":automerger_test_helpers",
         ":automerger__plugin",
         "@commons_net//jar",
     ],
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
index 4baaf4b..b61d4ef 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
@@ -41,6 +41,7 @@
 import com.google.gerrit.testing.TestTimeUtil;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+import com.googlesource.gerrit.plugins.automerger.helpers.ConfigOption;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.sql.Timestamp;
@@ -72,7 +73,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -205,14 +206,7 @@
 
     // Either bottomChangeInfoA came from left and bottomChangeInfoB came from right, or vice versa
     // We don't know which, so we use the if condition to check
-    String bottomChangeInfoASecondParent =
-        bottomChangeInfoA
-            .revisions
-            .get(bottomChangeInfoA.currentRevision)
-            .commit
-            .parents
-            .get(1)
-            .commit;
+    String bottomChangeInfoASecondParent = getParent(bottomChangeInfoA, 1);
     if (bottomChangeInfoASecondParent.equals(leftChangeInfo.currentRevision)) {
       assertThat(bottomChangeInfoA.subject)
           .isEqualTo(
@@ -314,8 +308,7 @@
     // Project name is scoped by test, so we need to get it from our initial change
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
-    createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -327,64 +320,32 @@
             .query("topic: " + gApi.changes().id(result.getChangeId()).topic())
             .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
             .get();
-    assertThat(changesInTopic).hasSize(6);
+    assertThat(changesInTopic).hasSize(4);
     List<ChangeInfo> sortedChanges = sortedChanges(changesInTopic);
 
-    // Change A
-    ChangeInfo dsOneChangeInfo = sortedChanges.get(0);
-    assertThat(dsOneChangeInfo.branch).isEqualTo("ds_one");
-    // Change B
-    ChangeInfo dsOneChangeInfo2 = sortedChanges.get(1);
-    assertThat(dsOneChangeInfo2.branch).isEqualTo("ds_one");
-    String dsOneChangeInfo2FirstParentSha =
-        dsOneChangeInfo2
-            .revisions
-            .get(dsOneChangeInfo2.currentRevision)
-            .commit
-            .parents
-            .get(0)
-            .commit;
-    assertThat(dsOneChangeInfo.currentRevision).isEqualTo(dsOneChangeInfo2FirstParentSha);
-
     // Change A'
-    ChangeInfo dsTwoChangeInfo = sortedChanges.get(2);
-    assertThat(dsTwoChangeInfo.branch).isEqualTo("ds_two");
+    ChangeInfo aPrime = sortedChanges.get(0);
+    assertThat(aPrime.branch).isEqualTo("ds_one");
     // Change B'
-    ChangeInfo dsTwoChangeInfo2 = sortedChanges.get(3);
-    assertThat(dsTwoChangeInfo2.branch).isEqualTo("ds_two");
-    String dsTwoChangeInfo2FirstParentSha =
-        dsTwoChangeInfo2
-            .revisions
-            .get(dsTwoChangeInfo2.currentRevision)
-            .commit
-            .parents
-            .get(0)
-            .commit;
-    // Check that first parent of B' is A'
-    assertThat(dsTwoChangeInfo.currentRevision).isEqualTo(dsTwoChangeInfo2FirstParentSha);
+    ChangeInfo bPrime = sortedChanges.get(1);
+    assertThat(bPrime.branch).isEqualTo("ds_one");
+    String bPrimeFirstParent = getParent(bPrime, 0);
+    assertThat(aPrime.currentRevision).isEqualTo(bPrimeFirstParent);
 
-    // Change A''
-    ChangeInfo masterChangeInfo = sortedChanges.get(4);
-    assertThat(masterChangeInfo.branch).isEqualTo("master");
-    // Change B''
-    ChangeInfo masterChangeInfo2 = sortedChanges.get(5);
-    assertThat(masterChangeInfo2.branch).isEqualTo("master");
-    String masterChangeInfo2FirstParentSha =
-        masterChangeInfo2
-            .revisions
-            .get(masterChangeInfo2.currentRevision)
-            .commit
-            .parents
-            .get(0)
-            .commit;
-    // Check that first parent of B'' is A''
-    assertThat(masterChangeInfo.currentRevision).isEqualTo(masterChangeInfo2FirstParentSha);
+    // Change A
+    ChangeInfo a = sortedChanges.get(2);
+    assertThat(a.branch).isEqualTo("master");
+    // Change B
+    ChangeInfo b = sortedChanges.get(3);
+    assertThat(b.branch).isEqualTo("master");
+    String bFirstParent = getParent(b, 0);
+    // Check that first parent of B is A
+    assertThat(bFirstParent).isEqualTo(a.currentRevision);
 
     // Ensure that commit subjects are correct
-    String shortMasterSha = masterChangeInfo.currentRevision.substring(0, 10);
-    assertThat(masterChangeInfo.subject).doesNotContainMatch("automerger");
-    assertThat(dsOneChangeInfo.subject).isEqualTo("[automerger] test commit am: " + shortMasterSha);
-    assertThat(dsTwoChangeInfo.subject).isEqualTo("[automerger] test commit am: " + shortMasterSha);
+    String shortASha = a.currentRevision.substring(0, 10);
+    assertThat(a.subject).doesNotContainMatch("automerger");
+    assertThat(aPrime.subject).isEqualTo("[automerger] test commit am: " + shortASha);
   }
 
   @Test
@@ -397,7 +358,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId(), "DO NOT MERGE subject", "filename", "content");
     result.assertOkStatus();
@@ -460,7 +421,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId(), "DO NOT MERGE ANYWHERE subject", "filename", "content");
     result.assertOkStatus();
@@ -533,7 +494,7 @@
     merge(ds1Result);
     // Reset to allow our merge conflict to come
     testRepo.reset(initial);
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new change to create the downstreams
     PushOneCommit.Result masterResult =
         pushFactory
@@ -600,7 +561,7 @@
     merge(ds1Result);
     // Reset to allow our merge conflict to come
     testRepo.reset(initial);
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
 
     // Block Code Review label to test restrictions
     blockLabel("Code-Review", -2, 2, SystemGroupBackend.CHANGE_OWNER, "refs/heads/*", project);
@@ -658,7 +619,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -683,7 +644,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -710,7 +671,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
     createBranch(new Branch.NameKey(projectName, "ds_two"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
+    pushDefaultConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", "ds_two");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -735,7 +696,7 @@
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "branch{}braces"));
     createBranch(new Branch.NameKey(projectName, "branch\"quotes"));
-    pushConfig(
+    pushDefaultConfig(
         "automerger.config",
         manifestNameKey.get(),
         projectName,
@@ -762,7 +723,7 @@
     // Project name is scoped by test, so we need to get it from our initial change
     String projectName = result.getChange().project().get();
     createBranch(new Branch.NameKey(projectName, "ds_one"));
-    pushConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one", null);
+    pushSimpleConfig("automerger.config", manifestNameKey.get(), projectName, "ds_one");
     // After we upload our config, we upload a new patchset to create the downstreams
     amendChange(result.getChangeId());
     result.assertOkStatus();
@@ -805,7 +766,8 @@
         false,
         AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
         true);
-    pushContextUserConfig(manifestNameKey.get(), projectName, contextUserApi.get()._accountId);
+    pushContextUserConfig(
+        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());
 
     // After we upload our config, we upload a new patchset to create the downstreams
     PushOneCommit.Result result = createChange("subject", "filename2", "echo Hello", "sometopic");
@@ -872,7 +834,8 @@
         false,
         AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
         false);
-    pushContextUserConfig(manifestNameKey.get(), projectName, contextUserApi.get()._accountId);
+    pushContextUserConfig(
+        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());
 
     // After we upload our config, we upload a new patchset to create the downstreams
     PushOneCommit.Result result = createChange("subject", "filename2", "echo Hello", "sometopic");
@@ -965,7 +928,8 @@
         false,
         AccountGroup.UUID.parse(gApi.groups().id(contextUserGroup).get().id),
         false);
-    pushContextUserConfig(manifestNameKey.get(), projectName, contextUserApi.get()._accountId);
+    pushContextUserConfig(
+        manifestNameKey.get(), projectName, contextUserApi.get()._accountId.toString());
 
     // After we upload our config, we upload a new patchset to create the downstreams
     PushOneCommit.Result result = createChange("subject", "filename2", "echo Hello", "sometopic");
@@ -1009,9 +973,7 @@
     }
   }
 
-  private void pushConfig(
-      String resourceName, String manifestName, String project, String branch1, String branch2)
-      throws Exception {
+  private void pushConfig(List<ConfigOption> cfgOptions, String resourceName) throws Exception {
     TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin);
     GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config");
     allProjectRepo.reset("config");
@@ -1020,15 +982,11 @@
 
       Config cfg = new Config();
       cfg.fromText(resourceString);
-      // Update manifest project path to the result of createProject(resourceName), since it is
-      // scoped to the test method
-      cfg.setString("global", null, "manifestProject", manifestName);
-      if (branch1 != null) {
-        cfg.setString("automerger", "master:" + branch1, "setProjects", project);
+
+      for (ConfigOption cfgOption : cfgOptions) {
+        cfg.setString(cfgOption.section, cfgOption.subsection, cfgOption.key, cfgOption.value);
       }
-      if (branch2 != null) {
-        cfg.setString("automerger", "master:" + branch2, "setProjects", project);
-      }
+
       PushOneCommit push =
           pushFactory.create(
               db, admin.getIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
@@ -1036,49 +994,42 @@
     }
   }
 
+  private void pushSimpleConfig(
+      String resourceName, String manifestName, String project, String branch1) throws Exception {
+    List<ConfigOption> options = new ArrayList<>();
+    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
+    options.add(new ConfigOption("automerger", "master:" + branch1, "setProjects", project));
+    pushConfig(options, resourceName);
+  }
+
+  private void pushDefaultConfig(
+      String resourceName, String manifestName, String project, String branch1, String branch2)
+      throws Exception {
+    List<ConfigOption> options = new ArrayList<>();
+    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
+    options.add(new ConfigOption("automerger", "master:" + branch1, "setProjects", project));
+    options.add(new ConfigOption("automerger", "master:" + branch2, "setProjects", project));
+    pushConfig(options, resourceName);
+  }
+
   private void pushDiamondConfig(String manifestName, String project) throws Exception {
-    TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin);
-    GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config");
-    allProjectRepo.reset("config");
-    try (InputStream in = getClass().getResourceAsStream("diamond.config")) {
-      String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));
-      Config cfg = new Config();
-      cfg.fromText(resourceString);
-      // Update manifest project path to the result of createProject(resourceName), since it is
-      // scoped to the test method
-      cfg.setString("global", null, "manifestProject", manifestName);
-      cfg.setString("automerger", "master:left", "setProjects", project);
-      cfg.setString("automerger", "master:right", "setProjects", project);
-      cfg.setString("automerger", "left:bottom", "setProjects", project);
-      cfg.setString("automerger", "right:bottom", "setProjects", project);
-      PushOneCommit push =
-          pushFactory.create(
-              db, admin.getIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
-      push.to(RefNames.REFS_CONFIG).assertOkStatus();
-    }
+    List<ConfigOption> options = new ArrayList<>();
+    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
+    options.add(new ConfigOption("automerger", "master:left", "setProjects", project));
+    options.add(new ConfigOption("automerger", "master:right", "setProjects", project));
+    options.add(new ConfigOption("automerger", "left:bottom", "setProjects", project));
+    options.add(new ConfigOption("automerger", "right:bottom", "setProjects", project));
+    pushConfig(options, "diamond.config");
   }
 
-  private void pushContextUserConfig(String manifestName, String project, int contextUserId)
+  private void pushContextUserConfig(String manifestName, String project, String contextUserId)
       throws Exception {
-    TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin);
-    GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config");
-    allProjectRepo.reset("config");
-    try (InputStream in = getClass().getResourceAsStream("context_user.config")) {
-      String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));
-
-      Config cfg = new Config();
-      cfg.fromText(resourceString);
-      // Update manifest project path to the result of createProject(resourceName), since it is
-      // scoped to the test method
-      cfg.setString("global", null, "manifestProject", manifestName);
-      cfg.setInt("global", null, "contextUserId", contextUserId);
-      cfg.setString("automerger", "master:ds_one", "setProjects", project);
-      cfg.setString("automerger", "ds_one:ds_two", "setProjects", project);
-      PushOneCommit push =
-          pushFactory.create(
-              db, admin.getIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
-      push.to(RefNames.REFS_CONFIG).assertOkStatus();
-    }
+    List<ConfigOption> options = new ArrayList<>();
+    options.add(new ConfigOption("global", null, "manifestProject", manifestName));
+    options.add(new ConfigOption("global", null, "contextUserId", contextUserId));
+    options.add(new ConfigOption("automerger", "master:ds_one", "setProjects", project));
+    options.add(new ConfigOption("automerger", "ds_one:ds_two", "setProjects", project));
+    pushConfig(options, "context_user.config");
   }
 
   private ApprovalInfo getVote(ChangeApi change, String label) throws RestApiException {
@@ -1111,4 +1062,8 @@
         });
     return listCopy;
   }
+
+  public String getParent(ChangeInfo info, int number) {
+    return info.revisions.get(info.currentRevision).commit.parents.get(number).commit;
+  }
 }
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/helpers/ConfigOption.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/helpers/ConfigOption.java
new file mode 100644
index 0000000..838d3ea
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/helpers/ConfigOption.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2017 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.automerger.helpers;
+
+public class ConfigOption {
+  public String section;
+  public String subsection;
+  public String key;
+  public String value;
+
+  /**
+   * @param section
+   * @param subsection
+   * @param key
+   * @param value
+   */
+  public ConfigOption(String section, String subsection, String key, String value) {
+    this.section = section;
+    this.subsection = subsection;
+    this.key = key;
+    this.value = value;
+  }
+}