Convert unit tests to integration tests.
Change-Id: I26f848ec0903f230afa99fba5cf4e3437741a0da
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java
new file mode 100644
index 0000000..86ae78b
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderIT.java
@@ -0,0 +1,213 @@
+// 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.CharStreams;
+import com.google.gerrit.acceptance.GitUtil;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.config.PluginConfigFactory;
+import com.google.inject.Inject;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.HashSet;
+import java.util.Set;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Config;
+import org.junit.Test;
+
+@TestPlugin(
+ name = "automerger",
+ sysModule = "com.googlesource.gerrit.plugins.automerger.AutomergerModule"
+)
+public class ConfigLoaderIT extends LightweightPluginDaemonTest {
+ private ConfigLoader configLoader;
+ @Inject private AllProjectsName allProjectsName;
+ @Inject private PluginConfigFactory cfgFactory;
+ private Project.NameKey manifestNameKey;
+
+ @Test
+ public void getProjectsInScopeTest_addProjects() throws Exception {
+ defaultSetup("automerger.config");
+ Set<String> expectedProjects = new HashSet<String>();
+ expectedProjects.add("platform/whee");
+ expectedProjects.add("platform/added/project");
+ assertThat(configLoader.getProjectsInScope("master", "ds_one")).isEqualTo(expectedProjects);
+ }
+
+ @Test
+ public void getProjectsInScopeTest_setProjects() throws Exception {
+ defaultSetup("automerger.config");
+ Set<String> otherExpectedProjects = new HashSet<String>();
+ otherExpectedProjects.add("platform/some/project");
+ otherExpectedProjects.add("platform/other/project");
+ assertThat(configLoader.getProjectsInScope("master", "ds_two"))
+ .isEqualTo(otherExpectedProjects);
+ }
+
+ @Test
+ public void getProjectsInScope_missingSourceManifest() throws Exception {
+ createProject("All-Projects");
+ manifestNameKey = createProject("platform/manifest");
+ setupTestRepo("ds_one.xml", manifestNameKey, "ds_one", "default.xml");
+ setupTestRepo("ds_two.xml", manifestNameKey, "ds_two", "default.xml");
+ loadConfig("alternate.config");
+ assertThat(configLoader.getProjectsInScope("master", "ds_one").isEmpty()).isTrue();
+ }
+
+ @Test
+ public void getProjectsInScope_ignoreSourceManifest() throws Exception {
+ defaultSetup("alternate.config");
+ Set<String> expectedProjects = new HashSet<String>();
+ expectedProjects.add("platform/whee");
+ expectedProjects.add("whuu");
+ assertThat(configLoader.getProjectsInScope("master", "ds_two")).isEqualTo(expectedProjects);
+ }
+
+ @Test
+ public void getProjectsInScope_ignoreSourceManifestWithMissingDestManifest() throws Exception {
+ defaultSetup("alternate.config");
+ assertThat(configLoader.getProjectsInScope("master", "ds_four").isEmpty()).isTrue();
+ }
+
+ @Test
+ public void isSkipMergeTest_noSkip() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(configLoader.isSkipMerge("ds_two", "ds_three", "bla")).isFalse();
+ }
+
+ @Test
+ public void isSkipMergeTest_blankMerge() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(configLoader.isSkipMerge("ds_two", "ds_three", "test test \n \n DO NOT MERGE lala"))
+ .isTrue();
+ }
+
+ @Test
+ public void isSkipMergeTest_blankMergeWithMergeAll() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(configLoader.isSkipMerge("master", "ds_two", "test test \n \n DO NOT MERGE"))
+ .isFalse();
+ }
+
+ @Test
+ public void isSkipMergeTest_alwaysBlankMerge() throws Exception {
+ defaultSetup("automerger.config");
+ assertThat(
+ configLoader.isSkipMerge("master", "ds_one", "test test \n \n DO NOT MERGE ANYWHERE"))
+ .isTrue();
+ }
+
+ @Test
+ public void isSkipMergeTest_alwaysBlankMergeDummy() throws Exception {
+ defaultSetup("alternate.config");
+ assertThat(configLoader.isSkipMerge("master", "ds_two", "test test")).isFalse();
+ }
+
+ @Test
+ public void isSkipMergeTest_alwaysBlankMergeNull() throws Exception {
+ defaultSetup("alternate.config");
+ assertThat(configLoader.isSkipMerge("master", "ds_two", "test test \n \n BLANK ANYWHERE"))
+ .isTrue();
+ }
+
+ @Test
+ public void isSkipMergeTest_noBlankMergeSpecified() throws Exception {
+ defaultSetup("empty_blank.config");
+ assertThat(configLoader.isSkipMerge("master", "ds_one", "test test \n \n DO NOT MERGE"))
+ .isFalse();
+ }
+
+ @Test
+ public void downstreamBranchesTest() throws Exception {
+ defaultSetup("automerger.config");
+ Set<String> expectedBranches = new HashSet<String>();
+ expectedBranches.add("ds_two");
+ assertThat(configLoader.getDownstreamBranches("master", "platform/some/project"))
+ .isEqualTo(expectedBranches);
+ }
+
+ @Test
+ public void downstreamBranchesTest_nonexistentBranch() throws Exception {
+ defaultSetup("automerger.config");
+ Set<String> expectedBranches = new HashSet<String>();
+ assertThat(configLoader.getDownstreamBranches("idontexist", "platform/some/project"))
+ .isEqualTo(expectedBranches);
+ }
+
+ @Test
+ public void downstreamBranchesTest_configException() throws Exception {
+ defaultSetup("wrong.config");
+
+ exception.expect(ConfigInvalidException.class);
+ exception.expectMessage("Automerger config branch pair malformed: master..ds_one");
+ configLoader.getDownstreamBranches("master", "platform/some/project");
+ }
+
+ private void defaultSetup(String resourceName) throws Exception {
+ createProject("All-Projects");
+ manifestNameKey = createProject("platform/manifest");
+ setupTestRepo("default.xml", manifestNameKey, "master", "default.xml");
+ setupTestRepo("ds_one.xml", manifestNameKey, "ds_one", "default.xml");
+ setupTestRepo("ds_two.xml", manifestNameKey, "ds_two", "default.xml");
+ loadConfig(resourceName);
+ }
+
+ private void setupTestRepo(
+ String resourceName, Project.NameKey projectNameKey, String branchName, String filename)
+ throws Exception {
+ TestRepository<InMemoryRepository> repo = cloneProject(projectNameKey, admin);
+ try (InputStream in = getClass().getResourceAsStream(resourceName)) {
+ String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));
+
+ PushOneCommit push =
+ pushFactory.create(db, admin.getIdent(), repo, "some subject", filename, resourceString);
+ push.to("refs/heads/" + branchName).assertOkStatus();
+ }
+ }
+
+ private void pushConfig(String resourceName) throws Exception {
+ TestRepository<InMemoryRepository> allProjectRepo = cloneProject(allProjects, admin);
+ GitUtil.fetch(allProjectRepo, RefNames.REFS_CONFIG + ":config");
+ allProjectRepo.reset("config");
+ try (InputStream in = getClass().getResourceAsStream(resourceName)) {
+ 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", manifestNameKey.get());
+ PushOneCommit push =
+ pushFactory.create(
+ db, admin.getIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
+ push.to("refs/meta/config").assertOkStatus();
+ }
+ }
+
+ private void loadConfig(String configFilename) throws Exception {
+ pushConfig(configFilename);
+ configLoader = new ConfigLoader(gApi, allProjectsName, "automerger", cfgFactory);
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderTest.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderTest.java
deleted file mode 100644
index 56348db..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/ConfigLoaderTest.java
+++ /dev/null
@@ -1,210 +0,0 @@
-// Copyright (C) 2016 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;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.CharStreams;
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.PluginConfigFactory;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.HashSet;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
-public class ConfigLoaderTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private GerritApi gApiMock;
-
- private ConfigLoader configLoader;
- private AllProjectsName allProjectsName;
- @Mock private PluginConfigFactory cfgFactory;
-
- @Rule public ExpectedException thrown = ExpectedException.none();
-
- @Before
- public void setUp() throws Exception {
- allProjectsName = new AllProjectsName("All-Projects");
- mockFile("automerger.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- mockFile("default.xml", "platform/manifest", "master", "default.xml");
- mockFile("ds_one.xml", "platform/manifest", "ds_one", "default.xml");
- mockFile("ds_two.xml", "platform/manifest", "ds_two", "default.xml");
- }
-
- private void mockFile(String resourceName, String projectName, String branchName, String filename)
- throws Exception {
- try (InputStream in = getClass().getResourceAsStream(resourceName)) {
- String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));
- Mockito.when(
- gApiMock.projects().name(projectName).branch(branchName).file(filename).asString())
- .thenReturn(resourceString);
- }
- }
-
- private void loadConfig() throws Exception {
- Config cfg = new Config();
- cfg.fromText(
- gApiMock
- .projects()
- .name(allProjectsName.get())
- .branch(RefNames.REFS_CONFIG)
- .file("automerger.config")
- .asString());
- Mockito.when(cfgFactory.getProjectPluginConfig(allProjectsName, "automerger")).thenReturn(cfg);
- configLoader = new ConfigLoader(gApiMock, allProjectsName, "automerger", cfgFactory);
- }
-
- @Test
- public void getProjectsInScopeTest_addProjects() throws Exception {
- loadConfig();
- Set<String> expectedProjects = new HashSet<String>();
- expectedProjects.add("platform/whee");
- expectedProjects.add("platform/added/project");
- assertThat(configLoader.getProjectsInScope("master", "ds_one")).isEqualTo(expectedProjects);
- }
-
- @Test
- public void getProjectsInScopeTest_setProjects() throws Exception {
- loadConfig();
- Set<String> otherExpectedProjects = new HashSet<String>();
- otherExpectedProjects.add("platform/some/project");
- otherExpectedProjects.add("platform/other/project");
- assertThat(configLoader.getProjectsInScope("master", "ds_two"))
- .isEqualTo(otherExpectedProjects);
- }
-
- @Test
- public void getProjectsInScope_missingSourceManifest() throws Exception {
- mockFile("alternate.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- Mockito.when(gApiMock.projects().name("platform/manifest").branch("master"))
- .thenThrow(new ResourceNotFoundException());
- loadConfig();
- assertThat(configLoader.getProjectsInScope("master", "ds_one").isEmpty()).isTrue();
- }
-
- @Test
- public void getProjectsInScope_ignoreSourceManifest() throws Exception {
- mockFile("alternate.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- loadConfig();
- Set<String> expectedProjects = new HashSet<String>();
- expectedProjects.add("platform/whee");
- expectedProjects.add("whuu");
- assertThat(configLoader.getProjectsInScope("master", "ds_two")).isEqualTo(expectedProjects);
- }
-
- @Test
- public void getProjectsInScope_ignoreSourceManifestWithMissingDestManifest() throws Exception {
- mockFile("alternate.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- Mockito.when(gApiMock.projects().name("platform/manifest").branch("ds_four"))
- .thenThrow(new ResourceNotFoundException());
- loadConfig();
- assertThat(configLoader.getProjectsInScope("master", "ds_four").isEmpty()).isTrue();
- }
-
- @Test
- public void isSkipMergeTest_noSkip() throws Exception {
- loadConfig();
- assertThat(configLoader.isSkipMerge("ds_two", "ds_three", "bla")).isFalse();
- }
-
- @Test
- public void isSkipMergeTest_blankMerge() throws Exception {
- loadConfig();
- assertThat(configLoader.isSkipMerge("ds_two", "ds_three", "test test \n \n DO NOT MERGE lala"))
- .isTrue();
- }
-
- @Test
- public void isSkipMergeTest_blankMergeWithMergeAll() throws Exception {
- loadConfig();
- assertThat(configLoader.isSkipMerge("master", "ds_two", "test test \n \n DO NOT MERGE"))
- .isFalse();
- }
-
- @Test
- public void isSkipMergeTest_alwaysBlankMerge() throws Exception {
- loadConfig();
- assertThat(
- configLoader.isSkipMerge("master", "ds_one", "test test \n \n DO NOT MERGE ANYWHERE"))
- .isTrue();
- }
-
- @Test
- public void isSkipMergeTest_alwaysBlankMergeDummy() throws Exception {
- mockFile("alternate.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- loadConfig();
- assertThat(configLoader.isSkipMerge("master", "ds_two", "test test")).isFalse();
- }
-
- @Test
- public void isSkipMergeTest_alwaysBlankMergeNull() throws Exception {
- mockFile("alternate.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- loadConfig();
- assertThat(configLoader.isSkipMerge("master", "ds_two", "test test \n \n BLANK ANYWHERE"))
- .isTrue();
- }
-
- @Test
- public void isSkipMergeTest_noBlankMergeSpecified() throws Exception {
- mockFile(
- "empty_blank.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- loadConfig();
- assertThat(configLoader.isSkipMerge("master", "ds_one", "test test \n \n DO NOT MERGE"))
- .isFalse();
- }
-
- @Test
- public void downstreamBranchesTest() throws Exception {
- loadConfig();
- Set<String> expectedBranches = new HashSet<String>();
- expectedBranches.add("ds_two");
- assertThat(configLoader.getDownstreamBranches("master", "platform/some/project"))
- .isEqualTo(expectedBranches);
- }
-
- @Test
- public void downstreamBranchesTest_nonexistentBranch() throws Exception {
- loadConfig();
- Set<String> expectedBranches = new HashSet<String>();
- assertThat(configLoader.getDownstreamBranches("idontexist", "platform/some/project"))
- .isEqualTo(expectedBranches);
- }
-
- @Test
- public void downstreamBranchesTest_configException() throws Exception {
- mockFile("wrong.config", allProjectsName.get(), RefNames.REFS_CONFIG, "automerger.config");
- loadConfig();
-
- thrown.expect(ConfigInvalidException.class);
- thrown.expectMessage("Automerger config branch pair malformed: master..ds_one");
- configLoader.getDownstreamBranches("master", "platform/some/project");
- }
-}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
new file mode 100644
index 0000000..4a7fc24
--- /dev/null
+++ b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorIT.java
@@ -0,0 +1,215 @@
+// 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.base.Charsets;
+import com.google.common.io.CharStreams;
+import com.google.gerrit.acceptance.GitUtil;
+import com.google.gerrit.acceptance.LightweightPluginDaemonTest;
+import com.google.gerrit.acceptance.PushOneCommit;
+import com.google.gerrit.acceptance.TestPlugin;
+import com.google.gerrit.extensions.api.changes.ChangeApi;
+import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.restapi.BinaryResult;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.client.Project;
+import com.google.gerrit.reviewdb.client.RefNames;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.List;
+import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
+import org.eclipse.jgit.junit.TestRepository;
+import org.eclipse.jgit.lib.Config;
+import org.eclipse.jgit.lib.ObjectId;
+import org.junit.Test;
+
+@TestPlugin(
+ name = "automerger",
+ sysModule = "com.googlesource.gerrit.plugins.automerger.AutomergerModule"
+)
+public class DownstreamCreatorIT extends LightweightPluginDaemonTest {
+ @Test
+ public void testExpectedFlow() throws Exception {
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Create initial change
+ PushOneCommit.Result result = createChange("subject", "filename", "content", "testtopic");
+ // 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);
+ // After we upload our config, we upload a new patchset to create the downstreams
+ amendChange(result.getChangeId());
+ result.assertOkStatus();
+ // Check that there are the correct number of changes in the topic
+ List<ChangeInfo> changesInTopic =
+ gApi.changes().query("topic: " + gApi.changes().id(result.getChangeId()).topic()).get();
+ assertThat(changesInTopic).hasSize(3);
+ // +2 and submit
+ merge(result);
+ }
+
+ @Test
+ public void testBlankMerge() throws Exception {
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Create initial change
+ PushOneCommit.Result result =
+ createChange("DO NOT MERGE subject", "filename", "content", "testtopic");
+ // 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);
+ // 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();
+
+ ChangeApi change = gApi.changes().id(result.getChangeId());
+ BinaryResult content = change.current().file("filename").content();
+
+ List<ChangeInfo> changesInTopic = gApi.changes().query("topic: " + change.topic()).get();
+ assertThat(changesInTopic).hasSize(3);
+ for (ChangeInfo c : changesInTopic) {
+ ChangeApi downstreamChange = gApi.changes().id(c._number);
+ // It should skip ds_one, since this is a DO NOT MERGE
+ if (c.branch.equals("ds_one")) {
+ assertThat(downstreamChange.get().subject).contains("skipped:");
+ assertThat(downstreamChange.current().files().keySet()).contains("filename");
+ assertThat(downstreamChange.current().files().get("filename").linesDeleted).isEqualTo(1);
+ } else if (c.branch.equals("ds_two")) {
+ // It should not skip ds_two, since it is marked with mergeAll: true
+ assertThat(downstreamChange.get().subject).doesNotContain("skipped:");
+ BinaryResult downstreamContent = downstreamChange.current().file("filename").content();
+ assertThat(downstreamContent.asString()).isEqualTo(content.asString());
+ } else {
+ assertThat(c.branch).isEqualTo("master");
+ }
+ }
+ }
+
+ @Test
+ public void testAlwaysBlankMerge() throws Exception {
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Create initial change
+ PushOneCommit.Result result =
+ createChange("DO NOT MERGE ANYWHERE subject", "filename", "content", "testtopic");
+ // 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);
+ // 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();
+
+ ChangeApi change = gApi.changes().id(result.getChangeId());
+
+ List<ChangeInfo> changesInTopic = gApi.changes().query("topic: " + change.topic()).get();
+ assertThat(changesInTopic).hasSize(3);
+ for (ChangeInfo c : changesInTopic) {
+ ChangeApi downstreamChange = gApi.changes().id(c._number);
+ // It should skip ds_one and ds_two, since this is a DO NOT MERGE ANYWHERE
+ if (c.branch.equals("ds_one") || c.branch.equals("ds_two")) {
+ assertThat(downstreamChange.get().subject).contains("skipped:");
+ assertThat(downstreamChange.current().files().keySet()).contains("filename");
+ assertThat(downstreamChange.current().files().get("filename").linesDeleted).isEqualTo(1);
+ } else {
+ assertThat(c.branch).isEqualTo("master");
+ }
+ }
+ }
+
+ @Test
+ public void testDownstreamMergeConflict() throws Exception {
+ Project.NameKey manifestNameKey = defaultSetup();
+ // Create initial change
+ PushOneCommit.Result result = createChange("subject", "filename", "echo Hello");
+ // 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"));
+ result.assertOkStatus();
+ merge(result);
+ // Reset to create a sibling
+ ObjectId initial = repo().exactRef("HEAD").getLeaf().getObjectId();
+ testRepo.reset(initial);
+ // Set up a merge conflict between master and ds_one
+ PushOneCommit.Result ds1Result =
+ createChange(
+ testRepo, "ds_one", "subject", "filename", "echo \"Hello asdfsd World\"", "randtopic");
+ ds1Result.assertOkStatus();
+ merge(ds1Result);
+ // Reset to allow our merge conflict to come
+ testRepo.reset(initial);
+ pushConfig("automerger.config", manifestNameKey.get(), projectName);
+ // After we upload our config, we upload a new change to create the downstreams
+ PushOneCommit.Result masterResult =
+ pushFactory
+ .create(db, admin.getIdent(), testRepo, "subject", "filename", "echo 'Hello World!'")
+ .to("refs/for/master");
+ masterResult.assertOkStatus();
+ // Since there's a conflict with ds_one, there should only be two changes in the topic
+ List<ChangeInfo> changesInTopic =
+ gApi.changes()
+ .query("topic: " + gApi.changes().id(masterResult.getChangeId()).topic())
+ .get();
+ assertThat(changesInTopic).hasSize(2);
+ }
+
+ private Project.NameKey defaultSetup() throws Exception {
+ Project.NameKey manifestNameKey = createProject("platform/manifest");
+ setupTestRepo("default.xml", manifestNameKey, "master", "default.xml");
+ setupTestRepo("ds_one.xml", manifestNameKey, "ds_one", "default.xml");
+ setupTestRepo("ds_two.xml", manifestNameKey, "ds_two", "default.xml");
+ return manifestNameKey;
+ }
+
+ private void setupTestRepo(
+ String resourceName, Project.NameKey projectNameKey, String branchName, String filename)
+ throws Exception {
+ TestRepository<InMemoryRepository> repo = cloneProject(projectNameKey, admin);
+ try (InputStream in = getClass().getResourceAsStream(resourceName)) {
+ String resourceString = CharStreams.toString(new InputStreamReader(in, Charsets.UTF_8));
+
+ PushOneCommit push =
+ pushFactory.create(db, admin.getIdent(), repo, "some subject", filename, resourceString);
+ push.to("refs/heads/" + branchName).assertOkStatus();
+ }
+ }
+
+ private void pushConfig(String resourceName, 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(resourceName)) {
+ 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:ds_one", "setProjects", project);
+ cfg.setString("automerger", "master:ds_two", "setProjects", project);
+ PushOneCommit push =
+ pushFactory.create(
+ db, admin.getIdent(), allProjectRepo, "Subject", "automerger.config", cfg.toText());
+ push.to(RefNames.REFS_CONFIG).assertOkStatus();
+ }
+ }
+}
diff --git a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorTest.java b/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorTest.java
deleted file mode 100644
index 54198f8..0000000
--- a/src/test/java/com/googlesource/gerrit/plugins/automerger/DownstreamCreatorTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-// Copyright (C) 2016 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;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.api.changes.ChangeApi;
-import com.google.gerrit.extensions.api.changes.RevisionApi;
-import com.google.gerrit.extensions.client.ListChangesOption;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.common.ChangeInput;
-import com.google.gerrit.extensions.common.CommitInfo;
-import com.google.gerrit.extensions.common.MergePatchSetInput;
-import com.google.gerrit.extensions.common.RevisionInfo;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.runners.MockitoJUnitRunner;
-
-@RunWith(MockitoJUnitRunner.class)
-public class DownstreamCreatorTest {
- private final String changeId = "testid";
- private final String changeProject = "testproject";
- private final String changeTopic = "testtopic";
- private final String changeSubject = "testmessage";
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private GerritApi gApiMock;
-
- private DownstreamCreator ds;
-
- @Before
- public void setUp() throws Exception {
- ds = new DownstreamCreator(gApiMock, Mockito.mock(ConfigLoader.class));
- }
-
- private List<ChangeInfo> mockChangeInfoList(String upstreamBranch) {
- return ImmutableList.of(
- mockChangeInfo(upstreamBranch, 1),
- mockChangeInfo("testwhee", 2),
- mockChangeInfo(upstreamBranch, 3));
- }
-
- private ChangeInfo mockChangeInfo(String upstreamRevision, int number) {
- CommitInfo parent1 = Mockito.mock(CommitInfo.class);
- parent1.commit = "infoparent" + number;
- CommitInfo parent2 = Mockito.mock(CommitInfo.class);
- parent2.commit = upstreamRevision;
-
- ChangeInfo info = Mockito.mock(ChangeInfo.class);
- info._number = number;
- info.currentRevision = "info" + number;
- info.revisions = new HashMap<>();
-
- RevisionInfo revisionInfoMock = Mockito.mock(RevisionInfo.class);
- CommitInfo commit = Mockito.mock(CommitInfo.class);
- commit.parents = ImmutableList.of(parent1, parent2);
- revisionInfoMock.commit = commit;
-
- info.revisions.put(info.currentRevision, revisionInfoMock);
- return info;
- }
-
- @Test
- public void testCreateDownstreamMerge() throws Exception {
- String currentRevision = "testCurrentRevision";
-
- ChangeInfo changeInfoMock = Mockito.mock(ChangeInfo.class);
- changeInfoMock.id = "testnewchangeid";
- ChangeApi changeApiMock = Mockito.mock(ChangeApi.class);
- Mockito.when(changeApiMock.get(EnumSet.of(ListChangesOption.CURRENT_REVISION)))
- .thenReturn(changeInfoMock);
- Mockito.when(gApiMock.changes().create(Mockito.any(ChangeInput.class)))
- .thenReturn(changeApiMock);
- RevisionApi revisionApiMock = Mockito.mock(RevisionApi.class);
- Mockito.when(gApiMock.changes().id(Mockito.anyString()).revision(Mockito.anyString()))
- .thenReturn(revisionApiMock);
-
- SingleDownstreamMergeInput dsMergeInput = new SingleDownstreamMergeInput();
- dsMergeInput.currentRevision = currentRevision;
- dsMergeInput.sourceId = changeId;
- dsMergeInput.project = changeProject;
- dsMergeInput.topic = changeTopic;
- dsMergeInput.subject = changeSubject;
- dsMergeInput.downstreamBranch = "testds";
- dsMergeInput.doMerge = true;
-
- ds.createSingleDownstreamMerge(dsMergeInput);
-
- // Check ChangeInput is the right project, branch, topic, subject
- ArgumentCaptor<ChangeInput> changeInputCaptor = ArgumentCaptor.forClass(ChangeInput.class);
- Mockito.verify(gApiMock.changes()).create(changeInputCaptor.capture());
- ChangeInput changeInput = changeInputCaptor.getValue();
- assertThat(changeInput.project).isEqualTo(changeProject);
- assertThat(changeInput.branch).isEqualTo("testds");
- assertThat(changeInput.topic).isEqualTo(changeTopic);
- assertThat(changeInput.merge.source).isEqualTo(currentRevision);
- assertThat(changeInput.merge.strategy).isEqualTo("recursive");
-
- String expectedSubject = changeSubject + " am: " + currentRevision.substring(0, 10);
- assertThat(expectedSubject).isEqualTo(changeInput.subject);
- }
-
- @Test
- public void testCreateDownstreamMerge_skipMerge() throws Exception {
- String currentRevision = "testCurrentRevision";
-
- ChangeInfo changeInfoMock = Mockito.mock(ChangeInfo.class);
- changeInfoMock.id = "testnewchangeid";
- ChangeApi changeApiMock = Mockito.mock(ChangeApi.class);
- Mockito.when(changeApiMock.get(EnumSet.of(ListChangesOption.CURRENT_REVISION)))
- .thenReturn(changeInfoMock);
- Mockito.when(gApiMock.changes().create(Mockito.any(ChangeInput.class)))
- .thenReturn(changeApiMock);
- RevisionApi revisionApiMock = Mockito.mock(RevisionApi.class);
- Mockito.when(gApiMock.changes().id(Mockito.anyString()).revision(Mockito.anyString()))
- .thenReturn(revisionApiMock);
-
- SingleDownstreamMergeInput dsMergeInput = new SingleDownstreamMergeInput();
- dsMergeInput.currentRevision = currentRevision;
- dsMergeInput.sourceId = changeId;
- dsMergeInput.project = changeProject;
- dsMergeInput.topic = changeTopic;
- dsMergeInput.subject = changeSubject;
- dsMergeInput.downstreamBranch = "testds";
- dsMergeInput.doMerge = false;
-
- ds.createSingleDownstreamMerge(dsMergeInput);
-
- // Check ChangeInput is the right project, branch, topic, subject
- ArgumentCaptor<ChangeInput> changeInputCaptor = ArgumentCaptor.forClass(ChangeInput.class);
- Mockito.verify(gApiMock.changes()).create(changeInputCaptor.capture());
- ChangeInput changeInput = changeInputCaptor.getValue();
- assertThat(changeInput.project).isEqualTo(changeProject);
- assertThat(changeInput.branch).isEqualTo("testds");
- assertThat(changeInput.topic).isEqualTo(changeTopic);
- assertThat(changeInput.merge.source).isEqualTo(currentRevision);
-
- // Check that it was actually skipped
- String expectedSubject = changeSubject + " skipped: " + currentRevision.substring(0, 10);
- assertThat(changeInput.merge.strategy).isEqualTo("ours");
- assertThat(expectedSubject).isEqualTo(changeInput.subject);
- }
-
- @Test
- public void testCreateDownstreamMerges() throws Exception {
- Map<String, Boolean> downstreamBranchMap = new HashMap<>();
- downstreamBranchMap.put("testone", true);
- downstreamBranchMap.put("testtwo", true);
-
- MultipleDownstreamMergeInput mdsMergeInput = new MultipleDownstreamMergeInput();
- mdsMergeInput.dsBranchMap = downstreamBranchMap;
- mdsMergeInput.sourceId = changeId;
- mdsMergeInput.project = changeProject;
- mdsMergeInput.topic = changeTopic;
- mdsMergeInput.subject = changeSubject;
- mdsMergeInput.obsoleteRevision = null;
- mdsMergeInput.currentRevision = "testCurrent";
-
- ds.createDownstreamMerges(mdsMergeInput);
-
- ArgumentCaptor<ChangeInput> changeInputCaptor = ArgumentCaptor.forClass(ChangeInput.class);
- Mockito.verify(gApiMock.changes(), Mockito.times(2)).create(changeInputCaptor.capture());
- List<String> capturedBranches =
- Lists.transform(
- changeInputCaptor.getAllValues(),
- new Function<ChangeInput, String>() {
- @Override
- public String apply(ChangeInput c) {
- return c.branch;
- }
- });
- assertThat(capturedBranches).containsExactly("testone", "testtwo");
- }
-
- @Test
- public void testCreateDownstreamMerges_withPreviousRevisions() throws Exception {
- Map<String, Boolean> downstreamBranchMap = new HashMap<>();
- downstreamBranchMap.put("testone", true);
- downstreamBranchMap.put("testtwo", true);
-
- List<ChangeInfo> changeInfoList = mockChangeInfoList("testup");
- Mockito.when(
- gApiMock
- .changes()
- .query(Mockito.anyString())
- .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
- .get())
- .thenReturn(changeInfoList);
-
- MultipleDownstreamMergeInput mdsMergeInput = new MultipleDownstreamMergeInput();
- mdsMergeInput.dsBranchMap = downstreamBranchMap;
- mdsMergeInput.sourceId = changeId;
- mdsMergeInput.project = changeProject;
- mdsMergeInput.topic = changeTopic;
- mdsMergeInput.subject = changeSubject;
- mdsMergeInput.obsoleteRevision = "testup";
- mdsMergeInput.currentRevision = "testCurrent";
-
- ds.createDownstreamMerges(mdsMergeInput);
-
- // Check that previous revisions were updated
- Mockito.verify(gApiMock.changes().id(Mockito.anyInt()), Mockito.times(2))
- .createMergePatchSet(Mockito.any(MergePatchSetInput.class));
- }
-
- @Test
- public void testGetExistingMergesOnBranch() throws Exception {
- List<ChangeInfo> changeInfoList = mockChangeInfoList("testup");
- Mockito.when(
- gApiMock
- .changes()
- .query(Mockito.anyString())
- .withOptions(ListChangesOption.ALL_REVISIONS, ListChangesOption.CURRENT_COMMIT)
- .get())
- .thenReturn(changeInfoList);
-
- List<Integer> downstreamChangeNumbers =
- ds.getExistingMergesOnBranch("testup", "testtopic", "testdown");
- assertThat(downstreamChangeNumbers).containsExactly(1, 3).inOrder();
- }
-}