Skip to content

Commit

Permalink
Registering the ProjectStatus module among default plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
t-dan committed Jun 2, 2014
1 parent 07cd78b commit 78558d8
Show file tree
Hide file tree
Showing 2 changed files with 377 additions and 1 deletion.
Expand Up @@ -43,6 +43,7 @@ mercurial=net.sourceforge.cruisecontrol.sourcecontrols.Mercurial
mks=net.sourceforge.cruisecontrol.sourcecontrols.MKS
p4=net.sourceforge.cruisecontrol.sourcecontrols.P4
plasticscm=net.sourceforge.cruisecontrol.sourcecontrols.PlasticSCM
projectstatus=net.sourceforge.cruisecontrol.sourcecontrols.ProjectStatus
pvcs=net.sourceforge.cruisecontrol.sourcecontrols.PVCS
snapshotcm=net.sourceforge.cruisecontrol.sourcecontrols.SnapshotCM
store=net.sourceforge.cruisecontrol.sourcecontrols.Store
Expand Down

This file was deleted.

@@ -0,0 +1,376 @@
/********************************************************************************
* CruiseControl, a Continuous Integration Toolkit
* Copyright (c) 2001, ThoughtWorks, Inc.
* 200 E. Randolph, 25th Floor
* Chicago, IL 60601 USA
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* + Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* + Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided
* with the distribution.
*
* + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
* names of its contributors may be used to endorse or promote
* products derived from this software without specific prior
* written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
********************************************************************************/

package net.sourceforge.cruisecontrol.sourcecontrols;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.util.Date;
import java.util.List;

import javax.management.RuntimeErrorException;

import org.jdom.Element;
import org.junit.Test;

import junit.framework.TestCase;
import net.sourceforge.cruisecontrol.BuildQueue;
import net.sourceforge.cruisecontrol.Builder;
import net.sourceforge.cruisecontrol.CruiseControlConfig;
import net.sourceforge.cruisecontrol.CruiseControlException;
import net.sourceforge.cruisecontrol.Modification;
import net.sourceforge.cruisecontrol.ProjectConfig;
import net.sourceforge.cruisecontrol.ProjectInterface;
import net.sourceforge.cruisecontrol.builders.MockBuilder;
import net.sourceforge.cruisecontrol.testutil.TestUtil.FilesToDelete;
import net.sourceforge.cruisecontrol.util.IO;
import net.sourceforge.cruisecontrol.util.Util;

/**
* Unit tests for {@link ProjectStatus}
* @author Dan Tihelka
*/
public class ProjectStatusTest extends TestCase {

private final FilesToDelete filesToDelete = new FilesToDelete();
private CruiseControlConfig config;
private BuildQueue queue;
private File proj1Data;

protected void setUp() throws Exception {
proj1Data = filesToDelete.add(this);
IO.write(proj1Data, "");

final String xml = "<cruisecontrol>"
+ " <plugin name='mock.builder' classname='" + MockBuilder.class.getName() + "' />"

+ " <project name='proj1'>"
+ " <modificationset quietperiod='0'>"
+ " <filesystem folder='" + proj1Data.getAbsoluteFile() + "'/>"
+ " </modificationset>"
+ " <schedule interval='1'><mock.builder/></schedule>"
+ " </project>"

+ " <project name='proj.main'>"
+ " <modificationset quietperiod='0'>"
+ " <projectstatus project='proj1' buildonsuccess='true'/>"
+ " </modificationset>"
+ " <schedule interval='1'><mock.builder/></schedule>"
+ " </project>"
+ "</cruisecontrol>";

// Create the config
Element ccElement = Util.loadRootElement(new ByteArrayInputStream(xml.getBytes()));
config = new CruiseControlConfig(ccElement);

// Set the build queue to all projects
queue = new BuildQueue();
for (String proj : config.getProjectNames()) {
ProjectInterface pi = config.getProject(proj);
// Configure and set the queue
pi.configureProject();
pi.setBuildQueue(queue);
// Prepare *.ser project files for removal
final File serFile = new File(Builder.getFileSystemSafeProjectName(pi.getName()) + ".ser");
filesToDelete.add(serFile);
// clear log files as well
filesToDelete.add(new File(pi.getLogDir()));
}
}

protected void tearDown() {
// Stop all projects
for (String proj : config.getProjectNames()) {
config.getProject(proj).stop();
}
// Clear the rest
config = null;
filesToDelete.delete();
}
/**
* Make sure the validate() method works properly.
*/
@Test
public void testValidate() throws Exception {
ProjectStatus status = new ProjectStatus();

// Project is not set
assertInvalid(status, "'project' is required for ProjectStatus");

// Project is set, but it is not valid
status.setProject("p1");
assertInvalid(status, "No project named 'p1'");
}

/**
* Tests, if a modification is returned when successful build of <code>proj1</code> is after the
* last build of the main project. It means that default values are used for all values.
*/
@Test
public void testBuildOnSuccess() throws Exception {
final ProjectStatus status = new ProjectStatus();
final ProjectConfig proj1 = (ProjectConfig) config.getProject("proj1");
long lastP1;

// configure the status watcher
status.setProject("proj1");
status.validate();
lastP1 = new Date().getTime();
// Check the status - proj1 was not build yet. The status must return 'not modified'
// since the proj1 has not been built yet and we are waiting for its successful build here
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build.
proj1.start();
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// the last successful build of proj1 (just made at time lastP1) is after the last build of
// proj.main. Therefore, it must report "have modification" to trigger the build of proj.main
assertModified(status, lastP1 -1000, lastP1 +1000);
// the last successful build of proj1 is before the last build of proj.main, so it looks like
// there is no modification of which should trigger the build of proj.main
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Write to the file which will introduce modification in proj1 since its last build
// Sleep ensures that the file modification time will be AFTER lastP1, which is crucial for
// the test
Thread.sleep(1100 - lastP1 % 1000);
IO.write(proj1Data, "test.BuildOnSuccess: " + new Date());

// The same as the previous check - although there is a modification in proj1 waiting for
// the build, it is not taken into account here (VetoIfModified was not set)
assertModified(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build. The status must return 'has modifications' now
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// the last successful build of proj1 (just made at time lastP1) is after the last build of
// proj.main. Therefore, it must report "have modification" to trigger the build of proj.main
assertModified(status, lastP1 -1000, lastP1 +1000);
// the last successful build of proj1 is before the last build of proj.main, so it looks like
// there is no modification of which should trigger the build of proj.main
assertNoModifs(status, lastP1 +1000, lastP1 +2000);
}

/**
* The same as {@link #testBuildOnSuccess()}, plus veto must be signalized if checked when there
* is a modification in <code>proj1</code> after its successful build. It means that
* {@link ProjectStatus#setVetoIfModified(boolean)} is set to <code>true</code>.
*/
@Test
public void testVetoIfModified() throws Exception {
final ProjectStatus status = new ProjectStatus();
final ProjectConfig proj1 = (ProjectConfig) config.getProject("proj1");
long lastP1;

// configure the status watcher
status.setProject("proj1");
status.setVetoIfModified(true);
status.validate();
lastP1 = new Date().getTime();

// The proj1 has not been built yet and we depend on it. Therefore, our build must be
// delayed until the successful build of proj1
assertVeto(status, lastP1 -1000, lastP1 +1000);
// Here the last build is after ...
// TODO: DOPSAT!!!!
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build.
proj1.start();
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// The same as in testBuildOnSuccess
assertModified(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Write to the file ... (the same as in testBuildOnSuccess)
Thread.sleep(1100 - lastP1 % 1000);
IO.write(proj1Data, "test.VetoIfModified: " + new Date());

// The successful build of proj1 after the last build of proj.main should trigger the build
// of proj.main. However, there is a modification which must veto the the build.
assertVeto(status, lastP1 -1000, lastP1 +1000);
// The same as in testBuildOnSuccess
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build. The status must return 'has modifications' now
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// The same as in testBuildOnSuccess
assertModified(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);
}

/**
* The same as {@link #testVetoIfModified()}, except the modifications are not reported. It means
* that {@link ProjectStatus#setVetoIfModified(boolean)} is set to <code>true</code> and
* {@link ProjectStatus#setTriggerOnSuccess(boolean)} is set to <code>false</code>.
*/
@Test
public void testVetoNoTrigger() throws Exception {
final ProjectStatus status = new ProjectStatus();
final ProjectConfig proj1 = (ProjectConfig) config.getProject("proj1");
long lastP1;

// configure the status watcher
status.setProject("proj1");
status.setVetoIfModified(true);
status.setTriggerOnSuccess(false); // Do not report modifications
status.validate();
lastP1 = new Date().getTime();

// The same as in #testVetoIfModified()
assertVeto(status, lastP1 -1000, lastP1 +1000);
// Never returns any modification
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build.
proj1.start();
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Write to the file ... (the same as in testBuildOnSuccess)
Thread.sleep(1100 - lastP1 % 1000);
IO.write(proj1Data, "test.VetoIfModified: " + new Date());

// The same as in #testVetoIfModified()
assertVeto(status, lastP1 -1000, lastP1 +1000);
// Never returns any modification
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build. The status must return 'has modifications' now
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);
}

/**
* The case when no modification and no veto is set, It means that only
* {@link ProjectStatus#setTriggerOnSuccess(boolean)} is set to <code>false</code>.
*/
@Test
public void testNoTriggerOnSuccess() throws Exception {
final ProjectStatus status = new ProjectStatus();
final ProjectConfig proj1 = (ProjectConfig) config.getProject("proj1");
long lastP1;

// configure the status watcher
status.setProject("proj1");
status.setTriggerOnSuccess(false);
status.validate();
lastP1 = new Date().getTime();

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build.
proj1.start();
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Write to the file ... (the same as in testBuildOnSuccess)
Thread.sleep(1100 - lastP1 % 1000);
IO.write(proj1Data, "test.BuildOnSuccess: " + new Date());

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

// Force the build
proj1.execute();
lastP1 = proj1.successLastBuild().getTime();

// Never returns any modification
assertNoModifs(status, lastP1 -1000, lastP1 +1000);
assertNoModifs(status, lastP1 +1000, lastP1 +2000);

}


/** Expects that {@link ProjectStatus#getModifications(Date, Date)} returns non-empty array */
private void assertModified(ProjectStatus status, long lastBuild, long now) {
assertFalse("At least one modification expected, none got",
status.getModifications(new Date(lastBuild), new Date(now)).isEmpty());
}
/** Expects that {@link ProjectStatus#getModifications(Date, Date)} returns empty array */
private void assertNoModifs(ProjectStatus status, long lastBuild, long now) {
final List<Modification> modifs = status.getModifications(new Date(lastBuild), new Date(now));
assertTrue("No modification expected, " + modifs.size() + " got", modifs.isEmpty());
}

/** Expects that {@link ProjectStatus#getModifications(Date, Date)} throws {@link RuntimeErrorException}
* exception */
private void assertVeto(ProjectStatus status, long lastBuild, long now) {
try {
status.getModifications(new Date(lastBuild), new Date(now));
fail("Invalid status returned");
} catch (RuntimeException exc) {
// OK
}
}

/** Expects that {@link ProjectStatus#validate()} throws {@link CruiseControlException}
* exception with the given message */
private void assertInvalid(ProjectStatus status, String message) {
// Verify log directory is mandatory
try {
status.validate();
fail("Validation passed while it should not");
} catch (CruiseControlException exc) {
assertEquals("Wrong exception", message, exc.getMessage());
}
}
}

0 comments on commit 78558d8

Please sign in to comment.