4040import java .util .concurrent .ExecutionException ;
4141import java .util .concurrent .Executor ;
4242import java .util .concurrent .ExecutorService ;
43+ import java .util .concurrent .Executors ;
4344import java .util .concurrent .ForkJoinPool ;
4445import java .util .concurrent .RejectedExecutionException ;
4546import java .util .concurrent .SynchronousQueue ;
5051import java .util .concurrent .atomic .AtomicReference ;
5152import java .util .function .Function ;
5253import org .assertj .core .api .IterableAssert ;
54+ import org .junit .jupiter .api .Nested ;
5355import org .junit .jupiter .api .Test ;
5456import org .junit .jupiter .api .extension .AfterEachCallback ;
5557import org .junit .jupiter .api .extension .BeforeEachCallback ;
5961import static io .vavr .concurrent .Concurrent .waitUntil ;
6062import static io .vavr .concurrent .Concurrent .zZz ;
6163import static java .util .concurrent .TimeUnit .MILLISECONDS ;
64+ import static org .assertj .core .api .Assertions .assertThatThrownBy ;
6265import static org .junit .jupiter .api .Assertions .assertThrows ;
6366
6467@ SuppressWarnings ("deprecation" )
@@ -112,7 +115,8 @@ protected <T> IterableAssert<T> assertThat(Iterable<T> actual) {
112115 @ Override
113116 public IterableAssert <T > isEqualTo (Object expected ) {
114117 if (actual instanceof Future && expected instanceof Future ) {
115- FutureTest .super .assertThat (((Future <T >) actual ).getValue ()).isEqualTo (((Future <T >) expected ).getValue ());
118+ FutureTest .super .assertThat (((Future <T >) actual ).getValue ())
119+ .isEqualTo (((Future <T >) expected ).getValue ());
116120 return this ;
117121 } else {
118122 return super .isEqualTo (expected );
@@ -487,7 +491,7 @@ public void shouldReduceSequenceOfFutures() {
487491 public void shouldReduceWithErrorIfSequenceOfFuturesContainsOneError () {
488492 final Future <Integer > future = Future .reduce (
489493 List .of (Future .of (zZz (13 )), Future .of (zZz (new Error ()))),
490- ( i1 , i2 ) -> i1 + i2
494+ Integer :: sum
491495 ).await ();
492496 assertFailed (future , Error .class );
493497 }
@@ -692,46 +696,29 @@ public void shouldFallbackToThisFailure() {
692696 @ Test
693697 public void shouldFoldEmptyIterable () {
694698 final Seq <Future <Integer >> futures = Stream .empty ();
695- final Future <Integer > testee = Future .fold (futures , 0 , ( a , b ) -> a + b ).await ();
699+ final Future <Integer > testee = Future .fold (futures , 0 , Integer :: sum ).await ();
696700 assertThat (testee .getValue ().get ()).isEqualTo (Try .success (0 ));
697701 }
698702
699703 @ Test
700704 public void shouldFoldNonEmptyIterableOfSucceedingFutures () {
701705 final Seq <Future <Integer >> futures = Stream .from (1 ).map (i -> Future .of (zZz (i ))).take (5 );
702- final Future <Integer > testee = Future .fold (futures , 0 , ( a , b ) -> a + b ).await ();
706+ final Future <Integer > testee = Future .fold (futures , 0 , Integer :: sum ).await ();
703707 assertThat (testee .getValue ().get ()).isEqualTo (Try .success (15 ));
704708 }
705709
706710 @ Test
707711 public void shouldFoldNonEmptyIterableOfFailingFutures () {
708712 final Seq <Future <Integer >> futures = Stream .from (1 ).map (i -> Future .<Integer >of (zZz (new Error ()))).take (5 );
709- final Future <Integer > testee = Future .fold (futures , 0 , ( a , b ) -> a + b ).await ();
713+ final Future <Integer > testee = Future .fold (futures , 0 , Integer :: sum ).await ();
710714 assertFailed (testee , Error .class );
711715 }
712716
713- // -- cancel()
714-
715- @ Test
716- public void shouldInterruptLockedFuture () {
717- final Object monitor = new Object ();
718- final AtomicBoolean running = new AtomicBoolean (false );
719- final Future <?> future = blocking (() -> {
720- synchronized (monitor ) {
721- running .set (true );
722- monitor .wait (); // wait forever
723- }
724- });
725- waitUntil (running ::get );
726- synchronized (monitor ) {
727- future .cancel ();
728- }
729- assertThat (future .isCancelled ()).isTrue ();
730- }
731-
732- @ Test
733- public void shouldThrowOnGetAfterCancellation () {
734- assertThrows (CancellationException .class , () -> {
717+ @ Nested
718+ public class CancellationTests {
719+
720+ @ Test
721+ public void shouldInterruptLockedFuture () {
735722 final Object monitor = new Object ();
736723 final AtomicBoolean running = new AtomicBoolean (false );
737724 final Future <?> future = blocking (() -> {
@@ -745,21 +732,67 @@ public void shouldThrowOnGetAfterCancellation() {
745732 future .cancel ();
746733 }
747734 assertThat (future .isCancelled ()).isTrue ();
748- future .get ();
749- });
750- }
735+ }
751736
752- @ Test
753- public void shouldCancelFutureThatNeverCompletes () {
754- @ SuppressWarnings ("deprecation" ) final Future <?> future = Future .run (complete -> {
755- // we break our promise, the Future is never completed
756- });
737+ @ Test
738+ public void shouldThrowOnGetAfterCancellation () {
739+ assertThrows (CancellationException .class , () -> {
740+ final Object monitor = new Object ();
741+ final AtomicBoolean running = new AtomicBoolean (false );
742+ final Future <?> future = blocking (() -> {
743+ synchronized (monitor ) {
744+ running .set (true );
745+ monitor .wait (); // wait forever
746+ }
747+ });
748+ waitUntil (running ::get );
749+ synchronized (monitor ) {
750+ future .cancel ();
751+ }
752+ assertThat (future .isCancelled ()).isTrue ();
753+ future .get ();
754+ });
755+ }
757756
758- assertThat (future .isCompleted ()).isFalse ();
759- assertThat (future .isCancelled ()).isFalse ();
757+ @ Test
758+ public void shouldCancelFutureThatNeverCompletes () {
759+ @ SuppressWarnings ("deprecation" ) final Future <?> future = Future .run (complete -> {
760+ // we break our promise, the Future is never completed
761+ });
760762
761- assertThat (future .cancel ()).isTrue ();
762- assertThat (future .isCompleted ()).isTrue ();
763+ assertThat (future .isCompleted ()).isFalse ();
764+ assertThat (future .isCancelled ()).isFalse ();
765+
766+ assertThat (future .cancel ()).isTrue ();
767+ assertThat (future .isCompleted ()).isTrue ();
768+ }
769+
770+ @ Test
771+ void shouldNotRunCancelledFuture () {
772+ ExecutorService es = Executors .newSingleThreadExecutor ();
773+
774+ AtomicBoolean f1Executed = new AtomicBoolean (false );
775+ AtomicBoolean f2Executed = new AtomicBoolean (false );
776+
777+ Future <Void > f1 = Future .run (es , () -> {Thread .sleep (10000 );f1Executed .set (true );});
778+ Future <Void > f2 = Future .run (es , () -> {f2Executed .set (true );Thread .sleep (10000 );});
779+
780+ f2 .cancel (true );
781+ f1 .cancel (true );
782+
783+ f1 .await ();
784+ f2 .await ();
785+
786+ assertThat (f1 .isCancelled ()).isTrue ();
787+ assertThat (f2 .isCancelled ()).isTrue ();
788+
789+ assertThat (f1 .isFailure ()).isTrue ();
790+ assertThat (f2 .isFailure ()).isTrue ();
791+ assertThatThrownBy (f1 ::get ).isInstanceOf (CancellationException .class );
792+ assertThatThrownBy (f2 ::get ).isInstanceOf (CancellationException .class );
793+ assertThat (f1Executed .get ()).isFalse ();
794+ assertThat (f2Executed .get ()).isFalse ();
795+ }
763796 }
764797
765798 // -- collect()
0 commit comments