@Before public void prepareFixture() throws Exception { Class<AbstractNodeIteratingGraphTraverser> traverserClass = AbstractNodeIteratingGraphTraverser.class; traverser = createMock( traverserClass, traverserClass.getMethod("hasNext", (Class[]) null), traverserClass.getMethod("next", (Class[]) null), traverserClass.getDeclaredMethod("enqueueNodes", Collection.class)); // creating the mock doesn't initialize instance fields, for some reason ReflectionUtils.setValue( traverser, "nodeVisitors", new ArrayList<NodeVisitor<Object, StringBuilder>>()); ReflectionUtils.setValue(traverser, "visitedOrQueuedNodes", new HashSet<Object>()); }
@Test public void addNode_node_seen() throws IllegalAccessException { ReflectionUtils.setValue(traverser, "visitedOrQueuedNodes", SetUtils.asSet(1)); // expect no calls to enqueue traverser.addNode(1); }
@Test public void addNode_nodes_seen() throws IllegalAccessException { ReflectionUtils.setValue(traverser, "visitedOrQueuedNodes", SetUtils.asSet(1)); traverser.enqueueNodes(colEq(Arrays.asList(2))); expectLastCall(); replay(traverser); traverser.addNode(Arrays.asList(1, 2)); verify(traverser); }
/** * Starting from a node 1, traverse the graph. Node 1 discovers two extra nodes, 1 and 2, of which * only 2 should be called. * * <p>Ensures that any state maintained during traversal is cleared. */ @Test public void traverseFrom_node() throws IllegalAccessException { traverser.addNodeVisitor(visitor1); // initially, node 1 will be queued traverser.enqueueNodes(colEq(Arrays.<Object>asList(1))); expectLastCall(); traverser.hasNext(); expectLastCall().andReturn(true); traverser.next(); expectLastCall().andReturn(1); StringBuilder traversalState = new StringBuilder(); visitor1.visitNode(1, traverser, traversalState); expectLastCall() .andAnswer(new NodeVisitorAction(traverser, Arrays.<Object>asList(1, 2), "James", true)); // the second node 1 should not be enqueued traverser.enqueueNodes(colEq(Arrays.<Object>asList(2))); expectLastCall(); traverser.hasNext(); expectLastCall().andReturn(true); traverser.next(); expectLastCall().andReturn(2); // the visitor should *not* be called again for node 1 visitor1.visitNode(2, traverser, traversalState); expectLastCall().andAnswer(new NodeVisitorAction(traverser, null, " Bond", true)); // all nodes have been visited traverser.hasNext(); expectLastCall().andReturn(false); replay(traverser, visitor1); // none of the visitors returned "false", so the traversal should succeed assertTrue(traverser.traverseFrom(1, traversalState)); verify(traverser, visitor1); // check that the state object was correctly updated assertEquals("James Bond", traversalState.toString()); // check that any internal state maintained during the cloning has been cleaned up assertTrue(ReflectionUtils.<Set<?>>getValue(traverser, "visitedOrQueuedNodes").isEmpty()); }
/** * Starting from nodes 1, 1 and 2, traverse the graph. Node 1 will be called twice because it is * specified with the starting nodes, and the second visitor is not called for node 2 because the * first one aborts the traversal. * * <p>This also tests that the visitors are called in the expected order, and ensures that any * state maintained during traversal is cleared. */ @Test public void traverseFrom_nodes() throws IllegalAccessException { traverser.addNodeVisitor(visitor1); traverser.addNodeVisitor(visitor2); // initially, nodes 1, 1 and 2 will be queued traverser.enqueueNodes(colEq(Arrays.<Object>asList(1, 1, 2))); expectLastCall(); StringBuilder traversalState = new StringBuilder(); /* * The visitors will also be called for the *second* 1 (even though it is equal * to the previous one), because it was specified with the initial objects. */ traverser.hasNext(); expectLastCall().andReturn(true).times(2); traverser.next(); expectLastCall().andReturn(1).times(2); visitor1.visitNode(1, traverser, traversalState); expectLastCall().andAnswer(new NodeVisitorAction(traverser, null, null, true)).times(2); visitor2.visitNode(1, traverser, traversalState); expectLastCall().andAnswer(new NodeVisitorAction(traverser, null, null, true)).times(2); // graph traversal is aborted by visitor1, so no further call to visitor2 is expected traverser.hasNext(); expectLastCall().andReturn(true); traverser.next(); expectLastCall().andReturn(2); visitor1.visitNode(2, traverser, traversalState); expectLastCall().andAnswer(new NodeVisitorAction(traverser, null, null, false)); replay(traverser, visitor1, visitor2); // of the visitors returned "false", so the traversal should have failed assertFalse(traverser.traverseFrom(Arrays.<Object>asList(1, 1, 2), traversalState)); verify(traverser, visitor1, visitor2); // check that the state object was not updated assertEquals("", traversalState.toString()); // check that any internal state maintained during the cloning has been cleaned up assertTrue(ReflectionUtils.<Set<?>>getValue(traverser, "visitedOrQueuedNodes").isEmpty()); }