package io.vertx.ext.unit.impl;
import io.vertx.core.Context;
import io.vertx.core.Handler;
import io.vertx.core.Vertx;
import io.vertx.core.streams.ReadStream;
import io.vertx.ext.unit.report.TestSuiteReport;
import io.vertx.ext.unit.TestContext;
import io.vertx.ext.unit.report.TestCaseReport;
import java.util.HashMap;
import java.util.Map;
class TestSuiteReportImpl implements TestSuiteReport {
private final String name;
private final long timeout;
private final Handler<TestContext> before;
private final Handler<TestContext> after;
private final Handler<TestContext> beforeEach;
private final Handler<TestContext> afterEach;
private final TestCaseImpl[] tests;
private Handler<Void> endHandler;
private Handler<Throwable> exceptionHandler;
private Handler<TestCaseReport> handler;
TestSuiteReportImpl(String name, long timeout, Handler<TestContext> before, Handler<TestContext> after,
Handler<TestContext> beforeEach, Handler<TestContext> afterEach,
TestCaseImpl[] tests) {
this.name = name;
this.timeout = timeout;
this.before = before;
this.after = after;
this.beforeEach = beforeEach;
this.afterEach = afterEach;
this.tests = tests;
}
@Override
public String name() {
return name;
}
@Override
public TestSuiteReport exceptionHandler(Handler<Throwable> handler) {
exceptionHandler = handler;
return this;
}
@Override
public TestSuiteReport handler(Handler<TestCaseReport> handler) {
this.handler = handler;
return this;
}
@Override
public TestSuiteReport pause() {
return this;
}
@Override
public TestSuiteReport resume() {
return this;
}
@Override
public ReadStream<TestCaseReport> fetch(long amount) {
return this;
}
@Override
public TestSuiteReport endHandler(Handler<Void> handler) {
endHandler = handler;
return this;
}
private Task<?> buildTestCasesTasks(Map<String, Object> attributes, TestCaseImpl[] tests, int index, Task<Result> endTask) {
if (tests.length > index) {
TestCaseImpl test = tests[index];
Task<?> nextTask = buildTestCasesTasks(attributes, tests, index + 1, endTask);
return (v, context) -> {
TestCaseReportImpl testReport = new TestCaseReportImpl(test.name, timeout, test.repeat, new HashMap<>(attributes), beforeEach, test.handler, afterEach, exceptionHandler);
if (handler != null) {
handler.handle(testReport);
}
Task<?> task = testReport.buildTask(nextTask);
task.execute(null, context);
};
} else {
if (after != null) {
return new TestContextTask(new TestContextImpl(new HashMap<>(attributes), exceptionHandler), after, endTask, 0);
} else {
return endTask;
}
}
}
private Task<?> buildTask() {
Task<Result> endTask = (result, context) -> {
if (result != null && result.failure != null && exceptionHandler != null) {
exceptionHandler.handle(result.failure);
}
if (endHandler != null) {
endHandler.handle(null);
}
};
if (before != null) {
HashMap<String, Object> attributes = new HashMap<>();
return new TestContextTask(new TestContextImpl(attributes, exceptionHandler), before, result -> {
if (result.failure == null) {
Task<?> runTask = buildTestCasesTasks(attributes, tests, 0, endTask);
return (result_, context) -> runTask.execute(null, context);
} else {
return endTask;
}
}, 0);
} else {
return buildTestCasesTasks(new HashMap<>(), tests, 0, endTask);
}
}
public void run(ExecutionContext context) {
context.run(buildTask());
}
public void run(Boolean useEventLoop) {
Context context = null;
if (useEventLoop == null) {
context = Vertx.currentContext();
} else if (useEventLoop) {
context = Vertx.currentContext();
if (context == null) {
throw new IllegalStateException("No event loop, your test should either provide a Vertx instance or " +
"be executed in a Verticle");
}
}
new ExecutionContext(context).run(buildTask());
}
public void run(Vertx vertx, Boolean useEventLoop) {
Context context = Boolean.FALSE.equals(useEventLoop) ? null : vertx.getOrCreateContext();
Task<?> task = buildTask();
new ExecutionContext(context).run(task);
}
}