1 package org.apache.continuum.buildmanager;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.continuum.buildqueue.BuildQueueService;
23 import org.apache.continuum.dao.BuildDefinitionDao;
24 import org.apache.continuum.dao.ProjectDao;
25 import org.apache.continuum.taskqueue.BuildProjectTask;
26 import org.apache.continuum.taskqueue.CheckOutTask;
27 import org.apache.continuum.taskqueue.OverallBuildQueue;
28 import org.apache.continuum.taskqueue.PrepareBuildProjectsTask;
29 import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
30 import org.apache.continuum.utils.build.BuildTrigger;
31 import org.apache.maven.continuum.configuration.ConfigurationService;
32 import org.apache.maven.continuum.model.project.BuildDefinition;
33 import org.apache.maven.continuum.model.project.BuildQueue;
34 import org.apache.maven.continuum.model.project.Project;
35 import org.apache.maven.continuum.model.project.Schedule;
36 import org.apache.maven.continuum.store.ContinuumStoreException;
37 import org.codehaus.plexus.spring.PlexusInSpringTestCase;
38 import org.codehaus.plexus.taskqueue.Task;
39 import org.codehaus.plexus.taskqueue.TaskQueue;
40 import org.codehaus.plexus.taskqueue.TaskQueueException;
41 import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
42 import org.jmock.Expectations;
43 import org.jmock.Mockery;
44 import org.jmock.integration.junit3.JUnit3Mockery;
45 import org.jmock.lib.legacy.ClassImposteriser;
46
47 import java.io.File;
48 import java.util.ArrayList;
49 import java.util.Collections;
50 import java.util.HashMap;
51 import java.util.List;
52 import java.util.Map;
53
54
55
56
57
58
59 public class ParallelBuildsManagerTest
60 extends PlexusInSpringTestCase
61 {
62 private ParallelBuildsManager buildsManager;
63
64 private Mockery context;
65
66 private BuildDefinitionDao buildDefinitionDao;
67
68 private ProjectDao projectDao;
69
70 private ConfigurationService configurationService;
71
72 private OverallBuildQueue overallBuildQueue;
73
74 private TaskQueue buildQueue;
75
76 private TaskQueue checkoutQueue;
77
78 private TaskQueue prepareBuildQueue;
79
80 private List<Project> projects;
81
82 private TaskQueueExecutor buildTaskQueueExecutor;
83
84 private TaskQueueExecutor checkoutTaskQueueExecutor;
85
86 private TaskQueueExecutor prepareBuildTaskQueueExecutor;
87
88 @Override
89 public void setUp()
90 throws Exception
91 {
92 super.setUp();
93
94 buildsManager = (ParallelBuildsManager) lookup( BuildsManager.class, "parallel" );
95
96 context = new JUnit3Mockery();
97 context.setImposteriser( ClassImposteriser.INSTANCE );
98
99 buildDefinitionDao = context.mock( BuildDefinitionDao.class );
100
101 buildsManager.setBuildDefinitionDao( buildDefinitionDao );
102
103 configurationService = context.mock( ConfigurationService.class );
104
105 buildsManager.setConfigurationService( configurationService );
106
107 BuildQueueService buildQueueService = context.mock( BuildQueueService.class );
108
109 buildsManager.setBuildQueueService( buildQueueService );
110
111 buildQueue = context.mock( TaskQueue.class, "build-queue" );
112
113 checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
114
115 prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
116
117 projectDao = context.mock( ProjectDao.class );
118
119 buildsManager.setProjectDao( projectDao );
120
121 buildTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "build-task-queue" );
122
123 checkoutTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "checkout-task-queue" );
124
125 prepareBuildTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "prepare-build-task-queue" );
126 }
127
128 @Override
129 public void tearDown()
130 throws Exception
131 {
132 super.tearDown();
133
134 buildsManager = null;
135 }
136
137 private List<BuildQueue> getBuildQueues( int start, int end )
138 {
139 List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();
140 for ( int i = start; i <= end; i++ )
141 {
142 BuildQueue buildQueue = new BuildQueue();
143 buildQueue.setId( i );
144 if ( i == 1 )
145 {
146 buildQueue.setName( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME );
147 }
148 else
149 {
150 buildQueue.setName( "BUILD_QUEUE_" + String.valueOf( i ) );
151 }
152 buildQueues.add( buildQueue );
153 }
154
155 return buildQueues;
156 }
157
158 private Schedule getSchedule( int id, int start, int end )
159 {
160 Schedule schedule = new Schedule();
161 schedule.setId( id );
162 schedule.setName( "DEFAULT_SCHEDULE" );
163 schedule.setCronExpression( "0 0 * * * ?" );
164 schedule.setDelay( 100 );
165 schedule.setMaxJobExecutionTime( 10000 );
166 schedule.setBuildQueues( getBuildQueues( start, end ) );
167
168 return schedule;
169 }
170
171 public void setupMockOverallBuildQueues()
172 throws Exception
173 {
174 Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
175 new HashMap<Integer, OverallBuildQueue>() );
176 overallBuildQueue = context.mock( OverallBuildQueue.class );
177 for ( int i = 1; i <= 5; i++ )
178 {
179 overallBuildQueues.put( i, overallBuildQueue );
180 }
181
182 buildsManager.setOverallBuildQueues( overallBuildQueues );
183 }
184
185
186 private void recordStartOfBuildProjectSequence()
187 throws TaskQueueException, ContinuumStoreException
188 {
189 context.checking( new Expectations()
190 {
191 {
192 exactly( 5 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
193 will( returnValue( false ) );
194
195 exactly( 5 ).of( buildTaskQueueExecutor ).getCurrentTask();
196 will( returnValue( null ) );
197
198 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
199 will( returnValue( projects ) );
200
201 one( configurationService ).getNumberOfBuildsInParallel();
202 will( returnValue( 2 ) );
203
204 exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
205 will( returnValue( buildQueue ) );
206
207 exactly( 7 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
208 will( returnValue( buildTaskQueueExecutor ) );
209 }
210 } );
211 }
212
213 private void recordBuildProjectBuildQueuesAreEmpty()
214 throws TaskQueueException, ContinuumStoreException
215 {
216
217 recordStartOfBuildProjectSequence();
218
219 final List<Task> tasks = new ArrayList<Task>();
220 context.checking( new Expectations()
221 {
222 {
223 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
224 will( returnValue( tasks ) );
225
226 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
227 will( returnValue( null ) );
228
229 one( overallBuildQueue ).getName();
230 will( returnValue( "BUILD_QUEUE_2" ) );
231 }
232 } );
233
234 recordAddToBuildQueue();
235 }
236
237 private void recordAddToBuildQueue()
238 throws TaskQueueException
239 {
240 context.checking( new Expectations()
241 {
242 {
243 one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
244 }
245 } );
246 }
247
248
249 private void recordStartOfCheckoutProjectSequence()
250 throws TaskQueueException
251 {
252 context.checking( new Expectations()
253 {
254 {
255 exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
256 will( returnValue( false ) );
257
258 one( configurationService ).getNumberOfBuildsInParallel();
259 will( returnValue( 2 ) );
260
261 exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
262 will( returnValue( checkoutQueue ) );
263
264 exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
265 will( returnValue( checkoutTaskQueueExecutor ) );
266 }
267 } );
268
269 }
270
271 private void recordCheckoutProjectBuildQueuesAreEmpty()
272 throws TaskQueueException
273 {
274 recordStartOfCheckoutProjectSequence();
275
276 final List<Task> tasks = new ArrayList<Task>();
277 context.checking( new Expectations()
278 {
279 {
280 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
281 will( returnValue( tasks ) );
282
283 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
284 will( returnValue( null ) );
285
286 one( overallBuildQueue ).getName();
287 will( returnValue( "BUILD_QUEUE_2" ) );
288 }
289 } );
290
291 recordAddToCheckoutQueue();
292 }
293
294 private void recordAddToCheckoutQueue()
295 throws TaskQueueException
296 {
297 context.checking( new Expectations()
298 {
299 {
300 one( overallBuildQueue ).addToCheckoutQueue( with( any( CheckOutTask.class ) ) );
301 }
302 } );
303 }
304
305
306 private void recordStartOfPrepareBuildProjectSequence()
307 throws TaskQueueException, ContinuumStoreException
308 {
309 final BuildDefinition buildDef = new BuildDefinition();
310 buildDef.setId( 1 );
311 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
312
313 context.checking( new Expectations()
314 {
315 {
316 exactly( 5 ).of( overallBuildQueue ).isInPrepareBuildQueue( with( any( int.class ) ), with( any(
317 int.class ) ) );
318 will( returnValue( false ) );
319
320 one( buildDefinitionDao ).getBuildDefinition( 1 );
321 will( returnValue( buildDef ) );
322
323 one( configurationService ).getNumberOfBuildsInParallel();
324 will( returnValue( 2 ) );
325
326 exactly( 2 ).of( overallBuildQueue ).getPrepareBuildQueue();
327 will( returnValue( prepareBuildQueue ) );
328
329 exactly( 2 ).of( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
330 will( returnValue( prepareBuildTaskQueueExecutor ) );
331 }
332 } );
333 }
334
335 private void recordPrepareBuildProjectPrepareBuildQueuesAreEmpty()
336 throws TaskQueueException, ContinuumStoreException
337 {
338 recordStartOfPrepareBuildProjectSequence();
339
340 final List<Task> tasks = new ArrayList<Task>();
341 context.checking( new Expectations()
342 {
343 {
344 exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
345 will( returnValue( tasks ) );
346
347 exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
348 will( returnValue( null ) );
349
350 one( overallBuildQueue ).getName();
351 will( returnValue( "BUILD_QUEUE_2" ) );
352 }
353 } );
354
355 recordAddToPrepareBuildQueue();
356 }
357
358 private void recordAddToPrepareBuildQueue()
359 throws TaskQueueException
360 {
361 context.checking( new Expectations()
362 {
363 {
364 one( overallBuildQueue ).addToPrepareBuildQueue( with( any( PrepareBuildProjectsTask.class ) ) );
365 }
366 } );
367 }
368
369
370
371 public void testContainer()
372 throws Exception
373 {
374 buildsManager.setContainer( getContainer() );
375
376 buildsManager.isProjectInAnyCurrentBuild( 1 );
377
378 assertTrue( true );
379 }
380
381 public void testBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
382 throws Exception
383 {
384 setupMockOverallBuildQueues();
385
386 BuildDefinition buildDef = new BuildDefinition();
387 buildDef.setId( 1 );
388 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
389
390 recordBuildProjectBuildQueuesAreEmpty();
391
392 buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
393 1 );
394
395 context.assertIsSatisfied();
396 }
397
398 public void testBuildProjectProjectsAreAlreadyQueuedInOverallBuildQueues()
399 throws Exception
400 {
401 setupMockOverallBuildQueues();
402
403 BuildDefinition buildDef = new BuildDefinition();
404 buildDef.setId( 1 );
405 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
406
407 recordBuildProjectBuildQueuesAreEmpty();
408
409 buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
410 1 );
411 context.assertIsSatisfied();
412
413
414 recordStartOfBuildProjectSequence();
415
416
417 final List<Task> tasks = new ArrayList<Task>();
418 final List<Task> tasksOfFirstBuildQueue = new ArrayList<Task>();
419 tasksOfFirstBuildQueue.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ),
420 "continuum-project-test-2", buildDef.getDescription(), null,
421 2 ) );
422 context.checking( new Expectations()
423 {
424 {
425 one( buildQueue ).getQueueSnapshot();
426 will( returnValue( tasksOfFirstBuildQueue ) );
427
428
429 one( buildQueue ).getQueueSnapshot();
430 will( returnValue( tasks ) );
431
432 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
433 will( returnValue( null ) );
434
435 one( overallBuildQueue ).getName();
436 will( returnValue( "BUILD_QUEUE_3" ) );
437 }
438 } );
439
440 recordAddToBuildQueue();
441
442 buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", new BuildTrigger( 1, "test-user" ), null,
443 2 );
444 context.assertIsSatisfied();
445
446
447 recordStartOfBuildProjectSequence();
448
449
450 context.checking( new Expectations()
451 {
452 {
453 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
454 will( returnValue( tasksOfFirstBuildQueue ) );
455
456 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
457 will( returnValue( null ) );
458
459 one( overallBuildQueue ).getName();
460 will( returnValue( "BUILD_QUEUE_2" ) );
461 }
462 } );
463
464 recordAddToBuildQueue();
465
466 buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", new BuildTrigger( 1, "test-user" ), null,
467 3 );
468 context.assertIsSatisfied();
469 }
470
471 public void testRemoveProjectFromBuildQueue()
472 throws Exception
473 {
474 setupMockOverallBuildQueues();
475
476 context.checking( new Expectations()
477 {
478 {
479 one( overallBuildQueue ).isInBuildQueue( 1 );
480 will( returnValue( true ) );
481
482 one( overallBuildQueue ).removeProjectFromBuildQueue( 1 );
483 }
484 } );
485
486 buildsManager.removeProjectFromBuildQueue( 1 );
487 context.assertIsSatisfied();
488 }
489
490 public void testRemoveProjectsFromBuildQueue()
491 throws Exception
492 {
493 setupMockOverallBuildQueues();
494 int[] projectIds = new int[]{1, 2, 3};
495
496 context.checking( new Expectations()
497 {
498 {
499 exactly( 3 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
500 will( returnValue( true ) );
501
502 exactly( 3 ).of( overallBuildQueue ).removeProjectFromBuildQueue( with( any( int.class ) ) );
503 }
504 } );
505
506 buildsManager.removeProjectsFromBuildQueue( projectIds );
507 context.assertIsSatisfied();
508 }
509
510 public void testCheckoutProjectSingle()
511 throws Exception
512 {
513 setupMockOverallBuildQueues();
514
515 BuildDefinition buildDef = new BuildDefinition();
516 buildDef.setId( 1 );
517 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
518
519 recordCheckoutProjectBuildQueuesAreEmpty();
520
521 buildsManager.checkoutProject( 1, "continuum-project-test-1", new File( getBasedir(),
522 "/target/test-working-dir/1" ), null,
523 "dummy", "dummypass", buildDef, null );
524 context.assertIsSatisfied();
525 }
526
527 public void testCheckoutProjectMultiple()
528 throws Exception
529 {
530 setupMockOverallBuildQueues();
531
532 BuildDefinition buildDef = new BuildDefinition();
533 buildDef.setId( 1 );
534 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
535
536 recordCheckoutProjectBuildQueuesAreEmpty();
537
538 buildsManager.checkoutProject( 1, "continuum-project-test-1", new File( getBasedir(),
539 "/target/test-working-dir/1" ), null,
540 "dummy", "dummypass", buildDef, null );
541 context.assertIsSatisfied();
542
543
544
545 recordStartOfCheckoutProjectSequence();
546
547 final List<Task> tasks = new ArrayList<Task>();
548
549 final List<Task> tasksInFirstCheckoutQueue = new ArrayList<Task>();
550 tasksInFirstCheckoutQueue.add( new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ),
551 "continuum-project-test-1", "dummy", "dummypass", null,
552 null ) );
553
554 context.checking( new Expectations()
555 {
556 {
557 one( checkoutQueue ).getQueueSnapshot();
558 will( returnValue( tasksInFirstCheckoutQueue ) );
559
560 one( checkoutQueue ).getQueueSnapshot();
561 will( returnValue( tasks ) );
562
563 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
564 will( returnValue( null ) );
565
566 one( overallBuildQueue ).getName();
567 will( returnValue( "BUILD_QUEUE_3" ) );
568 }
569 } );
570
571 recordAddToCheckoutQueue();
572
573 buildsManager.checkoutProject( 2, "continuum-project-test-2", new File( getBasedir(),
574 "/target/test-working-dir/1" ), null,
575 "dummy", "dummypass", buildDef, null );
576 context.assertIsSatisfied();
577
578
579 recordStartOfCheckoutProjectSequence();
580
581 context.checking( new Expectations()
582 {
583 {
584 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
585 will( returnValue( tasksInFirstCheckoutQueue ) );
586
587 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
588 will( returnValue( null ) );
589
590 one( overallBuildQueue ).getName();
591 will( returnValue( "BUILD_QUEUE_2" ) );
592 }
593 } );
594
595 recordAddToCheckoutQueue();
596
597 buildsManager.checkoutProject( 3, "continuum-project-test-3", new File( getBasedir(),
598 "/target/test-working-dir/1" ), null,
599 "dummy", "dummypass", buildDef, null );
600 context.assertIsSatisfied();
601 }
602
603 public void testRemoveProjectFromCheckoutQueue()
604 throws Exception
605 {
606 setupMockOverallBuildQueues();
607
608 context.checking( new Expectations()
609 {
610 {
611 one( overallBuildQueue ).isInCheckoutQueue( 1 );
612 will( returnValue( true ) );
613
614 one( overallBuildQueue ).removeProjectFromCheckoutQueue( 1 );
615 }
616 } );
617
618 buildsManager.removeProjectFromCheckoutQueue( 1 );
619 context.assertIsSatisfied();
620 }
621
622 public void testRemoveProjectsFromCheckoutQueue()
623 throws Exception
624 {
625 setupMockOverallBuildQueues();
626
627 context.checking( new Expectations()
628 {
629 {
630 exactly( 3 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
631 will( returnValue( true ) );
632
633 exactly( 3 ).of( overallBuildQueue ).removeProjectFromCheckoutQueue( with( any( int.class ) ) );
634 }
635 } );
636
637 int[] projectIds = new int[]{1, 2, 3};
638
639 buildsManager.removeProjectsFromCheckoutQueue( projectIds );
640 context.assertIsSatisfied();
641 }
642
643 public void testRemoveProjectFromCheckoutQueueProjectNotFound()
644 throws Exception
645 {
646 setupMockOverallBuildQueues();
647
648
649 context.checking( new Expectations()
650 {
651 {
652 exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( 1 );
653 will( returnValue( false ) );
654 }
655 } );
656
657 buildsManager.removeProjectFromCheckoutQueue( 1 );
658 context.assertIsSatisfied();
659 }
660
661 public void testRemoveDefaultOverallBuildQueue()
662 throws Exception
663 {
664 setupMockOverallBuildQueues();
665
666 try
667 {
668 context.checking( new Expectations()
669 {
670 {
671 one( overallBuildQueue ).getName();
672 will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
673 }
674 } );
675
676 buildsManager.removeOverallBuildQueue( 1 );
677 context.assertIsSatisfied();
678 fail( "An exception should have been thrown." );
679 }
680 catch ( BuildManagerException e )
681 {
682 assertEquals( "Cannot remove default build queue.", e.getMessage() );
683 }
684 }
685
686 public void testRemoveOverallBuildQueueNoTasksCurrentlyExecuting()
687 throws Exception
688 {
689
690 setupMockOverallBuildQueues();
691
692 final BuildDefinition buildDef = new BuildDefinition();
693 buildDef.setId( 1 );
694 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
695
696 final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
697 final TaskQueueExecutor checkoutQueueExecutor = context.mock( TaskQueueExecutor.class,
698 "checkout-queue-executor" );
699 final TaskQueueExecutor prepareBuildQueueExecutor = context.mock( TaskQueueExecutor.class,
700 "prepare-build-queue-executor" );
701
702 final List<Task> buildTasks = new ArrayList<Task>();
703 buildTasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
704 "BUILD_DEF", null, 2 ) );
705
706 final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
707 checkoutTasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
708 "continuum-project-test-2", "dummy", "dummypass", null, null ) );
709
710 final List<Task> prepareBuildTasks = new ArrayList<Task>();
711 final Map<Integer, Integer> map = new HashMap<Integer, Integer>();
712 map.put( 1, 1 );
713 prepareBuildTasks.add( new PrepareBuildProjectsTask( map, new BuildTrigger( 1, "test-user" ), 1,
714 "Project Group A", "http://scm.root.address", 2 ) );
715
716 final ParallelBuildsThreadedTaskQueueExecutor buildTaskQueueExecutor = context.mock(
717 ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-build-task-executor" );
718 final ParallelBuildsThreadedTaskQueueExecutor checkoutTaskQueueExecutor = context.mock(
719 ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-checkout-task-executor" );
720 final ParallelBuildsThreadedTaskQueueExecutor prepareBuildTaskQueueExecutor = context.mock(
721 ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-prepare-build-task-executor" );
722
723 final List<Task> tasks = new ArrayList<Task>();
724
725 context.checking( new Expectations()
726 {
727 {
728 one( overallBuildQueue ).getName();
729 will( returnValue( "BUILD_QUEUE_5" ) );
730
731
732 one( overallBuildQueue ).getBuildTaskQueueExecutor();
733 will( returnValue( buildQueueExecutor ) );
734 one( buildQueueExecutor ).getCurrentTask();
735 will( returnValue( null ) );
736
737
738
739 one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
740 will( returnValue( checkoutQueueExecutor ) );
741 one( checkoutQueueExecutor ).getCurrentTask();
742 will( returnValue( null ) );
743
744
745
746 one( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
747 will( returnValue( prepareBuildQueueExecutor ) );
748 one( prepareBuildQueueExecutor ).getCurrentTask();
749 will( returnValue( null ) );
750
751
752 one( overallBuildQueue ).getProjectsInBuildQueue();
753 will( returnValue( buildTasks ) );
754 one( overallBuildQueue ).getBuildQueue();
755 will( returnValue( buildQueue ) );
756 one( buildQueue ).removeAll( buildTasks );
757
758
759 one( overallBuildQueue ).getProjectsInCheckoutQueue();
760 will( returnValue( checkoutTasks ) );
761 one( overallBuildQueue ).getCheckoutQueue();
762 will( returnValue( checkoutQueue ) );
763 one( checkoutQueue ).removeAll( checkoutTasks );
764
765
766 one( overallBuildQueue ).getProjectsInPrepareBuildQueue();
767 will( returnValue( prepareBuildTasks ) );
768 one( overallBuildQueue ).getPrepareBuildQueue();
769 will( returnValue( prepareBuildQueue ) );
770 one( prepareBuildQueue ).removeAll( prepareBuildTasks );
771
772
773 one( overallBuildQueue ).getBuildTaskQueueExecutor();
774 will( returnValue( buildTaskQueueExecutor ) );
775 one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
776 will( returnValue( checkoutTaskQueueExecutor ) );
777 one( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
778 will( returnValue( prepareBuildTaskQueueExecutor ) );
779
780 one( buildTaskQueueExecutor ).stop();
781 one( checkoutTaskQueueExecutor ).stop();
782 one( prepareBuildTaskQueueExecutor ).stop();
783
784
785
786
787
788 one( buildDefinitionDao ).getBuildDefinition( 1 );
789 will( returnValue( buildDef ) );
790
791
792 exactly( 4 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
793 will( returnValue( false ) );
794
795 exactly( 4 ).of( buildQueueExecutor ).getCurrentTask();
796 will( returnValue( null ) );
797
798 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
799 will( returnValue( projects ) );
800
801 one( configurationService ).getNumberOfBuildsInParallel();
802 will( returnValue( 2 ) );
803
804 exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
805 will( returnValue( buildQueue ) );
806
807 exactly( 6 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
808 will( returnValue( buildQueueExecutor ) );
809
810 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
811 will( returnValue( tasks ) );
812
813 exactly( 2 ).of( buildQueueExecutor ).getCurrentTask();
814 will( returnValue( null ) );
815
816 one( overallBuildQueue ).getName();
817 will( returnValue( "BUILD_QUEUE_2" ) );
818
819 recordAddToBuildQueue();
820
821
822 one( buildDefinitionDao ).getDefaultBuildDefinition( 2 );
823 will( returnValue( buildDef ) );
824
825
826 exactly( 4 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
827 will( returnValue( false ) );
828
829 one( configurationService ).getNumberOfBuildsInParallel();
830 will( returnValue( 2 ) );
831
832 exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
833 will( returnValue( checkoutQueue ) );
834
835 exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
836 will( returnValue( checkoutQueueExecutor ) );
837
838 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
839 will( returnValue( tasks ) );
840
841 exactly( 2 ).of( checkoutQueueExecutor ).getCurrentTask();
842 will( returnValue( null ) );
843
844 one( overallBuildQueue ).getName();
845 will( returnValue( "BUILD_QUEUE_2" ) );
846
847 recordAddToCheckoutQueue();
848
849
850 exactly( 4 ).of( overallBuildQueue ).isInPrepareBuildQueue( with( any( int.class ) ), with( any(
851 int.class ) ) );
852 will( returnValue( false ) );
853
854 one( buildDefinitionDao ).getBuildDefinition( 1 );
855 will( returnValue( buildDef ) );
856
857 one( configurationService ).getNumberOfBuildsInParallel();
858 will( returnValue( 2 ) );
859
860 exactly( 2 ).of( overallBuildQueue ).getPrepareBuildQueue();
861 will( returnValue( prepareBuildQueue ) );
862
863 exactly( 2 ).of( overallBuildQueue ).getPrepareBuildTaskQueueExecutor();
864 will( returnValue( prepareBuildQueueExecutor ) );
865
866 exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
867 will( returnValue( tasks ) );
868
869 exactly( 2 ).of( prepareBuildQueueExecutor ).getCurrentTask();
870 will( returnValue( null ) );
871
872 one( overallBuildQueue ).getName();
873 will( returnValue( "BUILD_QUEUE_2" ) );
874
875 recordAddToPrepareBuildQueue();
876 }
877 } );
878
879 buildsManager.removeOverallBuildQueue( 5 );
880 context.assertIsSatisfied();
881
882 Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
883 assertNull( overallBuildQueues.get( 5 ) );
884 }
885
886 public void testRemoveOverallBuildQueueTasksCurrentlyExecuting()
887 throws Exception
888 {
889 setupMockOverallBuildQueues();
890
891 final BuildDefinition buildDef = new BuildDefinition();
892 buildDef.setId( 1 );
893 buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
894
895 final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
896 final Task buildTask = new BuildProjectTask( 1, 1, new BuildTrigger( 1, "test-user" ),
897 "continuum-project-test-1", "BUILD_DEF", null, 1 );
898
899 final List<BuildProjectTask> buildTasks = new ArrayList<BuildProjectTask>();
900 buildTasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
901 "BUILD_DEF", null, 2 ) );
902
903 final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
904 checkoutTasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
905 "continuum-project-test-2", "dummy", "dummypass", null, null ) );
906
907 try
908 {
909 context.checking( new Expectations()
910 {
911 {
912 one( overallBuildQueue ).getName();
913 will( returnValue( "BUILD_QUEUE_5" ) );
914
915
916 one( overallBuildQueue ).getBuildTaskQueueExecutor();
917 will( returnValue( buildQueueExecutor ) );
918 one( buildQueueExecutor ).getCurrentTask();
919 will( returnValue( buildTask ) );
920 }
921 } );
922
923 buildsManager.removeOverallBuildQueue( 5 );
924 context.assertIsSatisfied();
925 fail( "An exception should have been thrown." );
926 }
927 catch ( BuildManagerException e )
928 {
929 assertEquals( "Cannot remove build queue. A task is currently executing.", e.getMessage() );
930 }
931 }
932
933 public void testNoBuildQueuesConfigured()
934 throws Exception
935 {
936 overallBuildQueue = context.mock( OverallBuildQueue.class );
937
938 Map<Integer, OverallBuildQueue> overallBuildQueues = Collections.synchronizedMap(
939 new HashMap<Integer, OverallBuildQueue>() );
940 overallBuildQueues.put( 1, overallBuildQueue );
941
942 buildsManager.setOverallBuildQueues( overallBuildQueues );
943
944 Schedule schedule = new Schedule();
945 schedule.setId( 1 );
946 schedule.setName( "DEFAULT_SCHEDULE" );
947 schedule.setCronExpression( "0 0 * * * ?" );
948 schedule.setDelay( 100 );
949 schedule.setMaxJobExecutionTime( 10000 );
950
951 BuildDefinition buildDef = new BuildDefinition();
952 buildDef.setId( 1 );
953 buildDef.setSchedule( schedule );
954
955 context.checking( new Expectations()
956 {
957 {
958 one( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
959 will( returnValue( false ) );
960
961 one( overallBuildQueue ).getBuildTaskQueueExecutor();
962 will( returnValue( buildTaskQueueExecutor ) );
963
964 one( buildTaskQueueExecutor ).getCurrentTask();
965 will( returnValue( null ) );
966
967 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
968 will( returnValue( projects ) );
969
970 one( configurationService ).getNumberOfBuildsInParallel();
971 will( returnValue( 2 ) );
972
973 exactly( 2 ).of( overallBuildQueue ).getName();
974 will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
975
976 one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
977 }
978 } );
979
980 buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", new BuildTrigger( 1, "test-user" ), null,
981 1 );
982 context.assertIsSatisfied();
983 }
984
985 public void testGetProjectsInBuildQueue()
986 throws Exception
987 {
988 setupMockOverallBuildQueues();
989
990 final List<Task> tasks = new ArrayList<Task>();
991 tasks.add( new BuildProjectTask( 2, 1, new BuildTrigger( 1, "test-user" ), "continuum-project-test-2",
992 "BUILD_DEF", null, 2 ) );
993
994 context.checking( new Expectations()
995 {
996 {
997 exactly( 5 ).of( overallBuildQueue ).getName();
998 will( returnValue( "BUILD_QUEUE" ) );
999
1000 exactly( 5 ).of( overallBuildQueue ).getProjectsInBuildQueue();
1001 will( returnValue( tasks ) );
1002 }
1003 } );
1004
1005 buildsManager.getProjectsInBuildQueues();
1006 context.assertIsSatisfied();
1007 }
1008
1009 public void testGetProjectsInCheckoutQueue()
1010 throws Exception
1011 {
1012 setupMockOverallBuildQueues();
1013
1014 final List<Task> tasks = new ArrayList<Task>();
1015 tasks.add( new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ),
1016 "continuum-project-test-2", "dummy", "dummypass", null, null ) );
1017
1018 context.checking( new Expectations()
1019 {
1020 {
1021 exactly( 5 ).of( overallBuildQueue ).getName();
1022 will( returnValue( "BUILD_QUEUE" ) );
1023
1024 exactly( 5 ).of( overallBuildQueue ).getProjectsInCheckoutQueue();
1025 will( returnValue( tasks ) );
1026 }
1027 } );
1028
1029 buildsManager.getProjectsInCheckoutQueues();
1030 context.assertIsSatisfied();
1031 }
1032
1033
1034 public void testPrepareBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
1035 throws Exception
1036 {
1037 setupMockOverallBuildQueues();
1038
1039 Map<Integer, Integer> map = new HashMap<Integer, Integer>();
1040 map.put( 1, 1 );
1041
1042 recordPrepareBuildProjectPrepareBuildQueuesAreEmpty();
1043
1044 buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
1045 "http://scm.root.address", 1 );
1046 context.assertIsSatisfied();
1047 }
1048
1049 public void testPrepareBuildProjectsAlreadyQueued()
1050 throws Exception
1051 {
1052 setupMockOverallBuildQueues();
1053
1054 Map<Integer, Integer> map = new HashMap<Integer, Integer>();
1055 map.put( 1, 1 );
1056
1057
1058 recordStartOfPrepareBuildProjectSequence();
1059
1060
1061 final List<Task> tasks = new ArrayList<Task>();
1062 final List<Task> tasksOfFirstPrepareBuildQueue = new ArrayList<Task>();
1063 tasksOfFirstPrepareBuildQueue.add( new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(),
1064 new BuildTrigger( 1, "test-user" ), 1,
1065 "Project Group B", "http://scm.root.address2",
1066 2 ) );
1067 context.checking( new Expectations()
1068 {
1069 {
1070 one( prepareBuildQueue ).getQueueSnapshot();
1071 will( returnValue( tasksOfFirstPrepareBuildQueue ) );
1072
1073
1074 one( prepareBuildQueue ).getQueueSnapshot();
1075 will( returnValue( tasks ) );
1076
1077 exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
1078 will( returnValue( null ) );
1079
1080 one( overallBuildQueue ).getName();
1081 will( returnValue( "BUILD_QUEUE_3" ) );
1082 }
1083 } );
1084
1085 recordAddToPrepareBuildQueue();
1086
1087 buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
1088 "http://scm.root.address", 1 );
1089 context.assertIsSatisfied();
1090
1091
1092 recordStartOfPrepareBuildProjectSequence();
1093
1094
1095 context.checking( new Expectations()
1096 {
1097 {
1098 exactly( 2 ).of( prepareBuildQueue ).getQueueSnapshot();
1099 will( returnValue( tasksOfFirstPrepareBuildQueue ) );
1100
1101 exactly( 2 ).of( prepareBuildTaskQueueExecutor ).getCurrentTask();
1102 will( returnValue( null ) );
1103
1104 one( overallBuildQueue ).getName();
1105 will( returnValue( "BUILD_QUEUE_2" ) );
1106 }
1107 } );
1108
1109 recordAddToPrepareBuildQueue();
1110
1111 buildsManager.prepareBuildProjects( map, new BuildTrigger( 1, "test-user" ), 1, "Project Group A",
1112 "http://scm.root.address", 1 );
1113 context.assertIsSatisfied();
1114 }
1115
1116 public void testGetProjectsInPrepareBuildQueue()
1117 throws Exception
1118 {
1119 setupMockOverallBuildQueues();
1120
1121 final List<Task> tasks = new ArrayList<Task>();
1122 tasks.add( new PrepareBuildProjectsTask( new HashMap<Integer, Integer>(), new BuildTrigger( 1, "test-user" ), 1,
1123 "Project Group A", "http://scm.root.address", 2 ) );
1124
1125 context.checking( new Expectations()
1126 {
1127 {
1128 exactly( 5 ).of( overallBuildQueue ).getName();
1129 will( returnValue( "PREPARE_BUILD_QUEUE" ) );
1130
1131 exactly( 5 ).of( overallBuildQueue ).getProjectsInPrepareBuildQueue();
1132 will( returnValue( tasks ) );
1133 }
1134 } );
1135
1136 buildsManager.getProjectsInPrepareBuildQueue();
1137 context.assertIsSatisfied();
1138 }
1139
1140 public void testRemoveProjectFromPrepareBuildQueue()
1141 throws Exception
1142 {
1143 setupMockOverallBuildQueues();
1144 context.checking( new Expectations()
1145 {
1146 {
1147 exactly( 5 ).of( overallBuildQueue ).isInPrepareBuildQueue( 1, 2 );
1148 will( returnValue( true ) );
1149
1150 one( overallBuildQueue ).removeProjectFromPrepareBuildQueue( 1, 2 );
1151 }
1152 } );
1153
1154 buildsManager.removeProjectFromPrepareBuildQueue( 1, 2 );
1155 context.assertIsSatisfied();
1156 }
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177 }