Package nodebox.node

Source Code of nodebox.node.NodeContextTest

package nodebox.node;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import nodebox.function.*;
import nodebox.graphics.Color;
import nodebox.graphics.Point;
import nodebox.util.SideEffects;
import org.junit.Before;
import org.junit.Test;

import java.util.List;

import static junit.framework.TestCase.*;
import static nodebox.util.Assertions.assertNoResults;
import static nodebox.util.Assertions.assertResultsEqual;

public class NodeContextTest {

    public static final Node numberNode = Node.ROOT
            .withName("number")
            .withFunction("math/number")
            .withInputAdded(Port.floatPort("number", 0));

    public static final Node valuesToPointNode = Node.ROOT
            .withName("values_to_point")
            .withFunction("corevector/makePoint")
            .withOutputType("point")
            .withInputAdded(Port.floatPort("x", 0))
            .withInputAdded(Port.floatPort("y", 0));

    public static final Node addNode = Node.ROOT
            .withName("add")
            .withFunction("math/add")
            .withInputAdded(Port.floatPort("v1", 0.0))
            .withInputAdded(Port.floatPort("v2", 0.0));

    public static final Node invertNode = Node.ROOT
            .withName("negate")
            .withFunction("math/negate")
            .withInputAdded(Port.floatPort("value", 0.0));

    public static final Node makeNumbersNode = Node.ROOT
            .withName("makeNumbers")
            .withFunction("math/makeNumbers")
            .withOutputRange(Port.Range.LIST)
            .withInputAdded(Port.stringPort("string", ""))
            .withInputAdded(Port.stringPort("separator", " "));

    public static final Node threeNumbers = makeNumbersNode
            .extend()
            .withName("threeNumbers")
            .withInputValue("string", "1 2 3");

    public static final Node fiveNumbers = makeNumbersNode
            .extend()
            .withName("fiveNumbers")
            .withInputValue("string", "100 200 300 400 500");

    public static final Node makeStringsNode = Node.ROOT
            .withName("makeStrings")
            .withFunction("string/makeStrings")
            .withOutputRange(Port.Range.LIST)
            .withInputAdded(Port.stringPort("string", "Alpha;Beta;Gamma"))
            .withInputAdded(Port.stringPort("separator", ";"));

    public static final Node stringNode = Node.ROOT
            .withName("string")
            .withFunction("string/string")
            .withInputAdded(Port.stringPort("value", ""));

    public static final FunctionRepository functions = FunctionRepository.of(CoreVectorFunctions.LIBRARY, MathFunctions.LIBRARY, ListFunctions.LIBRARY, StringFunctions.LIBRARY, SideEffects.LIBRARY, TestFunctions.LIBRARY);
    public static final NodeLibrary testLibrary = NodeLibrary.create("test", Node.ROOT, functions);
    private NodeContext context;

    @Before
    public void setUp() throws Exception {
        context = new NodeContext(testLibrary);
        SideEffects.reset();
    }

    @Test
    public void testSingleOutput() {
        List<?> results = context.renderNode(valuesToPointNode);
        assertEquals(1, results.size());
        assertResultsEqual(results, Point.ZERO);
    }

    @Test
    public void testListRange() {
        Node node = Node.ROOT
                .withFunction("math/average")
                .withInputAdded(Port.floatPort("values", 42).withRange(Port.Range.LIST));
        assertResultsEqual(node, 0.0);
    }

    @Test
    public void testSameOutputPort() {
        Node invert1 = invertNode.extend().withName("invert1").withInputValue("value", 1.0);
        Node invert2 = invertNode.extend().withName("invert2").withInputValue("value", 10.0);
        assertResultsEqual(context.renderNode(invert1), -1.0);
        assertResultsEqual(context.renderNode(invert2), -10.0);
    }

    @Test
    public void testListAwareProcessing() {
        Node makeNumbers1 = makeNumbersNode.extend().withInputValue("string", "1 2 3 4");
        assertResultsEqual(context.renderNode(makeNumbers1), 1.0, 2.0, 3.0, 4.0);
    }

    @Test
    public void testListUnawareProcessing() {
        Node invert1 = invertNode.extend().withName("invert1").withInputValue("value", 42.0);
        assertResultsEqual(context.renderNode(invert1), -42.0);
    }

    @Test
    public void testConnectedListProcessing() {
        Node makeNumbers1 = makeNumbersNode.extend().withName("makeNumbers1").withInputValue("string", "1 2 3 4");
        Node invert1 = invertNode.extend().withName("invert1");
        Node net = Node.NETWORK
                .withChildAdded(makeNumbers1)
                .withChildAdded(invert1)
                .connect("makeNumbers1", "invert1", "value")
                .withRenderedChildName("invert1");
        assertResultsEqual(context.renderChild(net, invert1), -1.0, -2.0, -3.0, -4.0);
    }

    @Test
    public void testEmptyListProcessing() {
        Node noNumbers = makeNumbersNode.extend().withName("noNumbers").withInputValue("string", "");
        Node add1 = addNode.extend().withName("add1");
        Node net = Node.NETWORK
                .withChildAdded(noNumbers)
                .withChildAdded(add1)
                .connect("noNumbers", "add1", "v1");
        assertNoResults(net, add1);
    }

    /**
     * Some nodes are not "pure" but produce side-effects, for example by fetching from an input device
     * or writing to an output device. Those nodes typically do not have inputs or outputs.
     */
    @Test
    public void testInputSideEffect() {
        Node getNumberNode = Node.ROOT
                .withFunction("side-effects/getNumber");
        SideEffects.theInput = 42;
        assertResultsEqual(context.renderNode(getNumberNode), 42L);
    }

    @Test
    public void testOutputSideEffect() {
        Node setNumberNode = Node.ROOT
                .withFunction("side-effects/setNumber")
                .withInputAdded(Port.intPort("number", 42));
        context.renderNode(setNumberNode);
        assertEquals(SideEffects.theOutput, 42L);
    }

    @Test
    public void testSamePrototypeTwice() {
        Node invert1Node = invertNode.withName("invert1").withInputValue("value", 42.0);
        Node invert2Node = invertNode.withName("invert2");
        Node net = Node.NETWORK
                .withChildAdded(invert1Node)
                .withChildAdded(invert2Node)
                .connect("invert1", "invert2", "value");
        assertResultsEqual(context.renderChild(net, invert2Node), 42.0);
    }

    /**
     * Test that the node function is executed the exact amount we expect.
     */
    @Test
    public void testExecuteAmount() {
        Node makeNumbers1 = makeNumbersNode.withName("makeNumbers1").withInputValue("string", "1 2 3");
        Node incNode = Node.ROOT
                .withName("inc")
                .withFunction("side-effects/increaseAndCount")
                .withInputAdded(Port.floatPort("number", 0));
        Node net = Node.NETWORK
                .withChildAdded(makeNumbers1)
                .withChildAdded(incNode)
                .connect("makeNumbers1", "inc", "number");
        assertResultsEqual(net, incNode, 2.0, 3.0, 4.0);
        assertEquals(3, SideEffects.theCounter);
    }

    /**
     * Test the combination of a list input and port value.
     */
    @Test
    public void testListWithValue() {
        Node makeNumbers1 = makeNumbersNode.withName("makeNumbers1").withInputValue("string", "1 2 3");
        Node add1 = addNode.extend().withName("add1").withInputValue("v2", 100.0);
        Node net = Node.NETWORK
                .withChildAdded(makeNumbers1)
                .withChildAdded(add1)
                .connect("makeNumbers1", "add1", "v1");
        assertResultsEqual(context.renderChild(net, add1), 101.0, 102.0, 103.0);
    }

    @Test
    public void testLongestList() {
        Node net = Node.NETWORK
                .withChildAdded(threeNumbers)
                .withChildAdded(fiveNumbers)
                .withChildAdded(addNode)
                .connect("threeNumbers", addNode.getName(), "v1")
                .connect("fiveNumbers", addNode.getName(), "v2");
        assertResultsEqual(context.renderChild(net, addNode), 101.0, 202.0, 303.0, 401.0, 502.0);
    }

    @Test
    public void testPortRangeMatching() {
        Node sum = Node.ROOT
                .withName("sum")
                .withFunction("math/sum")
                .withInputAdded(Port.floatPort("numbers", 0))
                .withInputRange("numbers", Port.Range.LIST);
        Node net = Node.NETWORK
                .withChildAdded(sum)
                .withChildAdded(threeNumbers)
                .connect("threeNumbers", sum.getName(), "numbers");
        assertResultsEqual(context.renderChild(net, sum), 6.0);
    }

    @Test
    public void testTypeConversion() {
        assertConversion(Port.TYPE_INT, Port.TYPE_INT, 42L, 42L);
        assertConversion(Port.TYPE_INT, Port.TYPE_FLOAT, 42L, 42.0);
        assertConversion(Port.TYPE_INT, Port.TYPE_STRING, 42L, "42");
        assertConversion(Port.TYPE_INT, Port.TYPE_BOOLEAN, 42L, true);
        assertConversion(Port.TYPE_INT, Port.TYPE_COLOR, 255L, Color.WHITE);
        assertConversion(Port.TYPE_INT, Port.TYPE_POINT, 42L, new Point(42, 42));

        assertConversion(Port.TYPE_FLOAT, Port.TYPE_INT, 42.0, 42L);
        assertConversion(Port.TYPE_FLOAT, Port.TYPE_FLOAT, 42.0, 42.0);
        assertConversion(Port.TYPE_FLOAT, Port.TYPE_STRING, 42.0, "42.0");
        assertConversion(Port.TYPE_FLOAT, Port.TYPE_BOOLEAN, 0.0, false);
        assertConversion(Port.TYPE_FLOAT, Port.TYPE_COLOR, 0.0, Color.BLACK);
        assertConversion(Port.TYPE_FLOAT, Port.TYPE_POINT, 42.0, new Point(42, 42));

        assertConversion(Port.TYPE_STRING, Port.TYPE_INT, "42", 42L);
        assertConversion(Port.TYPE_STRING, Port.TYPE_FLOAT, "42", 42.0);
        assertConversion(Port.TYPE_STRING, Port.TYPE_STRING, "hello", "hello");
        assertConversion(Port.TYPE_STRING, Port.TYPE_BOOLEAN, "true", true);
        assertConversion(Port.TYPE_STRING, Port.TYPE_BOOLEAN, "not-a-boolean", false);
        assertConversion(Port.TYPE_STRING, Port.TYPE_COLOR, "#ff0000ff", new Color(1, 0, 0));
        assertConversion(Port.TYPE_STRING, Port.TYPE_POINT, "4,2", new Point(4, 2));

        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_INT, true, 1L);
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_INT, false, 0L);
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_FLOAT, true, 1.0);
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_STRING, true, "true");
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_STRING, false, "false");
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_BOOLEAN, false, false);
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_COLOR, true, Color.WHITE);
        assertConversion(Port.TYPE_BOOLEAN, Port.TYPE_COLOR, false, Color.BLACK);

        assertConversion(Port.TYPE_COLOR, Port.TYPE_STRING, new Color(0, 1, 0), "#00ff00ff");
        assertConversion(Port.TYPE_COLOR, Port.TYPE_COLOR, Color.WHITE, Color.WHITE);

        assertConversion(Port.TYPE_POINT, Port.TYPE_STRING, new Point(4, 2), "4.00,2.00");
        assertConversion(Port.TYPE_POINT, Port.TYPE_POINT, new Point(4, 2), new Point(4, 2));
    }

    @Test
    public void testGeometryToPointsConversion() {
        Node line = Node.ROOT
                .withName("line")
                .withFunction("corevector/line")
                .withInputAdded(Port.pointPort("point1", new Point(10, 20)))
                .withInputAdded(Port.pointPort("point2", new Point(30, 40)))
                .withInputAdded(Port.intPort("points", 2));
        Node point = Node.ROOT
                .withName("point")
                .withFunction("corevector/point")
                .withInputAdded(Port.pointPort("value", Point.ZERO));
        Node net = Node.NETWORK
                .withChildAdded(line)
                .withChildAdded(point)
                .withRenderedChild(point)
                .connect("line", "point", "value");
        assertResultsEqual(net, new Point(10, 20), new Point(30, 40));
    }

    private void assertConversion(String sourceType, String targetType, Object sourceValue, Object targetValue) {
        String generateFunction = identityFunction(sourceType);
        Port generatePort = Port.parsedPort("value", sourceType, sourceValue.toString());
        String convertFunction = identityFunction(targetType);
        Port convertPort = Port.portForType("value", targetType);
        Node net = buildTypeConversionNetwork(generateFunction, generatePort, convertFunction, convertPort);
        assertResultsEqual(net, targetValue);
    }

    private String identityFunction(String portType) {
        ImmutableMap.Builder<String, String> b = ImmutableMap.builder();
        b.put(Port.TYPE_INT, "math/integer");
        b.put(Port.TYPE_FLOAT, "math/number");
        b.put(Port.TYPE_STRING, "string/string");
        b.put(Port.TYPE_BOOLEAN, "math/makeBoolean");
        b.put(Port.TYPE_COLOR, "color/color");
        b.put(Port.TYPE_POINT, "corevector/point");
        ImmutableMap<String, String> functions = b.build();
        return functions.get(portType);
    }

    private Node buildTypeConversionNetwork(String generateFunction, Port generatePort, String convertFunction, Port convertPort) {
        Node generator = Node.ROOT.withName("generate").withFunction(generateFunction).withInputAdded(generatePort);
        Node converter = Node.ROOT.withName("convert").withFunction(convertFunction).withInputAdded(convertPort);
        return Node.NETWORK
                .withChildAdded(generator)
                .withChildAdded(converter)
                .withRenderedChild(converter)
                .connect("generate", "convert", "value");
    }

    /**
     * Returned lists should not contain nulls.
     */
    @Test
    public void testListWithNulls() {
        Node makeNull = Node.ROOT
                .withName("makeNull")
                .withFunction("test/makeNull")
                .withInputAdded(Port.floatPort("value", 0.0));
        Node net = Node.NETWORK
                .withChildAdded(threeNumbers)
                .withChildAdded(makeNull)
                .connect("threeNumbers", "makeNull", "value");
        assertResultsEqual(net, makeNull);
    }

    @Test
    public void testNestedLists() {
        Node makeStrings = makeStringsNode.extend()
                .withInputValue("string", "1,2;3,4;5,6");
        Node makeNumbers = makeNumbersNode.extend()
                .withName("makeNumbers")
                .withInputValue("separator", ",");
        Node net = Node.NETWORK
                .withChildAdded(makeStrings)
                .withChildAdded(makeNumbers)
                .withRenderedChildName("makeNumbers")
                .connect("makeStrings", "makeNumbers", "string");
        assertResultsEqual(net, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0);
    }

    @Test
    public void testRenderSubnetwork() {
        Node subnet = createAddNetwork("subnet1", 1.0, 2.0);
        Node net = Node.NETWORK
                .withChildAdded(subnet)
                .withRenderedChildName("subnet1");
        assertResultsEqual(net, subnet, 3.0);
    }

    @Test
    public void testRenderEmptyNetwork() {
        Node network = Node.NETWORK;
        assertResultsEqual(network);
    }

    @Test
    public void testValidSubnetworkResults() {
        Node subnet1 = createAddNetwork("subnet1", 1.0, 2.0);
        Node subnet2 = createAddNetwork("subnet2", 3.0, 4.0);
        Node add1 = addNode.extend().withName("add1");
        Node net = Node.NETWORK
                .withChildAdded(subnet1)
                .withChildAdded(subnet2)
                .withChildAdded(add1)
                .withRenderedChildName("add1")
                .connect("subnet1", "add1", "v1")
                .connect("subnet2", "add1", "v2");
        assertResultsEqual(net, add1, 10.0);
    }

    @Test
    public void testRenderNetworkWithPublishedPorts() {
        Node subNet = createAddNetwork("subnet1", 0.0, 0.0)
                .publish("number1", "number", "value1")
                .publish("number2", "number", "value2")
                .withInputValue("value1", 2.0)
                .withInputValue("value2", 3.0);
        Node net = Node.NETWORK
                .withChildAdded(subNet)
                .withRenderedChildName("subnet1");
        assertResultsEqual(net, subNet, 5.0);
    }

    @Test
    public void testRenderNetworkWithConnectedPublishedPorts() {
        Node addNet = createAddNetwork("addNet", 0, 0)
                .publish("number1", "number", "value1")
                .publish("number2", "number", "value2");
        Node number1 = numberNode
                .withName("number1")
                .withInputValue("number", 5.0);
        Node number2 = numberNode
                .withName("number2")
                .withInputValue("number", 3.0);
        Node net = Node.NETWORK
                .withChildAdded(number1)
                .withChildAdded(number2)
                .withChildAdded(addNet)
                .withRenderedChild(addNet)
                .connect("number1", "addNet", "value1")
                .connect("number2", "addNet", "value2");
        assertResultsEqual(net, addNet, 8.0);
    }

    @Test
    public void testRenderNestedNetworkWithConnectedPublishedPorts() {
        Node subnet1 = createAddNetwork("subnet1", 0.0, 0.0)
                .publish("number1", "number", "n1")
                .publish("number2", "number", "n2");
        Node subnet2 = createAddNetwork("subnet2", 0.0, 0.0)
                .publish("number1", "number", "n1")
                .publish("number2", "number", "n2");
        Node add1 = addNode.extend().withName("add1");
        Node subnet = Node.NETWORK
                .withName("subnet")
                .withChildAdded(subnet1)
                .withChildAdded(subnet2)
                .withChildAdded(add1)
                .withRenderedChildName("add1")
                .connect("subnet1", "add1", "v1")
                .connect("subnet2", "add1", "v2")
                .publish("subnet1", "n1", "value1")
                .publish("subnet1", "n2", "value2")
                .publish("subnet2", "n1", "value3")
                .publish("subnet2", "n2", "value4");
        Node number1 = numberNode.extend()
                .withName("number1")
                .withInputValue("number", 11.0);
        Node number2 = numberNode.extend()
                .withName("number2")
                .withInputValue("number", 22.0);
        Node number3 = numberNode.extend()
                .withName("number3")
                .withInputValue("number", 33.0);
        Node number4 = numberNode.extend()
                .withName("number4")
                .withInputValue("number", 44.0);
        Node net = Node.NETWORK
                .withChildAdded(number1)
                .withChildAdded(number2)
                .withChildAdded(number3)
                .withChildAdded(number4)
                .withChildAdded(subnet)
                .withRenderedChildName("subnet")
                .connect("number1", "subnet", "value1")
                .connect("number2", "subnet", "value2")
                .connect("number3", "subnet", "value3")
                .connect("number4", "subnet", "value4");
        assertResultsEqual(net, subnet, 110.0);
    }

    @Test
    public void testRenderUnpublishAndDisconnect() {
        Node subNet = createAddNetwork("subNet", 2.0, 3.0)
                .publish("number1", "number", "n1")
                .publish("number2", "number", "n2");
        Node number = numberNode.extend()
                .withName("number")
                .withInputValue("number", 11.0);
        Node net = Node.NETWORK
                .withChildAdded(number)
                .withChildAdded(subNet)
                .withRenderedChildName("subNet")
                .connect("number", "subNet", "n1");
        assertResultsEqual(net, subNet, 14.0);
        subNet = subNet.unpublish("n1");
        net = net.withChildReplaced("subNet", subNet);
        assertResultsEqual(net, subNet, 5.0);
    }

    @Test
    public void testFrame() {
        Node frame = Node.ROOT
                .withName("frame")
                .withFunction("core/frame")
                .withInputAdded(Port.customPort("context", "context"));
        Node frameNet = Node.NETWORK.withChildAdded(frame).withRenderedChild(frame);
        NodeContext c = new NodeContext(testLibrary, FunctionRepository.of(), ImmutableMap.of("frame", 42.0));
        List<?> results = c.renderNode(frameNet);
        assertResultsEqual(results, 42.0);
    }

    // TODO Check list-aware node with no inputs.
    // TODO Check list-aware node with no outputs.
    // TODO Check list-aware node with single output.
    // TODO Check list-aware node with multiple outputs.

    // TODO Check list-unaware node with single output.
    // TODO Check list-unaware node with multiple outputs.
    // TODO Check list-unaware node with multiple inputs, single output.

    private Node createAddNetwork(String name, double v1, double v2) {
        Node number1 = numberNode.extend()
                .withName("number1")
                .withInputValue("number", v1);
        Node number2 = numberNode.extend()
                .withName("number2")
                .withInputValue("number", v2);
        return Node.NETWORK
                .withName(name)
                .withChildAdded(number1)
                .withChildAdded(number2)
                .withChildAdded(addNode)
                .withRenderedChild(addNode)
                .connect("number1", "add", "v1")
                .connect("number2", "add", "v2");
    }

    @Test
    public void testListOutputRange() {
        Node slice = Node.ROOT
                .withName("slice")
                .withFunction("list/slice")
                .withInputAdded(Port.stringPort("list", "").withRange(Port.Range.LIST))
                .withInputAdded(Port.intPort("start", 0))
                .withInputAdded(Port.intPort("size", 1000))
                .withInputAdded(Port.booleanPort("invert", false))
                .withOutputRange(Port.Range.LIST);
        Node makeStrings = Node.ROOT
                .withName("makeStrings")
                .withFunction("string/makeStrings")
                .withInputAdded(Port.stringPort("text", "A;B;C"))
                .withInputAdded(Port.stringPort("separator", ";"))
                .withOutputRange(Port.Range.LIST);
        Node makeNumbers = Node.ROOT
                .withName("makeNumbers")
                .withFunction("math/makeNumbers")
                .withInputAdded(Port.stringPort("text", "0;1;2"))
                .withInputAdded(Port.stringPort("separator", ";"))
                .withOutputRange(Port.Range.LIST);
        Node net = Node.NETWORK
                .withChildAdded(makeStrings)
                .withChildAdded(makeNumbers)
                .withChildAdded(slice)
                .connect("makeStrings", "slice", "list")
                .connect("makeNumbers", "slice", "start");

        assertResultsEqual(net, slice, "A", "B", "C", "B", "C", "C");
    }

    @Test
    public void testNestedGenerator() {
        Node makeStrings = Node.ROOT
                .withName("makeStrings")
                .withFunction("string/makeStrings")
                .withInputAdded(Port.stringPort("value", "A;B;C"))
                .withInputAdded(Port.stringPort("separator", ";"))
                .withOutputRange(Port.Range.LIST);

        Node repeat = Node.ROOT
                .withName("repeat")
                .withFunction("list/repeat")
                .withInputAdded(Port.customPort("value", "list").withRange(Port.Range.LIST))
                .withInputAdded(Port.intPort("amount", 3))
                .withInputAdded(Port.booleanPort("per_item", false))
                .withOutputRange(Port.Range.LIST);

        Node repeatNet = Node.NETWORK
                .withName("repeatNet")
                .withChildAdded(repeat)
                .withRenderedChild(repeat)
                .publish("repeat", "value", "strings")
                .withOutputRange(Port.Range.VALUE);
        Port publishedPort = repeatNet.getInput("strings").withRange(Port.Range.VALUE);
        repeatNet = repeatNet.withInputChanged("strings", publishedPort);

        assertResultsEqual(repeatNet);

        Node net = Node.NETWORK
                .withChildAdded(makeStrings)
                .withChildAdded(repeatNet)
                .withRenderedChild(repeatNet)
                .connect("makeStrings", "repeatNet", "strings");

        assertResultsEqual(net, ImmutableList.of("A", "A", "A"), ImmutableList.of("B", "B", "B"), ImmutableList.of("C", "C", "C"));
    }

    @Test
    public void testSimpleNestedFilter() {
        Node makeStrings = Node.ROOT
                .withName("makeStrings")
                .withFunction("string/makeStrings")
                .withInputAdded(Port.stringPort("value", "alpha;beta;gamma"))
                .withInputAdded(Port.stringPort("separator", ";"))
                .withOutputRange(Port.Range.LIST);

        Node caseNode = Node.ROOT
                .withName("changeCase")
                .withFunction("string/changeCase")
                .withInputAdded(Port.stringPort("value", ""))
                .withInputAdded(Port.stringPort("method", "uppercase"));

        Node caseNet = Node.NETWORK
                .withName("caseNet")
                .withChildAdded(caseNode)
                .withRenderedChild(caseNode)
                .publish("changeCase", "value", "value");

        Node net = Node.NETWORK
                .withChildAdded(makeStrings)
                .withChildAdded(caseNet)
                .connect("makeStrings", "caseNet", "value")
                .withRenderedChild(caseNet);

        assertResultsEqual(net, "ALPHA", "BETA", "GAMMA");
    }

    @Test
    public void testNestedFilter() {
        Node makeNestedWords = Node.ROOT
                .withName("makeNestedWords")
                .withFunction("test/makeNestedWords")
                .withOutputType("string")
                .withOutputRange(Port.Range.LIST);

        Node length = Node.ROOT
                .withName("length")
                .withFunction("string/length")
                .withOutputType("string")
                .withInputAdded(Port.stringPort("text", ""));

        Node lengthNet = Node.NETWORK
                .withName("lengthNet")
                .withChildAdded(length)
                .publish("length", "text", "text")
                .withRenderedChild(length)
                .withOutputRange(Port.Range.VALUE);

        Port textPort = lengthNet.getInput("text").withRange(Port.Range.VALUE);
        lengthNet = lengthNet.withInputChanged("text", textPort);

        Node mainNetwork = Node.NETWORK
                .withChildAdded(makeNestedWords)
                .withChildAdded(lengthNet)
                .connect("makeNestedWords", "lengthNet", "text")
                .withRenderedChild(lengthNet);

        List<Integer> aCounts = ImmutableList.of(5, 11, 9);
        List<Integer> bCounts = ImmutableList.of(6, 4, 4);
        List<Integer> cCounts = ImmutableList.of(5, 8, 6);
        assertResultsEqual(mainNetwork, aCounts, bCounts, cCounts);
    }

    @Test
    public void testClamping() {
        Port value = invertNode.getInput("value");
        value = value.withMaximumValue(10.0);
        Node clampedInvertNode = invertNode.withInputChanged("value", value);
        clampedInvertNode = clampedInvertNode.withInputValue("value", 25.0);
        assertResultsEqual(clampedInvertNode, -10.0);

        Node number1 = numberNode.withInputValue("number", 25.0);
        Node net = Node.NETWORK
                .withChildAdded(clampedInvertNode)
                .withChildAdded(number1)
                .connect("number", "negate", "value");
        assertResultsEqual(net, clampedInvertNode, -10.0);
    }

    @Test
    public void testStoreIntermediateResults() {
        Node increase = Node.ROOT
                .withName("increase")
                .withFunction("side-effects/increaseAndCount")
                .withInputAdded(Port.floatPort("counter", 42.0));

        Node network = Node.NETWORK
                .withChildAdded(addNode)
                .withChildAdded(increase)
                .connect("increase", "add", "v1")
                .connect("increase", "add", "v2");

        SideEffects.reset();

        assertResultsEqual(network, addNode, 86.0);
        assertEquals(1L, SideEffects.theCounter);
    }

    @Test
    public void testPortOverrides() {
        Node number3 = numberNode.withName("number3").withInputValue("number", 3.0);
        Node number5 = numberNode.withName("number5").withInputValue("number", 5.0);
        Node net = Node.NETWORK
                .withChildAdded(number3)
                .withChildAdded(number5)
                .withChildAdded(addNode)
                .connect("number3", "add", "v1")
                .connect("number5", "add", "v2")
                .withRenderedChildName("add");
        // With no overrides, the add node returns 8.0
        assertResultsEqual(net, addNode, 8.0);
        ImmutableMap<String,?> overrides = ImmutableMap.of("number3.number", 10.0);
        NodeContext ctx = new NodeContext(testLibrary, null, ImmutableMap.<String,Object>of(), ImmutableMap.<Node,List<?>>of(), overrides);
        Iterable<?> values = ctx.renderChild(net, addNode);
        assertResultsEqual(values, 15.0);
    }

}
TOP

Related Classes of nodebox.node.NodeContextTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.