1313
1414import java .util .concurrent .CompletableFuture ;
1515import java .util .concurrent .CountDownLatch ;
16+ import java .util .concurrent .Executor ;
1617import java .util .concurrent .ExecutorService ;
18+ import java .util .concurrent .Executors ;
19+ import java .util .concurrent .atomic .AtomicInteger ;
1720
21+ import static com .jnape .palatable .lambda .adt .Either .left ;
22+ import static com .jnape .palatable .lambda .adt .Either .right ;
1823import static com .jnape .palatable .lambda .adt .Unit .UNIT ;
1924import static com .jnape .palatable .lambda .functions .builtin .fn2 .Tupler2 .tupler ;
2025import static com .jnape .palatable .lambda .functions .builtin .fn3 .Times .times ;
2328import static java .util .concurrent .CompletableFuture .completedFuture ;
2429import static java .util .concurrent .Executors .newFixedThreadPool ;
2530import static java .util .concurrent .ForkJoinPool .commonPool ;
31+ import static org .junit .Assert .assertArrayEquals ;
2632import static org .junit .Assert .assertEquals ;
33+ import static org .junit .Assert .fail ;
2734import static testsupport .Constants .STACK_EXPLODING_NUMBER ;
2835
2936@ RunWith (Traits .class )
@@ -174,6 +181,66 @@ public IO<Integer> checkedApply(IO<Integer> a) {
174181 return a .flatMap (x -> x < STACK_EXPLODING_NUMBER ? apply (io (x + 1 )) : io (x ));
175182 }
176183 }.apply (io (0 )).unsafePerformAsyncIO ().join ());
184+ }
185+
186+ @ Test
187+ public void safe () {
188+ assertEquals (right (1 ), io (() -> 1 ).safe ().unsafePerformIO ());
189+ IllegalStateException thrown = new IllegalStateException ("kaboom" );
190+ assertEquals (left (thrown ), io (() -> {throw thrown ;}).safe ().unsafePerformIO ());
191+ }
192+
193+ @ Test
194+ public void ensuring () {
195+ AtomicInteger counter = new AtomicInteger (0 );
196+ IO <Integer > incCounter = io (counter ::incrementAndGet );
197+ assertEquals ("foo" , io (() -> "foo" ).ensuring (incCounter ).unsafePerformIO ());
198+ assertEquals (1 , counter .get ());
199+
200+ IllegalStateException thrown = new IllegalStateException ("kaboom" );
201+ try {
202+ io (() -> {throw thrown ;}).ensuring (incCounter ).unsafePerformIO ();
203+ fail ("Expected exception to have been thrown, but wasn't." );
204+ } catch (IllegalStateException actual ) {
205+ assertEquals (thrown , actual );
206+ assertEquals (2 , counter .get ());
207+ }
208+ }
177209
210+ @ Test
211+ public void ensuringRunsStrictlyAfterIO () {
212+ Executor twoThreads = Executors .newFixedThreadPool (2 );
213+ AtomicInteger counter = new AtomicInteger (0 );
214+ io (() -> {
215+ Thread .sleep (100 );
216+ counter .incrementAndGet ();
217+ }).ensuring (io (() -> {
218+ if (counter .get () == 0 )
219+ fail ("Expected to run after initial IO, but ran first" );
220+ })).unsafePerformAsyncIO (twoThreads ).join ();
221+ }
222+
223+ @ Test
224+ public void ensuringAttachesThrownExceptionToThrownBodyException () {
225+ IllegalStateException thrownByBody = new IllegalStateException ("kaboom" );
226+ IllegalStateException thrownByEnsuring = new IllegalStateException ("KABOOM" );
227+
228+ try {
229+ io (() -> {throw thrownByBody ;}).ensuring (io (() -> {throw thrownByEnsuring ;})).unsafePerformIO ();
230+ fail ("Expected exception to have been thrown, but wasn't." );
231+ } catch (IllegalStateException actual ) {
232+ assertEquals (thrownByBody , actual );
233+ assertArrayEquals (new Throwable []{thrownByEnsuring }, actual .getSuppressed ());
234+ }
235+ }
236+
237+ @ Test
238+ public void throwing () {
239+ IllegalStateException expected = new IllegalStateException ("thrown" );
240+ try {
241+ IO .throwing (expected ).unsafePerformIO ();
242+ } catch (IllegalStateException actual ) {
243+ assertEquals (expected , actual );
244+ }
178245 }
179246}
0 commit comments