package nodebox.node;
import com.google.common.collect.ImmutableList;
import nodebox.client.PythonUtils;
import nodebox.function.FunctionLibrary;
import nodebox.function.FunctionRepository;
import nodebox.function.ListFunctions;
import nodebox.function.MathFunctions;
import nodebox.graphics.Color;
import nodebox.graphics.Point;
import nodebox.util.LoadException;
import org.junit.Test;
import java.io.File;
import java.util.List;
import java.util.Locale;
import static junit.framework.TestCase.*;
import static nodebox.util.Assertions.assertResultsEqual;
public class NodeLibraryTest {
private final NodeLibrary library;
private final Node child1;
private final Node child2;
private final Node parent;
private final Node root;
private final FunctionRepository functions;
private final File userDir = new File(System.getProperty("user.dir"));
public NodeLibraryTest() {
PythonUtils.initializePython();
child1 = Node.ROOT.withName("child1");
child2 = Node.ROOT.withName("child2");
parent = Node.NETWORK.withName("parent")
.withChildAdded(child1)
.withChildAdded(child2);
root = Node.NETWORK.withChildAdded(parent);
library = NodeLibrary.create("test", root, FunctionRepository.of());
functions = FunctionRepository.of(MathFunctions.LIBRARY, ListFunctions.LIBRARY);
}
@Test()
public void testCoreNodes() {
assertTrue(NodeLibrary.coreLibrary.getRoot().hasChild(Node.ROOT));
assertTrue(NodeLibrary.coreLibrary.getRoot().hasChild(Node.NETWORK));
}
@Test
public void testNonExistingCoreNode() {
try {
File f = new File("src/test/files/bad-corenode.ndbx");
NodeLibrary library = NodeLibrary.load(f, NodeRepository.of());
fail("Should have thrown a LoadException.");
} catch (LoadException e) {
}
}
@Test
public void testNodeForPath() {
assertEquals(root, library.getNodeForPath("/"));
assertEquals(parent, library.getNodeForPath("/parent"));
assertEquals(child1, library.getNodeForPath("/parent/child1"));
assertEquals(child2, library.getNodeForPath("/parent/child2"));
assertNull("Invalid names return null.", library.getNodeForPath("/foo"));
assertNull("Invalid nested names return null.", library.getNodeForPath("/parent/foo"));
}
@Test(expected = IllegalArgumentException.class)
public void testRelativePath() {
library.getNodeForPath("parent");
}
@Test
public void testSimpleReadWrite() {
NodeLibrary simple = NodeLibrary.create("test", Node.ROOT.extend(), FunctionRepository.of());
assertReadWriteEquals(simple, NodeRepository.of());
}
@Test
public void testNestedReadWrite() {
assertReadWriteEquals(library, NodeRepository.of());
}
@Test
public void testPrototypeInSameLibrary() {
// You can refer to a prototype in the same library as the current node.
Node invert = Node.ROOT
.withName("negate")
.withFunction("math/negate")
.withInputAdded(Port.floatPort("number", 0));
Node invert1 = invert.extend().withName("invert1").withInputValue("number", 42.0);
Node net = Node.NETWORK
.withName("root")
.withChildAdded(invert)
.withChildAdded(invert1)
.withRenderedChild(invert1);
NodeLibrary originalLibrary = NodeLibrary.create("test", net, FunctionRepository.of(MathFunctions.LIBRARY));
// Assert the original library returns the correct result.
NodeContext context = new NodeContext(originalLibrary);
assertResultsEqual(context.renderNode(net), -42.0);
// Persist / load the library and assert it still returns the correct result.
NodeLibrary restoredLibrary = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
context = new NodeContext(restoredLibrary);
assertResultsEqual(context.renderNode(restoredLibrary.getRoot()), -42.0);
}
@Test
public void testRenderedNode() {
Node child1 = Node.ROOT.withName("child1");
Node originalRoot = Node.NETWORK.withChildAdded(child1).withRenderedChild(child1);
NodeLibrary originalLibrary = NodeLibrary.create("test", originalRoot, FunctionRepository.of());
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
assertEquals("child1", library.getRoot().getRenderedChildName());
assertNotNull(library.getRoot().getRenderedChild());
}
@Test
public void testPortSerialization() {
assertPortSerialization(Port.intPort("int", 42));
assertPortSerialization(Port.floatPort("float", 33.3));
assertPortSerialization(Port.stringPort("string", "hello"));
assertPortSerialization(Port.colorPort("color", Color.BLACK));
assertPortSerialization(Port.pointPort("point", new Point(11, 22)));
assertPortSerialization(Port.customPort("geometry", "nodebox.graphics.Geometry"));
}
@Test
public void testLink() {
Node originalAdd = Node.ROOT
.withName("add")
.withFunction("math/add")
.withInputAdded(Port.floatPort("v1", 11))
.withInputAdded(Port.floatPort("v2", 22));
NodeLibrary originalLibrary = NodeLibrary.create("test", originalAdd, FunctionRepository.of(MathFunctions.LIBRARY));
assertSingleResult(33.0, originalAdd, originalLibrary.getFunctionRepository());
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
assertTrue(library.getFunctionRepository().hasLibrary("math"));
Node add = library.getRoot();
assertEquals("add", add.getName());
assertEquals("math/add", add.getFunction());
assertSingleResult(33.0, add, library.getFunctionRepository());
}
/**
* Test if the NodeLibrary stores / loads function libraries relative to the path location of the library correctly.
*/
@Test
public void testRelativeImport() {
File relativeImportFile = new File("src/test/files/relative-import.ndbx");
NodeLibrary originalLibrary = NodeLibrary.load(relativeImportFile, NodeRepository.of());
FunctionRepository repository = originalLibrary.getFunctionRepository();
assertTrue(repository.hasLibrary("relative"));
assertTrue(repository.hasFunction("relative/concat"));
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
FunctionLibrary relativeLibrary = library.getFunctionRepository().getLibrary("relative");
assertEquals("python:src/test/files/relative.py", relativeLibrary.getLink(new File(userDir, "test.ndbx")));
assertEquals("python:relative.py", relativeLibrary.getLink(relativeImportFile));
}
/**
* Test if the NodeLibrary stores / loads the port range correctly.
*/
@Test
public void testPortRangePersistence() {
// Default check.
Node makeNumbers = Node.ROOT
.withName("makeNumbers")
.withFunction("math/makeNumbers")
.withOutputRange(Port.Range.LIST)
.withInputAdded(Port.stringPort("s", "1 2 3 4 5"))
.withInputAdded(Port.stringPort("sep", " "));
Node reverse = Node.ROOT
.withName("reverse")
.withFunction("list/reverse")
.withInputAdded(Port.customPort("list", "list"))
.withInputRange("list", Port.Range.LIST)
.withOutputRange(Port.Range.LIST);
Node net = Node.NETWORK
.withChildAdded(makeNumbers)
.withChildAdded(reverse)
.withRenderedChild(reverse)
.connect("makeNumbers", "reverse", "list");
NodeLibrary originalLibrary = NodeLibrary.create("test", net, functions);
assertResultsEqual(originalLibrary.getRoot(), 5.0, 4.0, 3.0, 2.0, 1.0);
// Now save / load the library and check the output.
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
assertResultsEqual(library.getRoot(), 5.0, 4.0, 3.0, 2.0, 1.0);
}
@Test
public void testPrototypeOverridePersistence() {
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
Node rangePrototype = mathLibrary.getRoot().getChild("range");
Node range1 = rangePrototype.extend().withName("range1").withInputValue("end", 5.0);
assertResultsEqual(range1, 0.0, 1.0, 2.0, 3.0, 4.0);
NodeLibrary originalLibrary = NodeLibrary.create("test", range1, NodeRepository.of(mathLibrary), functions);
// Now save / load the library and check the output.
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of(mathLibrary));
assertResultsEqual(library.getRoot(), 0.0, 1.0, 2.0, 3.0, 4.0);
}
@Test
public void testOutputTypeSerialization() {
Node myRect = Node.ROOT.withName("rect").withOutputType("geometry");
NodeLibrary originalLibrary = NodeLibrary.create("test", myRect);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
assertEquals("geometry", library.getRoot().getOutputType());
}
/**
* Test if ports can persist their min / max values.
*/
@Test
public void testMinMaxPersistence() {
Node originalRoot = Node.ROOT.withName("root").withInputAdded(Port.floatPort("v", 5.0, 0.0, 10.0));
NodeLibrary originalLibrary = NodeLibrary.create("test", originalRoot);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Port v = library.getRoot().getInput("v");
assertEquals(0.0, v.getMinimumValue());
assertEquals(10.0, v.getMaximumValue());
}
/**
* Test if file writing is independent from the locale.
* <p/>
* We use String.format in writing points, which is locale-dependent.
* Having the "wrong" locale would mean that the returned point was invalid.
*/
@Test
public void testLocale() {
Locale savedLocale = Locale.getDefault();
// The german locale uses a comma to separate the decimals, which could make points fail.
Locale.setDefault(Locale.GERMAN);
try {
// We use points for the position and for the input port.
Node originalRoot = Node.ROOT
.withName("root")
.withPosition(new Point(12, 34))
.withInputAdded(Port.pointPort("point", new Point(12, 34)));
NodeLibrary originalLibrary = NodeLibrary.create("test", originalRoot);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Node root = library.getRoot();
assertPointEquals(root.getPosition(), 12.0, 34.0);
assertPointEquals(root.getInput("point").pointValue(), 12.0, 34.0);
} finally {
Locale.setDefault(savedLocale);
}
}
@Test
public void testReadMenus() {
NodeLibrary menuLibrary = NodeLibrary.load(new File("src/test/files/menus.ndbx"), NodeRepository.of());
Port thePort = menuLibrary.getRoot().getInput("thePort");
assertTrue(thePort.hasMenu());
assertEquals(2, thePort.getMenuItems().size());
assertEquals(new MenuItem("a", "Alpha"), thePort.getMenuItems().get(0));
assertEquals(new MenuItem("b", "Beta"), thePort.getMenuItems().get(1));
}
@Test
public void testMenuSerialization() {
Node originalRoot = makeLetterMenuNode();
NodeLibrary originalLibrary = NodeLibrary.create("test", originalRoot);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Port letterPort = library.getRoot().getInput("letter");
assertTrue(letterPort.hasMenu());
assertEquals(2, letterPort.getMenuItems().size());
assertEquals(new MenuItem("a", "Alpha"), letterPort.getMenuItems().get(0));
assertEquals(new MenuItem("b", "Beta"), letterPort.getMenuItems().get(1));
}
/**
* Test if a port using a menu prototype is correctly serialized.
*/
@Test
public void testMenuPrototypeSerialization() {
Node letterPrototype = makeLetterMenuNode();
Node letterNode = letterPrototype.extend().withName("my_letter").withInputValue("letter", "b");
Node originalRoot = Node.NETWORK
.withChildAdded(letterPrototype)
.withChildAdded(letterNode);
NodeLibrary originalLibrary = NodeLibrary.create("test", originalRoot);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Port letterPort = library.getRoot().getChild("my_letter").getInput("letter");
assertTrue(letterPort.hasMenu());
assertEquals(2, letterPort.getMenuItems().size());
assertEquals("b", letterPort.getValue());
}
@Test
public void testWidgetSerialization() {
Node originalNode = Node.ROOT
.withInputAdded(Port.stringPort("file", "").withWidget(Port.Widget.FILE));
NodeLibrary originalLibrary = NodeLibrary.create("test", originalNode);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Port filePort = library.getRoot().getInput("file");
assertEquals(Port.Widget.FILE, filePort.getWidget());
}
@Test
public void testWritePrototypeFirst() {
// We execute the test multiple times with the names switched to avoid that the order is accidentally correct.
// This can happen because of the hashing algorithm.
assertPrototypeBeforeInstance("alpha", "beta", "gamma");
assertPrototypeBeforeInstance("beta", "alpha", "gamma");
assertPrototypeBeforeInstance("gamma", "alpha", "beta");
}
private void assertPrototypeBeforeInstance(String prototypeName, String... instanceNames) {
Node originalPrototype = Node.ROOT.withName(prototypeName);
Node network = Node.NETWORK.withChildAdded(originalPrototype);
for (String instanceName : instanceNames) {
Node originalInstance = originalPrototype.extend().withName(instanceName);
network = network.withChildAdded(originalInstance);
}
NodeLibrary originalLibrary = NodeLibrary.create("test", network);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Node prototype = library.getRoot().getChild(prototypeName);
for (String instanceName : instanceNames) {
Node instance = library.getRoot().getChild(instanceName);
assertSame(prototype, instance.getPrototype());
}
}
@Test
public void testRelativePathsInWidgets() {
NodeLibrary library = NodeLibrary.load(new File("src/test/files/relative-file.ndbx"), NodeRepository.of());
NodeContext context = new NodeContext(library);
Iterable<?> results = context.renderNode(library.getRoot());
Object firstResult = results.iterator().next();
assertEquals(true, firstResult);
}
@Test
public void testPublishedPortSerialization() {
Node inner = Node.ROOT.withName("inner")
.withInputAdded(Port.floatPort("value", 0.0))
.withFunction("math/number");
Node outer = Node.NETWORK.withName("outer")
.withChildAdded(inner)
.publish("inner", "value", "v")
.withInputValue("v", 11.0);
assertEquals(11, outer.getChild("inner").getInput("value").intValue());
NodeLibrary originalLibrary = libraryWithChildren("test", outer);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
assertTrue(library.getNodeForPath("/outer").hasPublishedInput("v"));
assertEquals(11, library.getNodeForPath("/outer/inner").getInput("value").intValue());
}
@Test
public void testParseFormatVersion() {
assertEquals("1.0", NodeLibraryUpgrades.parseFormatVersion("<ndbx formatVersion='1.0'>"));
assertEquals("2", NodeLibraryUpgrades.parseFormatVersion("<ndbx type=\"file\" formatVersion=\"2\">"));
}
/**
* Test if a file upgrade succeeds.
*/
@Test
public void testUpgrade1to2() {
File version1File = new File("src/test/files/upgrade-v1.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version1File);
assertTrue("Result should contain updated position: " + result.getXml(), result.getXml().contains("position=\"12.00,2.00\""));
NodeLibrary upgradedLibrary = result.getLibrary(version1File, NodeRepository.of());
Node root = upgradedLibrary.getRoot();
Node alpha = root.getChild("alpha");
assertEquals(new Point(12, 2), alpha.getPosition());
}
@Test
public void testUpgrade2to3() {
File version2File = new File("src/test/files/upgrade-v2.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version2File);
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version2File, NodeRepository.of(mathLibrary));
Node root = upgradedLibrary.getRoot();
assertTrue(root.hasChild("round2"));
Node round2 = root.getChild("round2");
assertEquals("round", round2.getPrototype().getName());
Node subnet1 = root.getChild("subnet1");
assertTrue(subnet1.hasChild("round1"));
assertEquals("round1", subnet1.getRenderedChildName());
Port value = subnet1.getInput("value");
assertEquals("round1.value", value.getChildReference());
}
@Test
public void testUpgrade3to4() {
File version3File = new File("src/test/files/upgrade-v3.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version3File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary listLibrary = NodeLibrary.load(new File("libraries/list/list.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version3File, NodeRepository.of(corevectorLibrary, listLibrary));
Node root = upgradedLibrary.getRoot();
assertEquals("make_point", root.getChild("point1").getPrototype().getName());
assertTrue(root.hasChild("point2"));
assertEquals("point", root.getChild("point2").getPrototype().getName());
assertTrue(root.getConnections().contains(new Connection("point2", "count1", "list")));
Node subnet1 = root.getChild("subnet1");
assertTrue(subnet1.hasChild("point1"));
assertEquals("point1", subnet1.getRenderedChildName());
Port value = subnet1.getInput("shape");
assertEquals("point1.value", value.getChildReference());
}
@Test
public void testUpgrade4to5() {
File version4File = new File("src/test/files/upgrade-v4.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version4File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version4File, NodeRepository.of(corevectorLibrary, mathLibrary));
Node root = upgradedLibrary.getRoot();
assertFalse(root.getChild("textpath1").hasInput("height"));
assertNull(root.getConnection("textpath2", "height"));
Node subnet1 = root.getChild("subnet1");
assertFalse(subnet1.hasInput("height"));
Node subnet2 = root.getChild("subnet2");
assertFalse(subnet2.hasInput("height"));
}
@Test
public void testUpgrade5to6() {
File version5File = new File("src/test/files/upgrade-v5.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version5File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version5File, NodeRepository.of(corevectorLibrary));
Node root = upgradedLibrary.getRoot();
Node delete1 = root.getChild("delete1");
assertTrue(delete1.hasInput("operation"));
assertFalse(delete1.hasInput("delete_selected"));
assertEquals("selected", delete1.getInput("operation").stringValue());
Node delete2 = root.getChild("delete2");
assertEquals("non-selected", delete2.getInput("operation").stringValue());
}
@Test
public void testUpgrade6to7() {
File version6File = new File("src/test/files/upgrade-v6.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version6File);
NodeLibrary listLibrary = NodeLibrary.load(new File("libraries/list/list.ndbx"), NodeRepository.of());
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version6File, NodeRepository.of(listLibrary, mathLibrary));
Node root = upgradedLibrary.getRoot();
assertFalse(root.hasChild("filter1"));
assertTrue(root.hasChild("cull1"));
assertEquals("cull1", root.getRenderedChildName());
assertResultsEqual(root, 0.0, 2.0, 4.0, 6.0, 8.0);
}
@Test
public void testUpgrade7to8() {
File version7File = new File("src/test/files/upgrade-v7.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version7File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version7File, NodeRepository.of(corevectorLibrary, mathLibrary));
Node root = upgradedLibrary.getRoot();
assertFalse(root.getChild("point_on_path1").hasInput("range"));
assertNull(root.getConnection("point_on_path2", "range"));
Node subnet1 = root.getChild("subnet1");
assertFalse(subnet1.hasInput("range"));
}
@Test
public void testUpgrade8to9() {
File version8File = new File("src/test/files/upgrade-v8.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version8File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version8File, NodeRepository.of(corevectorLibrary));
Node root = upgradedLibrary.getRoot();
assertTrue(root.hasChild("resample2"));
assertTrue(root.hasChild("resample3"));
assertEquals("resample", root.getChild("resample2").getPrototype().getName());
assertEquals("amount", root.getChild("resample2").getInput("method").getValue());
assertEquals("resample", root.getChild("resample3").getPrototype().getName());
assertEquals("length", root.getChild("resample3").getInput("method").getValue());
assertEquals("rect1", root.getConnection("resample2", "shape").getOutputNode());
assertEquals("rect1", root.getConnection("resample3", "shape").getOutputNode());
assertTrue(root.hasChild("subnet1"));
Node subnet1 = root.getChild("subnet1");
assertEquals("resample1", subnet1.getRenderedChildName());
assertEquals("resample", subnet1.getChild("resample1").getPrototype().getName());
assertEquals("amount", subnet1.getChild("resample1").getInput("method").getValue());
assertEquals("resample1.shape", subnet1.getInput("shape").getChildReference());
Node subnet2 = root.getChild("subnet2");
assertEquals("resample1", subnet2.getRenderedChildName());
assertEquals("resample", subnet2.getChild("resample1").getPrototype().getName());
assertEquals("length", subnet2.getChild("resample1").getInput("method").getValue());
assertEquals("resample1.shape", subnet2.getInput("shape").getChildReference());
}
@Test
public void testUpgrade9to10() {
File version9File = new File("src/test/files/upgrade-v9.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version9File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version9File, NodeRepository.of(corevectorLibrary));
Node root = upgradedLibrary.getRoot();
assertTrue(root.hasChild("wiggle2"));
assertTrue(root.hasChild("wiggle3"));
assertTrue(root.hasChild("wiggle4"));
assertEquals("wiggle", root.getChild("wiggle2").getPrototype().getName());
assertEquals("contours", root.getChild("wiggle2").getInput("scope").getValue());
assertEquals("paths", root.getChild("wiggle3").getInput("scope").getValue());
assertEquals("points", root.getChild("wiggle4").getInput("scope").getValue());
assertEquals(7, root.getConnections().size());
assertEquals("textpath1", root.getConnection("wiggle2", "shape").getOutputNode());
assertTrue(root.hasChild("subnet1"));
assertEquals("wiggle1", root.getChild("subnet1").getRenderedChildName());
assertEquals("wiggle", root.getChild("subnet2").getChild("wiggle1").getPrototype().getName());
assertEquals("contours", root.getChild("subnet1").getChild("wiggle1").getInput("scope").getValue());
assertEquals("paths", root.getChild("subnet2").getChild("wiggle1").getInput("scope").getValue());
assertEquals("points", root.getChild("subnet3").getChild("wiggle1").getInput("scope").getValue());
assertEquals("wiggle1.shape", root.getChild("subnet3").getInput("shape").getChildReference());
}
@Test
public void testUpgrade10to11() {
File version10File = new File("src/test/files/upgrade-v10.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version10File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary stringLibrary = NodeLibrary.load(new File("libraries/string/string.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version10File, NodeRepository.of(corevectorLibrary, stringLibrary));
Node root = upgradedLibrary.getRoot();
assertFalse(root.hasChild("draw_path1"));
assertFalse(root.hasChild("draw_path2"));
Node subnet1 = root.getChild("subnet1");
assertFalse(subnet1.hasRenderedChild());
assertFalse(subnet1.hasInput("path"));
assertEquals(1, subnet1.getChildren().size());
assertEquals(0, root.getConnections().size());
}
@Test
public void testUpgrade11to12() {
File version11File = new File("src/test/files/upgrade-v11.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version11File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version11File, NodeRepository.of(corevectorLibrary, mathLibrary));
Node root = upgradedLibrary.getRoot();
Node shapeOnPath1Node = root.getChild("shape_on_path1");
assertNotNull(shapeOnPath1Node);
assertTrue(shapeOnPath1Node.hasInput("path"));
assertEquals(10L, shapeOnPath1Node.getInput("amount").getValue());
assertEquals(15.0, shapeOnPath1Node.getInput("spacing").getValue());
assertEquals(10.0, shapeOnPath1Node.getInput("margin").getValue());
assertEquals("rect1", root.getConnection("shape_on_path2", "path").getOutputNode());
assertEquals("number1", root.getConnection("shape_on_path2", "spacing").getOutputNode());
assertEquals("number1", root.getConnection("shape_on_path2", "margin").getOutputNode());
Node subnet = root.getChild("subnet1");
assertEquals("shape_on_path1.path", subnet.getInput("template").getChildReference());
assertEquals("shape_on_path1.spacing", subnet.getInput("dist").getChildReference());
assertEquals("shape_on_path1.margin", subnet.getInput("start").getChildReference());
assertEquals("rect1", root.getConnection("subnet1", "template").getOutputNode());
assertEquals("number1", root.getConnection("subnet1", "dist").getOutputNode());
assertEquals("number1", root.getConnection("subnet1", "start").getOutputNode());
}
@Test
public void testUpgrade12to13() {
File version12File = new File("src/test/files/upgrade-v12.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version12File);
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version12File, NodeRepository.of(corevectorLibrary, mathLibrary));
Node root = upgradedLibrary.getRoot();
Node textOnPath1Node = root.getChild("text_on_path1");
assertNotNull(textOnPath1Node);
assertTrue(textOnPath1Node.hasInput("path"));
assertEquals(10.0, textOnPath1Node.getInput("margin").getValue());
assertEquals(5.0, textOnPath1Node.getInput("baseline_offset").getValue());
assertFalse(textOnPath1Node.hasInput("keep_geometry"));
assertEquals("rect1", root.getConnection("text_on_path2", "path").getOutputNode());
assertEquals("number1", root.getConnection("text_on_path2", "margin").getOutputNode());
assertEquals("number2", root.getConnection("text_on_path2", "baseline_offset").getOutputNode());
Node subnet = root.getChild("subnet1");
assertEquals("text_on_path1.path", subnet.getInput("shape").getChildReference());
assertEquals("text_on_path1.margin", subnet.getInput("position").getChildReference());
assertEquals("text_on_path1.baseline_offset", subnet.getInput("offset").getChildReference());
assertFalse(subnet.hasInput("keep_geometry"));
assertEquals("rect1", root.getConnection("subnet1", "shape").getOutputNode());
assertEquals("number1", root.getConnection("subnet1", "position").getOutputNode());
assertEquals("number2", root.getConnection("subnet1", "offset").getOutputNode());
assertNull(root.getConnection("subnet1", "keep_geometry"));
}
@Test
public void testUpgrade13to14() {
File version13File = new File("src/test/files/upgrade-v13.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version13File);
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version13File, NodeRepository.of(mathLibrary));
Node root = upgradedLibrary.getRoot();
Node waveNode = root.getChild("wave1");
assertFalse(waveNode.hasInput("speed"));
assertFalse(waveNode.hasInput("frame"));
assertEquals(100.0, waveNode.getInput("period").getValue());
assertEquals(20.0, waveNode.getInput("offset").getValue());
}
@Test
public void testUpgrade14to15() {
File version14File = new File("src/test/files/upgrade-v14.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version14File);
NodeLibrary stringLibrary = NodeLibrary.load(new File("libraries/string/string.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version14File, NodeRepository.of(stringLibrary));
Node root = upgradedLibrary.getRoot();
assertTrue(root.hasChild("split1"));
assertEquals("split1", root.getConnection("length1", "string").getOutputNode());
Node subnet = root.getChild("subnet1");
assertEquals("split1", subnet.getRenderedChildName());
assertEquals("split1.string", subnet.getInput("string").getChildReference());
assertEquals("string1", root.getConnection("subnet1", "string").getOutputNode());
assertEquals("subnet1", root.getConnection("length2", "string").getOutputNode());
}
@Test
public void testUpgrade15to16() {
File version15File = new File("src/test/files/upgrade-v15.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version15File);
NodeLibrary mathLibrary = NodeLibrary.load(new File("libraries/math/math.ndbx"), NodeRepository.of());
NodeLibrary corevectorLibrary = NodeLibrary.load(new File("libraries/corevector/corevector.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version15File, NodeRepository.of(mathLibrary, corevectorLibrary));
Node root = upgradedLibrary.getRoot();
assertEquals("root", root.getName());
assertEquals("network2", root.getRenderedChildName());
assertEquals("number", root.getChild("node3").getPrototype().getName());
assertEquals("node3", root.getConnection("add1", "value1").getOutputNode());
assertEquals(5.0, root.getChild("node2").getInput("value").getValue());
assertEquals("abs", root.getChild("root123").getPrototype().getName());
assertEquals(11.0, root.getChild("network1").getChild("node1").getInput("value").getValue());
assertEquals("node1", root.getChild("network1").getRenderedChildName());
assertEquals("node1", root.getChild("network2").getRenderedChildName());
assertEquals("node2", root.getChild("network2").getChild("node1").getRenderedChildName());
assertEquals(17.0, root.getChild("network2").getChild("node1").getChild("node2").getInput("value").getValue());
assertEquals(Node.NETWORK, root.getChild("geonet1").getPrototype());
assertEquals("geometry", root.getChild("geonet1").getOutputType());
}
@Test
public void testUpgrade16to17() {
File version16File = new File("src/test/files/upgrade-v16.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version16File);
NodeLibrary upgradedLibrary = result.getLibrary(version16File, NodeRepository.of());
assertFalse(upgradedLibrary.hasProperty("oscPort"));
assertTrue(upgradedLibrary.hasDevice("osc1"));
assertEquals(1, upgradedLibrary.getDevices().size());
assertEquals("2084", upgradedLibrary.getDevices().get(0).getProperties().get("port"));
assertEquals("true", upgradedLibrary.getDevices().get(0).getProperties().get("sync_with_timeline")); // was: autostart
}
@Test
public void testUpgrade18to19() {
File version18File = new File("src/test/files/upgrade-v18.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version18File);
NodeLibrary devicesLibrary = NodeLibrary.load(new File("libraries/device/device.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version18File, NodeRepository.of(devicesLibrary));
Node root = upgradedLibrary.getRoot();
assertEquals("audioplayer1", root.getChild("audio_analysis1").getInput("device_name").getValue());
assertEquals("audioplayer2", root.getChild("audio_analysis2").getInput("device_name").getValue());
assertEquals("audioplayer1", root.getChild("audio_wave1").getInput("device_name").getValue());
assertEquals("audioplayer1", root.getChild("beat_detect1").getInput("device_name").getValue());
}
@Test
public void testUpgrade19to20() {
File version19File = new File("src/test/files/upgrade-v19.ndbx");
UpgradeResult result = NodeLibraryUpgrades.upgrade(version19File);
NodeLibrary devicesLibrary = NodeLibrary.load(new File("libraries/device/device.ndbx"), NodeRepository.of());
NodeLibrary upgradedLibrary = result.getLibrary(version19File, NodeRepository.of(devicesLibrary));
assertEquals("false", upgradedLibrary.getDevice("audioinput1").getProperty("sync_with_timeline"));
assertEquals("true", upgradedLibrary.getDevice("audioplayer1").getProperty("sync_with_timeline"));
assertEquals("true", upgradedLibrary.getDevice("osc1").getProperty("sync_with_timeline"));
}
/**
* Test upgrading from 0.9 files, which should fail since we don't support those conversions.
*/
@Test
public void testTooOldToUpgrade() {
File version09File = new File("src/test/files/upgrade-v0.9.ndbx");
try {
NodeLibraryUpgrades.upgrade(version09File);
fail("Should have thrown a LoadException.");
} catch (LoadException e) {
assertTrue(e.getMessage().contains("NodeBox 2"));
}
}
/**
* Test upgrading from 999 files, which should fail since this format is too new.
*/
@Test
public void testTooNewToUpgrade() {
File version999Files = new File("src/test/files/upgrade-v999.ndbx");
try {
NodeLibraryUpgrades.upgrade(version999Files);
fail("Should have thrown a LoadException.");
} catch (LoadException e) {
assertTrue(e.getMessage().contains("too new"));
}
}
@Test
public void testDocumentProperties() {
NodeLibrary library = NodeLibrary.create("test", Node.ROOT);
assertFalse(library.hasProperty("alpha"));
library = library.withProperty("alpha", "42");
assertTrue(library.hasProperty("alpha"));
assertEquals("42", library.getProperty("alpha"));
library = library.withPropertyRemoved("alpha");
assertFalse(library.hasProperty("alpha"));
assertEquals("notFound", library.getProperty("alpha", "notFound"));
}
@Test
public void testDocumentPropertiesSerialization() {
NodeLibrary library = NodeLibrary.create("test", Node.ROOT.extend());
library = library.withProperty("alpha", "42");
String xml = library.toXml();
NodeLibrary newLibrary = NodeLibrary.load("test", xml, NodeRepository.of());
assertTrue(newLibrary.hasProperty("alpha"));
assertEquals("42", newLibrary.getProperty("alpha"));
}
public Node makeLetterMenuNode() {
MenuItem alpha = new MenuItem("a", "Alpha");
MenuItem beta = new MenuItem("b", "Beta");
return Node.ROOT.withName("letter")
.withInputAdded(Port.stringPort("letter", "a", ImmutableList.of(alpha, beta)));
}
private void assertPointEquals(Point point, double x, double y) {
assertEquals(x, point.getX());
assertEquals(y, point.getY());
}
private void assertSingleResult(Double expected, Node node, FunctionRepository functionRepository) {
NodeLibrary testLibrary = NodeLibrary.create("test", Node.ROOT, functionRepository);
NodeContext context = new NodeContext(testLibrary);
List<Object> values = ImmutableList.copyOf(context.renderNode(node));
assertEquals(1, values.size());
assertEquals(expected, values.get(0));
}
/**
* Assert that the value that goes in to the port comes out correctly in XML.
*
* @param originalPort The port to serialize / deserialize
*/
private void assertPortSerialization(Port originalPort) {
Node originalNode;
originalNode = Node.ROOT.withInputAdded(originalPort);
NodeLibrary originalLibrary = libraryWithChildren("test", originalNode);
NodeLibrary library = NodeLibrary.load("test", originalLibrary.toXml(), NodeRepository.of());
Node node = library.getRoot().getChild("node1");
assertNotNull(node);
Port port;
port = node.getInput(originalPort.getName());
assertEquals(originalPort.getName(), port.getName());
assertEquals(originalPort.getType(), port.getType());
assertEquals(originalPort.getValue(), port.getValue());
}
private NodeLibrary libraryWithChildren(String libraryName, Node... children) {
Node root = Node.NETWORK.withName("root");
for (Node child : children) {
root = root.withChildAdded(child);
}
return NodeLibrary.create(libraryName, root, FunctionRepository.of());
}
/**
* Assert that a NodeLibrary equals itself after reading and writing.
*
* @param library The NodeLibrary.
* @param nodeRepository The repository of NodeLibraries.
*/
private void assertReadWriteEquals(NodeLibrary library, NodeRepository nodeRepository) {
String xml = library.toXml();
assertEquals(library, NodeLibrary.load(library.getName(), xml, nodeRepository));
}
}