Search in sources :

Example 1 with TestTwo

use of org.structr.core.entity.TestTwo in project structr by structr.

the class BasicTest method test06DuplicateRelationshipsOneToOne.

@Test
public void test06DuplicateRelationshipsOneToOne() {
    try (final Tx tx = app.tx()) {
        final TestOne test1 = app.create(TestOne.class);
        final TestTwo test2 = app.create(TestTwo.class);
        // test duplicate prevention
        app.create(test1, test2, OneTwoOneToOne.class);
        app.create(test1, test2, OneTwoOneToOne.class);
        tx.success();
    } catch (FrameworkException ex) {
        fail("Creating duplicate relationships via app.create() should NOT throw an exception.");
    }
    try (final Tx tx = app.tx()) {
        final TestOne test1 = app.create(TestOne.class);
        final TestTwo test2 = app.create(TestTwo.class);
        test1.setProperty(TestOne.testTwo, test2);
        test1.setProperty(TestOne.testTwo, test2);
        tx.success();
    } catch (FrameworkException ex) {
        fail("Creating duplicate relationships via setProperty() should NOT throw an exception.");
    }
}
Also used : Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) TestTwo(org.structr.core.entity.TestTwo) TestOne(org.structr.core.entity.TestOne) Test(org.junit.Test)

Example 2 with TestTwo

use of org.structr.core.entity.TestTwo in project structr by structr.

the class BasicTest method testNodeCacheInvalidationInRelationshipWrapper.

@Test
public void testNodeCacheInvalidationInRelationshipWrapper() {
    try (final Tx tx = app.tx()) {
        final TestOne testOne = createTestNode(TestOne.class);
        final TestTwo testTwo1 = createTestNode(TestTwo.class, new NodeAttribute<>(TestTwo.testOne, testOne));
        final OneTwoOneToOne rel = testOne.getOutgoingRelationship(OneTwoOneToOne.class);
        final TestTwo testTwo2 = rel.getTargetNode();
        testTwo1.setProperty(AbstractNode.name, "test");
        assertEquals("Cache invalidation failure!", "test", testTwo2.getProperty(AbstractNode.name));
        tx.success();
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
    // fill cache with other nodes
    try {
        createTestNodes(TestSix.class, 1000);
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
    try (final Tx tx = app.tx()) {
        final TestOne testOne = app.nodeQuery(TestOne.class).getFirst();
        final TestTwo testTwo1 = app.nodeQuery(TestTwo.class).getFirst();
        final OneTwoOneToOne rel = testOne.getOutgoingRelationship(OneTwoOneToOne.class);
        final TestTwo testTwo2 = rel.getTargetNode();
        testTwo1.setProperty(AbstractNode.name, "test2");
        assertEquals("Cache invalidation failure!", "test2", testTwo2.getProperty(AbstractNode.name));
        tx.success();
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
}
Also used : Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) TestTwo(org.structr.core.entity.TestTwo) TestOne(org.structr.core.entity.TestOne) OneTwoOneToOne(org.structr.core.entity.OneTwoOneToOne) Test(org.junit.Test)

Example 3 with TestTwo

use of org.structr.core.entity.TestTwo in project structr by structr.

the class MaintenanceTest method testBulkSetNodePropertiesCommand.

@Test
public void testBulkSetNodePropertiesCommand() {
    final Integer one = 1;
    try {
        // create test nodes first
        createTestNodes(TestOne.class, 100);
        try {
            // test failure with wrong type
            app.command(BulkSetNodePropertiesCommand.class).execute(toMap("type", "NonExistingType"));
            fail("Using BulkSetNodePropertiesCommand with a non-existing type should throw an exception.");
        } catch (FrameworkException fex) {
            // status: 422
            assertEquals(422, fex.getStatus());
            assertEquals("Invalid type NonExistingType", fex.getMessage());
        }
        try {
            // test failure without type
            app.command(BulkSetNodePropertiesCommand.class).execute(toMap("anInt", 1));
            fail("Using BulkSetNodePropertiesCommand without a type property should throw an exception.");
        } catch (FrameworkException fex) {
            // status: 422
            assertEquals(422, fex.getStatus());
            assertEquals("Type must not be empty", fex.getMessage());
        }
        // test success
        app.command(BulkSetNodePropertiesCommand.class).execute(toMap("type", "TestOne", "anInt", 1, "aString", "one"));
        try (final Tx tx = app.tx()) {
            // check nodes, we should find 100 TestOnes here, and none TestTwos
            assertEquals(0, app.nodeQuery(TestTwo.class).getResult().size());
            assertEquals(100, app.nodeQuery(TestOne.class).getResult().size());
            // check nodes
            for (final TestOne test : app.nodeQuery(TestOne.class)) {
                assertEquals(one, test.getProperty(TestOne.anInt));
                assertEquals("one", test.getProperty(TestOne.aString));
            }
        }
        // advanced: modify type
        app.command(BulkSetNodePropertiesCommand.class).execute(toMap("type", "TestOne", "newType", "TestTwo"));
        try (final Tx tx = app.tx()) {
            // check nodes, we should find 100 TestTwos here, and none TestOnes
            assertEquals(0, app.nodeQuery(TestOne.class).getResult().size());
            assertEquals(100, app.nodeQuery(TestTwo.class).getResult().size());
        }
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
}
Also used : BulkSetNodePropertiesCommand(org.structr.core.graph.BulkSetNodePropertiesCommand) FrameworkException(org.structr.common.error.FrameworkException) Tx(org.structr.core.graph.Tx) TestTwo(org.structr.core.entity.TestTwo) TestOne(org.structr.core.entity.TestOne) StructrTest(org.structr.common.StructrTest) Test(org.junit.Test)

Example 4 with TestTwo

use of org.structr.core.entity.TestTwo in project structr by structr.

the class ScriptingTest method testScriptedFindWithJSONObject.

@Test
public void testScriptedFindWithJSONObject() {
    final Random random = new Random();
    final long long1 = 13475233523455L;
    final long long2 = 327326252322L;
    final double double1 = 1234.56789;
    final double double2 = 5678.975321;
    List<TestSix> testSixs = null;
    TestOne testOne1 = null;
    TestOne testOne2 = null;
    TestTwo testTwo1 = null;
    TestTwo testTwo2 = null;
    TestThree testThree1 = null;
    TestThree testThree2 = null;
    TestFour testFour1 = null;
    TestFour testFour2 = null;
    Date date1 = null;
    Date date2 = null;
    // setup phase
    try (final Tx tx = app.tx()) {
        testSixs = createTestNodes(TestSix.class, 10);
        testOne1 = app.create(TestOne.class);
        testOne2 = app.create(TestOne.class);
        testTwo1 = app.create(TestTwo.class);
        testTwo2 = app.create(TestTwo.class);
        testThree1 = app.create(TestThree.class);
        testThree2 = app.create(TestThree.class);
        testFour1 = app.create(TestFour.class);
        testFour2 = app.create(TestFour.class);
        date1 = new Date(random.nextLong());
        date2 = new Date();
        testOne1.setProperty(TestOne.anInt, 42);
        testOne1.setProperty(TestOne.aLong, long1);
        testOne1.setProperty(TestOne.aDouble, double1);
        testOne1.setProperty(TestOne.aDate, date1);
        testOne1.setProperty(TestOne.anEnum, Status.One);
        testOne1.setProperty(TestOne.aString, "aString1");
        testOne1.setProperty(TestOne.aBoolean, true);
        testOne1.setProperty(TestOne.testTwo, testTwo1);
        testOne1.setProperty(TestOne.testThree, testThree1);
        testOne1.setProperty(TestOne.testFour, testFour1);
        testOne1.setProperty(TestOne.manyToManyTestSixs, testSixs.subList(0, 5));
        testOne2.setProperty(TestOne.anInt, 33);
        testOne2.setProperty(TestOne.aLong, long2);
        testOne2.setProperty(TestOne.aDouble, double2);
        testOne2.setProperty(TestOne.aDate, date2);
        testOne2.setProperty(TestOne.anEnum, Status.Two);
        testOne2.setProperty(TestOne.aString, "aString2");
        testOne2.setProperty(TestOne.aBoolean, false);
        testOne2.setProperty(TestOne.testTwo, testTwo2);
        testOne2.setProperty(TestOne.testThree, testThree2);
        testOne2.setProperty(TestOne.testFour, testFour2);
        testOne2.setProperty(TestOne.manyToManyTestSixs, testSixs.subList(5, 10));
        tx.success();
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
    // test phase, find all the things using scripting
    try (final Tx tx = app.tx()) {
        final ActionContext actionContext = new ActionContext(securityContext);
        assertEquals("Invalid scripted find() result", testOne1, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { anInt: 42 })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne2, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { anInt: 33 })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne1, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aLong: " + long1 + " })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne2, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aLong: " + long2 + " })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne1, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aDouble: " + double1 + " })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne2, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aDouble: " + double2 + " })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne1, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { anEnum: 'One' })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne2, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { anEnum: 'Two' })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne1, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aBoolean: true })[0]; }}", "test"));
        assertEquals("Invalid scripted find() result", testOne2, Scripting.evaluate(actionContext, testOne1, "${{ return Structr.find('TestOne', { aBoolean: false })[0]; }}", "test"));
        tx.success();
    } catch (UnlicensedException | FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception.");
    }
}
Also used : TestFour(org.structr.core.entity.TestFour) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) ActionContext(org.structr.schema.action.ActionContext) Date(java.util.Date) UnlicensedException(org.structr.common.error.UnlicensedException) Random(java.util.Random) TestTwo(org.structr.core.entity.TestTwo) TestThree(org.structr.core.entity.TestThree) TestOne(org.structr.core.entity.TestOne) TestSix(org.structr.core.entity.TestSix) StructrTest(org.structr.common.StructrTest) Test(org.junit.Test)

Example 5 with TestTwo

use of org.structr.core.entity.TestTwo in project structr by structr.

the class ScriptingTest method testVariableReplacement.

@Test
public void testVariableReplacement() {
    final Date now = new Date();
    final SimpleDateFormat format1 = new SimpleDateFormat("dd.MM.yyyy");
    final SimpleDateFormat format2 = new SimpleDateFormat("HH:mm:ss");
    final SimpleDateFormat format3 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
    final String nowString1 = format1.format(now);
    final String nowString2 = format2.format(now);
    final String nowString3 = format3.format(now);
    final DecimalFormat numberFormat1 = new DecimalFormat("###0.00", DecimalFormatSymbols.getInstance(Locale.ENGLISH));
    final DecimalFormat numberFormat2 = new DecimalFormat("0000.0000", DecimalFormatSymbols.getInstance(Locale.GERMAN));
    final DecimalFormat numberFormat3 = new DecimalFormat("####", DecimalFormatSymbols.getInstance(Locale.SIMPLIFIED_CHINESE));
    final String numberString1 = numberFormat1.format(2.234);
    final String numberString2 = numberFormat2.format(2.234);
    final String numberString3 = numberFormat3.format(2.234);
    NodeInterface template = null;
    NodeInterface template2 = null;
    TestOne testOne = null;
    TestTwo testTwo = null;
    TestThree testThree = null;
    TestFour testFour = null;
    List<TestSix> testSixs = null;
    int index = 0;
    try (final Tx tx = app.tx()) {
        testOne = createTestNode(TestOne.class);
        testTwo = createTestNode(TestTwo.class);
        testThree = createTestNode(TestThree.class);
        testFour = createTestNode(TestFour.class);
        testSixs = createTestNodes(TestSix.class, 20);
        // set string array on test four
        testFour.setProperty(TestFour.stringArrayProperty, new String[] { "one", "two", "three", "four" });
        for (final TestSix testSix : testSixs) {
            testSix.setProperty(TestSix.name, "TestSix" + StringUtils.leftPad(Integer.toString(index), 2, "0"));
            testSix.setProperty(TestSix.index, index);
            index++;
        }
        // create mail template
        template = createTestNode(getType("MailTemplate"));
        template.setProperty(getKey("MailTemplate", "name"), "TEST");
        template.setProperty(getKey("MailTemplate", "locale"), "en_EN");
        template.setProperty(getKey("MailTemplate", "text"), "This is a template for ${this.name}");
        // create mail template
        template2 = createTestNode(getType("MailTemplate"));
        template2.setProperty(getKey("MailTemplate", "name"), "TEST2");
        template2.setProperty(getKey("MailTemplate", "locale"), "en_EN");
        template2.setProperty(getKey("MailTemplate", "text"), "${this.aDouble}");
        // check existance
        assertNotNull(testOne);
        testOne.setProperty(TestOne.name, "A-nice-little-name-for-my-test-object");
        testOne.setProperty(TestOne.anInt, 1);
        testOne.setProperty(TestOne.aString, "String");
        testOne.setProperty(TestOne.anotherString, "{\n\ttest: test,\n\tnum: 3\n}");
        testOne.setProperty(TestOne.replaceString, "${this.name}");
        testOne.setProperty(TestOne.aLong, 235242522552L);
        testOne.setProperty(TestOne.aDouble, 2.234);
        testOne.setProperty(TestOne.aDate, now);
        testOne.setProperty(TestOne.anEnum, TestOne.Status.One);
        testOne.setProperty(TestOne.aBoolean, true);
        testOne.setProperty(TestOne.testTwo, testTwo);
        testOne.setProperty(TestOne.testThree, testThree);
        testOne.setProperty(TestOne.testFour, testFour);
        testOne.setProperty(TestOne.manyToManyTestSixs, testSixs);
        testOne.setProperty(TestOne.cleanTestString, "a<b>c.d'e?f(g)h{i}j[k]l+m/n–o\\p\\q|r's!t,u-v_w`x-y-zöäüßABCDEFGH");
        testOne.setProperty(TestOne.stringWithQuotes, "A'B\"C");
        testOne.setProperty(TestOne.aStringArray, new String[] { "a", "b", "c" });
        testTwo.setProperty(TestTwo.name, "testTwo_name");
        testThree.setProperty(TestThree.name, "testThree_name");
        tx.success();
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail("Unexpected exception");
    }
    try (final Tx tx = app.tx()) {
        final ActionContext ctx = new ActionContext(securityContext, null);
        // test quotes etc.
        assertEquals("Invalid result for quoted template expression", "''", Scripting.replaceVariables(ctx, testOne, "'${err}'"));
        assertEquals("Invalid result for quoted template expression", " '' ", Scripting.replaceVariables(ctx, testOne, " '${err}' "));
        assertEquals("Invalid result for quoted template expression", "\"\"", Scripting.replaceVariables(ctx, testOne, "\"${this.error}\""));
        assertEquals("Invalid result for quoted template expression", "''''''", Scripting.replaceVariables(ctx, testOne, "'''${this.this.this.error}'''"));
        assertEquals("Invalid result for quoted template expression", "''", Scripting.replaceVariables(ctx, testOne, "'${parent.error}'"));
        assertEquals("Invalid result for quoted template expression", "''", Scripting.replaceVariables(ctx, testOne, "'${this.owner}'"));
        assertEquals("Invalid result for quoted template expression", "''", Scripting.replaceVariables(ctx, testOne, "'${this.alwaysNull}'"));
        assertEquals("Invalid result for quoted template expression", "''", Scripting.replaceVariables(ctx, testOne, "'${parent.owner}'"));
        // test for "empty" return value
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${err}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${this.error}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${this.this.this.error}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${parent.error}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${this.owner}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${this.alwaysNull}"));
        assertEquals("Invalid expressions should yield an empty result", "", Scripting.replaceVariables(ctx, testOne, "${parent.owner}"));
        assertEquals("${this} should evaluate to the current node", testOne.toString(), Scripting.replaceVariables(ctx, testOne, "${this}"));
        // assertEquals("${parent} should evaluate to the context parent node", testOne.toString(), Scripting.replaceVariables(ctx, testOne, "${parent}"));
        assertEquals("${this} should evaluate to the current node", testTwo.toString(), Scripting.replaceVariables(ctx, testTwo, "${this}"));
        // assertEquals("${parent} should evaluate to the context parent node", testOne.toString(), Scripting.replaceVariables(ctx, testOne, "${parent}"));
        assertEquals("Invalid variable reference", testTwo.toString(), Scripting.replaceVariables(ctx, testOne, "${this.testTwo}"));
        assertEquals("Invalid variable reference", testThree.toString(), Scripting.replaceVariables(ctx, testOne, "${this.testThree}"));
        assertEquals("Invalid variable reference", testFour.toString(), Scripting.replaceVariables(ctx, testOne, "${this.testFour}"));
        assertEquals("Invalid variable reference", testTwo.getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.testTwo.id}"));
        assertEquals("Invalid variable reference", testThree.getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.testThree.id}"));
        assertEquals("Invalid variable reference", testFour.getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.testFour.id}"));
        assertEquals("Invalid size result", "20", Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs.size}"));
        try {
            Scripting.replaceVariables(ctx, testOne, "${(this.alwaysNull.size}");
            fail("A mismatched opening bracket should throw an exception.");
        } catch (FrameworkException fex) {
            assertEquals("Invalid expression: mismatched closing bracket after this.alwaysNull.size", fex.getMessage());
        }
        assertEquals("Invalid size result", "", Scripting.replaceVariables(ctx, testOne, "${this.alwaysNull.size}"));
        assertEquals("Invalid variable reference", "1", Scripting.replaceVariables(ctx, testOne, "${this.anInt}"));
        assertEquals("Invalid variable reference", "String", Scripting.replaceVariables(ctx, testOne, "${this.aString}"));
        assertEquals("Invalid variable reference", "235242522552", Scripting.replaceVariables(ctx, testOne, "${this.aLong}"));
        assertEquals("Invalid variable reference", "2.234", Scripting.replaceVariables(ctx, testOne, "${this.aDouble}"));
        // test with property
        assertEquals("Invalid md5() result", "27118326006d3829667a400ad23d5d98", Scripting.replaceVariables(ctx, testOne, "${md5(this.aString)}"));
        assertEquals("Invalid upper() result", "27118326006D3829667A400AD23D5D98", Scripting.replaceVariables(ctx, testOne, "${upper(md5(this.aString))}"));
        assertEquals("Invalid upper(lower() result", "27118326006D3829667A400AD23D5D98", Scripting.replaceVariables(ctx, testOne, "${upper(lower(upper(md5(this.aString))))}"));
        assertEquals("Invalid md5() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${md5(this.alwaysNull)}"));
        assertEquals("Invalid upper() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${upper(this.alwaysNull)}"));
        assertEquals("Invalid lower() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${lower(this.alwaysNull)}"));
        // test literal value as well
        assertEquals("Invalid md5() result", "cc03e747a6afbbcbf8be7668acfebee5", Scripting.replaceVariables(ctx, testOne, "${md5(\"test123\")}"));
        assertEquals("Invalid lower() result", "string", Scripting.replaceVariables(ctx, testOne, "${lower(this.aString)}"));
        assertEquals("Invalid upper() result", "STRING", Scripting.replaceVariables(ctx, testOne, "${upper(this.aString)}"));
        // merge
        assertEquals("Invalid merge() result", "[one, two, three]", Scripting.replaceVariables(ctx, testOne, "${merge('one', 'two', 'three')}"));
        assertEquals("Invalid merge() result", "[one, two, three, two, one, two, three]", Scripting.replaceVariables(ctx, testOne, "${merge(merge('one', 'two', 'three'), 'two', merge('one', 'two', 'three'))}"));
        assertEquals("Invalid merge() result", "[1, 2, 3, 4, 5, 6, 7, 8]", Scripting.replaceVariables(ctx, testOne, "${merge(merge('1', '2', '3'), merge('4', '5', merge('6', '7', '8')))}"));
        assertEquals("Invalid merge() result", "[1, 2, 3, 4, 5, 6, 1, 2, 3, 8]", Scripting.replaceVariables(ctx, testOne, "${ ( store('list', merge('1', '2', '3')), merge(retrieve('list'), merge('4', '5', merge('6', retrieve('list'), '8'))) )}"));
        // merge_unique
        assertEquals("Invalid merge_unique() result", "[one, two, three]", Scripting.replaceVariables(ctx, testOne, "${merge_unique('one', 'two', 'three', 'two')}"));
        assertEquals("Invalid merge_unique() result", "[one, two, three]", Scripting.replaceVariables(ctx, testOne, "${merge_unique(merge_unique('one', 'two', 'three'), 'two', merge_unique('one', 'two', 'three'))}"));
        assertEquals("Invalid merge_unique() result", "[1, 2, 3, 4, 5, 6, 7, 8]", Scripting.replaceVariables(ctx, testOne, "${merge_unique(merge_unique('1', '2', '3'), merge_unique('4', '5', merge_unique('6', '7', '8')))}"));
        assertEquals("Invalid merge_unique() result", "[1, 2, 3, 4, 5, 6, 8]", Scripting.replaceVariables(ctx, testOne, "${ ( store('list', merge_unique('1', '2', '3')), merge_unique(retrieve('list'), merge_unique('4', '5', merge_unique('6', retrieve('list'), '8'))) )}"));
        // complement
        assertEquals("Invalid complement() result", "[]", Scripting.replaceVariables(ctx, testOne, "${complement(merge('one', 'two', 'three'), 'one', merge('two', 'three', 'four'))}"));
        assertEquals("Invalid complement() result", "[two]", Scripting.replaceVariables(ctx, testOne, "${complement(merge('one', 'two', 'three'), merge('one', 'four', 'three'))}"));
        // join
        assertEquals("Invalid join() result", "one,two,three", Scripting.replaceVariables(ctx, testOne, "${join(merge(\"one\", \"two\", \"three\"), \",\")}"));
        // concat
        assertEquals("Invalid concat() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(\"one\", \"two\", \"three\")}"));
        assertEquals("Invalid concat() result", "oneStringthree", Scripting.replaceVariables(ctx, testOne, "${concat(\"one\", this.aString, \"three\")}"));
        assertEquals("Invalid concat() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${concat(this.alwaysNull, this.alwaysNull)}"));
        // split
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one,two,three\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one;two;three\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one two three\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one	two	three\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one;two;three\", \";\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one,two,three\", \",\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one.two.three\", \".\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one two three\", \" \"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one+two+three\", \"+\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one|two|three\", \"|\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one::two::three\", \"::\"))}"));
        assertEquals("Invalid split() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one-two-three\", \"-\"))}"));
        assertEquals("Invalid split() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${split(this.alwaysNull)}"));
        // split_regex
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one,two,three\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one;two;three\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one two three\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one	two	three\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one;two;three\", \";\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one,two,three\", \",\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one.two.three\", \"\\.\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one two three\", \" \"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one+two+three\", \"+\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one|two|three\", \"|\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one::two::three\", \"::\"))}"));
        assertEquals("Invalid split_regex() result", "onetwothree", Scripting.replaceVariables(ctx, testOne, "${concat(split(\"one-two-three\", \"-\"))}"));
        assertEquals("Invalid split_regex() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${split(this.alwaysNull)}"));
        // abbr
        assertEquals("Invalid abbr() result", "oneStringt…", Scripting.replaceVariables(ctx, testOne, "${abbr(concat(\"one\", this.aString, \"three\"), 10)}"));
        assertEquals("Invalid abbr() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${abbr(this.alwaysNull, 10)}"));
        // capitalize..
        assertEquals("Invalid capitalize() result", "One_two_three", Scripting.replaceVariables(ctx, testOne, "${capitalize(concat(\"one_\", \"two_\", \"three\"))}"));
        assertEquals("Invalid capitalize() result", "One_Stringthree", Scripting.replaceVariables(ctx, testOne, "${capitalize(concat(\"one_\", this.aString, \"three\"))}"));
        assertEquals("Invalid capitalize() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${capitalize(this.alwaysNull)}"));
        // titleize
        assertEquals("Invalid titleize() result", "One Two Three", Scripting.replaceVariables(ctx, testOne, "${titleize(concat(\"one_\", \"two_\", \"three\"), \"_\")}"));
        assertEquals("Invalid titleize() result", "One Stringthree", Scripting.replaceVariables(ctx, testOne, "${titleize(concat(\"one_\", this.aString, \"three\"), \"_\")}"));
        assertEquals("Invalid titleize() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${titleize(this.alwaysNull)}"));
        // num (explicit number conversion)
        assertEquals("Invalid num() result", "2.234", Scripting.replaceVariables(ctx, testOne, "${num(2.234)}"));
        assertEquals("Invalid num() result", "2.234", Scripting.replaceVariables(ctx, testOne, "${num(this.aDouble)}"));
        assertEquals("Invalid num() result", "1.0", Scripting.replaceVariables(ctx, testOne, "${num(this.anInt)}"));
        assertEquals("Invalid num() result", "", Scripting.replaceVariables(ctx, testOne, "${num(\"abc\")}"));
        assertEquals("Invalid num() result", "", Scripting.replaceVariables(ctx, testOne, "${num(this.aString)}"));
        assertEquals("Invalid num() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${num(this.alwaysNull)}"));
        // index_of
        assertEquals("Invalid index_of() result", "19", Scripting.replaceVariables(ctx, testOne, "${index_of(this.name, 'for')}"));
        assertEquals("Invalid index_of() result", "-1", Scripting.replaceVariables(ctx, testOne, "${index_of(this.name, 'entity')}"));
        assertEquals("Invalid index_of() result", "19", Scripting.replaceVariables(ctx, testOne, "${index_of('a-nice-little-name-for-my-test-object', 'for')}"));
        assertEquals("Invalid index_of() result", "-1", Scripting.replaceVariables(ctx, testOne, "${index_of('a-nice-little-name-for-my-test-object', 'entity')}"));
        // contains
        assertEquals("Invalid contains() result", "true", Scripting.replaceVariables(ctx, testOne, "${contains(this.name, 'for')}"));
        assertEquals("Invalid contains() result", "false", Scripting.replaceVariables(ctx, testOne, "${contains(this.name, 'entity')}"));
        assertEquals("Invalid contains() result", "true", Scripting.replaceVariables(ctx, testOne, "${contains('a-nice-little-name-for-my-test-object', 'for')}"));
        assertEquals("Invalid contains() result", "false", Scripting.replaceVariables(ctx, testOne, "${contains('a-nice-little-name-for-my-test-object', 'entity')}"));
        // contains with collection / entity
        assertEquals("Invalid contains() result", "true", Scripting.replaceVariables(ctx, testOne, "${contains(this.manyToManyTestSixs, first(find('TestSix')))}"));
        assertEquals("Invalid contains() result", "false", Scripting.replaceVariables(ctx, testOne, "${contains(this.manyToManyTestSixs, first(find('TestFive')))}"));
        // substring
        assertEquals("Invalid substring() result", "for", Scripting.replaceVariables(ctx, testOne, "${substring(this.name, 19, 3)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring(this.name, -1, -1)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring(this.name, 100, -1)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring(this.name, 5, -2)}"));
        assertEquals("Invalid substring() result", "for", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', 19, 3)}"));
        assertEquals("Invalid substring() result", "ice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', 3)}"));
        assertEquals("Invalid substring() result", "ice", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', 3, 3)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', -1, -1)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', 100, -1)}"));
        assertEquals("Invalid substring() result", "", Scripting.replaceVariables(ctx, testOne, "${substring('a-nice-little-name-for-my-test-object', 5, -2)}"));
        // length
        assertEquals("Invalid length() result", "37", Scripting.replaceVariables(ctx, testOne, "${length(this.name)}"));
        assertEquals("Invalid length() result", "37", Scripting.replaceVariables(ctx, testOne, "${length('a-nice-little-name-for-my-test-object')}"));
        assertEquals("Invalid length() result", "4", Scripting.replaceVariables(ctx, testOne, "${length('test')}"));
        assertEquals("Invalid length() result", "", Scripting.replaceVariables(ctx, testOne, "${length(this.alwaysNull)}"));
        // clean
        assertEquals("Invalid clean() result", "abcd-efghijkl-m-n-o-p-q-r-stu-v-w-x-y-zoauabcdefgh", Scripting.replaceVariables(ctx, testOne, "${clean(this.cleanTestString)}"));
        assertEquals("Invalid clean() result", "abcd-efghijkl-m-n-o-p-q-r-stu-v-w-x-y-zoauabcdefgh", Scripting.replaceVariables(ctx, testOne, "${clean(get(this, \"cleanTestString\"))}"));
        assertEquals("Invalid clean() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${clean(this.alwaysNull)}"));
        // trim
        assertEquals("Invalid trim() result", "test", Scripting.replaceVariables(ctx, testOne, "${trim('   \t\t\t\r\r\r\n\n\ntest')}"));
        assertEquals("Invalid trim() result", "test", Scripting.replaceVariables(ctx, testOne, "${trim('test   \t\t\t\r\r\r\n\n\n')}"));
        assertEquals("Invalid trim() result", "test", Scripting.replaceVariables(ctx, testOne, "${trim('   \t\t\t\r\r\r\n\n\ntest   \t\t\t\r\r\r\n\n\n')}"));
        assertEquals("Invalid trim() result", "test", Scripting.replaceVariables(ctx, testOne, "${trim('   test   ')}"));
        assertEquals("Invalid trim() result with null value", null, Scripting.replaceVariables(ctx, testOne, "${trim(null)}"));
        assertEquals("Invalid trim() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${trim(this.alwaysNull)}"));
        // urlencode
        assertEquals("Invalid urlencode() result", "a%3Cb%3Ec.d%27e%3Ff%28g%29h%7Bi%7Dj%5Bk%5Dl%2Bm%2Fn%E2%80%93o%5Cp%5Cq%7Cr%27s%21t%2Cu-v_w%60x-y-z%C3%B6%C3%A4%C3%BC%C3%9FABCDEFGH", Scripting.replaceVariables(ctx, testOne, "${urlencode(this.cleanTestString)}"));
        assertEquals("Invalid urlencode() result", "a%3Cb%3Ec.d%27e%3Ff%28g%29h%7Bi%7Dj%5Bk%5Dl%2Bm%2Fn%E2%80%93o%5Cp%5Cq%7Cr%27s%21t%2Cu-v_w%60x-y-z%C3%B6%C3%A4%C3%BC%C3%9FABCDEFGH", Scripting.replaceVariables(ctx, testOne, "${urlencode(get(this, \"cleanTestString\"))}"));
        assertEquals("Invalid urlencode() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${urlencode(this.alwaysNull)}"));
        // escape_javascript
        assertEquals("Invalid escape_javascript() result", "A\\'B\\\"C", Scripting.replaceVariables(ctx, testOne, "${escape_javascript(this.stringWithQuotes)}"));
        assertEquals("Invalid escape_javascript() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${escape_javascript(this.alwaysNull)}"));
        // escape_json
        assertEquals("Invalid escape_json() result", "A'B\\\"C", Scripting.replaceVariables(ctx, testOne, "${escape_json(this.stringWithQuotes)}"));
        assertEquals("Invalid escape_json() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${escape_json(this.alwaysNull)}"));
        // is
        assertEquals("Invalid is() result", "true", Scripting.replaceVariables(ctx, testOne, "${is(\"true\", \"true\")}"));
        assertEquals("Invalid is() result", null, Scripting.replaceVariables(ctx, testOne, "${is(\"false\", \"true\")}"));
        // is + equal
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(this.id, this.id), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(\"abc\", \"abc\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(3, 3), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(\"3\", \"3\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(3.1414, 3.1414), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(\"3.1414\", \"3.1414\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(23.44242222243633337234623462, 23.44242222243633337234623462), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(\"23.44242222243633337234623462\", \"23.44242222243633337234623462\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(13, 013), \"true\")}"));
        assertEquals("Invalid is(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${is(equal(13, \"013\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", null, Scripting.replaceVariables(ctx, testOne, "${is(equal(\"13\", \"013\"), \"true\")}"));
        assertEquals("Invalid is(equal()) result", null, Scripting.replaceVariables(ctx, testOne, "${is(equal(\"13\", \"00013\"), \"true\")}"));
        // if etc.
        assertEquals("Invalid if() result", "true", Scripting.replaceVariables(ctx, testOne, "${if(\"true\", \"true\", \"false\")}"));
        assertEquals("Invalid if() result", "false", Scripting.replaceVariables(ctx, testOne, "${if(\"false\", \"true\", \"false\")}"));
        // empty
        assertEquals("Invalid empty() result", "true", Scripting.replaceVariables(ctx, testOne, "${empty(\"\")}"));
        assertEquals("Invalid empty() result", "false", Scripting.replaceVariables(ctx, testOne, "${empty(\" \")}"));
        assertEquals("Invalid empty() result", "false", Scripting.replaceVariables(ctx, testOne, "${empty(\"   \")}"));
        assertEquals("Invalid empty() result", "false", Scripting.replaceVariables(ctx, testOne, "${empty(\"xyz\")}"));
        assertEquals("Invalid empty() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${empty(this.alwaysNull)}"));
        assertEquals("Invalid if(empty()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(empty(\"test\"), true, false)}"));
        assertEquals("Invalid if(empty()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(empty(\"test\n\"), true, false)}"));
        // functions can NOT handle literal strings containing newlines  (disabled for now, because literal strings pose problems in the matching process)
        assertEquals("Invalid if(empty()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(empty(\"\n\"), true, false)}"));
        assertEquals("Invalid if(empty()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(empty(\"\n\"), \"true\", \"false\")}"));
        // functions CAN handle variable values with newlines!
        assertEquals("Invalid if(empty()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(empty(this.anotherString), \"true\", \"false\")}"));
        // equal
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.id, this.id)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(\"1\", this.anInt)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(1, this.anInt)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(1.0, this.anInt)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.anInt, \"1\")}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.anInt, 1)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.anInt, 1.0)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.aBoolean, \"true\")}"));
        assertEquals("Invalid equal() result", "false", Scripting.replaceVariables(ctx, testOne, "${equal(this.aBoolean, \"false\")}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.aBoolean, true)}"));
        assertEquals("Invalid equal() result", "false", Scripting.replaceVariables(ctx, testOne, "${equal(this.aBoolean, false)}"));
        assertEquals("Invalid equal() result", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.anEnum, 'One')}"));
        // if + equal
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(this.id, this.id), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"abc\", \"abc\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(3, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"3\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(3.1414, 3.1414), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"3.1414\", \"3.1414\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(23.44242222243633337234623462, 23.44242222243633337234623462), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"23.44242222243633337234623462\", \"23.44242222243633337234623462\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(13, 013), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(13, \"013\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"13\", \"013\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"13\", \"00013\"), \"true\", \"false\")}"));
        // disabled: java StreamTokenizer can NOT handle scientific notation
        // assertEquals("Invalid if(equal()) result", "true",  Scripting.replaceVariables(ctx, testOne, "${equal(23.4462, 2.34462e1)}"));
        // assertEquals("Invalid if(equal()) result", "true",  Scripting.replaceVariables(ctx, testOne, "${equal(0.00234462, 2.34462e-3)}"));
        // assertEquals("Invalid if(equal()) result with null value", "false",  Scripting.replaceVariables(ctx, testOne, "${equal(this.alwaysNull, 2.34462e-3)}"));
        assertEquals("Invalid if(equal()) result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${equal(0.00234462, this.alwaysNull)}"));
        assertEquals("Invalid if(equal()) result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${equal(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + add
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, add(1, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, add(\"1\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, add(1, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, add(1, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, add(1, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, add(\"1\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, add(1, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, add(1, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(20, add(\"10\", \"10\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(20, add(\"10\", \"010\")), \"true\", \"false\")}"));
        // eq
        assertEquals("Invalideq) result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.id, this.id)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(\"1\", this.anInt)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(1, this.anInt)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(1.0, this.anInt)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.anInt, \"1\")}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.anInt, 1)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.anInt, 1.0)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.aBoolean, \"true\")}"));
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq(this.aBoolean, \"false\")}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.aBoolean, true)}"));
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq(this.aBoolean, false)}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.anEnum, 'One')}"));
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq('', '')}"));
        // eq with empty string and number
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq(3, '')}"));
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq('', 12.3456)}"));
        // eq with null
        assertEquals("Invalid eq() result", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.alwaysNull, this.alwaysNull)}"));
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq(this.alwaysNull, 'xyz')}"));
        assertEquals("Invalid eq() result", "false", Scripting.replaceVariables(ctx, testOne, "${eq('xyz', this.alwaysNull)}"));
        // if + eq
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(this.id, this.id), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"abc\", \"abc\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(3, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"3\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(3.1414, 3.1414), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"3.1414\", \"3.1414\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(23.44242222243633337234623462, 23.44242222243633337234623462), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"23.44242222243633337234623462\", \"23.44242222243633337234623462\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(13, 013), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(13, \"013\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"13\", \"013\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"13\", \"00013\"), \"true\", \"false\")}"));
        // disabled: java StreamTokenizer can NOT handle scientific notation
        // assertEquals("Invalid if(eq()) result", "true",  Scripting.replaceVariables(ctx, testOne, "${eq(23.4462, 2.34462e1)}"));
        // assertEquals("Invalid if(eq()) result", "true",  Scripting.replaceVariables(ctx, testOne, "${eq(0.00234462, 2.34462e-3)}"));
        // assertEquals("Invalid if(eq()) result with null value", "false",  Scripting.replaceVariables(ctx, testOne, "${eq(this.alwaysNull, 2.34462e-3)}"));
        assertEquals("Invalid if(eq()) result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${eq(0.00234462, this.alwaysNull)}"));
        assertEquals("Invalid if(eq()) result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${eq(this.alwaysNull, this.alwaysNull)}"));
        // if + eq + add
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"2\", add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(eq(\"2\", add(\"2\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2, add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2, add(1, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2, add(\"1\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2, add(1, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2, add(1, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2.0, add(\"1\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2.0, add(1, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2.0, add(\"1\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2.0, add(1, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(2.0, add(1, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(20, add(\"10\", \"10\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(eq(add())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(eq(20, add(\"10\", \"010\")), \"true\", \"false\")}"));
        // add with null
        assertEquals("Invalid add() result with null value", "10.0", Scripting.replaceVariables(ctx, testOne, "${add(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid add() result with null value", "11.0", Scripting.replaceVariables(ctx, testOne, "${add(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid add() result with null value", "0.0", Scripting.replaceVariables(ctx, testOne, "${add(this.alwaysNull, this.alwaysNull)}"));
        // if + lt
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"2\", \"2\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"2\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"2000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"2.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"2000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"12\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"12000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"12.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(\"12000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(2, 2), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(2, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(2000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(2.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(2000000.0, 3000000.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(12, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lt(1200000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(12000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(12.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lt(12000000.0, 3000000.0), \"true\", \"false\")}"));
        // compare numbers written as strings as numbers
        assertEquals("Invalid if(lt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${lt(\"1200\", \"30\")}"));
        // lt with numbers and empty string
        assertEquals("Invalid lt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${lt(10, '')}"));
        assertEquals("Invalid lt() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${lt('', 11)}"));
        assertEquals("Invalid lt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${lt('', '')}"));
        // lt with null
        assertEquals("Invalid lt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${lt(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid lt() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${lt(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid lt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${lt(this.alwaysNull, this.alwaysNull)}"));
        // if + gt
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"2\", \"2\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"2\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"2000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"2.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"2000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"12\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"12000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"12.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(\"12000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(2, 2), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(2, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(2000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(2.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gt(2000000.0, 3000000.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gt(12, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gt(12000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gt(12.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gt()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gt(12000000.0, 3000000.0), \"true\", \"false\")}"));
        // gt with null
        assertEquals("Invalid gt() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${gt(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid gt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${gt(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid gt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${gt(this.alwaysNull, this.alwaysNull)}"));
        // gt with numbers and empty string
        assertEquals("Invalid gt() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${gt(10, '')}"));
        assertEquals("Invalid gt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${gt('', 11)}"));
        assertEquals("Invalid gt() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${gt('', '')}"));
        // if + lte
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"2\", \"2\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"2\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"2000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"2.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"2000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"12\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"12000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"12.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(\"12000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(2, 2), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(2, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(2000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(2.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(lte(2000000.0, 3000000.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lte(12, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lte(12000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lte(12.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(lte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(lte(12000000.0, 3000000.0), \"true\", \"false\")}"));
        // lte with null
        assertEquals("Invalid lte() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${lte(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid lte() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${lte(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid lte() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${lte(this.alwaysNull, this.alwaysNull)}"));
        // if + gte
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"2\", \"2\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"2\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"2000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"2.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"2000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"12\", \"3\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"12000000\", \"3000000\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"12.0\", \"3.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(\"12000000.0\", \"3000000.0\"), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(2, 2), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(2, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(2000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(2.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(gte(2000000.0, 3000000.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(12, 3), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(12000000, 3000000), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(12.0, 3.0), \"true\", \"false\")}"));
        assertEquals("Invalid if(gte()) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(gte(12000000.0, 3000000.0), \"true\", \"false\")}"));
        // gte with null
        assertEquals("Invalid gte() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${gte(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid gte() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${gte(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid gte() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${gte(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + subt
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", subt(\"3\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", subt(\"4\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, subt(\"3\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, subt(3, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, subt(\"3\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, subt(3, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, subt(3, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, subt(\"3\", \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, subt(3, 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, subt(\"3\", 1)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, subt(3, \"1\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, subt(3, 1.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(20, subt(\"30\", \"10\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(subt())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(20, subt(\"30\", \"010\")), \"true\", \"false\")}"));
        // subt with null
        assertEquals("Invalid subt() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${subt(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid subt() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${subt(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid subt() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${subt(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + mult
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"6\", mult(\"3\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"6\", mult(\"4\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6, mult(\"3\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6, mult(3, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6, mult(\"3\", 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6, mult(3, \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6, mult(3, 2.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6.0, mult(\"3\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6.0, mult(3, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6.0, mult(\"3\", 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6.0, mult(3, \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(6.0, mult(3, 2.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(600, mult(\"30\", \"20\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(mult())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(600, mult(\"30\", \"020\")), \"true\", \"false\")}"));
        // mult with null
        assertEquals("Invalid mult() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${mult(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid mult() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${mult(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid mult() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${mult(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + quot
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"1.5\", quot(\"3\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"1.5\", quot(\"5\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.5, quot(\"3\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.5, quot(3, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.5, quot(\"3\", 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.5, quot(3, \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.5, quot(3, 2.0)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(15, quot(\"30\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(quot())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(15, quot(\"30\", \"02\")), \"true\", \"false\")}"));
        // quot with null
        assertEquals("Invalid quot() result with null value", "10.0", Scripting.replaceVariables(ctx, testOne, "${quot(10, this.alwaysNull)}"));
        assertEquals("Invalid quot() result with null value", "10.0", Scripting.replaceVariables(ctx, testOne, "${quot(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid quot() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${quot(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid quot() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${quot(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + round
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"1.9\", round(\"1.9\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", round(\"2.5\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", round(\"1.999999\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", round(\"2.499999\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(1.9, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2.5, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(1.999999, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2.499999, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.4, round(2.4, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.23, round(2.225234, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(1.9, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2.5, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(1.999999, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "false", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2.499999, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.999999, round(1.999999, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.499999, round(2.499999, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(1.999999999, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, round(2, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.4, round(2.4, 8)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(round())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.225234, round(2.225234, 8)), \"true\", \"false\")}"));
        // disabled because scientific notation is not supported :(
        // assertEquals("Invalid if(equal(round())) result", "true",  Scripting.replaceVariables(ctx, testOne, "${if(equal(0.00245, round(2.45e-3, 8)), \"true\", \"false\")}"));
        // assertEquals("Invalid if(equal(round())) result", "true",  Scripting.replaceVariables(ctx, testOne, "${if(equal(245, round(2.45e2, 8)), \"true\", \"false\")}"));
        // round with null
        assertEquals("Invalid round() result", "10", Scripting.replaceVariables(ctx, testOne, "${round(\"10\")}"));
        assertEquals("Invalid round() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${round(this.alwaysNull)}"));
        assertEquals("Invalid round() result with null value", RoundFunction.ERROR_MESSAGE_ROUND, Scripting.replaceVariables(ctx, testOne, "${round(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + max
        assertEquals("Invalid if(equal(max())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"2\", max(\"1.9\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(max())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, max(1.9, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(max())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(2.0, max(1.9, 2)), \"true\", \"false\")}"));
        // max with null
        assertEquals("Invalid max() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${max(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid max() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${max(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid max() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${max(this.alwaysNull, this.alwaysNull)}"));
        // if + equal + min
        assertEquals("Invalid if(equal(min())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(\"1.9\", min(\"1.9\", \"2\")), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(min())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1.9, min(1.9, 2)), \"true\", \"false\")}"));
        assertEquals("Invalid if(equal(min())) result", "true", Scripting.replaceVariables(ctx, testOne, "${if(equal(1, min(1, 2)), \"true\", \"false\")}"));
        // min with null
        assertEquals("Invalid min() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${min(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid min() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${min(this.alwaysNull, \"11\")}"));
        assertEquals("Invalid min() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${min(this.alwaysNull, this.alwaysNull)}"));
        // date_format
        assertEquals("Invalid date_format() result", nowString1, Scripting.replaceVariables(ctx, testOne, "${date_format(this.aDate, \"" + format1.toPattern() + "\")}"));
        assertEquals("Invalid date_format() result", nowString2, Scripting.replaceVariables(ctx, testOne, "${date_format(this.aDate, \"" + format2.toPattern() + "\")}"));
        assertEquals("Invalid date_format() result", nowString3, Scripting.replaceVariables(ctx, testOne, "${date_format(this.aDate, \"" + format3.toPattern() + "\")}"));
        // date_format with locale
        Locale locale = ctx.getLocale();
        ctx.setLocale(Locale.US);
        assertEquals("Invalid date_format() result", "01. Oct 2017", Scripting.replaceVariables(ctx, testOne, "${date_format(parse_date('01.10.2017', 'dd.MM.yyyy'), 'dd. MMM yyyy')}"));
        ctx.setLocale(Locale.GERMANY);
        assertEquals("Invalid date_format() result", "01. Okt 2017", Scripting.replaceVariables(ctx, testOne, "${date_format(parse_date('01.10.2017', 'dd.MM.yyyy'), 'dd. MMM yyyy')}"));
        ctx.setLocale(locale);
        // date_format with null
        assertEquals("Invalid date_format() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${date_format(this.alwaysNull, \"yyyy\")}"));
        assertEquals("Invalid date_format() result with null value", DateFormatFunction.ERROR_MESSAGE_DATE_FORMAT, Scripting.replaceVariables(ctx, testOne, "${date_format(\"10\", this.alwaysNull)}"));
        assertEquals("Invalid date_format() result with null value", DateFormatFunction.ERROR_MESSAGE_DATE_FORMAT, Scripting.replaceVariables(ctx, testOne, "${date_format(this.alwaysNull, this.alwaysNull)}"));
        // date_format error messages
        assertEquals("Invalid date_format() result for wrong number of parameters", DateFormatFunction.ERROR_MESSAGE_DATE_FORMAT, Scripting.replaceVariables(ctx, testOne, "${date_format()}"));
        assertEquals("Invalid date_format() result for wrong number of parameters", DateFormatFunction.ERROR_MESSAGE_DATE_FORMAT, Scripting.replaceVariables(ctx, testOne, "${date_format(this.aDouble)}"));
        assertEquals("Invalid date_format() result for wrong number of parameters", DateFormatFunction.ERROR_MESSAGE_DATE_FORMAT, Scripting.replaceVariables(ctx, testOne, "${date_format(this.aDouble, this.aDouble, this.aDouble)}"));
        // parse_date
        assertEquals("Invalid parse_date() result", ParseDateFunction.ERROR_MESSAGE_PARSE_DATE, Scripting.replaceVariables(ctx, testOne, "${parse_date('2015-12-12')}"));
        assertEquals("Invalid parse_date() result", "2015-12-12T00:00:00+0000", Scripting.replaceVariables(ctx, testOne, "${parse_date('2015-12-12', 'yyyy-MM-dd')}"));
        assertEquals("Invalid parse_date() result", "2015-12-12T00:00:00+0000", Scripting.replaceVariables(ctx, testOne, "${parse_date('2015-12-12', 'yyyy-MM-dd')}"));
        assertEquals("Invalid parse_date() result for wrong number of parameters", ParseDateFunction.ERROR_MESSAGE_PARSE_DATE, Scripting.replaceVariables(ctx, testOne, "${date_format(parse_date('2017-09-20T18:23:22+0200'), 'dd. MMM yyyy')}"));
        // to_date
        assertEquals("Invalid to_date() result", ToDateFunction.ERROR_MESSAGE_TO_DATE, Scripting.replaceVariables(ctx, testOne, "${to_date()}"));
        assertEquals("Invalid to_date() result", "2016-09-06T22:44:45+0000", Scripting.replaceVariables(ctx, testOne, "${to_date(1473201885000)}"));
        // number_format error messages
        assertEquals("Invalid number_format() result for wrong number of parameters", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format()}"));
        assertEquals("Invalid number_format() result for wrong number of parameters", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble)}"));
        assertEquals("Invalid number_format() result for wrong number of parameters", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, this.aDouble)}"));
        assertEquals("Invalid number_format() result for wrong number of parameters", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, this.aDouble, \"\", \"\")}"));
        assertEquals("Invalid number_format() result for wrong number of parameters", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, this.aDouble, \"\", \"\", \"\")}"));
        assertEquals("Invalid number_format() result", numberString1, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, \"en\", \"" + numberFormat1.toPattern() + "\")}"));
        assertEquals("Invalid number_format() result", numberString2, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, \"de\", \"" + numberFormat2.toPattern() + "\")}"));
        assertEquals("Invalid number_format() result", numberString3, Scripting.replaceVariables(ctx, testOne, "${number_format(this.aDouble, \"zh\", \"" + numberFormat3.toPattern() + "\")}"));
        assertEquals("Invalid number_format() result", "123456.79", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"en\", \"0.00\")}"));
        assertEquals("Invalid number_format() result", "123456.7890", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"en\", \"0.0000\")}"));
        assertEquals("Invalid number_format() result", "123456,79", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"de\", \"0.00\")}"));
        assertEquals("Invalid number_format() result", "123456,7890", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"de\", \"0.0000\")}"));
        assertEquals("Invalid number_format() result", "123456.79", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"zh\", \"0.00\")}"));
        assertEquals("Invalid number_format() result", "123456.7890", Scripting.replaceVariables(ctx, testOne, "${number_format(123456.789012, \"zh\", \"0.0000\")}"));
        // number_format with null
        assertEquals("Invalid number_format() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${number_format(this.alwaysNull, \"en\", \"#\")}"));
        assertEquals("Invalid number_format() result with null parameter(s)", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(\"10\", this.alwaysNull, this.alwaysNull)}"));
        assertEquals("Invalid number_format() result with null parameter(s)", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(\"10\", \"de\", this.alwaysNull)}"));
        assertEquals("Invalid number_format() result with null parameter(s)", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(\"10\", this.alwaysNull, \"#\")}"));
        assertEquals("Invalid number_format() result with null parameter(s)", NumberFormatFunction.ERROR_MESSAGE_NUMBER_FORMAT, Scripting.replaceVariables(ctx, testOne, "${number_format(this.alwaysNull, this.alwaysNull, this.alwaysNull)}"));
        // parse_number
        final Locale oldLocale = ctx.getLocale();
        ctx.setLocale(Locale.ENGLISH);
        assertEquals("Invalid parse_number() result", "123.456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123.456')}"));
        ctx.setLocale(oldLocale);
        assertEquals("Invalid parse_number() result", "123.456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123.456', 'en')}"));
        assertEquals("Invalid parse_number() result", "123.456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123,456', 'de')}"));
        assertEquals("Invalid parse_number() result", "123456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123456', 'de')}"));
        assertEquals("Invalid parse_number() result", "123456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123.456', 'de')}"));
        assertEquals("Invalid parse_number() result", "123456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123.456 €', 'de')}"));
        assertEquals("Invalid parse_number() result", "123456789", Scripting.replaceVariables(ctx, testOne, "${parse_number('£ 123,456,789.00 ', 'en')}"));
        assertEquals("Invalid parse_number() result", "123456789", Scripting.replaceVariables(ctx, testOne, "${parse_number('123,foo456,bar789.00 ', 'en')}"));
        assertEquals("Invalid parse_number() result", "123.456", Scripting.replaceVariables(ctx, testOne, "${parse_number('£ 123,456,789.00 ', 'de')}"));
        assertEquals("Invalid parse_number() result", "123.456", Scripting.replaceVariables(ctx, testOne, "${parse_number('123,foo456,bar789.00 ', 'de')}"));
        // not
        assertEquals("Invalid not() result", "true", Scripting.replaceVariables(ctx, testOne, "${not(false)}"));
        assertEquals("Invalid not() result", "false", Scripting.replaceVariables(ctx, testOne, "${not(true)}"));
        assertEquals("Invalid not() result", "true", Scripting.replaceVariables(ctx, testOne, "${not(\"false\")}"));
        assertEquals("Invalid not() result", "false", Scripting.replaceVariables(ctx, testOne, "${not(\"true\")}"));
        // not with null
        assertEquals("Invalid not() result with null value", "true", Scripting.replaceVariables(ctx, testOne, "${not(this.alwaysNull)}"));
        // and
        assertEquals("Invalid and() result", "true", Scripting.replaceVariables(ctx, testOne, "${and(true, true)}"));
        assertEquals("Invalid and() result", "false", Scripting.replaceVariables(ctx, testOne, "${and(true, false)}"));
        assertEquals("Invalid and() result", "false", Scripting.replaceVariables(ctx, testOne, "${and(false, true)}"));
        assertEquals("Invalid and() result", "false", Scripting.replaceVariables(ctx, testOne, "${and(false, false)}"));
        // and with null
        assertEquals("Invalid and() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${and(this.alwaysNull, this.alwaysNull)}"));
        // or
        assertEquals("Invalid or() result", "true", Scripting.replaceVariables(ctx, testOne, "${or(true, true)}"));
        assertEquals("Invalid or() result", "true", Scripting.replaceVariables(ctx, testOne, "${or(true, false)}"));
        assertEquals("Invalid or() result", "true", Scripting.replaceVariables(ctx, testOne, "${or(false, true)}"));
        assertEquals("Invalid or() result", "false", Scripting.replaceVariables(ctx, testOne, "${and(false, false)}"));
        // or with null
        assertEquals("Invalid or() result with null value", "false", Scripting.replaceVariables(ctx, testOne, "${or(this.alwaysNull, this.alwaysNull)}"));
        // get
        assertEquals("Invalid get() result", "1", Scripting.replaceVariables(ctx, testOne, "${get(this, \"anInt\")}"));
        assertEquals("Invalid get() result", "String", Scripting.replaceVariables(ctx, testOne, "${get(this, \"aString\")}"));
        assertEquals("Invalid get() result", "2.234", Scripting.replaceVariables(ctx, testOne, "${get(this, \"aDouble\")}"));
        assertEquals("Invalid get() result", testTwo.toString(), Scripting.replaceVariables(ctx, testOne, "${get(this, \"testTwo\")}"));
        assertEquals("Invalid get() result", testTwo.getUuid(), Scripting.replaceVariables(ctx, testOne, "${get(get(this, \"testTwo\"), \"id\")}"));
        assertEquals("Invalid get() result", testSixs.get(0).getUuid(), Scripting.replaceVariables(ctx, testOne, "${get(first(get(this, \"manyToManyTestSixs\")), \"id\")}"));
        // size
        assertEquals("Invalid size() result", "20", Scripting.replaceVariables(ctx, testOne, "${size(this.manyToManyTestSixs)}"));
        assertEquals("Invalid size() result", "0", Scripting.replaceVariables(ctx, testOne, "${size(null)}"));
        assertEquals("Invalid size() result", "0", Scripting.replaceVariables(ctx, testOne, "${size(xyz)}"));
        // is_collection
        assertEquals("Invalid is_collection() result", "true", Scripting.replaceVariables(ctx, testOne, "${is_collection(this.manyToManyTestSixs)}"));
        assertEquals("Invalid is_collection() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_collection(this.name)}"));
        assertEquals("Invalid is_collection() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_collection(null)}"));
        assertEquals("Invalid is_collection() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_collection(xyz)}"));
        // is_entity
        assertEquals("Invalid is_entity() result", "true", Scripting.replaceVariables(ctx, testOne, "${is_entity(this.testFour)}"));
        assertEquals("Invalid is_entity() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_entity(this.manyToManyTestSixs)}"));
        assertEquals("Invalid is_entity() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_entity(this.name)}"));
        assertEquals("Invalid is_entity() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_entity(null)}"));
        assertEquals("Invalid is_entity() result", "false", Scripting.replaceVariables(ctx, testOne, "${is_entity(xyz)}"));
        // first / last / nth
        assertEquals("Invalid first() result", testSixs.get(0).toString(), Scripting.replaceVariables(ctx, testOne, "${first(this.manyToManyTestSixs)}"));
        assertEquals("Invalid last() result", testSixs.get(19).toString(), Scripting.replaceVariables(ctx, testOne, "${last(this.manyToManyTestSixs)}"));
        assertEquals("Invalid nth() result", testSixs.get(2).toString(), Scripting.replaceVariables(ctx, testOne, "${nth(this.manyToManyTestSixs,  2)}"));
        assertEquals("Invalid nth() result", testSixs.get(7).toString(), Scripting.replaceVariables(ctx, testOne, "${nth(this.manyToManyTestSixs,  7)}"));
        assertEquals("Invalid nth() result", testSixs.get(9).toString(), Scripting.replaceVariables(ctx, testOne, "${nth(this.manyToManyTestSixs,  9)}"));
        assertEquals("Invalid nth() result", testSixs.get(12).toString(), Scripting.replaceVariables(ctx, testOne, "${nth(this.manyToManyTestSixs, 12)}"));
        assertEquals("Invalid nth() result", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.manyToManyTestSixs, 21)}"));
        // slice
        final Object sliceResult = Scripting.evaluate(ctx, testOne, "${slice(this.manyToManyTestSixs, 0, 5)}", "slice test");
        assertTrue("Invalid slice() result, must return collection for valid results", sliceResult instanceof Collection);
        assertTrue("Invalid slice() result, must return list for valid results", sliceResult instanceof List);
        final List sliceResultList = (List) sliceResult;
        assertEquals("Invalid slice() result, must return a list of 5 objects", 5, sliceResultList.size());
        // test error cases
        assertEquals("Invalid slice() result for invalid inputs", "", Scripting.replaceVariables(ctx, testOne, "${slice(this.alwaysNull, 1, 2)}"));
        assertEquals("Invalid slice() result for invalid inputs", "", Scripting.replaceVariables(ctx, testOne, "${slice(this.manyToManyTestSixs, -1, 1)}"));
        assertEquals("Invalid slice() result for invalid inputs", "", Scripting.replaceVariables(ctx, testOne, "${slice(this.manyToManyTestSixs, 2, 1)}"));
        // test with interval larger than number of elements
        assertEquals("Invalid slice() result for invalid inputs", testOne.getProperty(TestOne.manyToManyTestSixs).toString(), Scripting.replaceVariables(ctx, testOne, "${slice(this.manyToManyTestSixs, 0, 1000)}"));
        // slice with find
        final List sliceResult2 = (List) Scripting.evaluate(ctx, testOne, "${slice(find('TestSix'),  0,  5)}", "slice test");
        final List sliceResult3 = (List) Scripting.evaluate(ctx, testOne, "${slice(find('TestSix'),  5, 10)}", "slice test");
        final List sliceResult4 = (List) Scripting.evaluate(ctx, testOne, "${slice(find('TestSix'), 10, 15)}", "slice test");
        final List sliceResult5 = (List) Scripting.evaluate(ctx, testOne, "${slice(find('TestSix'), 15, 20)}", "slice test");
        assertEquals("Invalid slice() result, must return a list of 5 objects", 5, sliceResult2.size());
        assertEquals("Invalid slice() result, must return a list of 5 objects", 5, sliceResult3.size());
        assertEquals("Invalid slice() result, must return a list of 5 objects", 5, sliceResult4.size());
        assertEquals("Invalid slice() result, must return a list of 5 objects", 5, sliceResult5.size());
        assertEquals("Invalid slice() result", testSixs.get(0), sliceResult2.get(0));
        assertEquals("Invalid slice() result", testSixs.get(1), sliceResult2.get(1));
        assertEquals("Invalid slice() result", testSixs.get(2), sliceResult2.get(2));
        assertEquals("Invalid slice() result", testSixs.get(3), sliceResult2.get(3));
        assertEquals("Invalid slice() result", testSixs.get(4), sliceResult2.get(4));
        assertEquals("Invalid slice() result", testSixs.get(5), sliceResult3.get(0));
        assertEquals("Invalid slice() result", testSixs.get(6), sliceResult3.get(1));
        assertEquals("Invalid slice() result", testSixs.get(7), sliceResult3.get(2));
        assertEquals("Invalid slice() result", testSixs.get(8), sliceResult3.get(3));
        assertEquals("Invalid slice() result", testSixs.get(9), sliceResult3.get(4));
        assertEquals("Invalid slice() result", testSixs.get(10), sliceResult4.get(0));
        assertEquals("Invalid slice() result", testSixs.get(11), sliceResult4.get(1));
        assertEquals("Invalid slice() result", testSixs.get(12), sliceResult4.get(2));
        assertEquals("Invalid slice() result", testSixs.get(13), sliceResult4.get(3));
        assertEquals("Invalid slice() result", testSixs.get(14), sliceResult4.get(4));
        assertEquals("Invalid slice() result", testSixs.get(15), sliceResult5.get(0));
        assertEquals("Invalid slice() result", testSixs.get(16), sliceResult5.get(1));
        assertEquals("Invalid slice() result", testSixs.get(17), sliceResult5.get(2));
        assertEquals("Invalid slice() result", testSixs.get(18), sliceResult5.get(3));
        assertEquals("Invalid slice() result", testSixs.get(19), sliceResult5.get(4));
        // first / last / nth with null
        assertEquals("Invalid first() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${first(this.alwaysNull)}"));
        assertEquals("Invalid last() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${last(this.alwaysNull)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull,  2)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull,  7)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull,  9)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull, 12)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull, this.alwaysNull)}"));
        assertEquals("Invalid nth() result with null value", "", Scripting.replaceVariables(ctx, testOne, "${nth(this.alwaysNull, blah)}"));
        // each with null
        // get with null
        // set with null
        // set date (JS scripting)
        assertEquals("Setting the current date/time should not produce output (JS)", "", Scripting.replaceVariables(ctx, testOne, "${{var t = Structr.get('this'); t.aDate = new Date();}}"));
        try {
            // set date (old scripting)
            Scripting.replaceVariables(ctx, testOne, "${set(this, 'aDate', now)}");
        } catch (FrameworkException fex) {
            fail("Setting the current date/time should not cause an Exception (StructrScript)");
        }
        Scripting.replaceVariables(ctx, testOne, "${if(empty(this.alwaysNull), set(this, \"doResult\", true), set(this, \"doResult\", false))}");
        assertEquals("Invalid do() result", "true", Scripting.replaceVariables(ctx, testOne, "${this.doResult}"));
        Scripting.replaceVariables(ctx, testOne, "${if(empty(this.name), set(this, \"doResult\", true), set(this, \"doResult\", false))}");
        assertEquals("Invalid do() result", "false", Scripting.replaceVariables(ctx, testOne, "${this.doResult}"));
        // template method
        assertEquals("Invalid template() result", "This is a template for A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${template(\"TEST\", \"en_EN\", this)}"));
        // more complex tests
        Scripting.replaceVariables(ctx, testOne, "${each(split(\"setTestInteger1,setTestInteger2,setTestInteger3\"), set(this, data, 1))}");
        assertEquals("Invalid each() result", "1", Scripting.replaceVariables(ctx, testOne, "${get(this, \"setTestInteger1\")}"));
        assertEquals("Invalid each() result", "1", Scripting.replaceVariables(ctx, testOne, "${get(this, \"setTestInteger2\")}"));
        assertEquals("Invalid each() result", "1", Scripting.replaceVariables(ctx, testOne, "${get(this, \"setTestInteger3\")}"));
        // each expression
        assertEquals("Invalid each() result", "abc", Scripting.replaceVariables(ctx, testOne, "${each(split('a,b,c', ','), print(data))}"));
        assertEquals("Invalid each() result", "abc", Scripting.replaceVariables(ctx, testOne, "${each(this.aStringArray, print(data))}"));
        // complex each expression, sets the value of "testString" to the concatenated IDs of all testSixs that are linked to "this"
        Scripting.replaceVariables(ctx, testOne, "${each(this.manyToManyTestSixs, set(this, \"testString\", concat(get(this, \"testString\"), data.id)))}");
        assertEquals("Invalid each() result", "640", Scripting.replaceVariables(ctx, testOne, "${length(this.testString)}"));
        assertEquals("Invalid if(equal()) result", "String", Scripting.replaceVariables(ctx, testOne, "${if(empty(this.alwaysNull), titleize(this.aString, '-'), this.alwaysNull)}"));
        assertEquals("Invalid if(equal()) result", "String", Scripting.replaceVariables(ctx, testOne, "${if(empty(this.aString), titleize(this.alwaysNull, '-'), this.aString)}"));
        assertNull("Invalid result for special null value", Scripting.replaceVariables(ctx, testOne, "${null}"));
        assertNull("Invalid result for special null value", Scripting.replaceVariables(ctx, testOne, "${if(equal(this.anInt, 15), \"selected\", null)}"));
        // tests from real-life examples
        assertEquals("Invalid replacement result", "tile plan ", Scripting.replaceVariables(ctx, testOne, "tile plan ${plan.bannerTag}"));
        // more tests with pre- and postfixes
        assertEquals("Invalid replacement result", "abcdefghijklmnop", Scripting.replaceVariables(ctx, testOne, "abcdefgh${blah}ijklmnop"));
        assertEquals("Invalid replacement result", "abcdefghStringijklmnop", Scripting.replaceVariables(ctx, testOne, "abcdefgh${this.aString}ijklmnop"));
        assertEquals("Invalid replacement result", "#String", Scripting.replaceVariables(ctx, testOne, "#${this.aString}"));
        assertEquals("Invalid replacement result", "doc_sections/" + testOne.getUuid() + "/childSections?sort=pos", Scripting.replaceVariables(ctx, testOne, "doc_sections/${this.id}/childSections?sort=pos"));
        assertEquals("Invalid replacement result", "A Nice Little Name For My Test Object", Scripting.replaceVariables(ctx, testOne, "${titleize(this.name, '-')}"));
        assertEquals("Invalid replacement result", "STRINGtrueFALSE", Scripting.replaceVariables(ctx, testOne, "${upper(this.aString)}${lower(true)}${upper(false)}"));
        // null and NULL_STRING
        assertEquals("Invalid result for ___NULL___", null, Scripting.replaceVariables(ctx, testOne, "${null}"));
        assertEquals("Invalid result for ___NULL___", null, Scripting.replaceVariables(ctx, testOne, "${___NULL___}"));
        assertEquals("Invalid result for ___NULL___", null, Scripting.replaceVariables(ctx, testOne, "${is(true, ___NULL___)}"));
        assertEquals("Invalid result for ___NULL___", null, Scripting.replaceVariables(ctx, testOne, "${is(false, ___NULL___)}"));
        assertEquals("Invalid result for ___NULL___", "xy", Scripting.replaceVariables(ctx, testOne, "x${___NULL___}y"));
        assertEquals("Invalid result for ___NULL___", "xz", Scripting.replaceVariables(ctx, testOne, "x${is(true, ___NULL___)}z"));
        assertEquals("Invalid result for ___NULL___", "xz", Scripting.replaceVariables(ctx, testOne, "x${is(false, ___NULL___)}z"));
        // test store and retrieve
        assertEquals("Invalid store() result", "", Scripting.replaceVariables(ctx, testOne, "${store('tmp', this.name)}"));
        assertEquals("Invalid stored value", "A-nice-little-name-for-my-test-object", ctx.retrieve("tmp"));
        assertEquals("Invalid retrieve() result", "A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${retrieve('tmp')}"));
        assertEquals("Invalid retrieve() result", "", Scripting.replaceVariables(new ActionContext(SecurityContext.getSuperUserInstance()), testOne, "${retrieve('tmp')}"));
        // test store and retrieve within filter expression
        assertEquals("Invalid store() result", "", Scripting.replaceVariables(ctx, testOne, "${store('tmp', 10)}"));
        assertEquals("Invalid retrieve() result in filter expression", "9", Scripting.replaceVariables(ctx, testOne, "${size(filter(this.manyToManyTestSixs, gt(data.index, 10)))}"));
        assertEquals("Invalid retrieve() result in filter expression", "9", Scripting.replaceVariables(ctx, testOne, "${size(filter(this.manyToManyTestSixs, gt(data.index, retrieve('tmp'))))}"));
        // retrieve object and access attribute
        assertEquals("Invalid store() result", "", Scripting.replaceVariables(ctx, testOne, "${store('testOne', this)}"));
        assertEquals("Invalid retrieve() result", "A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${retrieve('testOne').name}"));
        // retrieve stored object attribute in if() expression via get() function
        assertEquals("Invalid retrieve() result", "A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${if(false,'true', get(retrieve('testOne'), 'name'))}"));
        // retrieve stored object attribute in if() expression via 'dot-name'
        assertEquals("Invalid retrieve() result", "A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${if(false,'true', retrieve('testOne').name)}"));
        // test replace() method
        assertEquals("Invalid replace() result", "A-nice-little-name-for-my-test-object", Scripting.replaceVariables(ctx, testOne, "${replace(this.replaceString, this)}"));
        // test error method
        try {
            Actions.execute(securityContext, testTwo, "${error(\"base\", \"test1\")}", "test");
            fail("error() should throw an exception.");
        } catch (UnlicensedException | FrameworkException fex) {
        }
        try {
            Actions.execute(securityContext, testTwo, "${error(\"base\", \"test1\", \"test2\")}", "test");
            fail("error() should throw an exception.");
        } catch (UnlicensedException | FrameworkException fex) {
        }
        // test multiline statements
        assertEquals("Invalid replace() result", "equal", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, 2),\n    (\"equal\"),\n    (\"not equal\")\n)}"));
        assertEquals("Invalid replace() result", "not equal", Scripting.replaceVariables(ctx, testOne, "${if(equal(2, 3),\n    (\"equal\"),\n    (\"not equal\")\n)}"));
        assertEquals("Invalid keys() / join() result", "id,name,owner,type,createdBy,deleted,hidden,createdDate,lastModifiedDate,visibleToPublicUsers,visibleToAuthenticatedUsers", Scripting.replaceVariables(ctx, testOne, "${join(keys(this, 'ui'), ',')}"));
        assertEquals("Invalid values() / join() result", "A-nice-little-name-for-my-test-object,1,String", Scripting.replaceVariables(ctx, testOne, "${join(values(this, 'protected'), ',')}"));
        // test default values
        assertEquals("Invalid string default value", "blah", Scripting.replaceVariables(ctx, testOne, "${this.alwaysNull!blah}"));
        assertEquals("Invalid numeric default value", "12", Scripting.replaceVariables(ctx, testOne, "${this.alwaysNull!12}"));
        // Number default value
        assertEquals("true", Scripting.replaceVariables(ctx, testOne, "${equal(42, this.alwaysNull!42)}"));
        // complex multi-statement tests
        Scripting.replaceVariables(ctx, testOne, "${(set(this, \"isValid\", true), each(this.manyToManyTestSixs, set(this, \"isValid\", and(this.isValid, equal(length(data.id), 32)))))}");
        assertEquals("Invalid multiline statement test result", "true", Scripting.replaceVariables(ctx, testOne, "${this.isValid}"));
        Scripting.replaceVariables(ctx, testOne, "${(set(this, \"isValid\", true), each(this.manyToManyTestSixs, set(this, \"isValid\", and(this.isValid, gte(now, data.createdDate)))))}");
        assertEquals("Invalid multiline statement test result", "true", Scripting.replaceVariables(ctx, testOne, "${this.isValid}"));
        Scripting.replaceVariables(ctx, testOne, "${(set(this, \"isValid\", false), each(this.manyToManyTestSixs, set(this, \"isValid\", and(this.isValid, gte(now, data.createdDate)))))}");
        assertEquals("Invalid multiline statement test result", "false", Scripting.replaceVariables(ctx, testOne, "${this.isValid}"));
        // test multiple nested dot-separated properties (this.parent.parent.parent)
        assertEquals("Invalid multilevel property expression result", "false", Scripting.replaceVariables(ctx, testOne, "${empty(this.testThree.testOne.testThree)}"));
        // test extract() with additional evaluation function
        assertEquals("Invalid filter() result", "1", Scripting.replaceVariables(ctx, testOne, "${size(filter(this.manyToManyTestSixs, equal(data.index, 4)))}"));
        assertEquals("Invalid filter() result", "9", Scripting.replaceVariables(ctx, testOne, "${size(filter(this.manyToManyTestSixs, gt(data.index, 10)))}"));
        assertEquals("Invalid filter() result", "10", Scripting.replaceVariables(ctx, testOne, "${size(filter(this.manyToManyTestSixs, gte(data.index, 10)))}"));
        // test complex multiline statement replacement
        final String test = // first expression should evaluate to ">2"
        "${if(lte(template('TEST2', 'en_EN', this), 2), '<2', '>2')}\n" + // second expression should evaluate to "<3"
        "${if(lte(template('TEST2', 'en_EN', this), 3), '<3', '>3')}";
        final String result = Scripting.replaceVariables(ctx, testOne, test);
        assertEquals("Invalid multiline and template() result", ">2\n<3", result);
        // incoming
        assertEquals("Invalid number of incoming relationships", "20", Scripting.replaceVariables(ctx, testOne, "${size(incoming(this))}"));
        assertEquals("Invalid number of incoming relationships", "20", Scripting.replaceVariables(ctx, testOne, "${size(incoming(this, 'MANY_TO_MANY'))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testTwo, "${size(incoming(this))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testThree, "${size(incoming(this))}"));
        assertEquals("Invalid relationship type", "IS_AT", Scripting.replaceVariables(ctx, testTwo, "${get(incoming(this), 'relType')}"));
        assertEquals("Invalid relationship type", "OWNS", Scripting.replaceVariables(ctx, testThree, "${get(incoming(this), 'relType')}"));
        // outgoing
        assertEquals("Invalid number of outgoing relationships", "3", Scripting.replaceVariables(ctx, testOne, "${size(outgoing(this))}"));
        assertEquals("Invalid number of outgoing relationships", "2", Scripting.replaceVariables(ctx, testOne, "${size(outgoing(this, 'IS_AT'))}"));
        assertEquals("Invalid number of outgoing relationships", "1", Scripting.replaceVariables(ctx, testOne, "${size(outgoing(this, 'OWNS' ))}"));
        assertEquals("Invalid relationship type", "IS_AT", Scripting.replaceVariables(ctx, testOne, "${get(first(outgoing(this, 'IS_AT')), 'relType')}"));
        assertEquals("Invalid relationship type", "OWNS", Scripting.replaceVariables(ctx, testOne, "${get(outgoing(this, 'OWNS'), 'relType')}"));
        // has_relationships
        assertEquals("Invalid result of has_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, this)}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')))}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'IS_AT')}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')}"));
        assertEquals("Invalid result of has_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testTwo, "${has_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this)}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testTwo, "${has_relationship(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')))}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestThree', 'name', 'testThree_name')))}"));
        assertEquals("Invalid result of has_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'OWNS')}"));
        assertEquals("Invalid result of has_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'THIS_DOES_NOT_EXIST')}"));
        // has_incoming_relationship
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, this)}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this)}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')))}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'IS_AT')}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testTwo, "${has_incoming_relationship(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')))}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_incoming_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this)}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestThree', 'name', 'testThree_name')))}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestThree', 'name', 'testThree_name')), this)}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'OWNS')}"));
        assertEquals("Invalid result of has_incoming_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'OWNS')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_incoming_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_incoming_relationship(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_incoming_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_incoming_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        // has_outgoing_relationship (since has_outgoing_relationship is just the inverse method to has_outgoing_relationship we can basically reuse the tests and just invert the result - except for the always-false or always-true tests)
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, this)}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this)}"));
        assertEquals("Invalid result of has_outgoing_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')))}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'IS_AT')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestTwo', 'name', 'testTwo_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_outgoing_relationship(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')))}"));
        assertEquals("Invalid result of has_outgoing_relationship", "true", Scripting.replaceVariables(ctx, testTwo, "${has_outgoing_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this)}"));
        assertEquals("Invalid result of has_outgoing_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestThree', 'name', 'testThree_name')))}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestThree', 'name', 'testThree_name')), this)}"));
        assertEquals("Invalid result of has_outgoing_relationship", "true", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'OWNS')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'OWNS')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_outgoing_relationship(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testTwo, "${has_outgoing_relationship(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(this, first(find('TestThree', 'name', 'testThree_name')), 'THIS_DOES_NOT_EXIST')}"));
        assertEquals("Invalid result of has_outgoing_relationship", "false", Scripting.replaceVariables(ctx, testOne, "${has_outgoing_relationship(first(find('TestThree', 'name', 'testThree_name')), this, 'THIS_DOES_NOT_EXIST')}"));
        // get_relationships (CAUTION! If the method returns a string (error-case) the size-method returns "1" => it seems like there is one relationsh)
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_relationships(this, this))}"));
        // non-existent relType between nodes which have a relationship
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'THIS_DOES_NOT_EXIST'))}"));
        // non-existent relType between a node and itself
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'THIS_DOES_NOT_EXIST'))}"));
        // identical result test (from and to are just switched around)
        assertEquals("Invalid number of relationships", "1", Scripting.replaceVariables(ctx, testTwo, "${size(get_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'IS_AT'))}"));
        assertEquals("Invalid number of relationships", "1", Scripting.replaceVariables(ctx, testTwo, "${size(get_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), 'IS_AT'))}"));
        // get_incoming_relationships (CAUTION! If the method returns a string (error-case) the size-method returns "1" => it seems like there is one relationsh)
        assertEquals("Invalid number of incoming relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_incoming_relationships(this, this))}"));
        assertEquals("Invalid number of incoming relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_incoming_relationships(this, first(find('TestTwo', 'name', 'testTwo_name'))))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testOne, "${size(get_incoming_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this))}"));
        assertEquals("Invalid number of incoming relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_incoming_relationships(this, first(find('TestTwo', 'name', 'testTwo_name')), 'IS_AT'))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testOne, "${size(get_incoming_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT'))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testTwo, "${size(get_incoming_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object'))))}"));
        assertEquals("Invalid number of incoming relationships", "1", Scripting.replaceVariables(ctx, testThree, "${size(get_incoming_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object'))))}"));
        assertEquals("Invalid relationship type", "IS_AT", Scripting.replaceVariables(ctx, testTwo, "${get(first(get_incoming_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')))), 'relType')}"));
        assertEquals("Invalid relationship type", "OWNS", Scripting.replaceVariables(ctx, testThree, "${get(first(get_incoming_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')))), 'relType')}"));
        // get_outgoing_relationships (CAUTION! If the method returns a string (error-case) the size-method returns "1" => it seems like there is one relationsh)
        assertEquals("Invalid number of outgoing relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this))}"));
        assertEquals("Invalid number of outgoing relationships", "0", Scripting.replaceVariables(ctx, testTwo, "${size(get_outgoing_relationships(this, first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object'))))}"));
        assertEquals("Invalid number of outgoing relationships", "1", Scripting.replaceVariables(ctx, testTwo, "${size(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this))}"));
        assertEquals("Invalid number of outgoing relationships", "0", Scripting.replaceVariables(ctx, testTwo, "${size(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this, 'THIS_DOES_NOT_EXIST'))}"));
        assertEquals("Invalid number of outgoing relationships", "1", Scripting.replaceVariables(ctx, testThree, "${size(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this))}"));
        assertEquals("Invalid relationship type", "IS_AT", Scripting.replaceVariables(ctx, testTwo, "${get(first(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this)), 'relType')}"));
        assertEquals("Invalid relationship type", "OWNS", Scripting.replaceVariables(ctx, testThree, "${get(first(get_outgoing_relationships(first(find('TestOne', 'name', 'A-nice-little-name-for-my-test-object')), this)), 'relType')}"));
        // create_relationship
        // lifecycle for relationship t1-[:NEW_RELATIONSHIP_NAME]->t1
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(this, this, 'IS_AT'))}"));
        assertEquals("unexpected result of create_relationship", "IS_AT", Scripting.replaceVariables(ctx, testOne, "${get(create_relationship(this, this, 'IS_AT'), 'relType')}"));
        assertEquals("Invalid number of relationships", "1", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(this, this, 'IS_AT'))}"));
        assertEquals("unexpected result of delete", "", Scripting.replaceVariables(ctx, testOne, "${delete(first(get_outgoing_relationships(this, this, 'IS_AT')))}"));
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(this, this, 'IS_AT'))}"));
        // lifecycle for relationship t2-[:NEW_RELATIONSHIP_NAME]->t1
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT'))}"));
        assertEquals("unexpected result of create_relationship", "IS_AT", Scripting.replaceVariables(ctx, testOne, "${get(create_relationship(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT'), 'relType')}"));
        assertEquals("Invalid number of relationships", "1", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT'))}"));
        assertEquals("unexpected result of delete", "", Scripting.replaceVariables(ctx, testOne, "${delete(first(get_outgoing_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT')))}"));
        assertEquals("Invalid number of relationships", "0", Scripting.replaceVariables(ctx, testOne, "${size(get_outgoing_relationships(first(find('TestTwo', 'name', 'testTwo_name')), this, 'IS_AT'))}"));
        // array index access
        assertEquals("Invalid array index accessor result", testSixs.get(0).getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs[0]}"));
        assertEquals("Invalid array index accessor result", testSixs.get(2).getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs[2]}"));
        assertEquals("Invalid array index accessor result", testSixs.get(4).getUuid(), Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs[4]}"));
        // test new dot notation
        assertEquals("Invalid dot notation result", testSixs.get(0).getProperty(AbstractNode.name), Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs[0].name}"));
        assertEquals("Invalid dot notation result", testSixs.get(0).getProperty(AbstractNode.name), Scripting.replaceVariables(ctx, testOne, "${sort(find('TestSix'), 'name')[0].name}"));
        assertEquals("Invalid dot notation result", testSixs.get(15).getProperty(AbstractNode.name), Scripting.replaceVariables(ctx, testOne, "${sort(find('TestSix'), 'name')[15].name}"));
        assertEquals("Invalid dot notation result", "20", Scripting.replaceVariables(ctx, testOne, "${this.manyToManyTestSixs.size}"));
        // test array property access
        assertEquals("Invalid string array access result", "one", Scripting.replaceVariables(ctx, testFour, "${this.stringArrayProperty[0]}"));
        assertEquals("Invalid string array access result", "two", Scripting.replaceVariables(ctx, testFour, "${this.stringArrayProperty[1]}"));
        assertEquals("Invalid string array access result", "three", Scripting.replaceVariables(ctx, testFour, "${this.stringArrayProperty[2]}"));
        assertEquals("Invalid string array access result", "four", Scripting.replaceVariables(ctx, testFour, "${this.stringArrayProperty[3]}"));
        // test string array property support in collection access methods
        assertEquals("Invalid string array access result with join()", "one,two,three,four", Scripting.replaceVariables(ctx, testFour, "${join(this.stringArrayProperty, ',')}"));
        assertEquals("Invalid string array access result with concat()", "onetwothreefour", Scripting.replaceVariables(ctx, testFour, "${concat(this.stringArrayProperty)}"));
        assertEquals("Invalid string array access result with slice()", "two,three", Scripting.replaceVariables(ctx, testFour, "${join(slice(this.stringArrayProperty, 1, 3), ',')}"));
        assertEquals("Invalid string array access result with first()", "one", Scripting.replaceVariables(ctx, testFour, "${first(this.stringArrayProperty)}"));
        assertEquals("Invalid string array access result with last()", "four", Scripting.replaceVariables(ctx, testFour, "${last(this.stringArrayProperty)}"));
        assertEquals("Invalid string array access result with size()", "4", Scripting.replaceVariables(ctx, testFour, "${size(this.stringArrayProperty)}"));
        assertEquals("Invalid string array access result with .size", "4", Scripting.replaceVariables(ctx, testFour, "${this.stringArrayProperty.size}"));
        assertEquals("Invalid string array access result with nth", "one", Scripting.replaceVariables(ctx, testFour, "${nth(this.stringArrayProperty, 0)}"));
        assertEquals("Invalid string array access result with nth", "two", Scripting.replaceVariables(ctx, testFour, "${nth(this.stringArrayProperty, 1)}"));
        assertEquals("Invalid string array access result with nth", "three", Scripting.replaceVariables(ctx, testFour, "${nth(this.stringArrayProperty, 2)}"));
        assertEquals("Invalid string array access result with nth", "four", Scripting.replaceVariables(ctx, testFour, "${nth(this.stringArrayProperty, 3)}"));
        assertEquals("Invalid string array access result with contains()", "true", Scripting.replaceVariables(ctx, testFour, "${contains(this.stringArrayProperty, 'two')}"));
        assertEquals("Invalid string array access result with contains()", "false", Scripting.replaceVariables(ctx, testFour, "${contains(this.stringArrayProperty, 'five')}"));
        // sort
        assertEquals("Invalid sort result", "[b, a, c]", Scripting.replaceVariables(ctx, null, "${merge('b', 'a', 'c')}"));
        assertEquals("Invalid sort result", "[a, b, c]", Scripting.replaceVariables(ctx, null, "${sort(merge('b', 'a', 'c'))}"));
        assertEquals("Invalid sort result", "", Scripting.replaceVariables(ctx, null, "${sort()}"));
        assertEquals("Invalid sort result", "[A-nice-little-name-for-my-test-object, testThree_name, testTwo_name]", Scripting.replaceVariables(ctx, testOne, "${extract(sort(merge(this, this.testTwo, this.testThree), 'name'), 'name')}"));
        assertEquals("Invalid sort result", "[A-nice-little-name-for-my-test-object, testThree_name, testTwo_name]", Scripting.replaceVariables(ctx, testOne, "${extract(sort(merge(this.testTwo, this, this.testThree), 'name'), 'name')}"));
        assertEquals("Invalid sort result", "[A-nice-little-name-for-my-test-object, testThree_name, testTwo_name]", Scripting.replaceVariables(ctx, testOne, "${extract(sort(merge(this.testTwo, this.testThree, this), 'name'), 'name')}"));
        // find
        assertEquals("Invalid find() result for empty values", testThree.getUuid(), Scripting.replaceVariables(ctx, testOne, "${first(find('TestThree', 'oneToOneTestSix', this.alwaysNull))}"));
        assertEquals("Invalid find() result for empty values", testThree.getUuid(), Scripting.replaceVariables(ctx, testOne, "${first(find('TestThree', 'oneToManyTestSix', this.alwaysNull))}"));
        // find with incorrect number of parameters
        assertEquals("Invalid find() result", FindFunction.ERROR_MESSAGE_FIND_NO_TYPE_SPECIFIED, Scripting.replaceVariables(ctx, testOne, "${find()}"));
        assertEquals("Invalid find() result", FindFunction.ERROR_MESSAGE_FIND_NO_TYPE_SPECIFIED, Scripting.replaceVariables(ctx, testOne, "${find(this.alwaysNull)}"));
        assertEquals("Invalid find() result", FindFunction.ERROR_MESSAGE_FIND_NO_TYPE_SPECIFIED, Scripting.replaceVariables(ctx, testOne, "${find(this.alwaysNull, this.alwaysNull)}"));
        assertEquals("Invalid find() result", FindFunction.ERROR_MESSAGE_FIND_TYPE_NOT_FOUND + "NonExistingType", Scripting.replaceVariables(ctx, testOne, "${find('NonExistingType')}"));
        // search
        assertEquals("Invalid search() result", testOne.getUuid(), Scripting.replaceVariables(ctx, testTwo, "${first(search('TestOne', 'name', 'A-nice-little-name-for-my-test-object'))}"));
        assertEquals("Invalid search() result", testOne.getUuid(), Scripting.replaceVariables(ctx, testTwo, "${first(search('TestOne', 'name', 'little-name-for-my-test-object'))}"));
        assertEquals("Invalid search() result", testOne.getUuid(), Scripting.replaceVariables(ctx, testTwo, "${first(search('TestOne', 'name', 'A-nice-little-name-for'))}"));
        // negative test for find()
        assertEquals("Invalid find() result", "", Scripting.replaceVariables(ctx, testTwo, "${first(find('TestOne', 'name', 'little-name-for-my-test-object'))}"));
        assertEquals("Invalid find() result", "", Scripting.replaceVariables(ctx, testTwo, "${first(find('TestOne', 'name', 'A-nice-little-name-for'))}"));
        // create
        Integer noOfOnes = 1;
        assertEquals("Invalid number of TestOne's", "" + noOfOnes, Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne'))}"));
        // currently the creation of nodes must take place in a node of another type
        Scripting.replaceVariables(ctx, testFour, "${create('TestOne', 'name', 'createTestOne1')}");
        noOfOnes++;
        assertEquals("Invalid number of TestOne's", "" + noOfOnes, Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne1'))}"));
        Scripting.replaceVariables(ctx, testFour, "${create('TestOne', 'name', 'createTestOne1')}");
        noOfOnes++;
        assertEquals("Invalid number of TestOne's", "" + noOfOnes, Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne'))}"));
        assertEquals("Invalid number of TestOne's", "2", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne1'))}"));
        // currently this must be executed on another node type
        Scripting.replaceVariables(ctx, testFour, "${create('TestOne', 'name', 'createTestOne2', 'aCreateString', 'newCreateString1')}");
        noOfOnes++;
        assertEquals("Invalid number of TestOne's", "" + noOfOnes, Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2'))}"));
        assertEquals("Invalid number of TestOne's", "0", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'aCreateString', 'DOES_NOT_EXIST'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'aCreateString', 'newCreateString1'))}"));
        assertEquals("Invalid number of TestOne's", "0", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2', 'aCreateString', 'NOT_newCreateString1'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2', 'aCreateString', 'newCreateString1'))}"));
        // currently this must be executed on another node type
        Scripting.replaceVariables(ctx, testFour, "${create('TestOne', 'name', 'createTestOne2', 'aCreateInt', '256')}");
        noOfOnes++;
        assertEquals("Invalid number of TestOne's", "" + noOfOnes, Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne'))}"));
        assertEquals("Invalid number of TestOne's", "2", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'aCreateInt', '256'))}"));
        assertEquals("Invalid number of TestOne's", "0", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2', 'aCreateInt', '255'))}"));
        assertEquals("Invalid number of TestOne's", "1", Scripting.replaceVariables(ctx, testOne, "${size(find('TestOne', 'name', 'createTestOne2', 'aCreateInt', '256'))}"));
        // test parser with different quote leves etc.
        assertEquals("Parser does not handle quotes correctly,", "test\"test", Scripting.replaceVariables(ctx, testOne, "${join(merge('test', 'test'), '\"')}"));
        assertEquals("Parser does not handle quotes correctly,", "test\'test", Scripting.replaceVariables(ctx, testOne, "${join(merge('test', 'test'), '\\'')}"));
        assertEquals("Parser does not handle quotes correctly,", "test\"test", Scripting.replaceVariables(ctx, testOne, "${join(merge(\"test\", \"test\"), \"\\\"\")}"));
        assertEquals("Parser does not handle quotes correctly,", "test\'test", Scripting.replaceVariables(ctx, testOne, "${join(merge(\"test\", \"test\"), \"\\'\")}"));
        // get_or_create()
        final String newUuid1 = Scripting.replaceVariables(ctx, null, "${get_or_create('TestOne', 'name', 'new-object-1')}");
        assertNotNull("Invalid get_or_create() result", newUuid1);
        assertEquals("Invalid get_or_create() result", newUuid1, Scripting.replaceVariables(ctx, null, "${get_or_create('TestOne', 'name', 'new-object-1')}"));
        assertEquals("Invalid get_or_create() result", newUuid1, Scripting.replaceVariables(ctx, null, "${get_or_create('TestOne', 'name', 'new-object-1')}"));
        assertEquals("Invalid get_or_create() result", newUuid1, Scripting.replaceVariables(ctx, null, "${get_or_create('TestOne', 'name', 'new-object-1')}"));
        // get_or_create()
        final String newUuid2 = Scripting.replaceVariables(ctx, null, "${{ Structr.getOrCreate('TestOne', { 'name': 'new-object-2', 'anInt': 13, 'aString': 'string' }) }}");
        assertNotNull("Invalid get_or_create() result", newUuid2);
        assertEquals("Invalid get_or_create() result", newUuid2, Scripting.replaceVariables(ctx, null, "${{ Structr.getOrCreate('TestOne', { 'name': 'new-object-2', 'anInt': 13, 'aString': 'string' }) }}"));
        assertEquals("Invalid get_or_create() result", newUuid2, Scripting.replaceVariables(ctx, null, "${{ Structr.getOrCreate('TestOne', { 'name': 'new-object-2', 'anInt': 13, 'aString': 'string' }) }}"));
        assertEquals("Invalid get_or_create() result", newUuid2, Scripting.replaceVariables(ctx, null, "${{ Structr.getOrCreate('TestOne', { 'name': 'new-object-2', 'anInt': 13, 'aString': 'string' }) }}"));
        tx.success();
    } catch (FrameworkException fex) {
        logger.warn("", fex);
        fail(fex.getMessage());
    }
}
Also used : Locale(java.util.Locale) TestFour(org.structr.core.entity.TestFour) Tx(org.structr.core.graph.Tx) FrameworkException(org.structr.common.error.FrameworkException) DecimalFormat(java.text.DecimalFormat) ActionContext(org.structr.schema.action.ActionContext) Date(java.util.Date) UnlicensedException(org.structr.common.error.UnlicensedException) TestTwo(org.structr.core.entity.TestTwo) TestThree(org.structr.core.entity.TestThree) Collection(java.util.Collection) GraphObject(org.structr.core.GraphObject) List(java.util.List) LinkedList(java.util.LinkedList) TestOne(org.structr.core.entity.TestOne) SimpleDateFormat(java.text.SimpleDateFormat) NodeInterface(org.structr.core.graph.NodeInterface) TestSix(org.structr.core.entity.TestSix) StructrTest(org.structr.common.StructrTest) Test(org.junit.Test)

Aggregations

Test (org.junit.Test)5 FrameworkException (org.structr.common.error.FrameworkException)5 TestOne (org.structr.core.entity.TestOne)5 TestTwo (org.structr.core.entity.TestTwo)5 Tx (org.structr.core.graph.Tx)5 StructrTest (org.structr.common.StructrTest)3 Date (java.util.Date)2 UnlicensedException (org.structr.common.error.UnlicensedException)2 TestFour (org.structr.core.entity.TestFour)2 TestSix (org.structr.core.entity.TestSix)2 TestThree (org.structr.core.entity.TestThree)2 ActionContext (org.structr.schema.action.ActionContext)2 DecimalFormat (java.text.DecimalFormat)1 SimpleDateFormat (java.text.SimpleDateFormat)1 Collection (java.util.Collection)1 LinkedList (java.util.LinkedList)1 List (java.util.List)1 Locale (java.util.Locale)1 Random (java.util.Random)1 GraphObject (org.structr.core.GraphObject)1