package expression.common; import base.ExtendedRandom; import base.Functional; import expression.ToMiniString; import expression.common.ExpressionKind.Variables; import java.util.*; import java.util.function.Function; import java.util.function.Supplier; import java.util.stream.Stream; /** * @author Georgiy Korneev (kgeorgiy@kgeorgiy.info) */ public class TestGeneratorBuilder { private final ExtendedRandom random; private final Generator.Builder generator; private final NodeRendererBuilder renderer; private final List>, Stream>>> basicTests = new ArrayList<>(); private final List> consts; private final boolean verbose; public TestGeneratorBuilder( final ExtendedRandom random, final Supplier constant, final List constants, final boolean verbose ) { this.random = random; this.verbose = verbose; generator = Generator.builder(constant, random); renderer = new NodeRendererBuilder<>(random); consts = Functional.map(constants, Node::constant); basicTests.add(vars -> consts.stream()); basicTests.add(List::stream); } private Node c() { return random.randomItem(consts); } private Node v(final List> variables) { return random.randomItem(variables); } private static Node f(final String name, final int priority, final Node arg) { return Node.op(name, priority, arg); } private static Node f(final String left, final Node arg) { return Node.op(left, Integer.MAX_VALUE, arg); } private static Node f(final String name, final Node arg1, final Node arg2) { return Node.op(name, arg1, arg2); } @SafeVarargs private void basicTests(final Function>, Node>... tests) { Arrays.stream(tests).map(test -> test.andThen(Stream::of)).forEachOrdered(basicTests::add); } public void unary(final String name, final int priority) { generator.add(name, (priority & 1) * 2 - 1); renderer.unary(name, priority); if (verbose) { basicTests.add(vars -> Stream.concat(consts.stream(), vars.stream()).map(a -> f(name, priority, a))); } else { basicTests(vars -> f(name, priority, c()), vars -> f(name, priority, v(vars))); } final Function>, Node> p1 = vars -> f(name, priority, f(name, priority, f("+", v(vars), c()))); final Function>, Node> p2 = vars -> f("*", v(vars), f("*", v(vars), f(name, priority, c()))); basicTests( vars -> f(name, priority, f("+", v(vars), v(vars))), vars -> f(name, priority, f(name, priority, v(vars))), vars -> f(name, priority, f("/", f(name, priority, v(vars)), f("+", v(vars), v(vars)))), p1, p2, vars -> f("+", p1.apply(vars), p2.apply(vars)) ); } public void unary(final String left, final String right) { generator.add(left, 1); renderer.unary(left, right); if (verbose) { basicTests.add(vars -> Stream.concat(consts.stream(), vars.stream()).map(a -> f(left, a))); } else { basicTests(vars -> f(left, c()), vars -> f(left, v(vars))); } final Function>, Node> p1 = vars -> f(left, f(left, f("+", v(vars), c()))); final Function>, Node> p2 = vars -> f("*", v(vars), f("*", v(vars), f(left, c()))); basicTests( vars -> f(left, f("+", v(vars), v(vars))), vars -> f(left, f(left, v(vars))), vars -> f(left, f("/", f(left, v(vars)), f("+", v(vars), v(vars)))), p1, p2, vars -> f("+", p1.apply(vars), p2.apply(vars)) ); } public void binary(final String name, final int priority) { generator.add(name, 2); renderer.binary(name, priority); if (verbose) { basicTests.add(vars -> Stream.concat(consts.stream(), vars.stream().limit(3)) .flatMap(a -> consts.stream().map(b -> f(name, a, b)))); } else { basicTests( vars -> f(name, c(), c()), vars -> f(name, v(vars), c()), vars -> f(name, c(), v(vars)), vars -> f(name, v(vars), v(vars)) ); } final Function>, Node> p1 = vars -> f(name, f(name, f("+", v(vars), c()), v(vars)), v(vars)); final Function>, Node> p2 = vars -> f("*", v(vars), f("*", v(vars), f(name, c(), v(vars)))); basicTests( vars -> f(name, f(name, v(vars), v(vars)), v(vars)), vars -> f(name, v(vars), f(name, v(vars), v(vars))), vars -> f(name, f(name, v(vars), v(vars)), f(name, v(vars), v(vars))), vars -> f(name, f("-", f(name, v(vars), v(vars)), c()), f("+", v(vars), v(vars))), p1, p2, vars -> f("+", p1.apply(vars), p2.apply(vars)) ); } public TestGenerator build(final Variables variables) { return new TestGenerator<>(generator.build(variables, basicTests), renderer.build()); } }