/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package com.oracle.truffle.api.test.nodes;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import java.util.Iterator;
import org.junit.Assert;
import org.junit.Test;
import com.oracle.truffle.api.frame.VirtualFrame;
import com.oracle.truffle.api.nodes.Node;
import com.oracle.truffle.api.nodes.NodeUtil;
import com.oracle.truffle.api.nodes.NodeVisitor;
import com.oracle.truffle.api.nodes.RootNode;
public class NodeUtilTest {
@Test
public void testRecursiveIterator1() {
TestRootNode root = new TestRootNode();
TestNode testNode = new TestNode();
root.child0 = testNode;
root.adoptChildren();
int count = iterate(NodeUtil.makeRecursiveIterator(root));
assertThat(count, is(2));
assertThat(root.visited, is(0));
assertThat(testNode.visited, is(1));
}
@Test
public void testReplaceReplaced() {
TestRootNode rootNode = new TestRootNode();
TestNode replacedNode = new TestNode();
rootNode.child0 = replacedNode;
rootNode.adoptChildren();
rootNode.child0 = null;
TestNode test1 = new TestNode();
TestNode test11 = new TestNode();
TestNode test111 = new TestNode();
test11.child1 = test111;
test1.child1 = test11;
replacedNode.replace(test1);
Assert.assertSame(rootNode, test1.getParent());
Assert.assertSame(test1, test11.getParent());
Assert.assertSame(test11, test111.getParent());
}
@Test
public void testForEachChild() {
TestRootNode root = new TestRootNode();
TestForEachNode testForEachNode = new TestForEachNode(1);
root.child0 = testForEachNode;
TestNode testNode1 = new TestNode();
testForEachNode.firstChild = testNode1;
TestNode testNode2 = new TestNode();
testForEachNode.children[0] = testNode2;
TestNode testNode3 = new TestNode();
testForEachNode.lastChild = testNode3;
root.adoptChildren();
int[] count = new int[1];
NodeUtil.forEachChild(root, new NodeVisitor() {
public boolean visit(Node node) {
Assert.assertSame(testForEachNode, node);
count[0]++;
return true;
}
});
Assert.assertEquals(1, count[0]);
count[0] = 0;
NodeUtil.forEachChild(testForEachNode, new NodeVisitor() {
public boolean visit(Node node) {
((VisitableNode) node).visited++;
count[0]++;
return true;
}
});
Assert.assertEquals(3, count[0]);
Assert.assertEquals(1, testNode1.visited);
Assert.assertEquals(1, testNode2.visited);
Assert.assertEquals(1, testNode3.visited);
}
@Test
public void testAccept() {
TestRootNode root = new TestRootNode();
TestForEachNode testForEachNode = new TestForEachNode(1);
root.child0 = testForEachNode;
TestNode testNode1 = new TestNode();
testForEachNode.firstChild = testNode1;
TestNode testNode2 = new TestNode();
testForEachNode.children[0] = testNode2;
TestNode testNode3 = new TestNode();
testForEachNode.lastChild = testNode3;
root.adoptChildren();
int[] count = new int[1];
testForEachNode.accept(new NodeVisitor() {
public boolean visit(Node node) {
((VisitableNode) node).visited++;
count[0]++;
return true;
}
});
Assert.assertEquals(4, count[0]);
Assert.assertEquals(1, testForEachNode.visited);
Assert.assertEquals(1, testNode1.visited);
Assert.assertEquals(1, testNode2.visited);
Assert.assertEquals(1, testNode3.visited);
}
@Test
public void testRecursiveIterator() {
TestRootNode root = new TestRootNode();
TestForEachNode testForEachNode = new TestForEachNode(1);
root.child0 = testForEachNode;
TestNode testNode1 = new TestNode();
testForEachNode.firstChild = testNode1;
TestNode testNode2 = new TestNode();
testForEachNode.children[0] = testNode2;
TestNode testNode3 = new TestNode();
testForEachNode.lastChild = testNode3;
root.adoptChildren();
int count = 0;
Iterable<Node> iterable = () -> NodeUtil.makeRecursiveIterator(testForEachNode);
for (Node node : iterable) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(4, count);
Assert.assertEquals(1, testForEachNode.visited);
Assert.assertEquals(1, testNode1.visited);
Assert.assertEquals(1, testNode2.visited);
Assert.assertEquals(1, testNode3.visited);
}
@Test
public void testChildren() {
TestRootNode root = new TestRootNode();
TestForEachNode testForEachNode = new TestForEachNode(1);
root.child0 = testForEachNode;
TestNode testNode1 = new TestNode();
testForEachNode.firstChild = testNode1;
TestNode testNode2 = new TestNode();
testForEachNode.children[0] = testNode2;
TestNode testNode3 = new TestNode();
testForEachNode.lastChild = testNode3;
int count = 0;
for (Node node : testForEachNode.getChildren()) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(3, count);
Assert.assertEquals(1, testNode1.visited);
Assert.assertEquals(1, testNode2.visited);
Assert.assertEquals(1, testNode3.visited);
}
@Test
public void testChildrenArray() {
// 2 children in the array
TestForEachNode test2children = new TestForEachNode(2);
TestNode both1 = new TestNode();
TestNode both2 = new TestNode();
test2children.children[0] = both1;
test2children.children[1] = both2;
int count = 0;
for (Node node : test2children.getChildren()) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(2, count);
Assert.assertEquals(1, both1.visited);
Assert.assertEquals(1, both2.visited);
// First null
TestNode testChild1 = new TestNode();
test2children.children[0] = null;
test2children.children[1] = testChild1;
count = 0;
for (Node node : test2children.getChildren()) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(1, count);
Assert.assertEquals(1, testChild1.visited);
// Second null
TestNode testChild2 = new TestNode();
test2children.children[0] = testChild2;
test2children.children[1] = null;
count = 0;
for (Node node : test2children.getChildren()) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(1, count);
Assert.assertEquals(1, testChild2.visited);
// Both null, go to next child
TestNode otherChild = new TestNode();
test2children.children[0] = null;
test2children.children[1] = null;
test2children.lastChild = otherChild;
count = 0;
for (Node node : test2children.getChildren()) {
((VisitableNode) node).visited++;
count++;
}
Assert.assertEquals(1, count);
Assert.assertEquals(1, otherChild.visited);
}
private static int iterate(Iterator<Node> iterator) {
int iterationCount = 0;
while (iterator.hasNext()) {
Node node = iterator.next();
if (node == null) {
continue;
}
if (node instanceof TestNode) {
((TestNode) node).visited = iterationCount;
} else if (node instanceof TestRootNode) {
((TestRootNode) node).visited = iterationCount;
} else {
throw new AssertionError();
}
iterationCount++;
}
return iterationCount;
}
private static class VisitableNode extends Node {
int visited = 0;
}
private static class TestNode extends VisitableNode {
@Child TestNode child0;
@Child TestNode child1;
TestNode() {
}
}
private static class TestRootNode extends RootNode {
@Child Node child0;
protected int visited;
TestRootNode() {
super(null);
}
@Override
public Object execute(VirtualFrame frame) {
return null;
}
}
private static class TestForEachNode extends VisitableNode {
@Child private Node nullChild;
@SuppressWarnings("unused") private String data1;
@Child private Node firstChild;
@Children private final Node[] children;
@SuppressWarnings("unused") private boolean data2;
@Child private Node lastChild;
TestForEachNode(int childrenSize) {
this.children = new Node[childrenSize];
}
}
}