@TestFactory
    Stream<DynamicTest> testNegation() {
        final ValLong val1 = ValLong.create(10);
        final ValLong val2 = ValLong.create(5);

        return Stream.of(
                        TestCase.of("-20-10", ValDouble.create(-30)),

                        TestCase.of("20-10", ValDouble.create(10)),

                        TestCase.of("-20--10", ValDouble.create(-10)),
                        TestCase.of("-20+-10", ValDouble.create(-30)),
                        TestCase.of("-10", ValDouble.create(-10)),
                        TestCase.of("${val1}", val1, val1),
                        TestCase.of("-${val1}", ValDouble.create(-val1.toDouble()), val1),
//                        TestCase.of("-'text'", ValErr.INSTANCE),
                        TestCase.of("add(-10, 20)", ValDouble.create(10)),
                        TestCase.of(
                                "add(${val1}, ${val2})",
                                ValDouble.create(val1.toDouble() + val2.toDouble()),
                                val1, val2),
                        TestCase.of(
                                "add(${val1}, -${val2})",
                                ValDouble.create(val1.toDouble() - val2.toDouble()),
                                val1, val2),
                        TestCase.of(
                                "-add(${val1}, ${val2})",
                                ValDouble.create((val1.toDouble() + val2.toDouble()) * -1),
                                val1, val2)
                )
                .map(testCase -> DynamicTest.dynamicTest(testCase.toString(), () ->
                        assertThatItEvaluatesTo(
                                testCase.expression,
                                testCase.expectedResult,
                                testCase.inputValues)));
    }
Depending on context, `-X` should be turned into negate(X)
stroom-query/stroom-query-language/src/test/java/stroom/query/language/functions/TestExpressionParser.java