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()); }); } } }