/** * The MIT License * * Copyright (c) 2007-2010, Sun Microsystems, Inc., Kohsuke Kawaguchi, Erik Ramfelt, * Henrik Lynggaard, Peter Liljenberg, Andrew Bayer, Vincent Latombe * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package hudson.plugins.clearcase; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import hudson.EnvVars; import hudson.FilePath; import hudson.Launcher; import hudson.matrix.MatrixBuild; import hudson.model.AbstractBuild; import hudson.model.AbstractProject; import hudson.model.Build; import hudson.model.BuildListener; import hudson.model.Computer; import hudson.model.Node; import hudson.model.TaskListener; import hudson.plugins.clearcase.action.CheckOutAction; import hudson.plugins.clearcase.action.SaveChangeLogAction; import hudson.plugins.clearcase.history.HistoryAction; import hudson.scm.ChangeLogParser; import hudson.scm.PollingResult; import hudson.scm.SCMDescriptor; import hudson.scm.SCMRevisionState; import hudson.scm.PollingResult.Change; import hudson.util.LogTaskListener; import hudson.util.VariableResolver; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.jmock.Expectations; import org.jmock.Mockery; import org.jmock.integration.junit4.JUnit4Mockery; import org.jmock.lib.legacy.ClassImposteriser; import org.junit.After; import org.junit.Before; import org.junit.Test; public class AbstractClearCaseScmTest extends AbstractWorkspaceTest { private Mockery classContext; private Mockery context; private BuildListener taskListener; private Launcher launcher; private AbstractProject project; private Build build; private Computer computer; private Node node; private CheckOutAction checkOutAction; private HistoryAction historyAction; private String[] branchArray = new String[] {"branch"}; public SaveChangeLogAction saveChangeLogAction; private AbstractClearCaseSCMRevisionState scmRevisionState; @Before public void setUp() throws Exception { createWorkspace(); context = new JUnit4Mockery(); classContext = new JUnit4Mockery() { { setImposteriser(ClassImposteriser.INSTANCE); } }; checkOutAction = context.mock(CheckOutAction.class); historyAction = context.mock(HistoryAction.class); saveChangeLogAction = context.mock(SaveChangeLogAction.class); launcher = classContext.mock(Launcher.class); taskListener = context.mock(BuildListener.class); project = classContext.mock(AbstractProject.class); build = classContext.mock(Build.class); scmRevisionState = classContext.mock(AbstractClearCaseSCMRevisionState.class); computer = classContext.mock(Computer.class); node = classContext.mock(Node.class); Map<String, String> systemProperties = new HashMap<String, String>(); systemProperties.put("user.name", "henrik"); } @After public void teardown() throws Exception { deleteWorkspace(); } @Test public void testSupportsPolling() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); assertTrue("The ClearCase SCM supports polling but is reported not to", scm.supportsPolling()); } @Test public void assertWorkspaceisRequiredForPolling() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); assertTrue("The ClearCase SCM needs a workspace to poll but is reported no to require one", scm.requiresWorkspaceForPolling()); } @Test public void assertFilteringOutDestroySubBranchEventProperty() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", "", true); assertTrue("The ClearCase SCM is not filtering out destroy sub branch events", scm.isFilteringOutDestroySubBranchEvent()); } @Test public void testGetViewName() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); assertEquals("The view name isnt correct", "viewname", scm.getViewName()); } @Test(expected=IllegalArgumentException.class) public void testGetViewNameNonNull() { new AbstractClearCaseScmDummy(null, "vob", ""); } @Test public void testGetLoadRules() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "loadrules", null, false, "viewpath"); assertEquals("The load rules arent correct", "loadrules", scm.getLoadRules()); } @Test public void testGetLoadRulesWithSpaces() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "load rules", null, false, "viewpath"); assertEquals("The load rules arent correct", "load rules", scm.getLoadRules()); } @Test public void testGetViewPaths() throws Exception { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "loadrules", null, false, "viewpath"); assertEquals("The view paths aren't correct", "loadrules", scm.getViewPaths(null, null, launcher)[0]); } @Test public void testGetViewPathsWithSpaces() throws Exception { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "test rules", null, false, "viewpath"); assertEquals("The view paths aren't correct", "test rules", scm.getViewPaths(null, null, launcher)[0]); } @Test public void testGetViewPathsNoLoad() throws Exception { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "load loadrules", null, false, "viewpath"); assertEquals("The view paths aren't correct", "loadrules", scm.getViewPaths(null, null, launcher)[0]); } @Test public void testGetViewPathsLeadingSlash() throws Exception { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "/loadrules", null, false, "viewpath"); assertEquals("The view paths aren't correct", "loadrules", scm.getViewPaths(null, null, launcher)[0]); } @Test public void testGetViewPathsLeadingSlashAndLoad() throws Exception { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "viewparams", false, false, false, "", false, "", "load /loadrules", null, false, "viewpath"); assertEquals("The view paths aren't correct", "loadrules", scm.getViewPaths(null, null, launcher)[0]); } @Test public void testGetExcludedRegions() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", "", false, "excludedone\nexcludedtwo"); assertArrayEquals("The excluded regions array is incorrect", new String[] { "excludedone", "excludedtwo" }, scm.getExcludedRegionsNormalized()); } @Test public void assertViewNameMacrosAreWorking() throws IOException, InterruptedException { context.checking(new Expectations() { { } }); classContext.checking(new Expectations() { { one(build).getBuiltOn(); will(returnValue(node)); allowing(build).getProject(); will(returnValue(project)); allowing(project).getName(); will(returnValue("Hudson")); one(node).toComputer(); will(returnValue(computer)); one(node).getNodeName(); will(returnValue("test-node")); one(computer).getSystemProperties(); will(returnValue(System.getProperties())); one(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); one(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson"))); } }); String username = System.getProperty("user.name"); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("${JOB_NAME}-${USER_NAME}-${NODE_NAME}-view", "vob", "", true); assertEquals("The macros were not replaced in the normalized view name", "Hudson-" + username + "-test-node-view", scm .generateNormalizedViewName(build)); } @Test public void testViewNameMacrosUsingBuildEnv() throws IOException, InterruptedException { classContext.checking(new Expectations() { { one(build).getBuiltOn(); will(returnValue(node)); allowing(build).getProject(); will(returnValue(project)); allowing(project).getName(); will(returnValue("Hudson")); one(node).toComputer(); will(returnValue(computer)); one(node).getNodeName(); will(returnValue("test-node")); allowing(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); allowing(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); one(computer).getSystemProperties(); will(returnValue(System.getProperties())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("${JOB_NAME}-${TEST_VARIABLE}-view", "vob", "", true); assertEquals("The macros were not replaced in the normalized view name", "Hudson-result-of-test-view", scm.generateNormalizedViewName(build)); } @Test public void assertNormalizedViewNameDoesNotContainInvalidChars() throws IOException, InterruptedException { classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("view with\\-/-:-?-*-|-,", "vob", "", true); assertEquals("The invalid view name chars were not removed from the view name", "view_with_-_-_-_-_-_-,", scm.generateNormalizedViewName(build)); } @Test public void testGetMkviewOptionalParam() { AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", "extra params"); assertEquals("The MkviewOptionalParam isnt correct", "extra params", scm.getMkviewOptionalParam()); } @Test public void testBuildEnvVars() throws IOException, InterruptedException { classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); Map<String, String> env = new HashMap<String, String>(); env.put("WORKSPACE", "/hudson/jobs/job/workspace"); scm.generateNormalizedViewName(build); scm.buildEnvVars(build, env); assertEquals("The env var VIEWNAME wasnt set", "viewname", env.get(AbstractClearCaseScm.CLEARCASE_VIEWNAME_ENVSTR)); assertEquals("The env var VIEWPATH wasnt set", "/hudson/jobs/job/workspace" + File.separator + "viewname", env .get(AbstractClearCaseScm.CLEARCASE_VIEWPATH_ENVSTR)); } @Test public void testBuildEnvVarsNoWorkspaceVar() throws IOException, InterruptedException { classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); Map<String, String> env = new HashMap<String, String>(); scm.generateNormalizedViewName(build); scm.buildEnvVars(build, env); assertTrue("The env var VIEWNAME wasnt set", env.containsKey(AbstractClearCaseScm.CLEARCASE_VIEWNAME_ENVSTR)); assertFalse("The env var VIEWPATH was set", env.containsKey(AbstractClearCaseScm.CLEARCASE_VIEWPATH_ENVSTR)); } @Test public void assertBuildEnvVarsUsesNormalizedViewName() throws IOException, InterruptedException { classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); allowing(build).getProject(); will(returnValue(project)); allowing(project).getName(); will(returnValue("CCHudson")); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); allowing(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname-${JOB_NAME}-${NODE_NAME}", "vob", ""); Map<String, String> env = new HashMap<String, String>(); env.put("WORKSPACE", "/hudson/jobs/job/workspace"); env.put("NODE_NAME", "test-node"); scm.buildEnvVars(build, env); assertEquals("The env var VIEWNAME wasn't set", "viewname-CCHudson-test-node", env.get(AbstractClearCaseScm.CLEARCASE_VIEWNAME_ENVSTR)); assertEquals("The env var VIEWPATH wasn't set", "/hudson/jobs/job/workspace" + File.separator + "viewname-CCHudson-test-node", env .get(AbstractClearCaseScm.CLEARCASE_VIEWPATH_ENVSTR)); } @Test public void testFirstBuild() throws Exception { context.checking(new Expectations() { { one(checkOutAction).checkout(launcher, workspace, "viewname"); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); one(build).getPreviousBuild(); will(returnValue(null)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); File changelogFile = new File(parentFile, "changelog.xml"); boolean hasChanges = scm.checkout(build, launcher, workspace, taskListener, changelogFile); assertTrue("The first time should always return true", hasChanges); FilePath changeLogFilePath = new FilePath(changelogFile); assertTrue("The change log file is empty", changeLogFilePath.length() == 0); } @Test public void assertCheckoutWithChanges() throws Exception { workspace.child("viewname").mkdirs(); final File changelogFile = new File(parentFile, "changelog.xml"); final ArrayList<ClearCaseChangeLogEntry> list = new ArrayList<ClearCaseChangeLogEntry>(); list.add(new ClearCaseChangeLogEntry(new Date(12), "user", "comment")); list.add(new ClearCaseChangeLogEntry(new Date(12), "user", "comment")); final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(100000); context.checking(new Expectations() { { one(checkOutAction).isViewValid(launcher, workspace, "viewname"); will(returnValue(true)); one(checkOutAction).checkout(launcher, workspace, "viewname"); will(returnValue(true)); // normal changelog one(historyAction).getChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(list)); one(saveChangeLogAction).saveChangeLog(changelogFile, list); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); // normal changelog exactly(2).of(build).getPreviousBuild(); will(returnValue(build)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); allowing(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); boolean hasChanges = scm.checkout(build, launcher, workspace, taskListener, changelogFile); assertTrue("The first time should always return true", hasChanges); } @Test public void assertCheckoutWithChangesWithBuffer() throws Exception { workspace.child("viewpath").mkdirs(); final File changelogFile = new File(parentFile, "changelog.xml"); final ArrayList<ClearCaseChangeLogEntry> list = new ArrayList<ClearCaseChangeLogEntry>(); list.add(new ClearCaseChangeLogEntry(new Date(12), "user", "comment")); list.add(new ClearCaseChangeLogEntry(new Date(12), "user", "comment")); final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(1000000); final Date bufferedDate = new Date(mockedCalendar.getTimeInMillis() - (1000 * 60 * 5)); context.checking(new Expectations() { { one(checkOutAction).isViewValid(launcher, workspace, "viewname"); will(returnValue(true)); one(checkOutAction).checkout(launcher, workspace, "viewname"); will(returnValue(true)); // normal changelog one(historyAction).getChanges(with(equal(bufferedDate)), with(equal("viewpath")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(list)); one(saveChangeLogAction).saveChangeLog(changelogFile, list); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); // normal changelog exactly(2).of(build).getPreviousBuild(); will(returnValue(build)); allowing(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); allowing(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "", false, false, false, "", false, "", "vob", "5", false, "viewpath"); boolean hasChanges = scm.checkout(build, launcher, workspace, taskListener, changelogFile); assertTrue("The first time should always return true", hasChanges); } @Test public void assertCheckoutUsesNormalizedViewName() throws Exception { workspace.child("viewname-CCHudson").mkdirs(); final File changelogFile = new File(parentFile, "changelog.xml"); context.checking(new Expectations() { { one(checkOutAction).isViewValid(launcher, workspace, "viewname-CCHudson-test-node"); will(returnValue(true)); one(checkOutAction).checkout(launcher, workspace, "viewname-CCHudson-test-node"); will(returnValue(true)); ignoring(historyAction).getChanges(with(any(Date.class)), with(equal("viewname-CCHudson-test-node")), with(equal("viewname-CCHudson-test-node")), with(any(String[].class)), with(any(String[].class))); will(returnValue(new ArrayList<ClearCaseChangeLogEntry>())); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); allowing(build).getProject(); will(returnValue(project)); allowing(project).getName(); will(returnValue("CCHudson")); allowing(build).getBuildVariables(); will(returnValue(new HashMap())); allowing(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "CCHudson", "NODE_NAME", "test-node"))); allowing(computer).getSystemProperties(); will(returnValue(System.getProperties())); allowing(computer).getName(); will(returnValue("test-node")); // normal changelog ignoring(build).getPreviousBuild(); will(returnValue(build)); ignoring(build).getTimestamp(); will(returnValue(Calendar.getInstance())); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname-${JOB_NAME}-${NODE_NAME}", "vob", ""); scm.checkout(build, launcher, workspace, taskListener, changelogFile); } @Test public void assertCheckoutWithNoChanges() throws Exception { workspace.child("viewname").mkdirs(); final File changelogFile = new File(parentFile, "changelog.xml"); final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(100000); context.checking(new Expectations() { { one(checkOutAction).isViewValid(launcher, workspace, "viewname"); will(returnValue(true)); one(checkOutAction).checkout(launcher, workspace, "viewname"); will(returnValue(true)); one(historyAction).getChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(null)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); exactly(2).of(build).getPreviousBuild(); will(returnValue(build)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); ignoring(build).getEnvironment(with(any(TaskListener.class))); will(returnValue(new EnvVars())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); boolean hasChanges = scm.checkout(build, launcher, workspace, taskListener, changelogFile); assertTrue("The first time should always return true", hasChanges); FilePath changeLogFilePath = new FilePath(changelogFile); assertTrue("The change log file is empty", changeLogFilePath.length() > 5); } @Test public void assertCheckoutWithMultipleBranches() throws Exception { branchArray = new String[] { "branchone", "branchtwo" }; workspace.child("viewname").mkdirs(); final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(100000); context.checking(new Expectations() { { one(checkOutAction).isViewValid(launcher, workspace, "viewname"); will(returnValue(true)); one(checkOutAction).checkout(launcher, workspace, "viewname"); will(returnValue(true)); one(historyAction).getChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branchone", "branchtwo" })), with(equal(new String[] { "vob" }))); will(returnValue(null)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getPreviousBuild(); will(returnValue(build)); ignoring(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); ignoring(build).getEnvironment(with(any(TaskListener.class))); will(returnValue(new EnvVars())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); File changelogFile = new File(parentFile, "changelog.xml"); boolean hasChanges = scm.checkout(build, launcher, workspace, taskListener, changelogFile); assertTrue("The first time should always return true", hasChanges); FilePath changeLogFilePath = new FilePath(changelogFile); assertTrue("The change log file is empty", changeLogFilePath.length() > 5); } @Test public void testPollChanges() throws Exception { final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(400000); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getParent(); will(returnValue(project)); allowing(build).getTimestamp(); will(returnValue(mockedCalendar)); allowing(computer).getName(); will(returnValue("test-node")); one(project).getLastBuild(); will(returnValue(build)); one(build).getPreviousBuild(); will(returnValue(build)); } }); AbstractClearCaseScmDummy scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); scm.setFirstBuild(true); PollingResult pr = scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, null); assertEquals("The first time should always have a significant change", PollingResult.BUILD_NOW, pr); } @Test public void testPollChangesWithBuffer() throws Exception { final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(1000000); final Date bufferedDate = new Date(mockedCalendar.getTimeInMillis() - (1000 * 60 * 5)); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(bufferedDate)), with(equal("viewpath")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getParent(); will(returnValue(project)); allowing(build).getTimestamp(); will(returnValue(mockedCalendar)); one(project).getLastBuild(); will(returnValue(build)); } }); AbstractClearCaseScmDummy scm = new AbstractClearCaseScmDummy("viewname", "", false, false, false, "", false, "", "vob", "5", false, "viewpath"); scm.setFirstBuild(true); PollingResult pr = scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, null); assertEquals("The first time should always have a significant change", PollingResult.BUILD_NOW, pr); } @Test public void assertPollChangesUsesNormalizedViewName() throws Exception { createWorkspace(); context.checking(new Expectations() { { one(historyAction).hasChanges(with(any(Date.class)), with(equal("view-CCHudson-test-node")), with(equal("view-CCHudson-test-node")), with(any(String[].class)), with(any(String[].class))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); allowing(build).getProject(); will(returnValue(project)); allowing(project).getName(); will(returnValue("CCHudson")); ignoring(project).getLastBuild(); will(returnValue(build)); ignoring(build).getTimestamp(); will(returnValue(Calendar.getInstance())); allowing(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); allowing(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "CCHudson"))); allowing(scmRevisionState).getBuildTime(); will(returnValue(new Date())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{})); allowing(computer).getSystemProperties(); will(returnValue(System.getProperties())); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("view-${JOB_NAME}-${NODE_NAME}", "vob", ""); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); } @Test public void testPollChangesFirstTime() throws Exception { classContext.checking(new Expectations() { { one(project).getLastBuild(); will(returnValue(null)); } }); AbstractClearCaseScmDummy scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); PollingResult pr = scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, null); assertEquals("The first time should always have a significant change", PollingResult.BUILD_NOW, pr); } @Test public void testPollChangesWithNoHistory() throws Exception { final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(400000); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob" }))); will(returnValue(false)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); one(project).getLastBuild(); will(returnValue(build)); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{"vob"})); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); PollingResult pr = scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); assertEquals("There shouldn't be any change", Change.NONE, pr.change); } @Test public void testPollChangesWithMultipleBranches() throws Exception { branchArray = new String[] { "branchone", "branchtwo" }; final ArrayList<Object[]> list = new ArrayList<Object[]>(); list.add(new String[] { "A" }); final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(400000); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branchone", "branchtwo" })), with(equal(new String[] { "vob" }))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); one(project).getLastBuild(); will(returnValue(build)); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{"vob"})); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob", ""); PollingResult pr = scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); assertEquals("The first time should always have a significant change", Change.SIGNIFICANT, pr.change); } @Test public void testPollChangesMultipleVobPaths() throws Exception { final Calendar mockedCalendar = Calendar.getInstance(); context.checking(new Expectations() { { ignoring(build).getParent(); will(returnValue(project)); one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(equal(new String[] { "vob1", "vob2/vob2-1", "vob\\ 3" }))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); one(project).getLastBuild(); will(returnValue(build)); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{"vob1", "vob2/vob2-1", "vob\\ 3"})); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "vob1\nvob2/vob2-1\nvob\\ 3", ""); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); } @Test public void testPollChangesNoBranch() throws Exception { branchArray = new String[] { "" }; final Calendar mockedCalendar = Calendar.getInstance(); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "" })), with(aNull(String[].class))); will(returnValue(false)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); one(build).getTimestamp(); will(returnValue(mockedCalendar)); one(project).getLastBuild(); will(returnValue(build)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(null)); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "", ""); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); } @Test public void testPollChangesWithMatrixProject() throws Exception { final Calendar mockedCalendar = Calendar.getInstance(); mockedCalendar.setTimeInMillis(400000); context.checking(new Expectations() { { one(historyAction).hasChanges(with(equal(mockedCalendar.getTime())), with(equal("viewname")), with(equal("viewname")), with(equal(new String[] { "branch" })), with(aNull(String[].class))); will(returnValue(true)); } }); final MatrixBuild matrixBuild = classContext.mock(MatrixBuild.class); classContext.checking(new Expectations() { { ignoring(matrixBuild).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(matrixBuild).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(matrixBuild).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(matrixBuild).getParent(); will(returnValue(project)); one(project).getLastBuild(); will(returnValue(matrixBuild)); one(matrixBuild).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(build).addAction(with(any(ClearCaseDataAction.class))); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(null)); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("viewname", "", ""); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); } @Test public void assertGetModuleRootReturnsViewFolderSnapshot() throws Exception { // Must initiate a pollChanges() or checkout() to update the normalizedViewName createWorkspace(); final Calendar mockedCalendar = Calendar.getInstance(); context.checking(new Expectations() { { ignoring(historyAction).hasChanges(with(any(Date.class)), with(any(String.class)), with(any(String.class)), with(any(String[].class)), with(any(String[].class))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(project).getLastBuild(); will(returnValue(build)); ignoring(project).getName(); will(returnValue("CCHudson")); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{})); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("view name", "", ""); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); FilePath moduleRoot = scm.getModuleRoot(workspace); assertEquals("The module root path is incorrect", "view_name", moduleRoot.getName()); FilePath[] moduleRoots = scm.getModuleRoots(workspace); assertEquals("The number of module roots are incorrect", 1, moduleRoots.length); assertEquals("The module root path is incorrect", "view_name", moduleRoots[0].getName()); } @Test public void assertGetModuleRootReturnsViewFolderDynamic() throws Exception { // Must initiate a pollChanges() or checkout() to update the normalizedViewName createWorkspace(); final Calendar mockedCalendar = Calendar.getInstance(); context.checking(new Expectations() { { ignoring(historyAction).hasChanges(with(any(Date.class)), with(any(String.class)), with(any(String.class)), with(any(String[].class)), with(any(String[].class))); will(returnValue(true)); } }); classContext.checking(new Expectations() { { ignoring(build).getBuiltOn(); will(returnValue(node)); ignoring(node).toComputer(); will(returnValue(computer)); ignoring(node).getNodeName(); will(returnValue("test-node")); ignoring(build).getBuildVariables(); will(returnValue(new HashMap<String, String>())); ignoring(build).getEnvironment(with(any(LogTaskListener.class))); will(returnValue(new EnvVars("JOB_NAME", "Hudson", "TEST_VARIABLE", "result-of-test"))); ignoring(computer).getSystemProperties(); will(returnValue(System.getProperties())); ignoring(build).getParent(); will(returnValue(project)); ignoring(build).getTimestamp(); will(returnValue(mockedCalendar)); ignoring(project).getLastBuild(); will(returnValue(build)); ignoring(project).getName(); will(returnValue("CCHudson")); one(scmRevisionState).getBuildTime(); will(returnValue(mockedCalendar.getTime())); ignoring(scmRevisionState).getLoadRules(); will(returnValue(new String[]{})); } }); AbstractClearCaseScm scm = new AbstractClearCaseScmDummy("view name", null, true, true, true, null, true, "M:", null, null, false, null); scm.compareRemoteRevisionWith(project, launcher, workspace, taskListener, scmRevisionState); FilePath moduleRoot = scm.getModuleRoot(workspace); assertEquals("The module root path is incorrect", "view_name", moduleRoot.getName()); FilePath[] moduleRoots = scm.getModuleRoots(workspace); assertEquals("The number of module roots are incorrect", 1, moduleRoots.length); assertEquals("The module root path is incorrect", "view_name", moduleRoots[0].getName()); } private class AbstractClearCaseScmDummy extends AbstractClearCaseScm { public AbstractClearCaseScmDummy(String viewName, String vobPaths, String mkviewOptionalParam, boolean filterOutDestroySubBranchEvent) { this(viewName, mkviewOptionalParam, filterOutDestroySubBranchEvent, false, false, "", false, "", vobPaths, null, false, viewName); } public AbstractClearCaseScmDummy(String viewName, String vobPaths, String mkviewOptionalParam, boolean filterOutDestroySubBranchEvent, String excludedRegions) { this(viewName, mkviewOptionalParam, filterOutDestroySubBranchEvent, false, false, excludedRegions, false, "", vobPaths, null, false, viewName); } public AbstractClearCaseScmDummy(String viewName, String vobPaths, String mkviewOptionalParam) { this(viewName, mkviewOptionalParam, false, false, false, "", false, "", vobPaths, null, false, viewName); } public AbstractClearCaseScmDummy(String viewName, String mkviewOptionalParam, boolean filterOutDestroySubBranchEvent, boolean useUpdate, boolean rmviewonrename, String excludedRegions, boolean useDynamicView, String viewDrive, String loadRules, String multiSitePollBuffer, boolean createDynView, String viewpath) { super(viewName, mkviewOptionalParam, filterOutDestroySubBranchEvent, useUpdate, rmviewonrename, excludedRegions, useDynamicView, viewDrive, loadRules, multiSitePollBuffer, createDynView, "", "", createDynView, createDynView, viewpath); } @Override public Computer getCurrentComputer() { return computer; } @Override public Computer getBuildComputer(AbstractBuild<?, ?> build) { return computer; } @Override public SCMDescriptor<?> getDescriptor() { throw new IllegalStateException("GetDescriptor() can not be used in tests"); } @Override public ClearToolLauncher createClearToolLauncher(TaskListener listener, FilePath workspace, Launcher launcher) { return null; } @Override public String[] getBranchNames() { return branchArray; } @Override protected SaveChangeLogAction createSaveChangeLogAction(ClearToolLauncher launcher) { return saveChangeLogAction; } @Override public ChangeLogParser createChangeLogParser() { return null; } @Override protected CheckOutAction createCheckOutAction(VariableResolver<String> variableResolver, ClearToolLauncher launcher, AbstractBuild<?, ?> build) { // TODO Auto-generated method stub return checkOutAction; } @Override protected HistoryAction createHistoryAction(VariableResolver<String> variableResolver, ClearToolLauncher launcher, AbstractBuild<?, ?> build) { // TODO Auto-generated method stub return historyAction; } @Override public String[] getBranchNames(VariableResolver<String> variableResolver) { // TODO Auto-generated method stub return branchArray; } @Override public SCMRevisionState calcRevisionsFromBuild(AbstractBuild<?, ?> arg0, Launcher arg1, TaskListener arg2) throws IOException, InterruptedException { // TODO Auto-generated method stub return null; } @Override public SCMRevisionState calcRevisionsFromPoll(AbstractBuild<?, ?> build, Launcher launcher, TaskListener taskListener) throws IOException, InterruptedException { // TODO Auto-generated method stub return null; } private boolean firstBuild; @Override protected boolean isFirstBuild(SCMRevisionState baseline) { return firstBuild; } public void setFirstBuild(boolean firstBuild) { this.firstBuild = firstBuild; } } }