/* * 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.domain; import com.thoughtworks.go.config.CaseInsensitiveString; import com.thoughtworks.go.config.materials.ScmMaterial; import com.thoughtworks.go.config.materials.mercurial.HgMaterial; import com.thoughtworks.go.config.materials.svn.SvnMaterial; import com.thoughtworks.go.domain.label.PipelineLabel; import com.thoughtworks.go.domain.materials.Modification; import com.thoughtworks.go.helper.MaterialsMother; import com.thoughtworks.go.helper.ModificationsMother; import org.hamcrest.core.Is; import org.junit.BeforeClass; import org.junit.Test; import java.util.HashMap; import java.util.Map; import static org.hamcrest.core.Is.is; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertThat; public class PipelineLabelTest { private final String testingTemplate = "testing." + PipelineLabel.COUNT_TEMPLATE + ".label"; @Test public void shouldUseCounterAsDefaultTemplate() throws Exception { PipelineLabel defaultLabel = PipelineLabel.defaultLabel(); assertThat(defaultLabel.toString(), is("${COUNT}")); } @Test public void shouldFormatLabelAccordingToCountingTemplate() throws Exception { PipelineLabel label = PipelineLabel.create(testingTemplate); label.updateLabel(getNamedRevision(99)); assertThat(label.toString(), is("testing.99.label")); } @Test public void shouldIgnoreCaseInCountingTemplate() throws Exception { PipelineLabel label = PipelineLabel.create(testingTemplate); label.updateLabel(getNamedRevision(2)); assertThat(label.toString(), is("testing.2.label")); } @Test public void shouldReplaceTheTemplateWithMaterialRevision() throws Exception { PipelineLabel label = PipelineLabel.create("release-${svnMaterial}"); MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); label.updateLabel(materialRevisions.getNamedRevisions()); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision())); } @Test public void shouldReplaceTheTemplateCaseInsensitively() throws Exception { PipelineLabel label = PipelineLabel.create("release-${SVNMaterial}"); MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); label.updateLabel(materialRevisions.getNamedRevisions()); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision())); } @Test public void shouldReplaceTheTemplateWithMultipleMaterialRevision() throws Exception { PipelineLabel label = PipelineLabel.create("release-${svnMaterial}-${hg}"); MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); HgMaterial material = MaterialsMother.hgMaterial(); material.setName(new CaseInsensitiveString("hg")); Modification modification = new Modification(); modification.setRevision("ae09876hj"); materialRevisions.addRevision(material, modification); label.updateLabel(materialRevisions.getNamedRevisions()); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision() + "-ae09876hj")); } @Test public void shouldReplaceTheTemplateWithGitMaterialRevision() throws Exception { PipelineLabel label = PipelineLabel.create("release-${svnMaterial}-${git}"); MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); ScmMaterial material = MaterialsMother.gitMaterial(""); material.setName(new CaseInsensitiveString("git")); Modification modification = new Modification(); modification.setRevision("8c8a273e12a45e57fed5ce978d830eb482f6f666"); materialRevisions.addRevision(material, modification); label.updateLabel(materialRevisions.getNamedRevisions()); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision() + "-8c8a273e12a45e57fed5ce978d830eb482f6f666")); } @Test public void shouldTruncateMaterialRevision() throws Exception { PipelineLabel label = PipelineLabel.create("release-${svnMaterial}-${git[:6]}"); MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); ScmMaterial material = MaterialsMother.gitMaterial(""); material.setName(new CaseInsensitiveString("git")); Modification modification = new Modification(); modification.setRevision("8c8a273e12a45e57fed5ce978d830eb482f6f666"); materialRevisions.addRevision(material, modification); label.updateLabel(materialRevisions.getNamedRevisions()); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision() + "-8c8a27")); } @Test public void shouldTrimLongLabelTo255() { PipelineLabel label = PipelineLabel.create("Pipeline-${upstream}"); HashMap<CaseInsensitiveString, String> namedRevisions = new HashMap<>(); namedRevisions.put(new CaseInsensitiveString("upstream"), longLabel(300)); label.updateLabel(namedRevisions); assertThat(label.toString().length(), Is.is(255)); } @Test public void shouldKeepLabelIfLessThan255() { PipelineLabel label = PipelineLabel.create("${upstream}"); HashMap<CaseInsensitiveString, String> namedRevisions = new HashMap<>(); namedRevisions.put(new CaseInsensitiveString("upstream"), longLabel(154)); label.updateLabel(namedRevisions); assertThat(label.toString().length(), Is.is(154)); } @Test public void shouldCreateDefaultLabelIfTemplateIsNull() { PipelineLabel label = PipelineLabel.create(null); assertThat(label, Is.is(PipelineLabel.defaultLabel())); } @Test public void shouldCreateDefaultLabelIfTemplateIsEmtpty() { PipelineLabel label = PipelineLabel.create(""); assertThat(label, Is.is(PipelineLabel.defaultLabel())); } @Test public void shouldCreateLabelIfTemplateIsProvided() { PipelineLabel label = PipelineLabel.create("Pipeline-${ABC}"); assertThat(label, Is.is(new PipelineLabel("Pipeline-${ABC}"))); } @Test public void shouldNotReplaceTemplateWithoutMaterial() throws Exception { PipelineLabel label = new PipelineLabel("1.5.0"); label.updateLabel(new HashMap<>()); assertThat(label, is(new PipelineLabel("1.5.0"))); } @Test public void canMatchMaterialName() throws Exception { final String[][] expectedGroups = { { "git" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION)); } @Test public void canMatchMaterialNameWithTrial() throws Exception { final String[][] expectedGroups = { { "git" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git}.alpha.0", expectedGroups); assertThat(res, is("release-" + GIT_REVISION + ".alpha.0")); } @Test public void canHandleWrongMaterialName() throws Exception { final String[][] expectedGroups = { { "gitUnused" } }; String res = assertLabelGroupsMatchingAndReplace("release-${gitUnused}", expectedGroups); assertThat(res, is("release-${gitUnused}")); } @Test public void canMatchWithoutTruncation() throws Exception { final String[][] expectedGroups = { { "svnRepo.verynice" }, { "git" } }; String res = assertLabelGroupsMatchingAndReplace("release-${svnRepo.verynice}-${git}", expectedGroups); assertThat(res, is("release-" + SVN_REVISION + "-" + GIT_REVISION)); } @Test public void canMatchWithOneGitTruncation() throws Exception { final String[][] expectedGroups = { { "git", "7" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git[:7]}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION.substring(0, 7))); } @Test public void canMatchWithOneGitTruncationTooLongToTruncate() throws Exception { final String[][] expectedGroups = { { "git", "9999" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git[:9999]}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION)); } @Test public void canMatchWithOneGitTruncationAlmostTruncated() throws Exception { final String[][] expectedGroups = { { "git", GIT_REV_LENGTH + "" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git[:" + GIT_REV_LENGTH + "]}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION)); } @Test public void canMatchWithOneGitTruncationByOneChar() throws Exception { final int size = GIT_REV_LENGTH - 1; final String[][] expectedGroups = { { "git", size + "" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git[:" + size + "]}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION.substring(0, GIT_REV_LENGTH - 1))); } @Test public void canMatchWithOneTruncationAsFirstRevision() throws Exception { final String[][] expectedGroups = { {"git", "4"}, { "svn" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git[:4]}-${svn}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION.substring(0, 4) + "-" + SVN_REVISION)); } @Test public void canMatchWithTwoTruncation() throws Exception { final String[][] expectedGroups = { { "git", "5" }, {"svn", "3"}}; String res = assertLabelGroupsMatchingAndReplace("release-${git[:5]}-${svn[:3]}", expectedGroups); assertThat(res, is("release-" + GIT_REVISION.substring(0, 5) + "-" + SVN_REVISION.substring(0, 3))); } @Test public void canNotMatchWithTruncationWhenMaterialNameHasAColon() throws Exception { final String[][] expectedGroups = { { "git:one", "7" } }; String res = assertLabelGroupsMatchingAndReplace("release-${git:one[:7]}", expectedGroups); assertThat(res, is("release-${git:one[:7]}")); } @Test public void shouldReplaceTheTemplateWithSpecialCharacters() throws Exception { ensureLabelIsReplaced("SVNMaterial"); ensureLabelIsReplaced("SVN-Material"); ensureLabelIsReplaced("SVN_Material"); ensureLabelIsReplaced("SVN!Material"); ensureLabelIsReplaced("SVN__##Material_1023_WithNumbers"); ensureLabelIsReplaced("SVN_Material-_!!_"); ensureLabelIsReplaced("svn_Material'WithQuote"); ensureLabelIsReplaced("SVN_Material.With.Period"); ensureLabelIsReplaced("SVN_Material#With#Hash"); ensureLabelIsReplaced("SVN_Material:With:Colon"); ensureLabelIsReplaced("SVN_Material~With~Tilde"); ensureLabelIsNOTReplaced("SVN*MATERIAL"); ensureLabelIsNOTReplaced("SVN+Material"); ensureLabelIsNOTReplaced("SVN^Material"); ensureLabelIsNOTReplaced("SVN_Material(With)Parentheses"); ensureLabelIsNOTReplaced("SVN_Material{With}Braces"); ensureLabelIsNOTReplaced("SVN**Material"); ensureLabelIsNOTReplaced("SVN\\Material_With_Backslash"); } @BeforeClass public static void setup() { MATERIAL_REVISIONS.put(new CaseInsensitiveString("svnRepo.verynice"), SVN_REVISION); MATERIAL_REVISIONS.put(new CaseInsensitiveString("svn"), SVN_REVISION); MATERIAL_REVISIONS.put(new CaseInsensitiveString("git"), GIT_REVISION); } public static final Map<CaseInsensitiveString, String> MATERIAL_REVISIONS = new HashMap<>(); public static final String SVN_REVISION = "3456"; public static final String GIT_REVISION = "c42c0bfa57d00a25496ba899b1f476e6ec8872bd"; public static final int GIT_REV_LENGTH = GIT_REVISION.length(); private String assertLabelGroupsMatchingAndReplace(String labelTemplate, String[][] expectedGroups) throws Exception { assertLabelGroupsMatching(labelTemplate, expectedGroups); PipelineLabel label = new PipelineLabel(labelTemplate); label.updateLabel(MATERIAL_REVISIONS); return label.toString(); } private void assertLabelGroupsMatching(String labelTemplate, String[][] expectedGroups) { java.util.regex.Matcher matcher = PipelineLabel.PATTERN.matcher(labelTemplate); for (String[] groups : expectedGroups) { assertThat(matcher.find(), is(true)); final String truncationLengthLiteral = matcher.group(3); if (groups.length != 2) { assertNull(truncationLengthLiteral); } else { assertThat(truncationLengthLiteral, is(groups[1])); } } final boolean actual = matcher.find(); assertThat(actual, is(false)); } private HashMap<CaseInsensitiveString, String> getNamedRevision(final Integer counter) { return new HashMap<CaseInsensitiveString, String>() { { put(new CaseInsensitiveString("COUNT"), counter.toString()); } }; } private String longLabel(int length) { StringBuilder builder = new StringBuilder(); for (int i = 0; i < length; i++) { builder.append("a"); } return builder.toString(); } private void ensureLabelIsReplaced(String name) { PipelineLabel label = getReplacedLabelFor(name, String.format("release-${%s}", name)); assertThat(label.toString(), is("release-" + ModificationsMother.currentRevision())); } private void ensureLabelIsNOTReplaced(String name) { String labelFormat = String.format("release-${%s}", name); PipelineLabel label = getReplacedLabelFor(name, labelFormat); assertThat(label.toString(), is(labelFormat)); } private PipelineLabel getReplacedLabelFor(String name, String labelFormat) { MaterialRevisions materialRevisions = ModificationsMother.oneUserOneFile(); PipelineLabel label = PipelineLabel.create(labelFormat); ((SvnMaterial) materialRevisions.getRevisions().get(0).getMaterial()).setName(new CaseInsensitiveString(name)); label.updateLabel(materialRevisions.getNamedRevisions()); return label; } }