@@ -272,23 +272,26 @@ void invokeAllQueueEntriesSkipsOverUnavailableResources() throws Exception {
272272 var resourceLock = new SingleLock (exclusiveResource (LockMode .READ_WRITE ), new ReentrantLock ());
273273
274274 var lockFreeChildrenStarted = new CountDownLatch (2 );
275- var child4Started = new CountDownLatch (1 );
275+ var child2Started = new CountDownLatch (1 );
276276
277277 Executable child1Behaviour = () -> {
278278 lockFreeChildrenStarted .countDown ();
279- child4Started .await ();
279+ child2Started .await ();
280280 };
281- Executable child4Behaviour = () -> {
282- child4Started .countDown ();
281+ Executable child2Behaviour = () -> {
282+ child2Started .countDown ();
283283 lockFreeChildrenStarted .await ();
284284 };
285285
286286 var child1 = new TestTaskStub (ExecutionMode .CONCURRENT , child1Behaviour ) //
287287 .withName ("child1" );
288- var child2 = new TestTaskStub (ExecutionMode .CONCURRENT ).withResourceLock (resourceLock ) //
289- .withName ("child2" ); //
290- var child3 = new TestTaskStub (ExecutionMode .CONCURRENT , lockFreeChildrenStarted ::countDown ).withName ("child3" );
291- var child4 = new TestTaskStub (ExecutionMode .CONCURRENT , child4Behaviour ).withResourceLock (resourceLock ) //
288+ var child2 = new TestTaskStub (ExecutionMode .CONCURRENT , child2Behaviour ) //
289+ .withResourceLock (resourceLock ) //
290+ .withName ("child2" );
291+ var child3 = new TestTaskStub (ExecutionMode .CONCURRENT ) //
292+ .withResourceLock (resourceLock ) //
293+ .withName ("child3" ); //
294+ var child4 = new TestTaskStub (ExecutionMode .CONCURRENT , lockFreeChildrenStarted ::countDown ) //
292295 .withName ("child4" );
293296 var children = List .of (child1 , child2 , child3 , child4 );
294297 var root = new TestTaskStub (ExecutionMode .CONCURRENT , () -> requiredService ().invokeAll (children )) //
@@ -298,8 +301,8 @@ void invokeAllQueueEntriesSkipsOverUnavailableResources() throws Exception {
298301
299302 root .assertExecutedSuccessfully ();
300303 assertThat (children ).allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
301- assertThat (child1 .executionThread ).isEqualTo (child3 .executionThread );
302- assertThat (child2 .startTime ).isAfterOrEqualTo (child3 .startTime );
304+ assertThat (child1 .executionThread ).isEqualTo (child4 .executionThread );
305+ assertThat (child3 .startTime ).isAfterOrEqualTo (child4 .startTime );
303306 }
304307
305308 @ Test
@@ -315,7 +318,7 @@ void prioritizesChildrenOfStartedContainers() throws Exception {
315318 var leaf = new TestTaskStub (ExecutionMode .CONCURRENT , leavesStarted ::countDown ) //
316319 .withName ("leaf" ).withLevel (3 );
317320 var child3 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> requiredService ().submit (leaf ).get ()) //
318- .withName ("child3" ).withLevel (2 );
321+ .withType ( CONTAINER ). withName ("child3" ).withLevel (2 );
319322
320323 var root = new TestTaskStub (ExecutionMode .SAME_THREAD ,
321324 () -> requiredService ().invokeAll (List .of (child1 , child2 , child3 ))) //
@@ -453,33 +456,6 @@ public void release() {
453456 void executesChildrenInOrder () throws Exception {
454457 service = new WorkerThreadPoolHierarchicalTestExecutorService (configuration (1 , 1 ));
455458
456- var leaf1a = new TestTaskStub (ExecutionMode .CONCURRENT ) //
457- .withName ("leaf1a" ).withLevel (2 );
458- var leaf1b = new TestTaskStub (ExecutionMode .CONCURRENT ) //
459- .withName ("leaf1b" ).withLevel (2 );
460- var leaf1c = new TestTaskStub (ExecutionMode .CONCURRENT ) //
461- .withName ("leaf1c" ).withLevel (2 );
462- var leaf1d = new TestTaskStub (ExecutionMode .CONCURRENT ) //
463- .withName ("leaf1d" ).withLevel (2 );
464-
465- var root = new TestTaskStub (ExecutionMode .SAME_THREAD ,
466- () -> requiredService ().invokeAll (List .of (leaf1a , leaf1b , leaf1c , leaf1d ))) //
467- .withName ("root" ).withLevel (1 );
468-
469- service .submit (root ).get ();
470-
471- assertThat (List .of (root , leaf1a , leaf1b , leaf1c , leaf1d )) //
472- .allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
473-
474- assertThat (Stream .of (leaf1a , leaf1b , leaf1c , leaf1d )) //
475- .extracting (TestTaskStub ::startTime ) //
476- .isSorted ();
477- }
478-
479- @ Test
480- void executesChildrenInInvokeAllOrder () throws Exception {
481- service = new WorkerThreadPoolHierarchicalTestExecutorService (configuration (1 , 1 ));
482-
483459 var leaf1a = new TestTaskStub (ExecutionMode .CONCURRENT ) //
484460 .withName ("leaf1a" ).withLevel (2 );
485461 var leaf1b = new TestTaskStub (ExecutionMode .CONCURRENT ) //
@@ -507,52 +483,52 @@ void executesChildrenInInvokeAllOrder() throws Exception {
507483 }
508484
509485 @ Test
510- void workIsStolenInReverseOrder () throws Exception {
486+ void testsAreStolenRatherThanContainers () throws Exception {
511487 service = new WorkerThreadPoolHierarchicalTestExecutorService (configuration (2 , 2 ));
512488
513489 // Execute tasks pairwise
514490 CyclicBarrier cyclicBarrier = new CyclicBarrier (2 );
515491 Executable behavior = cyclicBarrier ::await ;
516492
517- // With half of the leaves to be executed normally
518- var leaf1a = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
519- .withName ("leaf1a" ).withLevel (2 );
520- var leaf1b = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
521- .withName ("leaf1b" ).withLevel (2 );
522- var leaf1c = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
523- .withName ("leaf1c" ).withLevel (2 );
524-
525- // And half of the leaves to be stolen
526- var leaf2a = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
527- .withName ("leaf2a" ).withLevel (2 );
528- var leaf2b = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
529- .withName ("leaf2b" ).withLevel (2 );
530- var leaf2c = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
531- .withName ("leaf2c" ).withLevel (2 );
493+ // With half of the leaves being containers
494+ var container1 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
495+ .withName ("container1" ). withType ( CONTAINER ).withLevel (2 );
496+ var container2 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
497+ .withName ("container2" ). withType ( CONTAINER ).withLevel (2 );
498+ var container3 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
499+ .withName ("container3" ). withType ( CONTAINER ).withLevel (2 );
500+
501+ // And half of the leaves being tests, to be stolen
502+ var test1 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
503+ .withName ("test1" ). withType ( TEST ).withLevel (2 );
504+ var test2 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
505+ .withName ("test2" ). withType ( TEST ).withLevel (2 );
506+ var test3 = new TestTaskStub (ExecutionMode .CONCURRENT , behavior ) //
507+ .withName ("test3" ). withType ( TEST ).withLevel (2 );
532508
533509 var root = new TestTaskStub (ExecutionMode .SAME_THREAD ,
534- () -> requiredService ().invokeAll (List .of (leaf1a , leaf1b , leaf1c , leaf2a , leaf2b , leaf2c ))) //
510+ () -> requiredService ().invokeAll (List .of (container1 , container2 , container3 , test1 , test2 , test3 ))) //
535511 .withName ("root" ).withLevel (1 );
536512
537513 service .submit (root ).get ();
538514
539- assertThat (List .of (root , leaf1a , leaf1b , leaf1c , leaf2a , leaf2b , leaf2c )) //
515+ assertThat (List .of (root , container1 , container2 , container3 , test1 , test2 , test3 )) //
540516 .allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
541517
542- // If the last node was stolen.
543- assertThat (leaf1a .executionThread ).isNotEqualTo (leaf2c .executionThread );
544- // Then it must follow that the last half of the nodes were stolen
545- assertThat (Stream .of (leaf1a , leaf1b , leaf1c )) //
518+ // If the last test node was stolen
519+ assertThat (container1 .executionThread ).isNotEqualTo (test3 .executionThread );
520+ // Then it must follow that the test nodes were stolen
521+ assertThat (Stream .of (container1 , container2 , container3 )) //
546522 .extracting (TestTaskStub ::executionThread ) //
547- .containsOnly (leaf1a .executionThread );
548- assertThat (Stream .of (leaf2a , leaf2b , leaf2c )) //
523+ .containsOnly (container1 .executionThread );
524+ assertThat (Stream .of (test1 , test2 , test3 )) //
549525 .extracting (TestTaskStub ::executionThread ) //
550- .containsOnly (leaf2c .executionThread );
526+ .containsOnly (test3 .executionThread );
551527
552- assertThat (Stream .of (leaf1a , leaf1b , leaf1c )) //
528+ assertThat (Stream .of (container1 , container2 , container3 )) //
553529 .extracting (TestTaskStub ::startTime ) //
554530 .isSorted ();
555- assertThat (Stream .of (leaf2c , leaf2b , leaf2a )) //
531+ assertThat (Stream .of (test1 , test2 , test3 )) //
556532 .extracting (TestTaskStub ::startTime ) //
557533 .isSorted ();
558534 }
@@ -587,6 +563,45 @@ void stealsDynamicChildren() throws Exception {
587563 assertThat (child2 .executionThread ).isEqualTo (root .executionThread ).isNotEqualTo (child1 .executionThread );
588564 }
589565
566+ @ Test
567+ void stealsDynamicChildrenInOrder () throws Exception {
568+ service = new WorkerThreadPoolHierarchicalTestExecutorService (configuration (2 , 2 ));
569+
570+ var child1Started = new CountDownLatch (1 );
571+ var childrenSubmitted = new CountDownLatch (1 );
572+ var childrenFinished = new CountDownLatch (2 );
573+ var child1 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
574+ child1Started .countDown ();
575+ childrenSubmitted .await ();
576+ }) //
577+ .withName ("child1" ).withLevel (2 );
578+ var child2 = new TestTaskStub (ExecutionMode .CONCURRENT , childrenFinished ::countDown ) //
579+ .withName ("child2" ).withLevel (2 );
580+ var child3 = new TestTaskStub (ExecutionMode .CONCURRENT , childrenFinished ::countDown ) //
581+ .withName ("child3" ).withLevel (2 );
582+
583+ var root = new TestTaskStub (ExecutionMode .SAME_THREAD , () -> {
584+ var future1 = requiredService ().submit (child1 );
585+ child1Started .await ();
586+ var future2 = requiredService ().submit (child2 );
587+ var future3 = requiredService ().submit (child3 );
588+ childrenSubmitted .countDown ();
589+ childrenFinished .await ();
590+ future1 .get ();
591+ future2 .get ();
592+ future3 .get ();
593+ }) //
594+ .withName ("root" ).withLevel (1 );
595+
596+ service .submit (root ).get ();
597+
598+ assertThat (Stream .of (root , child1 , child2 , child3 )) //
599+ .allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
600+ assertThat (List .of (child1 , child2 , child3 )) //
601+ .extracting (TestTaskStub ::startTime ) //
602+ .isSorted ();
603+ }
604+
590605 @ Test
591606 void executesDynamicChildrenInSubmitOrder () throws Exception {
592607 service = new WorkerThreadPoolHierarchicalTestExecutorService (configuration (1 , 1 ));
@@ -686,27 +701,27 @@ void stealsSiblingDynamicChildrenOnly() throws Exception {
686701 var leaf1ASubmitted = new CountDownLatch (1 );
687702 var leaf1AStarted = new CountDownLatch (1 );
688703
689- var leaf1a = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
690- leaf1AStarted .countDown ();
691- child2Started .await ();
692- }) //
693- .withName ("leaf1a" ).withLevel (3 );
694-
695704 var child1 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
696705 child1Started .countDown ();
697706 leaf1ASubmitted .await ();
698707 }) //
699708 .withName ("child1" ).withLevel (2 );
700709
701- var child2 = new TestTaskStub (ExecutionMode .CONCURRENT , child2Started ::countDown ) //
702- .withName ("child2" ).withLevel (2 );
710+ var leaf1a = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
711+ leaf1AStarted .countDown ();
712+ child2Started .await ();
713+ }) //
714+ .withName ("leaf1a" ).withLevel (3 );
703715
704- var child3 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
716+ var child2 = new TestTaskStub (ExecutionMode .CONCURRENT , () -> {
705717 var futureA = requiredService ().submit (leaf1a );
706718 leaf1ASubmitted .countDown ();
707719 leaf1AStarted .await ();
708720 futureA .get ();
709721 }) //
722+ .withName ("child2" ).withType (CONTAINER ).withLevel (2 );
723+
724+ var child3 = new TestTaskStub (ExecutionMode .CONCURRENT , child2Started ::countDown ) //
710725 .withName ("child3" ).withLevel (2 );
711726
712727 var root = new TestTaskStub (ExecutionMode .SAME_THREAD , () -> {
@@ -715,18 +730,18 @@ void stealsSiblingDynamicChildrenOnly() throws Exception {
715730 var future2 = requiredService ().submit (child2 );
716731 var future3 = requiredService ().submit (child3 );
717732 future1 .get ();
718- future2 .get ();
719733 future3 .get ();
734+ future2 .get ();
720735 }) //
721736 .withName ("root" ).withLevel (1 );
722737
723738 service .submit (root ).get ();
724739
725- assertThat (Stream .of (root , child1 , child2 , child3 , leaf1a )) //
740+ assertThat (Stream .of (root , child1 , child3 , child2 , leaf1a )) //
726741 .allSatisfy (TestTaskStub ::assertExecutedSuccessfully );
727742
728- assertThat (child3 .executionThread ).isNotEqualTo (child1 .executionThread ).isNotEqualTo (child2 .executionThread );
729- assertThat (child1 .executionThread ).isNotEqualTo (child2 .executionThread );
743+ assertThat (child2 .executionThread ).isNotEqualTo (child1 .executionThread ).isNotEqualTo (child3 .executionThread );
744+ assertThat (child1 .executionThread ).isNotEqualTo (child3 .executionThread );
730745 assertThat (child1 .executionThread ).isEqualTo (leaf1a .executionThread );
731746 }
732747
0 commit comments