View Javadoc

1   package org.apache.continuum.buildmanager;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.io.File;
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.HashMap;
26  import java.util.List;
27  import java.util.Map;
28  
29  import org.apache.continuum.buildqueue.BuildQueueService;
30  import org.apache.continuum.dao.BuildDefinitionDao;
31  import org.apache.continuum.dao.ProjectDao;
32  import org.apache.continuum.taskqueue.BuildProjectTask;
33  import org.apache.continuum.taskqueue.CheckOutTask;
34  import org.apache.continuum.taskqueue.OverallBuildQueue;
35  import org.apache.continuum.taskqueueexecutor.ParallelBuildsThreadedTaskQueueExecutor;
36  import org.apache.maven.continuum.configuration.ConfigurationService;
37  import org.apache.maven.continuum.model.project.BuildDefinition;
38  import org.apache.maven.continuum.model.project.BuildQueue;
39  import org.apache.maven.continuum.model.project.Project;
40  import org.apache.maven.continuum.model.project.Schedule;
41  import org.apache.maven.continuum.store.ContinuumStoreException;
42  import org.codehaus.plexus.spring.PlexusInSpringTestCase;
43  import org.codehaus.plexus.taskqueue.Task;
44  import org.codehaus.plexus.taskqueue.TaskQueue;
45  import org.codehaus.plexus.taskqueue.TaskQueueException;
46  import org.codehaus.plexus.taskqueue.execution.TaskQueueExecutor;
47  import org.jmock.Expectations;
48  import org.jmock.Mockery;
49  import org.jmock.integration.junit3.JUnit3Mockery;
50  import org.jmock.lib.legacy.ClassImposteriser;
51  
52  /**
53   * ParallelBuildsManagerTest
54   *
55   * @author <a href="mailto:oching@apache.org">Maria Odea Ching</a>
56   */
57  public class ParallelBuildsManagerTest
58      extends PlexusInSpringTestCase
59  {
60      private ParallelBuildsManager buildsManager;
61  
62      private Mockery context;
63  
64      private BuildDefinitionDao buildDefinitionDao;
65  
66      private ProjectDao projectDao;
67  
68      private ConfigurationService configurationService;
69  
70      private OverallBuildQueue overallBuildQueue;
71  
72      private TaskQueue buildQueue;
73  
74      private TaskQueue checkoutQueue;
75  
76      private List<Project> projects;
77  
78      private TaskQueueExecutor buildTaskQueueExecutor;
79  
80      private TaskQueueExecutor checkoutTaskQueueExecutor;
81  
82      @Override
83      public void setUp()
84          throws Exception
85      {
86          super.setUp();
87  
88          buildsManager = (ParallelBuildsManager) lookup( BuildsManager.class, "parallel" );
89  
90          context = new JUnit3Mockery();
91          context.setImposteriser( ClassImposteriser.INSTANCE );
92  
93          buildDefinitionDao = context.mock( BuildDefinitionDao.class );
94  
95          buildsManager.setBuildDefinitionDao( buildDefinitionDao );
96  
97          TaskQueue prepareBuildQueue = context.mock( TaskQueue.class, "prepare-build-queue" );
98  
99          buildsManager.setPrepareBuildQueue( prepareBuildQueue );
100 
101         configurationService = context.mock( ConfigurationService.class );
102 
103         buildsManager.setConfigurationService( configurationService );
104 
105         BuildQueueService buildQueueService = context.mock( BuildQueueService.class );
106 
107         buildsManager.setBuildQueueService( buildQueueService );
108 
109         buildQueue = context.mock( TaskQueue.class, "build-queue" );
110 
111         checkoutQueue = context.mock( TaskQueue.class, "checkout-queue" );
112 
113         projectDao = context.mock( ProjectDao.class );
114 
115         buildsManager.setProjectDao( projectDao );
116 
117         buildTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "build-task-queue" );
118 
119         checkoutTaskQueueExecutor = context.mock( TaskQueueExecutor.class, "checkout-task-queue" );
120     }
121 
122     @Override
123     public void tearDown()
124         throws Exception
125     {
126         super.tearDown();
127 
128         buildsManager = null;
129     }
130 
131     private List<BuildQueue> getBuildQueues( int start, int end )
132     {
133         List<BuildQueue> buildQueues = new ArrayList<BuildQueue>();
134         for ( int i = start; i <= end; i++ )
135         {
136             BuildQueue buildQueue = new BuildQueue();
137             buildQueue.setId( i );
138             if ( i == 1 )
139             {
140                 buildQueue.setName( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME );
141             }
142             else
143             {
144                 buildQueue.setName( "BUILD_QUEUE_" + String.valueOf( i ) );
145             }
146             buildQueues.add( buildQueue );
147         }
148 
149         return buildQueues;
150     }
151 
152     private Schedule getSchedule( int id, int start, int end )
153     {
154         Schedule schedule = new Schedule();
155         schedule.setId( id );
156         schedule.setName( "DEFAULT_SCHEDULE" );
157         schedule.setCronExpression( "0 0 * * * ?" );
158         schedule.setDelay( 100 );
159         schedule.setMaxJobExecutionTime( 10000 );
160         schedule.setBuildQueues( getBuildQueues( start, end ) );
161 
162         return schedule;
163     }
164 
165     public void setupMockOverallBuildQueues()
166         throws Exception
167     {
168         Map<Integer, OverallBuildQueue> overallBuildQueues =
169             Collections.synchronizedMap( new HashMap<Integer, OverallBuildQueue>() );
170         overallBuildQueue = context.mock( OverallBuildQueue.class );
171         for ( int i = 1; i <= 5; i++ )
172         {
173             overallBuildQueues.put( i, overallBuildQueue );
174         }
175 
176         buildsManager.setOverallBuildQueues( overallBuildQueues );
177     }
178 
179     // build project recordings
180     private void recordStartOfBuildProjectSequence()
181         throws TaskQueueException, ContinuumStoreException
182     {
183         context.checking( new Expectations()
184         {
185             {
186                 exactly( 5 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
187                 will( returnValue( false ) );
188 
189                 exactly( 5 ).of( buildTaskQueueExecutor ).getCurrentTask();
190                 will( returnValue( null ) );
191 
192                 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
193                 will( returnValue( projects ) );
194 
195                 one( configurationService ).getNumberOfBuildsInParallel();
196                 will( returnValue( 2 ) );
197 
198                 exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
199                 will( returnValue( buildQueue ) );
200 
201                 exactly( 7 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
202                 will( returnValue( buildTaskQueueExecutor ) );
203             }} );
204     }
205 
206     private void recordBuildProjectBuildQueuesAreEmpty()
207         throws TaskQueueException, ContinuumStoreException
208     {
209         // shouldn't only the build queues attached to the schedule be checked?
210         recordStartOfBuildProjectSequence();
211 
212         final List<Task> tasks = new ArrayList<Task>();
213         context.checking( new Expectations()
214         {
215             {
216                 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
217                 will( returnValue( tasks ) );
218                 
219                 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
220                 will( returnValue( null ) );
221 
222                 one( overallBuildQueue ).getName();
223                 will( returnValue( "BUILD_QUEUE_2" ) );
224             }} );
225 
226         recordAddToBuildQueue();
227     }
228 
229     private void recordAddToBuildQueue()
230         throws TaskQueueException
231     {
232         context.checking( new Expectations()
233         {
234             {
235                 one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
236             }} );
237     }
238 
239     // checkout project recordings
240     private void recordStartOfCheckoutProjectSequence()
241         throws TaskQueueException
242     {
243         context.checking( new Expectations()
244         {
245             {
246                 exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
247                 will( returnValue( false ) );
248 
249                 one( configurationService ).getNumberOfBuildsInParallel();
250                 will( returnValue( 2 ) );
251 
252                 exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
253                 will( returnValue( checkoutQueue ) );
254 
255                 exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
256                 will( returnValue( checkoutTaskQueueExecutor ) );
257             }} );
258 
259     }
260 
261     private void recordCheckoutProjectBuildQueuesAreEmpty()
262         throws TaskQueueException
263     {
264         recordStartOfCheckoutProjectSequence();
265 
266         final List<Task> tasks = new ArrayList<Task>();
267         context.checking( new Expectations()
268         {
269             {
270                 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
271                 will( returnValue( tasks ) );
272 
273                 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
274                 will( returnValue( null ) );
275 
276                 one( overallBuildQueue ).getName();
277                 will( returnValue( "BUILD_QUEUE_2" ) );
278             }} );
279 
280         recordAddToCheckoutQueue();
281     }
282 
283     private void recordAddToCheckoutQueue()
284         throws TaskQueueException
285     {
286         context.checking( new Expectations()
287         {
288             {
289                 one( overallBuildQueue ).addToCheckoutQueue( with( any( CheckOutTask.class ) ) );
290             }} );
291     }
292 
293     // start of test cases..
294 
295     public void testContainer()
296         throws Exception
297     {
298         buildsManager.setContainer( getContainer() );
299 
300         buildsManager.isProjectInAnyCurrentBuild( 1 );
301 
302         assertTrue( true );
303     }
304 
305     public void testBuildProjectNoProjectQueuedInAnyOverallBuildQueues()
306         throws Exception
307     {
308         setupMockOverallBuildQueues();
309 
310         BuildDefinition buildDef = new BuildDefinition();
311         buildDef.setId( 1 );
312         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
313 
314         recordBuildProjectBuildQueuesAreEmpty();
315 
316         buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1, null, 1 );
317 
318         context.assertIsSatisfied();
319     }
320 
321     public void testBuildProjectProjectsAreAlreadyQueuedInOverallBuildQueues()
322         throws Exception
323     {
324         setupMockOverallBuildQueues();
325 
326         BuildDefinition buildDef = new BuildDefinition();
327         buildDef.setId( 1 );
328         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
329 
330         recordBuildProjectBuildQueuesAreEmpty();
331 
332         buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1, null, 1 );
333         context.assertIsSatisfied();
334 
335         //queue second project - 1st queue is not empty, 2nd queue is empty 
336         recordStartOfBuildProjectSequence();
337 
338         // the first build queue already has a task queued
339         final List<Task> tasks = new ArrayList<Task>();
340         final List<Task> tasksOfFirstBuildQueue = new ArrayList<Task>();
341         tasksOfFirstBuildQueue.add(
342             new BuildProjectTask( 2, 1, 1, "continuum-project-test-2", buildDef.getDescription(), null, 2 ) );
343         context.checking( new Expectations()
344         {
345             {
346                 one( buildQueue ).getQueueSnapshot();
347                 will( returnValue( tasksOfFirstBuildQueue ) );
348 
349                 // the second build queue has no tasks queued, so it should return 0
350                 one( buildQueue ).getQueueSnapshot();
351                 will( returnValue( tasks ) );
352 
353                 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
354                 will( returnValue( null ) );
355 
356                 one( overallBuildQueue ).getName();
357                 will( returnValue( "BUILD_QUEUE_3" ) );
358             }} );
359 
360         recordAddToBuildQueue();
361 
362         buildsManager.buildProject( 2, buildDef, "continuum-project-test-2", 1, null, 2 );
363         context.assertIsSatisfied();
364 
365         // queue third project - both queues have 1 task queued each
366         recordStartOfBuildProjectSequence();
367 
368         // both queues have 1 task each        
369         context.checking( new Expectations()
370         {
371             {
372                 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
373                 will( returnValue( tasksOfFirstBuildQueue ) );
374 
375                 exactly( 2 ).of( buildTaskQueueExecutor ).getCurrentTask();
376                 will( returnValue( null ) );
377                 
378                 one( overallBuildQueue ).getName();
379                 will( returnValue( "BUILD_QUEUE_2" ) );
380             }} );
381 
382         recordAddToBuildQueue();
383 
384         buildsManager.buildProject( 3, buildDef, "continuum-project-test-3", 1, null, 3 );
385         context.assertIsSatisfied();
386     }
387 
388     public void testRemoveProjectFromBuildQueue()
389         throws Exception
390     {
391         setupMockOverallBuildQueues();
392 
393         context.checking( new Expectations()
394         {
395             {
396                 one( overallBuildQueue ).isInBuildQueue( 1 );
397                 will( returnValue( true ) );
398 
399                 one( overallBuildQueue ).removeProjectFromBuildQueue( 1 );
400             }} );
401 
402         buildsManager.removeProjectFromBuildQueue( 1 );
403         context.assertIsSatisfied();
404     }
405 
406     public void testRemoveProjectsFromBuildQueue()
407         throws Exception
408     {
409         setupMockOverallBuildQueues();
410         int[] projectIds = new int[]{1, 2, 3};
411 
412         context.checking( new Expectations()
413         {
414             {
415                 exactly( 3 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
416                 will( returnValue( true ) );
417 
418                 exactly( 3 ).of( overallBuildQueue ).removeProjectFromBuildQueue( with( any( int.class ) ) );
419             }} );
420 
421         buildsManager.removeProjectsFromBuildQueue( projectIds );
422         context.assertIsSatisfied();
423     }
424 
425     public void testCheckoutProjectSingle()
426         throws Exception
427     {
428         setupMockOverallBuildQueues();
429 
430         BuildDefinition buildDef = new BuildDefinition();
431         buildDef.setId( 1 );
432         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
433 
434         recordCheckoutProjectBuildQueuesAreEmpty();
435 
436         buildsManager.checkoutProject( 1, "continuum-project-test-1",
437                                        new File( getBasedir(), "/target/test-working-dir/1" ), "dummy", "dummypass",
438                                        buildDef );
439         context.assertIsSatisfied();
440     }
441 
442     public void testCheckoutProjectMultiple()
443         throws Exception
444     {
445         setupMockOverallBuildQueues();
446 
447         BuildDefinition buildDef = new BuildDefinition();
448         buildDef.setId( 1 );
449         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
450 
451         recordCheckoutProjectBuildQueuesAreEmpty();
452 
453         buildsManager.checkoutProject( 1, "continuum-project-test-1",
454                                        new File( getBasedir(), "/target/test-working-dir/1" ), "dummy", "dummypass",
455                                        buildDef );
456         context.assertIsSatisfied();
457 
458         // queue second project - 1st queue has 1 task while 2nd queue is empty; project should be queued in
459         //      2nd queue
460         recordStartOfCheckoutProjectSequence();
461 
462         final List<Task> tasks = new ArrayList<Task>();
463 
464         final List<Task> tasksInFirstCheckoutQueue = new ArrayList<Task>();
465         tasksInFirstCheckoutQueue.add(
466             new CheckOutTask( 1, new File( getBasedir(), "/target/test-working-dir/1" ), "continuum-project-test-1",
467                               "dummy", "dummypass" ) );
468 
469         context.checking( new Expectations()
470         {
471             {
472                 one( checkoutQueue ).getQueueSnapshot();
473                 will( returnValue( tasksInFirstCheckoutQueue ) );
474 
475                 one( checkoutQueue ).getQueueSnapshot();
476                 will( returnValue( tasks ) );
477 
478                 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
479                 will( returnValue( null ) );
480                 
481                 one( overallBuildQueue ).getName();
482                 will( returnValue( "BUILD_QUEUE_3" ) );
483             }} );
484 
485         recordAddToCheckoutQueue();
486 
487         buildsManager.checkoutProject( 2, "continuum-project-test-2",
488                                        new File( getBasedir(), "/target/test-working-dir/1" ), "dummy", "dummypass",
489                                        buildDef );
490         context.assertIsSatisfied();
491 
492         // queue third project - both queues have 1 task queued each; third project should be queued in 1st queue
493         recordStartOfCheckoutProjectSequence();
494 
495         context.checking( new Expectations()
496         {
497             {
498                 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
499                 will( returnValue( tasksInFirstCheckoutQueue ) );
500 
501                 exactly( 2 ).of( checkoutTaskQueueExecutor ).getCurrentTask();
502                 will( returnValue( null ) );
503                 
504                 one( overallBuildQueue ).getName();
505                 will( returnValue( "BUILD_QUEUE_2" ) );
506             }} );
507 
508         recordAddToCheckoutQueue();
509 
510         buildsManager.checkoutProject( 3, "continuum-project-test-3",
511                                        new File( getBasedir(), "/target/test-working-dir/1" ), "dummy", "dummypass",
512                                        buildDef );
513         context.assertIsSatisfied();
514     }
515 
516     public void testRemoveProjectFromCheckoutQueue()
517         throws Exception
518     {
519         setupMockOverallBuildQueues();
520 
521         context.checking( new Expectations()
522         {
523             {
524                 one( overallBuildQueue ).isInCheckoutQueue( 1 );
525                 will( returnValue( true ) );
526 
527                 one( overallBuildQueue ).removeProjectFromCheckoutQueue( 1 );
528             }} );
529 
530         buildsManager.removeProjectFromCheckoutQueue( 1 );
531         context.assertIsSatisfied();
532     }
533 
534     public void testRemoveProjectsFromCheckoutQueue()
535         throws Exception
536     {
537         setupMockOverallBuildQueues();
538 
539         context.checking( new Expectations()
540         {
541             {
542                 exactly( 3 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
543                 will( returnValue( true ) );
544 
545                 exactly( 3 ).of( overallBuildQueue ).removeProjectFromCheckoutQueue( with( any( int.class ) ) );
546             }} );
547 
548         int[] projectIds = new int[]{1, 2, 3};
549 
550         buildsManager.removeProjectsFromCheckoutQueue( projectIds );
551         context.assertIsSatisfied();
552     }
553 
554     public void testRemoveProjectFromCheckoutQueueProjectNotFound()
555         throws Exception
556     {
557         setupMockOverallBuildQueues();
558 
559         // shouldn't only the project's build queues be checked instead of all the overall build queues?
560         context.checking( new Expectations()
561         {
562             {
563                 exactly( 5 ).of( overallBuildQueue ).isInCheckoutQueue( 1 );
564                 will( returnValue( false ) );
565             }} );
566 
567         buildsManager.removeProjectFromCheckoutQueue( 1 );
568         context.assertIsSatisfied();
569     }
570 
571     public void testRemoveDefaultOverallBuildQueue()
572         throws Exception
573     {
574         setupMockOverallBuildQueues();
575 
576         try
577         {
578             context.checking( new Expectations()
579             {
580                 {
581                     one( overallBuildQueue ).getName();
582                     will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
583                 }} );
584 
585             buildsManager.removeOverallBuildQueue( 1 );
586             context.assertIsSatisfied();
587             fail( "An exception should have been thrown." );
588         }
589         catch ( BuildManagerException e )
590         {
591             assertEquals( "Cannot remove default build queue.", e.getMessage() );
592         }
593     }
594 
595     public void testRemoveOverallBuildQueueNoTasksCurrentlyExecuting()
596         throws Exception
597     {
598         // queued tasks (both checkout & build tasks) must be transferred to the other queues!
599         setupMockOverallBuildQueues();
600 
601         final BuildDefinition buildDef = new BuildDefinition();
602         buildDef.setId( 1 );
603         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
604 
605         final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
606         final TaskQueueExecutor checkoutQueueExecutor =
607             context.mock( TaskQueueExecutor.class, "checkout-queue-executor" );
608 
609         final List<Task> buildTasks = new ArrayList<Task>();
610         buildTasks.add( new BuildProjectTask( 2, 1, 1, "continuum-project-test-2", "BUILD_DEF", null, 2 ) );
611 
612         final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
613         checkoutTasks.add(
614             new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ), "continuum-project-test-2",
615                               "dummy", "dummypass" ) );
616 
617         final ParallelBuildsThreadedTaskQueueExecutor buildTaskQueueExecutor =
618             context.mock( ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-build-task-executor" );
619         final ParallelBuildsThreadedTaskQueueExecutor checkoutTaskQueueExecutor =
620             context.mock( ParallelBuildsThreadedTaskQueueExecutor.class, "parallel-checkout-task-executor" );
621 
622         final List<Task> tasks = new ArrayList<Task>();
623 
624         context.checking( new Expectations()
625         {
626             {
627                 one( overallBuildQueue ).getName();
628                 will( returnValue( "BUILD_QUEUE_5" ) );
629 
630                 // check if there is any build task currently being executed
631                 one( overallBuildQueue ).getBuildTaskQueueExecutor();
632                 will( returnValue( buildQueueExecutor ) );
633                 one( buildQueueExecutor ).getCurrentTask();
634                 will( returnValue( null ) );
635                 //will( returnValue( buildTask ) );
636 
637                 // check if there is any checkout task currently being executed
638                 one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
639                 will( returnValue( checkoutQueueExecutor ) );
640                 one( checkoutQueueExecutor ).getCurrentTask();
641                 will( returnValue( null ) );
642                 //will( returnValue( checkoutTask ) );
643 
644                 // get all queued build tasks & remove them
645                 one( overallBuildQueue ).getProjectsInBuildQueue();
646                 will( returnValue( buildTasks ) );
647                 one( overallBuildQueue ).getBuildQueue();
648                 will( returnValue( buildQueue ) );
649                 one( buildQueue ).removeAll( buildTasks );
650 
651                 // get all queued checkout tasks & remove them
652                 one( overallBuildQueue ).getProjectsInCheckoutQueue();
653                 will( returnValue( checkoutTasks ) );
654                 one( overallBuildQueue ).getCheckoutQueue();
655                 will( returnValue( checkoutQueue ) );
656                 one( checkoutQueue ).removeAll( checkoutTasks );
657 
658                 // stop the build & checkout task queue executors
659                 one( overallBuildQueue ).getBuildTaskQueueExecutor();
660                 will( returnValue( buildTaskQueueExecutor ) );
661                 one( overallBuildQueue ).getCheckoutTaskQueueExecutor();
662                 will( returnValue( checkoutTaskQueueExecutor ) );
663 
664                 one( buildTaskQueueExecutor ).stop();
665                 one( checkoutTaskQueueExecutor ).stop();
666 
667                 // TODO: test scenario when there are no longer build queues configured aside from the one removed?
668                 //      - the behaviour should be that the default build queue will be used!
669 
670                 // re-queue projects in the build queue of the deleted overall build queue
671                 one( buildDefinitionDao ).getBuildDefinition( 1 );
672                 will( returnValue( buildDef ) );
673 
674                 // queue to other build queue
675                 exactly( 4 ).of( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
676                 will( returnValue( false ) );
677 
678                 exactly( 4 ).of( buildQueueExecutor ).getCurrentTask();
679                 will( returnValue( null ) );
680 
681                 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
682                 will( returnValue( projects ) );
683 
684                 one( configurationService ).getNumberOfBuildsInParallel();
685                 will( returnValue( 2 ) );
686 
687                 exactly( 2 ).of( overallBuildQueue ).getBuildQueue();
688                 will( returnValue( buildQueue ) );
689 
690                 exactly( 6 ).of( overallBuildQueue ).getBuildTaskQueueExecutor();
691                 will( returnValue( buildQueueExecutor ) );
692                 
693                 exactly( 2 ).of( buildQueue ).getQueueSnapshot();
694                 will( returnValue( tasks ) );
695 
696                 exactly( 2 ).of( buildQueueExecutor ).getCurrentTask();
697                 will( returnValue( null ) );
698                 
699                 one( overallBuildQueue ).getName();
700                 will( returnValue( "BUILD_QUEUE_2" ) );
701 
702                 recordAddToBuildQueue();
703 
704                 // re-queue projects in the checkout queue of the deleted overall build queue
705                 one( buildDefinitionDao ).getDefaultBuildDefinition( 2 );
706                 will( returnValue( buildDef ) );
707 
708                 // queue to other checkout queues
709                 exactly( 4 ).of( overallBuildQueue ).isInCheckoutQueue( with( any( int.class ) ) );
710                 will( returnValue( false ) );
711 
712                 one( configurationService ).getNumberOfBuildsInParallel();
713                 will( returnValue( 2 ) );
714 
715                 exactly( 2 ).of( overallBuildQueue ).getCheckoutQueue();
716                 will( returnValue( checkoutQueue ) );
717 
718                 exactly( 2 ).of( overallBuildQueue ).getCheckoutTaskQueueExecutor();
719                 will( returnValue( checkoutQueueExecutor ) );
720 
721                 exactly( 2 ).of( checkoutQueue ).getQueueSnapshot();
722                 will( returnValue( tasks ) );
723 
724                 exactly( 2 ).of( checkoutQueueExecutor ).getCurrentTask();
725                 will( returnValue( null ) );
726 
727                 one( overallBuildQueue ).getName();
728                 will( returnValue( "BUILD_QUEUE_2" ) );
729 
730                 recordAddToCheckoutQueue();
731             }} );
732 
733         buildsManager.removeOverallBuildQueue( 5 );
734         context.assertIsSatisfied();
735 
736         Map<Integer, OverallBuildQueue> overallBuildQueues = buildsManager.getOverallBuildQueues();
737         assertNull( overallBuildQueues.get( 5 ) );
738     }
739 
740     public void testRemoveOverallBuildQueueTasksCurrentlyExecuting()
741         throws Exception
742     {
743         setupMockOverallBuildQueues();
744 
745         final BuildDefinition buildDef = new BuildDefinition();
746         buildDef.setId( 1 );
747         buildDef.setSchedule( getSchedule( 1, 1, 2 ) );
748 
749         final TaskQueueExecutor buildQueueExecutor = context.mock( TaskQueueExecutor.class, "build-queue-executor" );
750         final Task buildTask = new BuildProjectTask( 1, 1, 1, "continuum-project-test-1", "BUILD_DEF", null, 1 );
751 
752         final List<BuildProjectTask> buildTasks = new ArrayList<BuildProjectTask>();
753         buildTasks.add( new BuildProjectTask( 2, 1, 1, "continuum-project-test-2", "BUILD_DEF", null, 2 ) );
754 
755         final List<CheckOutTask> checkoutTasks = new ArrayList<CheckOutTask>();
756         checkoutTasks.add(
757             new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ), "continuum-project-test-2",
758                               "dummy", "dummypass" ) );
759 
760         try
761         {
762             context.checking( new Expectations()
763             {
764                 {
765                     one( overallBuildQueue ).getName();
766                     will( returnValue( "BUILD_QUEUE_5" ) );
767 
768                     // check if there is any build task currently being executed
769                     one( overallBuildQueue ).getBuildTaskQueueExecutor();
770                     will( returnValue( buildQueueExecutor ) );
771                     one( buildQueueExecutor ).getCurrentTask();
772                     will( returnValue( buildTask ) );
773                 }} );
774 
775             buildsManager.removeOverallBuildQueue( 5 );
776             context.assertIsSatisfied();
777             fail( "An exception should have been thrown." );
778         }
779         catch ( BuildManagerException e )
780         {
781             assertEquals( "Cannot remove build queue. A task is currently executing.", e.getMessage() );
782         }
783     }
784 
785     public void testNoBuildQueuesConfigured()
786         throws Exception
787     {
788         overallBuildQueue = context.mock( OverallBuildQueue.class );
789 
790         Map<Integer, OverallBuildQueue> overallBuildQueues =
791             Collections.synchronizedMap( new HashMap<Integer, OverallBuildQueue>() );
792         overallBuildQueues.put( 1, overallBuildQueue );
793 
794         buildsManager.setOverallBuildQueues( overallBuildQueues );
795 
796         Schedule schedule = new Schedule();
797         schedule.setId( 1 );
798         schedule.setName( "DEFAULT_SCHEDULE" );
799         schedule.setCronExpression( "0 0 * * * ?" );
800         schedule.setDelay( 100 );
801         schedule.setMaxJobExecutionTime( 10000 );
802 
803         BuildDefinition buildDef = new BuildDefinition();
804         buildDef.setId( 1 );
805         buildDef.setSchedule( schedule );
806 
807         context.checking( new Expectations()
808         {
809             {
810                 one( overallBuildQueue ).isInBuildQueue( with( any( int.class ) ) );
811                 will( returnValue( false ) );
812 
813                 one( overallBuildQueue ).getBuildTaskQueueExecutor();
814                 will( returnValue( buildTaskQueueExecutor ) );
815 
816                 one( buildTaskQueueExecutor ).getCurrentTask();
817                 will( returnValue( null ) );
818 
819                 one( projectDao ).getProjectsInGroup( with( any( int.class ) ) );
820                 will( returnValue( projects ) );
821 
822                 one( configurationService ).getNumberOfBuildsInParallel();
823                 will( returnValue( 2 ) );
824 
825                 exactly( 2 ).of( overallBuildQueue ).getName();
826                 will( returnValue( ConfigurationService.DEFAULT_BUILD_QUEUE_NAME ) );
827 
828                 one( overallBuildQueue ).addToBuildQueue( with( any( BuildProjectTask.class ) ) );
829             }} );
830 
831         buildsManager.buildProject( 1, buildDef, "continuum-project-test-1", 1, null, 1 );
832         context.assertIsSatisfied();
833     }
834 
835     public void testGetProjectsInBuildQueue()
836         throws Exception
837     {
838         setupMockOverallBuildQueues();
839 
840         final List<Task> tasks = new ArrayList<Task>();
841         tasks.add( new BuildProjectTask( 2, 1, 1, "continuum-project-test-2", "BUILD_DEF", null, 2  ) );
842 
843         context.checking( new Expectations()
844         {
845             {
846                 exactly( 5 ).of( overallBuildQueue ).getName();
847                 will( returnValue( "BUILD_QUEUE" ) );
848 
849                 exactly( 5 ).of( overallBuildQueue ).getProjectsInBuildQueue();
850                 will( returnValue( tasks ) );
851             }} );
852 
853         buildsManager.getProjectsInBuildQueues();
854         context.assertIsSatisfied();
855     }
856 
857     public void testGetProjectsInCheckoutQueue()
858         throws Exception
859     {
860         setupMockOverallBuildQueues();
861 
862         final List<Task> tasks = new ArrayList<Task>();
863         tasks.add(
864             new CheckOutTask( 2, new File( getBasedir(), "/target/test-working-dir/1" ), "continuum-project-test-2",
865                               "dummy", "dummypass" ) );
866 
867         context.checking( new Expectations()
868         {
869             {
870                 exactly( 5 ).of( overallBuildQueue ).getName();
871                 will( returnValue( "BUILD_QUEUE" ) );
872 
873                 exactly( 5 ).of( overallBuildQueue ).getProjectsInCheckoutQueue();
874                 will( returnValue( tasks ) );
875             }} );
876 
877         buildsManager.getProjectsInCheckoutQueues();
878         context.assertIsSatisfied();
879     }
880 
881     /*
882     public void testNumOfAllowedParallelBuildsIsLessThanConfiguredBuildQueues()
883         throws Exception
884     {
885     
886     }
887     
888     public void testPrepareBuildProjects()
889         throws Exception
890     {
891     
892     }
893     
894     public void testRemoveProjectFromPrepareBuildQueue()
895         throws Exception
896     {
897 
898     }
899     */
900 }