/*
* Copyright 2017 ThoughtWorks, Inc.
*
* 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.thoughtworks.go.server.service;
import com.rits.cloning.Cloner;
import com.thoughtworks.go.config.CaseInsensitiveString;
import com.thoughtworks.go.config.CruiseConfig;
import com.thoughtworks.go.config.GoConfigDao;
import com.thoughtworks.go.config.materials.PackageMaterial;
import com.thoughtworks.go.config.materials.PackageMaterialConfig;
import com.thoughtworks.go.config.materials.PluggableSCMMaterial;
import com.thoughtworks.go.config.materials.dependency.DependencyMaterial;
import com.thoughtworks.go.config.materials.git.GitMaterial;
import com.thoughtworks.go.config.materials.mercurial.HgMaterial;
import com.thoughtworks.go.config.materials.svn.SvnMaterial;
import com.thoughtworks.go.domain.MaterialRevision;
import com.thoughtworks.go.domain.MaterialRevisions;
import com.thoughtworks.go.domain.Pipeline;
import com.thoughtworks.go.domain.buildcause.BuildCause;
import com.thoughtworks.go.helper.MaterialsMother;
import com.thoughtworks.go.server.cache.GoCache;
import com.thoughtworks.go.server.dao.DatabaseAccessHelper;
import com.thoughtworks.go.server.domain.PipelineTimeline;
import com.thoughtworks.go.server.materials.DependencyMaterialUpdateNotifier;
import com.thoughtworks.go.server.materials.MaterialChecker;
import com.thoughtworks.go.server.persistence.MaterialRepository;
import com.thoughtworks.go.server.transaction.TransactionTemplate;
import com.thoughtworks.go.serverhealth.ServerHealthService;
import com.thoughtworks.go.util.GoConfigFileHelper;
import com.thoughtworks.go.util.SystemEnvironment;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import static com.thoughtworks.go.util.SystemEnvironment.RESOLVE_FANIN_MAX_BACK_TRACK_LIMIT;
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = {
"classpath:WEB-INF/applicationContext-global.xml",
"classpath:WEB-INF/applicationContext-dataLocalAccess.xml",
"classpath:WEB-INF/applicationContext-acegi-security.xml"
})
public class FaninDependencyResolutionTest {
public static final String STAGE_NAME = "s";
public static final Cloner CLONER = new Cloner();
@Autowired
private DatabaseAccessHelper dbHelper;
@Autowired
private GoCache goCache;
@Autowired
private GoConfigDao goConfigDao;
@Autowired
private PipelineService pipelineService;
@Autowired
private MaterialRepository materialRepository;
@Autowired
private TransactionTemplate transactionTemplate;
@Autowired
private GoConfigService goConfigService;
@Autowired
private SystemEnvironment systemEnvironment;
@Autowired
private MaterialChecker materialChecker;
@Autowired
private PipelineTimeline pipelineTimeline;
@Autowired
private ServerHealthService serverHealthService;
@Autowired
private DependencyMaterialUpdateNotifier notifier;
private GoConfigFileHelper configHelper = new GoConfigFileHelper();
private ScheduleTestUtil u;
@Before
public void setUp() throws Exception {
goCache.clear();
configHelper.usingCruiseConfigDao(goConfigDao);
configHelper.onSetUp();
dbHelper.onSetUp();
u = new ScheduleTestUtil(transactionTemplate, materialRepository, dbHelper, configHelper);
notifier.disableUpdates();
}
@After
public void teardown() throws Exception {
notifier.enableUpdates();
systemEnvironment.reset(RESOLVE_FANIN_MAX_BACK_TRACK_LIMIT);
dbHelper.onTearDown();
configHelper.onTearDown();
}
private void setMaxBackTrackLimit(int limit) {
systemEnvironment.set(RESOLVE_FANIN_MAX_BACK_TRACK_LIMIT, limit);
}
private Integer maxBackTrackLimit() {
return systemEnvironment.get(SystemEnvironment.RESOLVE_FANIN_MAX_BACK_TRACK_LIMIT);
}
@Test
public void shouldRestoreMaterialNamesBasedOnMaterialConfig() throws Exception {
/*
g -> up -> down
+-> mid -+
*/
GitMaterial git = u.wf(new GitMaterial("git"), "folder1");
u.checkinInOrder(git, "g1");
ScheduleTestUtil.AddedPipeline up = u.saveConfigWith("up", u.m(git));
ScheduleTestUtil.MaterialDeclaration upForMid = u.m(up);
((DependencyMaterial) upForMid.material).setName(new CaseInsensitiveString("up-for-mid"));
ScheduleTestUtil.AddedPipeline mid = u.saveConfigWith("mid", upForMid);
ScheduleTestUtil.MaterialDeclaration upForDown = u.m(up);
((DependencyMaterial) upForDown.material).setName(new CaseInsensitiveString("up-for-down"));
ScheduleTestUtil.AddedPipeline down = u.saveConfigWith("down", u.m(mid), upForDown);
CruiseConfig cruiseConfig = goConfigDao.load();
String up_1 = u.runAndPass(up, "g1");
String mid_1 = u.runAndPass(mid, up_1);
String down_1 = u.runAndPass(down, mid_1, up_1);
MaterialRevisions given = u.mrs(
u.mr(mid, false, mid_1),
u.mr(up, false, up_1));
MaterialRevisions revisionsBasedOnDependencies = getRevisionsBasedOnDependencies(down, cruiseConfig, given);
for (MaterialRevision revisionsBasedOnDependency : revisionsBasedOnDependencies) {
DependencyMaterial dependencyPipeline = (DependencyMaterial) revisionsBasedOnDependency.getMaterial();
if (dependencyPipeline.getPipelineName().equals(new CaseInsensitiveString("up"))) {
assertThat(dependencyPipeline.getName(), is(new CaseInsensitiveString("up-for-down")));
}
}
assertThat(revisionsBasedOnDependencies, is(given));
}
@Test
public void shouldTriggerCommonCIAndCDPhasesCorrectly_FAILING_SCN() throws Exception {
// -----> Acceptance ----
// | | v
// Build | Staging ---> Production
// | v ^
// ----->Regression ----
//
GitMaterial git = u.wf(new GitMaterial("git"), "folder1");
u.checkinInOrder(git, "g1", "g2", "g3");
ScheduleTestUtil.AddedPipeline build = u.saveConfigWith("build", u.m(git));
ScheduleTestUtil.AddedPipeline acceptance = u.saveConfigWith("acceptance", u.m(build));
ScheduleTestUtil.AddedPipeline regression = u.saveConfigWith("regression", u.m(build), u.m(acceptance));
ScheduleTestUtil.AddedPipeline staging = u.saveConfigWith("staging", u.m(acceptance), u.m(regression));
ScheduleTestUtil.AddedPipeline production = u.saveConfigWith("production", u.m(staging));
CruiseConfig cruiseConfig = goConfigDao.load();
int i = 1;
String b_1 = u.runAndPass(build, "g1");
String a_1 = u.runAndPass(acceptance, b_1);
String r_1 = u.runAndPass(regression, b_1, a_1);
String s_1 = u.runAndPass(staging, a_1, r_1);
String p_1 = u.runAndPass(production, s_1);
String b_2 = u.runAndPass(build, "g2");
MaterialRevisions given = u.mrs(
u.mr(build, true, b_2),
u.mr(acceptance, false, a_1));
MaterialRevisions expected = u.mrs(
u.mr(build, true, b_1),
u.mr(acceptance, false, a_1));
assertThat(getRevisionsBasedOnDependencies(regression, cruiseConfig, given), is(expected));
String a_2 = u.runAndPass(acceptance, b_2);
given = u.mrs(
u.mr(build, true, b_2),
u.mr(acceptance, false, a_2));
expected = u.mrs(
u.mr(build, true, b_2),
u.mr(acceptance, true, a_2));
assertThat(getRevisionsBasedOnDependencies(regression, cruiseConfig, given), is(expected));
String r_2 = u.runAndPass(regression, b_2, a_2);
String r_3 = u.runAndPass(regression, b_1, a_2);
given = u.mrs(
u.mr(acceptance, true, a_2),
u.mr(regression, true, r_3));
expected = u.mrs(
u.mr(acceptance, true, a_2),
u.mr(regression, true, r_2));
assertThat(getRevisionsBasedOnDependencies(staging, cruiseConfig, given), is(expected));
String s_2 = u.runAndPass(staging, a_2, r_2);
String s_3 = u.runAndPass(staging, a_2, r_3);
given = u.mrs(u.mr(staging, true, s_3));
expected = u.mrs(u.mr(staging, true, s_2));
assertThat(getRevisionsBasedOnDependencies(production, cruiseConfig, given), is(expected));
String b_3 = u.runAndPass(build, "g3");
String a_3 = u.runAndPass(acceptance, b_3);
String r_4 = u.runAndPass(regression, b_3, a_3);
String s_4 = u.runAndPass(staging, a_3, r_1);
String s_5 = u.runAndPass(staging, a_1, r_4);
given = u.mrs(
u.mr(acceptance, true, a_3),
u.mr(regression, true, r_4));
expected = u.mrs(
u.mr(acceptance, true, a_3),
u.mr(regression, true, r_4));
MaterialRevisions previousMaterialRevisions = u.mrs(
u.mr(acceptance, false, a_1),
u.mr(regression, false, r_4));
assertThat(getRevisionsBasedOnDependencies(staging, cruiseConfig, given), is(expected));
// assertThat(getBuildCause(staging,given,previousMaterialRevisions), is(not(nullValue()))); //TODO: *************** Bug where pipeline should be triggered <Sara>
String r_5 = u.runAndPass(regression, b_3, a_3);
given = u.mrs(
u.mr(acceptance, true, a_3),
u.mr(regression, true, r_5));
expected = u.mrs(
u.mr(acceptance, true, a_3),
u.mr(regression, true, r_5));
assertThat(getRevisionsBasedOnDependencies(staging, cruiseConfig, given), is(expected));
previousMaterialRevisions = u.mrs(
u.mr(acceptance, false, a_1),
u.mr(regression, false, r_4));
assertThat(getBuildCause(staging, given, previousMaterialRevisions).getMaterialRevisions(), is(expected));
}
@Test
public void shouldReturnPreviousBuild_sRevisionsIfOneParentFailed() {
// git ----------
// | |
// ----- ------ |
// | | |
// v v |
// P1 P2 |
// | | |
// | | |
// --->P3<-- |
// ^____________|
GitMaterial gitMaterial = new GitMaterial("git-url");
u.checkinInOrder(gitMaterial, "g1", "g2");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(gitMaterial));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(gitMaterial));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("P3", u.m(p1), u.m(p2), u.m(gitMaterial));
String p1_1 = u.runAndPass(p1, "g1");
String p2_1 = u.runAndPass(p2, "g1");
String p3_1 = u.runAndPass(p3, p1_1, p2_1, "g1");
String p1_2 = u.runAndPass(p1, "g2");
String p2_2 = u.runAndFail(p2, "g2");
MaterialRevisions given = u.mrs(new MaterialRevision[]{
u.mr(gitMaterial, true, "g2"),
u.mr(p1, true, p1_2),
u.mr(p2, true, p2_1)});
MaterialRevisions expected = u.mrs(new MaterialRevision[]{
u.mr(gitMaterial, true, "g1"),
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_1)});
MaterialRevisions finalRevisions = getRevisionsBasedOnDependencies(p3, goConfigDao.load(), given);
assertThat(finalRevisions, is(expected));
}
@Test
public void shouldResolveWithMultipleDiamondsOnSamePipelines() throws Exception {
/*
|-------v
| /--P1--\
git hg P5
| \--P2--/
+------^
*/
HgMaterial hg = u.wf(new HgMaterial("hg", null), "folder1");
String[] hg_revs = {"h11", "h12"};
u.checkinInOrder(hg, hg_revs);
GitMaterial git = u.wf(new GitMaterial("git"), "folder2");
String[] git_revs = {"g11", "g12", "g13"};
u.checkinInOrder(git, git_revs);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(hg), u.m(git));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(hg), u.m(git));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", u.m(p1), u.m(p2));
String p1_1 = u.runAndPass(p1, "h12", "g11");
String p2_1 = u.runAndPass(p2, "h11", "g13");
String p1_2 = u.runAndPass(p1, "h11", "g13");
String p2_2 = u.runAndPass(p2, "h12", "g13");
MaterialRevisions given = u.mrs(new MaterialRevision[]{
u.mr(p1, true, p1_2),
u.mr(p2, true, p2_2)});
MaterialRevisions expected = u.mrs(new MaterialRevision[]{
u.mr(p1, true, p1_2),
u.mr(p2, true, p2_1)});
assertThat(getRevisionsBasedOnDependencies(p3, goConfigDao.load(), given), is(expected));
}
@Test
public void shouldFindCompatibleRevisionWhenDependencyMaterialHasMaterialName() throws Exception {
// Third <- Second
// | /
// | /
// Last
//
SvnMaterial svn = u.wf(new SvnMaterial("svn", "username", "password", false), "folder1");
String[] svn_revs = {"s1"};
u.checkinInOrder(svn, svn_revs);
ScheduleTestUtil.AddedPipeline second = u.saveConfigWith("second", u.m(svn));
ScheduleTestUtil.AddedPipeline third = u.saveConfigWith("third", u.m(second, "two"));
ScheduleTestUtil.AddedPipeline last = u.saveConfigWith("last", u.m(third, "three"), u.m(second, "two_2"));
String second_1 = u.runAndPass(second, "s1");
String third_1 = u.runAndPass(third, second_1);
MaterialRevisions given = u.mrs(
u.mr(third, true, third_1),
u.mr(second, true, second_1));
assertThat(getRevisionsBasedOnDependencies(last, goConfigDao.load(), given), is(given));
}
@Test
public void shouldFindCompatibleRevisionWhenSameMaterialHasDiffFolderNamesInGraph() throws Exception {
// Second <- Svn
// | /
// | /
// Third
//
SvnMaterial svn1 = u.wf(new SvnMaterial("svn", "username", "password", false), "one");
SvnMaterial svn2 = u.wf(new SvnMaterial("svn", "username", "password", false), "two");
String[] svn_revs = {"s1"};
u.checkinInOrder(svn1, svn_revs);
ScheduleTestUtil.AddedPipeline second = u.saveConfigWith("second", u.m(svn1));
ScheduleTestUtil.AddedPipeline third = u.saveConfigWith("third", u.m(second), u.m(svn2));
String second_1 = u.runAndPass(second, "s1");
MaterialRevisions given = u.mrs(
u.mr(second, true, second_1),
u.mr(svn2, true, "s1")
);
MaterialRevisions materialRevisions = getRevisionsBasedOnDependencies(third, goConfigDao.load(), given);
assertThat(materialRevisions, is(given));
}
@Test
public void shouldComputeRevisionCorrectlyWhenUpstreamPipelineHasModifications_ForDifferentStages() throws Exception {
/*
/-->P1------\ p2(s1) --> p4
git P3
\-->P2(S2)--/
*/
GitMaterial git = u.wf(new GitMaterial("git"), "f");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(git));
ScheduleTestUtil.AddedPipeline p2_s1 = u.saveConfigWith("p2", "s1", u.m(git));
ScheduleTestUtil.AddedPipeline p2_s2 = u.addStageToPipeline(p2_s1.config.name(), "s2");
ScheduleTestUtil.MaterialDeclaration p2_material = u.m(new DependencyMaterial(p2_s1.config.name(), new CaseInsensitiveString("s2")));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", p2_material, u.m(p1));
ScheduleTestUtil.AddedPipeline p4 = u.saveConfigWith("p4", u.m(new DependencyMaterial(p2_s1.config.name(), new CaseInsensitiveString("s1"))));
u.checkinInOrder(git, "g1");
String p1_1 = u.runAndPass(p1, "g1");
String p2_s2_1 = u.runAndPass(p2_s2, "g1");
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2_s2, true, p2_s2_1));
MaterialRevisions revisionsBasedOnDependencies = getRevisionsBasedOnDependencies(p3, goConfigDao.load(), given);
assertThat(revisionsBasedOnDependencies, is(given));
}
@Test
public void shouldPickTheRightRevisionsWhenMaterialIsRemovedAndPutBack() {
GitMaterial git1 = u.wf(new GitMaterial("git1-url"), "git-folder1");
GitMaterial git2 = u.wf(new GitMaterial("git2-url"), "git-folder2");
GitMaterial git3 = u.wf(new GitMaterial("git3-url"), "git-folder3");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(git1), u.m(git2));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(git2));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("P3", u.m(p1), u.m(p2), u.m(git1));
ScheduleTestUtil.AddedPipeline p4 = u.saveConfigWith("P4", u.m(p3), u.m(git2));
u.checkinInOrder(git1, "git1_1");
u.checkinInOrder(git2, "git2_1");
String p1_1 = u.runAndPass(p1, "git1_1", "git2_1");
String p2_1 = u.runAndPass(p2, "git2_1");
String p3_1 = u.runAndPass(p3, p1_1, p2_1, "git1_1");
String p4_1 = u.runAndPass(p4, p3_1, "git2_1");
u.checkinInOrder(git1, "git1_2");
u.checkinInOrder(git2, "git2_2");
String p1_2 = u.runAndPass(p1, "git1_2", "git2_2");
String p2_2 = u.runAndPass(p2, "git2_2");
String p3_2 = u.runAndPass(p3, p1_2, p2_2, "git1_2");
String p4_2 = u.runAndPass(p4, p3_2, "git2_2");
configHelper.setMaterialConfigForPipeline("P2", git3.config());
CruiseConfig cruiseConfig = goConfigDao.load();
p2 = new ScheduleTestUtil.AddedPipeline(cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("P2")), p2.material);
u.checkinInOrder(git1, "git1_3");
u.checkinInOrder(git2, "git2_3");
u.checkinInOrder(git3, "git3_1");
String p1_3 = u.runAndPass(p1, "git1_3", "git2_3");
String p2_3 = u.runAndPass(p2, "git3_1");
String p3_3 = u.runAndPass(p3, p1_3, p2_3, "git1_3");
//check wat happens to p4
MaterialRevisions given = u.mrs(new MaterialRevision[]{
u.mr(git2, true, "git2_3"),
u.mr(p3, true, p3_3)});
MaterialRevisions expected = u.mrs(new MaterialRevision[]{
u.mr(git2, true, "git2_3"),
u.mr(p3, true, p3_3)});
MaterialRevisions finalRevisions = getRevisionsBasedOnDependencies(p4, cruiseConfig, given);
assertThat(finalRevisions, is(expected));
//bring back git2 in p2
configHelper.setMaterialConfigForPipeline("P2", git2.config());
cruiseConfig = goConfigDao.load();
p2 = new ScheduleTestUtil.AddedPipeline(cruiseConfig.pipelineConfigByName(new CaseInsensitiveString("P2")), p2.material);
//check wat happend to p4
given = u.mrs(
u.mr(git2, true, "git2_3"),
u.mr(p3, true, p3_3));
expected = u.mrs(new MaterialRevision[]{
u.mr(git2, true, "git2_3"),
u.mr(p3, true, p3_3)});
finalRevisions = getRevisionsBasedOnDependencies(p4, cruiseConfig, given);
assertThat(finalRevisions, is(expected));
}
@Test
public void shouldResolveDifferentCasesInAPipelineGraphSimilarToOneInGo01() {
GitMaterial git1 = u.wf(new GitMaterial("git1-url"), "git-folder1");
GitMaterial git2 = u.wf(new GitMaterial("git2-url"), "git-folder2");
GitMaterial git3 = u.wf(new GitMaterial("git3-url"), "git-folder3");
GitMaterial git4 = u.wf(new GitMaterial("git4-url"), "git-folder4");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(git1));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(p1), u.m(git1));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("P3", u.m(p1), u.m(git2));
ScheduleTestUtil.AddedPipeline p4 = u.saveConfigWith("P4", u.m(p3), u.m(p2), u.m(git3));
ScheduleTestUtil.AddedPipeline p5 = u.saveConfigWith("P5", u.m(p2), u.m(git3), u.m(git4));
ScheduleTestUtil.AddedPipeline p6 = u.saveConfigWith("P6", u.m(p3), u.m(git3), u.m(git4));
ScheduleTestUtil.AddedPipeline p7 = u.saveConfigWith("P7", u.m(p4), u.m(p5), u.m(p6));
ScheduleTestUtil.AddedPipeline p8 = u.saveConfigWith("P8", u.m(p7));
}
@Test
public void shouldThrowExceptionWhenStageHasPassedButIsNotPresentInModificationsTable() {
GitMaterial git = u.wf(new GitMaterial("git1-url"), "git-folder1");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(git));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(git));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("P3", u.m(p1), u.m(p2));
u.checkinInOrder(git, "g1", "g2");
String p1_1 = u.runAndPass(p1, "g1");
String p2_1 = u.runAndPass(p2, "g1");
String p3_1 = u.runAndPass(p3, p1_1, p2_1);
String p1_2 = u.runAndPass(p1, "g2");
Pipeline p2_2instance = u.scheduleWith(p2, "g2");
dbHelper.pass(p2_2instance);
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_2),
u.mr(p2, false, p2_1)
);
MaterialRevisions previous = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_1)
);
try {
getBuildCause(p3, given, previous);
fail();
} catch (NoModificationsPresentForDependentMaterialException exception) {
assertThat(exception.getMessage(), Matchers.containsString(p2_2instance.getFirstStage().getIdentifier().getStageLocator()));
}
}
@Test
public void shouldComputeRevisionCorrectlyWhen_MoreThan1UpstreamPipelineHasMinimumRevision() throws Exception {
/* +----------
/-->P1---\ v
git------> P3 -> P4
\-->P2--/ ^
+----------
*/
GitMaterial git = u.wf(new GitMaterial("git"), "f");
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(git));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(git));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", u.m(p1), u.m(p2), u.m(git));
ScheduleTestUtil.AddedPipeline p4 = u.saveConfigWith("p4", u.m(p1), u.m(p2), u.m(p3));
int i = 0;
u.checkinInOrder(git, u.d(i++), "g0");
String p1_1 = u.runAndPass(p1, "g0");
String p2_1 = u.runAndPass(p2, "g0");
String p3_1 = u.runAndPass(p3, p1_1, p2_1, "g0");
String p4_1 = u.runAndPass(p4, p1_1, p2_1, p3_1);
u.checkinInOrder(git, u.d(i++), "g1");
String p1_2 = u.runAndPass(p1, "g1");
u.checkinInOrder(git, u.d(i++), "g2");
String p2_2 = u.runAndPass(p2, "g2");
String p3_2 = u.runAndPass(p3, p1_2, p2_2, "g2");
u.checkinInOrder(git, u.d(i++), "g3");
String p1_3 = u.runAndPass(p1, "g3");
String p2_3 = u.runAndPass(p2, "g3");
String p3_3 = u.runAndPass(p3, p1_3, p2_3, "g3");
String p4_2 = u.runAndPass(p4, p1_3, p2_3, p3_3);
String p2_4 = u.runAndPass(p2, "g1");
String p3_4 = u.runAndPass(p3, p1_2, p2_4, "g1");
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_3),
u.mr(p2, true, p2_4),
u.mr(p3, true, p3_4));
MaterialRevisions expected = u.mrs(
u.mr(p1, true, p1_2),
u.mr(p2, true, p2_4),
u.mr(p3, true, p3_4));
MaterialRevisions revisionsBasedOnDependencies = getRevisionsBasedOnDependencies(p4, goConfigDao.load(), given);
assertThat(revisionsBasedOnDependencies, is(expected));
}
@Test
public void shouldResolveWithNoPassedBuildOfRootNode() throws Exception {
/**
* git -------+
* | |
* | |
* v v
* P1 -----> P2
*/
GitMaterial git = u.wf(new GitMaterial("git"), "folder1");
String[] git_revs = {"g1"};
int i = 0;
u.checkinInOrder(git, u.d(i++), git_revs);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(git));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(p1), u.m(git));
CruiseConfig cruiseConfig = goConfigDao.load();
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g1");
setMaxBackTrackLimit(2);
for (int j = 1; j <= maxBackTrackLimit() + 1; j++) {
u.runAndFail(p2, u.d(i++), p1_1, "g1");
}
MaterialRevisions given = u.mrs(u.mr(p1, true, p1_1), u.mr(git, true, "g1"));
MaterialRevisions finalRevisions = getRevisionsBasedOnDependencies(p2, cruiseConfig, given);
assertThat(finalRevisions, is(given));
}
@Test
public void shouldResolveWithModifiedStageDefinitionOfRootNode() throws Exception {
/**
* git -------+
* | |
* | |
* v v
* P1 -----> P2
*/
GitMaterial git = u.wf(new GitMaterial("git"), "folder1");
String[] git_revs = {"g1", "g2"};
int i = 0;
u.checkinInOrder(git, u.d(i++), git_revs);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("P1", u.m(git));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("P2", u.m(p1), u.m(git));
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g1");
setMaxBackTrackLimit(2);
for (int j = 1; j <= maxBackTrackLimit() + 1; j++) {
u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), p1_1, "g1");
}
String p1_2 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g2");
p2 = u.changeStagenameForToPipeline("P2", "s", "new-stage");
CruiseConfig cruiseConfig = goConfigDao.load();
MaterialRevisions given = u.mrs(u.mr(p1, true, p1_2), u.mr(git, true, "g2"));
MaterialRevisions finalRevisions = getRevisionsBasedOnDependencies(p2, cruiseConfig, given);
assertThat(finalRevisions, is(given));
}
@Test
public void shouldConsiderFailedBuildOfRootNodeForFinalRevisionComputation() {
/*
+---> P1 ---+
| v
git-------> P2
*/
int i = 1;
GitMaterial git1 = u.wf(new GitMaterial("git1"), "folder");
String[] git_revs1 = {"g11", "g12", "g13"};
u.checkinInOrder(git1, u.d(i++), git_revs1);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(git1));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(git1), u.m(p1));
CruiseConfig cruiseConfig = goConfigDao.load();
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g11");
String p2_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "g11", p1_1);
String p1_2 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g12");
String p2_2 = u.runAndFail(p2, u.d(i++), "g12", p1_2);
String p1_3 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g13");
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_3),
u.mr(git1, true, "g13"));
assertThat(getRevisionsBasedOnDependencies(p2, cruiseConfig, given), is(given));
}
@Test
public void shouldResolveWithModifiedMaterialDefinitionOfRoot() throws Exception {
/*
+---> P1 ---+
| v
git-------> P2 <---- hg
*/
int i = 1;
GitMaterial git1 = u.wf(new GitMaterial("git1"), "folder");
String[] git_revs1 = {"g11"};
u.checkinInOrder(git1, u.d(i++), git_revs1);
HgMaterial hg = u.wf(new HgMaterial("hg", null), "folder1");
String[] hg_revs1 = {"h11"};
u.checkinInOrder(hg, u.d(i++), hg_revs1);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(git1));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(git1), u.m(p1));
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "g11");
String p2_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "g11", p1_1);
p2 = u.addMaterialToPipeline(p2, u.m(hg));
MaterialRevisions given = u.mrs(
u.mr(git1, true, "g11"),
u.mr(p1, true, p1_1),
u.mr(hg, true, "h11"));
assertThat(getRevisionsBasedOnDependencies(p2, goConfigDao.load(), given), is(given));
}
@Test
public void shouldResolveTriangleDependencyWithPackageMaterial() {
/*
+---> P1 ---+
| v
pkg1-------> P2
*/
int i = 1;
PackageMaterial pkg1 = MaterialsMother.packageMaterial();
u.addPackageDefinition((PackageMaterialConfig) pkg1.config());
String[] pkg_revs1 = {"pkg1-1", "pkg1-2"};
u.checkinInOrder(pkg1, u.d(i++), pkg_revs1);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(pkg1));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(pkg1), u.m(p1));
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "pkg1-1");
String p2_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "pkg1-1", p1_1);
MaterialRevisions given = u.mrs(
u.mr(pkg1, true, "pkg1-2"),
u.mr(p1, true, p1_1));
MaterialRevisions expected = u.mrs(
u.mr(pkg1, true, "pkg1-1"),
u.mr(p1, true, p1_1));
assertThat(getRevisionsBasedOnDependencies(p2, goConfigDao.load(), given), is(expected));
}
@Test
public void shouldResolveDiamondDependencyWithPackageMaterial() {
/*
+---> P1 ---+
| v
pkg1 P3
| ^
+--> P2 ----+
*/
int i = 1;
PackageMaterial pkg1 = MaterialsMother.packageMaterial();
u.addPackageDefinition((PackageMaterialConfig) pkg1.config());
String[] pkg_revs = {"pkg1-1", "pkg1-2"};
u.checkinInOrder(pkg1, u.d(i++), pkg_revs);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(pkg1));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(pkg1));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", u.m(p1), u.m(p2));
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "pkg1-1");
String p2_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "pkg1-1");
String p2_2 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "pkg1-2");
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_2));
MaterialRevisions expected = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_1));
assertThat(getRevisionsBasedOnDependencies(p3, goConfigDao.load(), given), is(expected));
}
@Test
public void shouldResolveDiamondDependencyWithPluggableSCMMaterial() {
/*
+---> P1 ---+
| v
scm1 P3
| ^
+--> P2 ----+
*/
int i = 1;
PluggableSCMMaterial pluggableSCMMaterial = MaterialsMother.pluggableSCMMaterial();
u.addSCMConfig(pluggableSCMMaterial.getScmConfig());
String[] pkg_revs = {"scm1-1", "scm1-2"};
u.checkinInOrder(pluggableSCMMaterial, u.d(i++), pkg_revs);
ScheduleTestUtil.AddedPipeline p1 = u.saveConfigWith("p1", u.m(pluggableSCMMaterial));
ScheduleTestUtil.AddedPipeline p2 = u.saveConfigWith("p2", u.m(pluggableSCMMaterial));
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", u.m(p1), u.m(p2));
String p1_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p1, u.d(i++), "scm1-1");
String p2_1 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "scm1-1");
String p2_2 = u.runAndPassWithGivenMDUTimestampAndRevisionStrings(p2, u.d(i++), "scm1-2");
MaterialRevisions given = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_2));
MaterialRevisions expected = u.mrs(
u.mr(p1, true, p1_1),
u.mr(p2, true, p2_1));
assertThat(getRevisionsBasedOnDependencies(p3, goConfigDao.load(), given), is(expected));
}
@Test
public void shouldResolveDiamondDependencyWithChildrenDependingOnDifferentStageDependency() throws Exception {
/*
+---> P3 ---+
| v
pkg -> P2 P5
| ^
+--> P4 ----+
*/
GitMaterial git = u.wf(new GitMaterial("git"), "f");
u.checkinInOrder(git, "g1");
ScheduleTestUtil.AddedPipeline p2_s1 = u.saveConfigWith("p2", "s1", u.m(git));
ScheduleTestUtil.AddedPipeline p2_s2 = u.addStageToPipeline(p2_s1.config.name(), "s2");
ScheduleTestUtil.AddedPipeline p3 = u.saveConfigWith("p3", u.m(new DependencyMaterial(p2_s1.config.name(), new CaseInsensitiveString("s1"))));
ScheduleTestUtil.AddedPipeline p4 = u.saveConfigWith("p4", u.m(new DependencyMaterial(p2_s1.config.name(), new CaseInsensitiveString("s2"))));
ScheduleTestUtil.AddedPipeline p5 = u.saveConfigWith("p5", u.m(p3), u.m(p4));
String p2_s1_1 = u.runAndPass(p2_s1, "g1");
String p2_s2_1 = u.runAndPass(p2_s2, "g1");
String p3_1 = u.runAndPass(p3, p2_s1_1);
String p4_1 = u.runAndPass(p4, p2_s2_1);
MaterialRevisions given = u.mrs(
u.mr(p3, true, p3_1),
u.mr(p4, true, p4_1));
MaterialRevisions revisionsBasedOnDependencies = getRevisionsBasedOnDependencies(p5, goConfigDao.load(), given);
assertThat(revisionsBasedOnDependencies, is(given));
}
private BuildCause getBuildCause(ScheduleTestUtil.AddedPipeline staging, MaterialRevisions given, MaterialRevisions previous) {
AutoBuild autoBuild = new AutoBuild(goConfigService, pipelineService, staging.config.name().toString(), systemEnvironment, materialChecker, serverHealthService);
pipelineTimeline.update();
return autoBuild.onModifications(given, false, previous);
}
private MaterialRevisions getRevisionsBasedOnDependencies(ScheduleTestUtil.AddedPipeline pipeline, CruiseConfig cruiseConfig, MaterialRevisions given) {
pipelineTimeline.update();
return pipelineService.getRevisionsBasedOnDependencies(given, cruiseConfig, pipeline.config.name());
}
}