1+ package com .baeldung .features ;
2+
3+ import jdk .incubator .concurrent .StructuredTaskScope ;
4+ import org .junit .jupiter .api .Test ;
5+
6+ import java .time .Instant ;
7+ import java .util .List ;
8+ import java .util .concurrent .*;
9+
10+ import static org .assertj .core .api .AssertionsForClassTypes .assertThat ;
11+ import static org .assertj .core .api .AssertionsForClassTypes .assertThatThrownBy ;
12+
13+ public class JEP428StructuredConcurrencyUnitTest {
14+
15+ private static final String ERROR_MESSAGE = "Failed to get the result" ;
16+
17+ @ Test
18+ public void givenStructuredConcurrency_whenThrowingException_thenCorrect () {
19+ assertThatThrownBy (() -> {
20+ try (var scope = new StructuredTaskScope .ShutdownOnFailure ()) {
21+ Future <Shelter > shelter = scope .fork (this ::getShelter );
22+ Future <List <Dog >> dogs = scope .fork (this ::getDogsWithException );
23+ scope .throwIfFailed (e -> new RuntimeException (ERROR_MESSAGE ));
24+ scope .join ();
25+ Response response = new Response (shelter .resultNow (), dogs .resultNow ());
26+
27+ assertThat (response ).isNotNull ();
28+ assertThat (response .shelter ()).isNotNull ();
29+ assertThat (response .dogs ()).isNotNull ();
30+ assertThat (response .dogs ().size ()).isEqualTo (2 );
31+ }
32+ }).isInstanceOf (RuntimeException .class )
33+ .hasMessage (ERROR_MESSAGE );
34+ }
35+
36+ @ Test
37+ public void givenStructuredConcurrency_whenSlowTasksReachesDeadline_thenCorrect () {
38+ assertThatThrownBy (() -> {
39+ try (var scope = new StructuredTaskScope .ShutdownOnFailure ()) {
40+ Future <Shelter > shelter = scope .fork (this ::getShelter );
41+ Future <List <Dog >> dogs = scope .fork (this ::getDogsSlowly );
42+ scope .throwIfFailed (e -> new RuntimeException (ERROR_MESSAGE ));
43+ scope .join ();
44+ scope .joinUntil (Instant .now ().plusMillis (50 ));
45+ Response response = new Response (shelter .resultNow (), dogs .resultNow ());
46+
47+ assertThat (response ).isNotNull ();
48+ assertThat (response .shelter ()).isNotNull ();
49+ assertThat (response .dogs ()).isNotNull ();
50+ assertThat (response .dogs ().size ()).isEqualTo (2 );
51+
52+ } catch (InterruptedException e ) {
53+ throw new RuntimeException (e );
54+ }
55+ }).isInstanceOf (IllegalStateException .class );
56+ }
57+
58+ @ Test
59+ public void givenStructuredConcurrency_whenResultNow_thenCorrect () {
60+ try (var scope = new StructuredTaskScope .ShutdownOnFailure ()) {
61+ Future <Shelter > shelter = scope .fork (this ::getShelter );
62+ Future <List <Dog >> dogs = scope .fork (this ::getDogs );
63+ scope .join ();
64+
65+ Response response = new Response (shelter .resultNow (), dogs .resultNow ());
66+
67+ assertThat (response ).isNotNull ();
68+ assertThat (response .shelter ()).isNotNull ();
69+ assertThat (response .dogs ()).isNotNull ();
70+ assertThat (response .dogs ().size ()).isEqualTo (2 );
71+ } catch (InterruptedException e ) {
72+ throw new RuntimeException (e );
73+ }
74+ }
75+
76+ @ Test
77+ public void givenUnstructuredConcurrency_whenGet_thenCorrect () {
78+ Future <Shelter > shelter ;
79+ Future <List <Dog >> dogs ;
80+ try (ExecutorService executorService = Executors .newFixedThreadPool (3 )) {
81+ shelter = executorService .submit (this ::getShelter );
82+ dogs = executorService .submit (this ::getDogs );
83+ Shelter theShelter = shelter .get (); // Join the shelter
84+ List <Dog > theDogs = dogs .get (); // Join the dogs
85+ Response response = new Response (theShelter , theDogs );
86+
87+ assertThat (response ).isNotNull ();
88+ assertThat (response .shelter ()).isNotNull ();
89+ assertThat (response .dogs ()).isNotNull ();
90+ assertThat (response .dogs ().size ()).isEqualTo (2 );
91+
92+ } catch (ExecutionException | InterruptedException e ) {
93+ throw new RuntimeException (e );
94+ }
95+ }
96+
97+ private Shelter getShelter () {
98+ return new Shelter ("Shelter" );
99+ }
100+
101+ private List <Dog > getDogs () {
102+ return List .of (new Dog ("Buddy" ), new Dog ("Simba" ));
103+ }
104+
105+ private List <Dog > getDogsWithException () {
106+ throw new RuntimeException (ERROR_MESSAGE );
107+ }
108+
109+ private List <Dog > getDogsSlowly () throws InterruptedException {
110+ Thread .sleep (1500 );
111+ throw new RuntimeException (ERROR_MESSAGE );
112+ }
113+
114+ record Shelter (String name ) {
115+ }
116+
117+ record Dog (String name ) {
118+ }
119+
120+ record Response (Shelter shelter , List <Dog > dogs ) {
121+ }
122+ }
0 commit comments