Project implements Serializable, Runnable { protected void build() throws CruiseControlException { if (projectConfig == null) { throw new IllegalStateException("projectConfig must be set on project before calling build()"); } if (stopped) { LOG.warn("not building project " + name + " because project has been stopped."); return; } if (forceOnly && !buildForced && !(!wasLastBuildSuccessful && buildAfterFailed)) { info("not building because project is forceOnly and build not forced."); return; } final boolean buildWasForced = buildForced; try { setBuildStartTime(new Date()); final Schedule schedule = projectConfig.getSchedule(); if (schedule == null) { throw new IllegalStateException("project must have a schedule"); } if (schedule.isPaused(buildStartTime)) { return; } bootstrap(); final String target = useAndResetBuildTargetIfBuildWasForced(buildWasForced); final Element modifications = getModifications(buildWasForced); if (modifications == null) { return; } final Log buildLog = projectConfig.getLog(); buildLog.addContent(modifications); final Date now; if (projectConfig.getModificationSet() != null && projectConfig.getModificationSet().getTimeOfCheck() != null) { now = projectConfig.getModificationSet().getTimeOfCheck(); } else { now = new Date(); } if (getLabelIncrementer().isPreBuildIncrementer()) { label = getLabelIncrementer().incrementLabel(label, buildLog.getContent()); } buildLog.addContent(getProjectPropertiesElement(now)); setState(ProjectState.BUILDING); final Element builderLog = schedule.build(buildCounter, lastBuild, now, getProjectPropertiesMap(now), target, progress); buildLog.addContent(builderLog.detach()); boolean buildSuccessful = buildLog.wasBuildSuccessful(); fireResultEvent(new BuildResultEvent(this, buildSuccessful)); if (!getLabelIncrementer().isPreBuildIncrementer() && buildSuccessful) { label = getLabelIncrementer().incrementLabel(label, buildLog.getContent()); } setState(ProjectState.MERGING_LOGS); buildLog.writeLogFile(now); if (!buildAfterFailed) { lastBuild = now; } if (buildSuccessful) { lastBuild = now; lastSuccessfulBuild = now; info("build successful"); } else { info("build failed"); } buildCounter++; setWasLastBuildSuccessful(buildSuccessful); serializeProject(); publish(buildLog); buildLog.reset(); } finally { resetBuildForcedOnlyIfBuildWasForced(buildWasForced); setState(ProjectState.IDLE); } } Project(); void execute(); void run(); void forceBuildWithTarget(String buildTarget); void forceBuildWithTarget(String buildTarget, Map<String, String> addedProperties); void serializeProject(); void setLabelIncrementer(final LabelIncrementer incrementer); LabelIncrementer getLabelIncrementer(); void setName(final String projectName); String getName(); void setLabel(final String newLabel); String getLabel(); void setLastBuild(final String newLastBuild); void setLastSuccessfulBuild(final String newLastSuccessfulBuild); String getLastBuild(); boolean getBuildForced(); void setBuildForced(boolean forceNewBuildNow); String getLastSuccessfulBuild(); String getLogDir(); long getBuildInterval(); void overrideBuildInterval(final long sleepMillis); boolean isPaused(); void setPaused(final boolean paused); void setBuildAfterFailed(final boolean rebuildEvenWithNoNewModifications); String getStatus(); String getStatusWithQueuePosition(); ProjectState getState(); void setBuildQueue(final BuildQueue buildQueue); String getBuildStartTime(); Log getLog(); boolean isLastBuildSuccessful(); void start(); void stop(); String toString(); void addBuildProgressListener(final BuildProgressListener listener); void addBuildResultListener(final BuildResultListener listener); void setProjectConfig(final ProjectConfig projectConfig); boolean equals(final Object arg0); int hashCode(); void register(final MBeanServer server); ProjectConfig getProjectConfig(); Date getLastBuildDate(); Progress getProgress(); List<String> getLogLabels(); String[] getLogLabelLines(final String logLabel, final int firstLine);  }
@Test public void testBuild() throws CruiseControlException, IOException { final Date now = new Date(); final MockModificationSet modSet = new MockModificationSet(); modSet.setTimeOfCheck(now); final MockSchedule sched = new MockSchedule(); projectConfig.add(sched); final Log log = new Log(); final File logDir = new File(TEST_DIR + File.separator + "test-results"); if (!logDir.exists()) { assertTrue(Util.doMkDirs(logDir)); } filesToDelete.add(logDir); final String myProjectName = "myproject"; log.setProjectName(myProjectName); filesToDelete.add(new File(TestUtil.getTargetDir(), myProjectName + ".ser")); log.setDir(logDir.getAbsolutePath()); log.setEncoding("ISO-8859-1"); log.validate(); projectConfig.add(log); MergeLogger logger = new MergeLogger(); logger.setFile(TEST_DIR + File.separator + "_auxLog1.xml"); logger.validate(); log.add(logger); logger = new MergeLogger(); logger.setDir(TEST_DIR + File.separator + "_auxLogs"); logger.validate(); log.add(logger); projectConfig.add(modSet); project.setProjectConfig(projectConfig); project.setLabel("1.2.2"); project.setName("myproject"); project.setWasLastBuildSuccessful(false); project.setLastBuild(formatTime(now)); project.setLastSuccessfulBuild(formatTime(now)); writeFile(TEST_DIR + File.separator + "_auxLog1.xml", "<one/>"); final File auxLogsDirectory = new File(TEST_DIR + File.separator + "_auxLogs"); if (!auxLogsDirectory.exists()) { assertTrue(Util.doMkDirs(auxLogsDirectory)); } filesToDelete.add(auxLogsDirectory); writeFile(TEST_DIR + File.separator + "_auxLogs/_auxLog2.xml", "<testsuite><properties><property/></properties><testcase/></testsuite>"); writeFile(TEST_DIR + File.separator + "_auxLogs/_auxLog3.xml", "<testsuite/>"); final List<BuildResultEvent> resultEvents = new ArrayList<BuildResultEvent>(); project.addBuildResultListener(new BuildResultListener() { public void handleBuildResult(BuildResultEvent event) { resultEvents.add(event); } }); final List<BuildProgressEvent> progressEvents = new ArrayList<BuildProgressEvent>(); project.addBuildProgressListener(new BuildProgressListener() { public void handleBuildProgress(BuildProgressEvent event) { progressEvents.add(event); } }); projectConfig.add(new DefaultLabelIncrementer()); project.init(); project.start(); project.build(); project.stop(); final File expectedLogFile = new File(logDir, "log" + DateUtil.getFormattedTime(now) + "L1.2.2.xml"); assertTrue(expectedLogFile.isFile()); filesToDelete.add(expectedLogFile); assertTrue(project.isLastBuildSuccessful()); final String expected = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><cruisecontrol><modifications />" + "<info>" + "<property name=\"projectname\" value=\"myproject\" />" + "<property name=\"lastbuild\" value=\"" + DateUtil.getFormattedTime(now) + "\" />" + "<property name=\"lastsuccessfulbuild\" value=\"" + project.getLastSuccessfulBuild() + "\" />" + "<property name=\"builddate\" value=\"" + DateUtil.formatIso8601(now) + "\" />" + "<property name=\"cctimestamp\" value=\"" + DateUtil.getFormattedTime(now) + "\" />" + "<property name=\"label\" value=\"1.2.2\" />" + "<property name=\"interval\" value=\"300\" />" + "<property name=\"lastbuildsuccessful\" value=\"false\" />" + "<property name=\"logdir\" value=\"" + logDir.getAbsolutePath() + "\" />" + "<property name=\"logfile\" value=\"" + "log" + DateUtil.getFormattedTime(now) + "L1.2.2.xml\" />" + "</info><build /><one /><testsuite><testcase /></testsuite><testsuite /></cruisecontrol>"; assertEquals(expected, Util.readFileToString(expectedLogFile)); assertEquals("Didn't increment the label", "1.2.3", project.getLabel().intern()); final Map<String, String> props = sched.getBuildProperties(); assertNotNull("Build properties were null.", props); assertEquals("Build property count.", 10, props.size()); assertTrue("projectname not found.", props.containsKey("projectname")); assertEquals("wrong projectname.", "myproject", props.get("projectname")); assertTrue("filemodified not found.", props.containsKey("filemodified")); assertTrue("fileremoved not found.", props.containsKey("fileremoved")); assertEquals(project.getLastSuccessfulBuild(), props.get("cclastgoodbuildtimestamp")); assertEquals(project.getLastBuild(), props.get("cclastbuildtimestamp")); assertTrue("cvstimestamp not passed.", props.containsKey("cvstimestamp")); assertEquals("Should be exactly one build result event", 1, resultEvents.size()); final BuildResultEvent resultEvent = resultEvents.get(0); assertTrue("Should be successful build result event", resultEvent.isBuildSuccessful()); assertTrue("Should have at least one of each project state except queued", progressEvents.size() >= 8); }