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;

Author:Julien Viet
/** * @author <a href="mailto:julien@julienviet.com">Julien Viet</a> */
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); } } // For unit testing 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); } }