1 37 package net.sourceforge.cruisecontrol; 38 39 import java.io.ByteArrayOutputStream ; 40 import java.io.File ; 41 import java.io.FileInputStream ; 42 import java.io.FileOutputStream ; 43 import java.io.FileWriter ; 44 import java.io.IOException ; 45 import java.io.ObjectInputStream ; 46 import java.io.ObjectOutputStream ; 47 import java.text.SimpleDateFormat ; 48 import java.util.ArrayList ; 49 import java.util.Calendar ; 50 import java.util.Date ; 51 import java.util.GregorianCalendar ; 52 import java.util.Iterator ; 53 import java.util.List ; 54 import java.util.Map ; 55 import java.util.TimeZone ; 56 57 import junit.framework.TestCase; 58 import net.sourceforge.cruisecontrol.builders.MockBuilder; 59 import net.sourceforge.cruisecontrol.buildloggers.MergeLogger; 60 import net.sourceforge.cruisecontrol.events.BuildProgressEvent; 61 import net.sourceforge.cruisecontrol.events.BuildProgressListener; 62 import net.sourceforge.cruisecontrol.events.BuildResultEvent; 63 import net.sourceforge.cruisecontrol.events.BuildResultListener; 64 import net.sourceforge.cruisecontrol.labelincrementers.DefaultLabelIncrementer; 65 import net.sourceforge.cruisecontrol.util.DateUtil; 66 import net.sourceforge.cruisecontrol.util.Util; 67 68 import org.apache.log4j.Level; 69 import org.jdom.Element; 70 71 public class ProjectTest extends TestCase { 72 private static final org.apache.log4j.Logger LOG4J = org.apache.log4j.Logger.getLogger(ProjectTest.class); 73 74 private static final String TEST_DIR = "tmp"; 75 76 private Project project; 77 private ProjectConfig projectConfig; 78 private final List filesToClear = new ArrayList (); 79 80 protected void setUp() throws CruiseControlException { 81 project = new Project(); 82 project.setName("TestProject"); 83 84 projectConfig = new ProjectConfig(); 85 projectConfig.add(new DefaultLabelIncrementer()); 86 project.setProjectConfig(projectConfig); 87 } 88 89 public void tearDown() { 90 project.stop(); 91 project = null; 92 projectConfig = null; 93 94 LOG4J.getLoggerRepository().setThreshold(Level.ALL); 95 for (Iterator iterator = filesToClear.iterator(); iterator.hasNext();) { 96 File file = (File ) iterator.next(); 97 Util.deleteFile(file); 98 } 99 } 100 101 public void testNotifyListeners() throws CruiseControlException { 102 103 MockListener listener = new MockListener(); 104 ProjectConfig.Listeners listeners = new ProjectConfig.Listeners(); 105 listeners.add(listener); 106 projectConfig.add(listeners); 107 project.init(); 109 ProjectEvent event = new ProjectEvent("foo") { 110 }; 111 project.notifyListeners(event); 112 assertTrue(listener.wasNotified()); 113 } 114 115 public void testBuild() throws Exception { 116 Date now = new Date (); 117 MockModificationSet modSet = new MockModificationSet(); 118 modSet.setTimeOfCheck(now); 119 MockSchedule sched = new MockSchedule(); 120 projectConfig.add(sched); 121 122 Log log = new Log(); 123 File logDir = new File (TEST_DIR + File.separator + "test-results"); 124 logDir.mkdir(); 125 log.setProjectName("myproject"); 126 log.setDir(logDir.getAbsolutePath()); 127 log.setEncoding("ISO-8859-1"); 128 log.validate(); 129 130 projectConfig.add(log); 131 132 MergeLogger logger = new MergeLogger(); 133 logger.setFile(TEST_DIR + File.separator + "_auxLog1.xml"); 134 logger.validate(); 135 log.add(logger); 136 137 logger = new MergeLogger(); 138 logger.setDir(TEST_DIR + File.separator + "_auxLogs"); 139 logger.validate(); 140 log.add(logger); 141 142 projectConfig.add(modSet); 143 project.setProjectConfig(projectConfig); 144 145 project.setLabel("1.2.2"); 146 project.setName("myproject"); 147 project.setWasLastBuildSuccessful(false); 148 149 project.setLastBuild(formatTime(now)); 150 project.setLastSuccessfulBuild(formatTime(now)); 151 writeFile(TEST_DIR + File.separator + "_auxLog1.xml", "<one/>"); 152 File auxLogsDirectory = new File (TEST_DIR + File.separator + "_auxLogs"); 153 auxLogsDirectory.mkdir(); 154 writeFile(TEST_DIR + File.separator + "_auxLogs/_auxLog2.xml", 155 "<testsuite><properties><property/></properties><testcase/></testsuite>"); 156 writeFile(TEST_DIR + File.separator + "_auxLogs/_auxLog3.xml", "<testsuite/>"); 157 158 final ArrayList resultEvents = new ArrayList (); 159 project.addBuildResultListener(new BuildResultListener() { 160 public void handleBuildResult(BuildResultEvent event) { 161 resultEvents.add(event); 162 } 163 }); 164 165 final ArrayList progressEvents = new ArrayList (); 166 project.addBuildProgressListener(new BuildProgressListener() { 167 public void handleBuildProgress(BuildProgressEvent event) { 168 progressEvents.add(event); 169 } 170 }); 171 172 projectConfig.add(new DefaultLabelIncrementer()); 173 project.init(); 174 175 project.start(); 176 project.build(); 177 project.stop(); 178 filesToClear.add(log.getLastLogFile()); 179 180 assertTrue(project.isLastBuildSuccessful()); 181 182 String expected = 183 "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?><cruisecontrol><modifications />" 184 + "<info>" 185 + "<property name=\"projectname\" value=\"myproject\" />" 186 + "<property name=\"lastbuild\" value=\"" 187 + DateUtil.getFormattedTime(now) 188 + "\" />" 189 + "<property name=\"lastsuccessfulbuild\" value=\"" 190 + project.getLastSuccessfulBuild() 191 + "\" />" 192 + "<property name=\"builddate\" value=\"" 193 + DateFormatFactory.getDateFormat().format(now) 194 + "\" />" 195 + "<property name=\"cctimestamp\" value=\"" 196 + DateUtil.getFormattedTime(now) 197 + "\" />" 198 + "<property name=\"label\" value=\"1.2.2\" />" 199 + "<property name=\"interval\" value=\"300\" />" 200 + "<property name=\"lastbuildsuccessful\" value=\"false\" />" 201 + "<property name=\"logdir\" value=\"" 202 + logDir.getAbsolutePath() 203 + "\" />" 204 + "<property name=\"logfile\" value=\"" 205 + "log" 206 + DateUtil.getFormattedTime(now) 207 + "L1.2.2.xml\" />" 208 + "</info><build /><one /><testsuite><testcase /></testsuite><testsuite /></cruisecontrol>"; 209 assertEquals(expected, Util.readFileToString(log.getLastLogFile())); 210 assertEquals("Didn't increment the label", "1.2.3", project.getLabel().intern()); 211 212 java.util.Map props = sched.getBuildProperties(); 214 assertNotNull("Build properties were null.", props); 215 assertEquals("Build property count.", 8, props.size()); 216 assertTrue("filemodified not found.", props.containsKey("filemodified")); 217 assertTrue("fileremoved not found.", props.containsKey("fileremoved")); 218 assertEquals(project.getLastSuccessfulBuild(), props.get("cclastgoodbuildtimestamp")); 219 assertEquals(project.getLastBuild(), props.get("cclastbuildtimestamp")); 220 assertTrue("cvstimestamp not passed.", props.containsKey("cvstimestamp")); 221 222 assertEquals("Should be exactly one build result event", 1, resultEvents.size()); 224 BuildResultEvent resultEvent = (BuildResultEvent) resultEvents.get(0); 225 assertTrue("Should be successful build result event", resultEvent.isBuildSuccessful()); 226 assertTrue("Should have at least one of each project state except queued", progressEvents.size() >= 8); 227 } 228 229 public void testBuildShouldThrowExceptionWhenNoConfig() throws CruiseControlException { 230 project = new Project(); 231 try { 232 project.build(); 233 fail(); 234 } catch (IllegalStateException expected) { 235 assertEquals("projectConfig must be set on project before calling build()", expected.getMessage()); 236 } 237 238 project.setProjectConfig(projectConfig); 239 project.build(); 240 } 241 242 public void testBuildRequiresSchedule() throws CruiseControlException { 243 MockProject mockProject = new MockProject() { 244 public void run() { 245 loop(); 246 } 247 248 void checkWait() throws InterruptedException { 249 waitIfPaused(); 250 } 251 }; 252 mockProject.setName("MockProject"); 253 mockProject.setProjectConfig(projectConfig); 254 mockProject.start(); 255 mockProject.init(); 256 try { 257 mockProject.build(); 258 fail(); 259 } catch (IllegalStateException expected) { 260 assertEquals("project must have a schedule", expected.getMessage()); 261 } finally { 262 mockProject.stopLooping(); 263 } 264 } 265 266 public void testBuildWithMinimumConfig() throws CruiseControlException { 267 Schedule schedule = new Schedule(); 268 schedule.add(new MockBuilder()); 269 projectConfig.add(schedule); 270 projectConfig.add(new MockLog()); 271 project.start(); 272 project.setBuildForced(true); 273 project.init(); 274 project.build(); 275 } 276 277 public void testBadLabel() { 278 try { 279 project.validateLabel("build_0", projectConfig.getLabelIncrementer()); 280 fail("Expected exception due to bad label"); 281 } catch (CruiseControlException expected) { 282 } 283 } 284 285 public void testPublish() throws CruiseControlException { 286 MockSchedule sched = new MockSchedule(); 287 projectConfig.add(sched); 288 289 MockPublisher publisher = new MockPublisher(); 290 Publisher exceptionThrower = new MockPublisher() { 291 public void publish(Element log) throws CruiseControlException { 292 throw new CruiseControlException("exception"); 293 } 294 }; 295 296 ProjectConfig.Publishers publishers = new ProjectConfig.Publishers(); 297 publishers.add(publisher); 298 publishers.add(exceptionThrower); 299 publishers.add(publisher); 300 301 projectConfig.add(publishers); 302 project.setName("projectName"); 303 project.setLabel("label.1"); 304 305 projectConfig.add(new DefaultLabelIncrementer()); 306 projectConfig.add(new Log()); 307 project.init(); 308 309 project.publish(); 310 311 assertEquals(2, publisher.getPublishCount()); 312 } 313 314 public void testSetLastBuild() throws CruiseControlException { 315 String lastBuild = "20000101120000"; 316 317 project.setLastBuild(lastBuild); 318 319 assertEquals(lastBuild, project.getLastBuild()); 320 } 321 322 public void testNullLastBuild() throws CruiseControlException { 323 try { 324 project.setLastBuild(null); 325 fail("Expected an IllegalArgumentException for a null last build"); 326 } catch (IllegalArgumentException e) { 327 } 328 } 329 330 public void testBadLastBuild() { 331 try { 332 project.setLastBuild("af32455432"); 333 fail("Expected a CruiseControlException for a bad last build"); 334 } catch (CruiseControlException e) { 335 } 336 } 337 338 public void testGetFormattedTime() { 339 assertNull(DateUtil.getFormattedTime(null)); 340 } 341 342 public void testGetModifications() throws CruiseControlException { 343 MockModificationSet modSet = new MockModificationSet(); 344 Element modifications = modSet.getModifications(null); 345 projectConfig.add(modSet); 346 project.init(); 347 348 modSet.setModified(true); 349 assertEquals(modifications, project.getModifications(false)); 350 assertEquals(modifications, project.getModifications(true)); 351 352 modSet.setModified(false); 353 assertEquals(null, project.getModifications(false)); 354 assertEquals(modifications, project.getModifications(true)); 355 356 } 358 359 public void testGetModifications_NoModificationElementRequired() { 360 assertNull(project.getModifications(false)); 361 project.setBuildForced(true); 362 assertNotNull(project.getModifications(true)); 363 } 364 365 public void testCheckOnlySinceLastBuild() throws CruiseControlException { 366 367 project.setLastBuild("20030218010101"); 368 project.setLastSuccessfulBuild("20030218010101"); 369 assertEquals(false, project.checkOnlySinceLastBuild()); 370 371 project.setLastBuild("20030218020202"); 372 assertEquals(false, project.checkOnlySinceLastBuild()); 373 374 project.setBuildAfterFailed(false); 375 assertEquals(true, project.checkOnlySinceLastBuild()); 376 377 project.setLastBuild("20030218010102"); 378 assertEquals(false, project.checkOnlySinceLastBuild()); 379 380 project.setLastBuild("20020101010101"); 381 assertEquals(false, project.checkOnlySinceLastBuild()); 382 } 383 384 public void testWaitIfPaused() throws InterruptedException , CruiseControlException { 385 MockProject mockProject = new MockProject() { 386 public void run() { 387 loop(); 388 } 389 390 void checkWait() throws InterruptedException { 391 waitIfPaused(); 392 } 393 }; 394 395 projectConfig.add(new MockSchedule()); 396 mockProject.setProjectConfig(projectConfig); 397 mockProject.init(); 398 399 new Thread (mockProject).start(); 400 401 int firstLoopCount = mockProject.getLoopCount(); 402 Thread.sleep(100); 403 int secondLoopCount = mockProject.getLoopCount(); 404 assertTrue("loop counts should have been different when not paused", 405 firstLoopCount != secondLoopCount); 406 407 mockProject.setPaused(true); 408 Thread.sleep(100); 409 firstLoopCount = mockProject.getLoopCount(); 410 Thread.sleep(100); 411 secondLoopCount = mockProject.getLoopCount(); 412 assertEquals("loop counts should be same when paused", firstLoopCount, secondLoopCount); 413 414 mockProject.setPaused(false); 415 Thread.sleep(100); 416 int lastLoopCount = mockProject.getLoopCount(); 417 assertTrue("loop count increased after pause ended", lastLoopCount > secondLoopCount); 418 419 mockProject.stopLooping(); 420 } 421 422 public void testWaitForNextBuild() throws InterruptedException , CruiseControlException { 423 projectConfig.add(new MockSchedule()); 424 425 MockProject mockProject = new MockProject() { 426 public void run() { 427 loop(); 428 } 429 430 void checkWait() throws InterruptedException { 431 waitForNextBuild(); 432 } 433 }; 434 mockProject.overrideBuildInterval(1000); 435 mockProject.setProjectConfig(projectConfig); 436 mockProject.init(); 437 438 new Thread (mockProject).start(); 439 440 Thread.sleep(100); 441 assertEquals(1, mockProject.getLoopCount()); 442 443 Thread.sleep(100); 444 assertEquals(1, mockProject.getLoopCount()); 445 446 mockProject.forceBuild(); 447 Thread.sleep(100); 448 assertEquals(2, mockProject.getLoopCount()); 449 450 mockProject.stopLooping(); 451 } 452 453 public void testWaitForBuildToFinish() throws InterruptedException { 454 MockProject mockProject = new MockProject() { 455 public void run() { 456 loop(); 457 } 458 459 void checkWait() throws InterruptedException { 460 waitForBuildToFinish(); 461 } 462 }; 463 464 new Thread (mockProject).start(); 465 466 Thread.sleep(100); 467 assertEquals(1, mockProject.getLoopCount()); 468 469 Thread.sleep(100); 470 assertEquals(1, mockProject.getLoopCount()); 471 472 mockProject.buildFinished(); 473 Thread.sleep(100); 474 assertEquals(2, mockProject.getLoopCount()); 475 476 mockProject.stopLooping(); 477 } 478 479 public void testNeedToWait() { 480 assertTrue(Project.needToWaitForNextBuild(1)); 481 assertFalse(Project.needToWaitForNextBuild(0)); 482 assertFalse(Project.needToWaitForNextBuild(-1)); 483 } 484 485 public void testToString() { 486 project.setName("foo"); 487 assertEquals("Project foo: stopped", project.toString()); 488 project.setPaused(true); 489 assertEquals("Project foo: stopped (paused)", project.toString()); 490 } 491 492 public void testInitShouldThrowExceptionWhenConfigNotSet() throws CruiseControlException { 493 project = new Project(); 494 try { 495 project.init(); 496 fail(); 497 } catch (IllegalStateException expected) { 498 assertEquals("projectConfig must be set on project before calling init()", expected.getMessage()); 499 } 500 501 project.setProjectConfig(projectConfig); 502 project.init(); 503 } 504 505 public void testSerialization() throws IOException { 506 ByteArrayOutputStream outBytes = new ByteArrayOutputStream (); 507 ObjectOutputStream objects = new ObjectOutputStream (outBytes); 508 509 objects.writeObject(new Project()); 510 objects.flush(); 511 objects.close(); 512 513 project.serializeProject(); 514 } 515 516 public void testDeserialization() throws Exception { 517 File f = new File ("test.ser"); 518 filesToClear.add(f); 519 FileOutputStream outFile = new FileOutputStream (f); 520 ObjectOutputStream objects = new ObjectOutputStream (outFile); 521 522 objects.writeObject(new Project()); 523 objects.flush(); 524 objects.close(); 525 526 FileInputStream inFile = new FileInputStream (f); 527 ObjectInputStream inObjects = new ObjectInputStream (inFile); 528 529 Object p = inObjects.readObject(); 530 inObjects.close(); 531 assertNotNull("Read object must not be null", p); 532 assertTrue("Object must be instanceof Project class", p instanceof Project); 533 Project deserializedProject = (Project) p; 534 deserializedProject.addBuildProgressListener(new BuildProgressListener() { 535 public void handleBuildProgress(BuildProgressEvent event) { 536 } 537 }); 538 } 539 540 public void testStartAfterDeserialization() throws Exception { 541 TestProject beforeSerialization = new TestProject(); 542 projectConfig.add(new MockSchedule()); 543 beforeSerialization.setProjectConfig(projectConfig); 544 beforeSerialization.init(); 545 546 beforeSerialization.start(); 547 548 File f = new File ("test.ser"); 549 filesToClear.add(f); 550 FileOutputStream outFile = new FileOutputStream (f); 551 ObjectOutputStream objects = new ObjectOutputStream (outFile); 552 553 objects.writeObject(beforeSerialization); 554 objects.flush(); 555 objects.close(); 556 557 FileInputStream inFile = new FileInputStream (f); 558 ObjectInputStream inObjects = new ObjectInputStream (inFile); 559 560 Object p = inObjects.readObject(); 561 inObjects.close(); 562 TestProject deserializedProject = (TestProject) p; 563 deserializedProject.resetCreateNewSchedulingThreadCalled(); 564 deserializedProject.setProjectConfig(projectConfig); 565 deserializedProject.start(); 566 assertTrue("failed to create schedule thread", deserializedProject.wasCreateNewSchedulingThreadCalled()); 567 } 568 569 public void testGetProjectPropertiesMap() throws CruiseControlException { 570 String label = "labeL.1"; 571 project.setLabel(label); 572 String lastBuild = "20000101120000"; 573 project.setLastBuild(lastBuild); 574 String lastGoodBuild = "19990101120000"; 575 project.setLastSuccessfulBuild(lastGoodBuild); 576 project.setWasLastBuildSuccessful(true); 577 TimeZone cest = TimeZone.getTimeZone("Europe/Copenhagen"); 578 Calendar now = new GregorianCalendar (cest); 579 now.set(2005, Calendar.AUGUST, 10, 13, 7, 43); 580 String cvstimestamp = "2005-08-10 11:07:43 GMT"; 581 582 projectConfig.add(new MockSchedule()); 583 project.init(); 584 585 String cctimestamp = DateUtil.getFormattedTime(now.getTime()); 588 Map map = project.getProjectPropertiesMap(now.getTime()); 589 590 assertEquals(label, map.get("label")); 591 assertEquals(cctimestamp, map.get("cctimestamp")); 592 assertEquals(lastGoodBuild, map.get("cclastgoodbuildtimestamp")); 593 assertEquals(lastBuild, map.get("cclastbuildtimestamp")); 594 assertEquals("true", map.get("lastbuildsuccessful")); 595 assertEquals(cvstimestamp, map.get("cvstimestamp")); 596 } 597 598 public void testGetTimeToNextBuild_AfterShortBuild() throws CruiseControlException { 599 Schedule schedule = new Schedule(); 600 MockBuilder noonBuilder = new MockBuilder(); 601 noonBuilder.setTime("1200"); 602 noonBuilder.setBuildLogXML(new Element("builder1")); 603 schedule.add(noonBuilder); 604 605 projectConfig.add(schedule); 606 607 Calendar cal = Calendar.getInstance(); 608 cal.set(2001, Calendar.NOVEMBER, 22); 609 cal.set(Calendar.HOUR_OF_DAY, 12); 610 cal.set(Calendar.MINUTE, 00); 611 Date noonBuild = cal.getTime(); 612 project.setBuildStartTime(noonBuild); 613 614 project.init(); 615 616 cal.set(Calendar.SECOND, 30); 617 Date postNoonBuild = cal.getTime(); 618 619 long time = project.getTimeToNextBuild(postNoonBuild); 620 assertEquals(Schedule.ONE_DAY, time); 621 } 622 623 private void writeFile(String fileName, String contents) throws IOException { 624 625 File theFile = new File (fileName); 626 filesToClear.add(theFile); 627 FileWriter fw = new FileWriter (theFile); 628 fw.write(contents); 629 fw.close(); 630 } 631 632 private static String formatTime(Date time) { 633 return new SimpleDateFormat ("yyyyMMddHHmmss").format(time); 634 } 635 636 private class MockPublisher implements Publisher { 637 private int publishCount = 0; 638 639 public void validate() { 640 } 641 642 public void publish(Element log) throws CruiseControlException { 643 publishCount++; 644 } 645 646 int getPublishCount() { 647 return publishCount; 648 } 649 } 650 651 private class MockListener implements Listener { 652 private boolean notified = false; 653 654 public boolean wasNotified() { 655 return notified; 656 } 657 658 public void handleEvent(ProjectEvent event) throws CruiseControlException { 659 notified = true; 660 } 661 662 public void validate() throws CruiseControlException { 663 } 664 } 665 666 private static class TestProject extends Project { 667 private boolean createNewSchedulingThreadCalled = false; 668 669 protected void createNewSchedulingThread() { 670 createNewSchedulingThreadCalled = true; 671 } 672 673 boolean wasCreateNewSchedulingThreadCalled() { 674 return createNewSchedulingThreadCalled; 675 } 676 677 void resetCreateNewSchedulingThreadCalled() { 678 createNewSchedulingThreadCalled = false; 679 } 680 } 681 682 private class MockLog extends Log { 683 684 public void writeLogFile(Date now) throws CruiseControlException { 685 } 686 687 } 688 } 689 | Popular Tags |