package com.linkedin.parseq.internal;
import com.linkedin.parseq.BaseEngineTest;
import com.linkedin.parseq.EngineBuilder;
import com.linkedin.parseq.Task;
import com.linkedin.parseq.trace.ResultType;
import com.linkedin.parseq.trace.ShallowTrace;
import com.linkedin.parseq.trace.Trace;
import java.util.Optional;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.testng.Assert;
import org.testng.annotations.Test;
import static com.linkedin.parseq.Task.value;
/**
* @author Ang Xu
*/
public class TestPlanCompletionListener extends BaseEngineTest {
private TraceCaptureListener _traceCaptureListener;
@Override
protected void customizeEngine(EngineBuilder engineBuilder) {
_traceCaptureListener = new TraceCaptureListener();
engineBuilder.setPlanCompletionListener(_traceCaptureListener);
}
@Test
public void testSingleTask() {
Task<?> task = value("taskName", "value").andThen(value("value2"));
runAndWait(task);
Assert.assertTrue(_traceCaptureListener.isDone());
}
@Test
public void testUnfinishedTask() {
Task<?> task = value("unFinished", "value");
Assert.assertFalse(_traceCaptureListener.isDone());
}
@Test
public void testWithTimerTask() {
Task<?> task = delayedValue("value", 1000, TimeUnit.MILLISECONDS).withTimeout(50, TimeUnit.MILLISECONDS);
runAndWaitException(task, TimeoutException.class);
Assert.assertTrue(_traceCaptureListener.isDone());
Trace trace = _traceCaptureListener.getTrace();
Assert.assertNotNull(trace);
Optional<ShallowTrace> timerTrace = findTraceByName(trace, "withTimeout");
Assert.assertTrue(timerTrace.isPresent());
Assert.assertEquals(timerTrace.get().getResultType(), ResultType.ERROR);
Optional<ShallowTrace> valueTrace = findTraceByName(trace, "value");
Assert.assertTrue(valueTrace.isPresent());
Assert.assertEquals(valueTrace.get().getResultType(), ResultType.EARLY_FINISH);
}
@Test
public void testWithSideEffect() throws InterruptedException {
Task<?> task = value("value1Task", "value1").withSideEffect("delayed sideEffect",
v -> delayedValue("value2", 100, TimeUnit.MILLISECONDS));
runAndWait(task);
Assert.assertTrue(_traceCaptureListener.await(30, TimeUnit.SECONDS));
Trace trace = _traceCaptureListener.getTrace();
Assert.assertNotNull(trace);
Optional<ShallowTrace> sideEffectTrace = findTraceByName(trace, "delayed sideEffect");
Assert.assertTrue(sideEffectTrace.isPresent());
Assert.assertEquals(sideEffectTrace.get().getResultType(), ResultType.SUCCESS);
Optional<ShallowTrace> valueTrace = findTraceByName(trace, "value2 delayed");
Assert.assertTrue(valueTrace.isPresent());
Assert.assertEquals(valueTrace.get().getResultType(), ResultType.SUCCESS);
}
@Test
public void testWithSideEffect2() throws InterruptedException {
Task<?> task = value("value1Task", "value1").withSideEffect("delayed sideEffect",
v -> delayedValue("value2", 100, TimeUnit.MILLISECONDS));
runAndWaitForPlanToComplete("side-effect task", task, 30, TimeUnit.SECONDS);
Trace trace = task.getTrace();
Assert.assertNotNull(trace);
Optional<ShallowTrace> sideEffectTrace = findTraceByName(trace, "delayed sideEffect");
Assert.assertTrue(sideEffectTrace.isPresent());
Assert.assertEquals(sideEffectTrace.get().getResultType(), ResultType.SUCCESS);
Optional<ShallowTrace> valueTrace = findTraceByName(trace, "value2 delayed");
Assert.assertTrue(valueTrace.isPresent());
Assert.assertEquals(valueTrace.get().getResultType(), ResultType.SUCCESS);
}
private Optional<ShallowTrace> findTraceByName(Trace trace, String name) {
return trace.getTraceMap().values().stream()
.filter(shallowTrace -> shallowTrace.getName().contains(name))
.findAny();
}
private class TraceCaptureListener implements PlanCompletionListener {
private volatile CountDownLatch _countDownLatch = new CountDownLatch(1);
private final AtomicReference<Trace> _traceRef = new AtomicReference<>();
@Override
public void onPlanCompleted(PlanContext planContext) {
_traceRef.set(planContext.getRelationshipsBuilder().build());
_countDownLatch.countDown();
}
public Trace getTrace() {
return _traceRef.get();
}
public boolean isDone() {
return _countDownLatch.getCount() == 0;
}
public boolean await(long timeout, TimeUnit unit) throws InterruptedException {
return _countDownLatch.await(timeout, unit);
}
}
}