package com.linkedin.parseq.internal; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; import static org.testng.Assert.fail; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import org.testng.annotations.Test; public class TestContinuations { @Test public void testActionCalled() { final AtomicBoolean action = new AtomicBoolean(false); Continuations CONT = new Continuations(); CONT.doSubmit(() -> { action.set(true); }); assertTrue(action.get()); } @Test public void testOnSuccessCalled() { final AtomicInteger sequence = new AtomicInteger(0); final AtomicInteger action = new AtomicInteger(); final AtomicInteger onSuccess = new AtomicInteger(); Continuations CONT = new Continuations(); CONT.doSubmit(() -> { action.set(sequence.incrementAndGet()); }); CONT.doSubmit(() -> { onSuccess.set(sequence.incrementAndGet()); }); assertEquals(action.get(), 1); assertEquals(onSuccess.get(), 2); } @Test public void testOnSuccessNotCalledWhenException() { final AtomicInteger sequence = new AtomicInteger(0); final AtomicInteger onSuccess = new AtomicInteger(); Continuations CONT = new Continuations(); try { CONT.doSubmit(() -> { throw new RuntimeException("test"); }); CONT.doSubmit(() -> { onSuccess.set(sequence.incrementAndGet()); }); fail("should have thrown exception"); } catch (Exception e) { assertEquals(e.getMessage(), "test"); } assertEquals(onSuccess.get(), 0); } @Test public void testRecursiveOrder() { final Continuations CONT = new Continuations(); final StringBuilder result = new StringBuilder(); CONT.doSubmit(() -> { result.append("BEGIN{"); recursivePostOrder(CONT, result, "root", 0); }); CONT.doSubmit(() -> { result.append("}END"); }); assertEquals(result.toString(), "BEGIN{[done(rootLL:2)][done(rootLR:2)][done(rootL:1)][done(rootRL:2)][done(rootRR:2)][done(rootR:1)][done(root:0)]}END"); } private void recursivePostOrder(final Continuations CONT, final StringBuilder result, final String branch, final int depth) { CONT.doSubmit(() -> { if (depth < 2) { recursivePostOrder(CONT, result, branch + "L", depth + 1); recursivePostOrder(CONT, result, branch + "R", depth + 1); } }); CONT.doSubmit(() -> { result.append("[done(" + branch + ":" + depth + ")]"); }); } @Test public void testRecursiveOrderWithException() { final Continuations CONT = new Continuations(); final StringBuilder result = new StringBuilder(); try { CONT.doSubmit(() -> { result.append("BEGIN{"); recursivePostOrderWithException(CONT, result, "root", 0); }); CONT.doSubmit(() -> { result.append("}END"); }); fail("should have thrown exception"); } catch (Exception e) { assertEquals(e.getMessage(), "nested"); } assertEquals(result.toString(), "BEGIN{[done(rootLL:2)][done(rootLR:2)][done(rootL:1)][done(rootRL:2)]"); } private void recursivePostOrderWithException(final Continuations CONT, final StringBuilder result, final String branch, final int depth) { CONT.doSubmit(() -> { if (depth < 2) { recursivePostOrderWithException(CONT, result, branch + "L", depth + 1); recursivePostOrderWithException(CONT, result, branch + "R", depth + 1); } else { if (branch.equals("rootRR")) { throw new RuntimeException("nested"); } } }); CONT.doSubmit(() -> { result.append("[done(" + branch + ":" + depth + ")]"); }); } @Test public void testDeepRecursion() { final Continuations CONT = new Continuations(); final AtomicInteger result = new AtomicInteger(); CONT.doSubmit(() -> { deepRecursion(CONT, result, 0); }); assertEquals(result.get(), 1000001); } private void deepRecursion(final Continuations CONT, final AtomicInteger result, final int depth) { CONT.doSubmit(() -> { if (depth < 1000000) { deepRecursion(CONT, result, depth + 1); } }); CONT.doSubmit(() -> { result.incrementAndGet(); }); } }