package markup; import base.Asserts; import base.BaseChecker; import base.TestCounter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Map; import java.util.function.BiConsumer; import java.util.function.Consumer; /** * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) */ public final class MarkupTester { private final Map mapping; private final String toString; private MarkupTester(final Map mapping, final String toString) { this.mapping = mapping; this.toString = toString; } public static Consumer variant(final Consumer checker, final String name, final Map mapping) { return counter -> test(checker).accept(new MarkupTester(mapping, "to" + name), counter); } public static BiConsumer test(final Consumer tester) { return (checker, counter) -> tester.accept(checker.new Checker(counter)); } @Override public String toString() { return toString; } public class Checker extends BaseChecker { public Checker(final TestCounter counter) { super(counter); } private MethodHandle findMethod(final T value) { try { return MethodHandles.publicLookup().findVirtual(value.getClass(), toString, MethodType.methodType(void.class, StringBuilder.class)); } catch (final NoSuchMethodException | IllegalAccessException e) { throw Asserts.error("Cannot find method 'void %s(StringBuilder)' for %s", toString, value.getClass()); } } public void test(final T value, String expectedTemplate) { final MethodHandle method = findMethod(value); for (final Map.Entry entry : mapping.entrySet()) { expectedTemplate = expectedTemplate.replace(entry.getKey(), entry.getValue()); } final String expected = expectedTemplate; counter.println("Test " + counter.getTestNo()); counter.test(() -> { final StringBuilder sb = new StringBuilder(); try { method.invoke(value, sb); } catch (final Throwable e) { throw Asserts.error("%s(StringBuilder) for %s thrown exception: %s", toString, value.getClass(), e); } Asserts.assertEquals("Result", expected, sb.toString()); }); } } }