/* * This file is part of the Jikes RVM project (http://jikesrvm.org). * * This file is licensed to You under the Eclipse Public License (EPL); * You may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.opensource.org/licenses/eclipse-1.0.php * * See the COPYRIGHT.txt file distributed with this work for information * regarding copyright ownership. */ package org.jikesrvm.compilers.opt.util; import static org.hamcrest.CoreMatchers.is; import static org.hamcrest.CoreMatchers.sameInstance; import static org.junit.Assert.assertThat; import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import java.util.ArrayList; import java.util.LinkedList; import java.util.NoSuchElementException; import org.jikesrvm.junit.runners.RequiresBootstrapVM; import org.jikesrvm.junit.runners.VMRequirements; import org.jikesrvm.tests.util.SimpleEnumeration; import org.jikesrvm.util.EmptyEnumeration; import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.runner.RunWith; @RunWith(VMRequirements.class) @Category(RequiresBootstrapVM.class) public class DepthFirstEnumeratorTest { @Test public void testGraphWithOneNode() throws Exception { GraphNode nodeWithoutSuccessors = buildNodeWithoutSuccessor(); DepthFirstEnumerator enumerator = getDepthFirstEnumerator(nodeWithoutSuccessors); assertThat(enumerator.hasMoreElements(), is(true)); verifyFirstElement(enumerator, nodeWithoutSuccessors); assertThat(enumerator.hasMoreElements(), is(false)); } private GraphNode buildNodeWithoutSuccessor() { GraphNode nodeWithoutSuccessors = mock(GraphNode.class); when(nodeWithoutSuccessors.outNodes()).thenReturn(EmptyEnumeration.<GraphNode>emptyEnumeration()); return nodeWithoutSuccessors; } private DepthFirstEnumerator getDepthFirstEnumerator(GraphNode startNode) { DepthFirstEnumerator enumerator = new DepthFirstEnumerator(startNode); return enumerator; } private void verifyFirstElement(DepthFirstEnumerator depthFirstEnumerator, GraphNode startNode) { GraphNode firstElement = depthFirstEnumerator.nextElement(); assertThat(firstElement, sameInstance(startNode)); } @Test(expected = NoSuchElementException.class) public void testThatExceptionIsThrownWhenNoElementsAreLeft() { GraphNode nodeWithoutSuccessors = buildNodeWithoutSuccessor(); DepthFirstEnumerator enumerator = getDepthFirstEnumerator(nodeWithoutSuccessors); enumerator.nextElement(); enumerator.nextElement(); } @Test public void testThatMultipleNodesAreEnumerated() throws Exception { GraphNode secondNode = buildNodeWithoutSuccessor(); GraphNode startNode = mock(GraphNode.class); setUpSuccessorsForNode(startNode, secondNode); DepthFirstEnumerator enumerator = getDepthFirstEnumerator(startNode); verifyFirstElement(enumerator, startNode); verifyNextElement(enumerator, secondNode); assertThat(enumerator.hasMoreElements(), is(false)); } private void setUpSuccessorsForNode(GraphNode startNode, GraphNode... successors) { ArrayList<GraphNode> successorNodes = new ArrayList<GraphNode>(successors.length); for (int i = 0; i < successors.length; i++) { successorNodes.add(successors[i]); } when(startNode.outNodes()).thenReturn(new SimpleEnumeration<GraphNode>(successorNodes)); } private void verifyNextElement(DepthFirstEnumerator enumerator, GraphNode expected) { assertThat(enumerator.hasMoreElements(), is(true)); GraphNode secondElement = enumerator.nextElement(); assertThat(secondElement, sameInstance(expected)); } @Test public void testThatEnumerationIsDepthFirst() throws Exception { GraphNode d = buildNodeWithoutSuccessor(); GraphNode b = mock(GraphNode.class); setUpSuccessorsForNode(b, d); GraphNode c = buildNodeWithoutSuccessor(); GraphNode startNode = mock(GraphNode.class); setUpSuccessorsForNode(startNode, b, c); DepthFirstEnumerator enumerator = getDepthFirstEnumerator(startNode); LinkedList<GraphNode> orderedList = new LinkedList<GraphNode>(); while (enumerator.hasMoreElements()) { orderedList.addLast(enumerator.nextElement()); } assertThat(orderedList.size(), is(4)); assertThat(orderedList.indexOf(startNode), is(0)); assertThat(orderedList.indexOf(d), is(orderedList.indexOf(b) + 1)); assertTrue(orderedList.indexOf(c) > orderedList.indexOf(startNode)); assertThat(enumerator.hasMoreElements(), is(false)); } @Test(timeout = 10000) public void testThatCirclesAreNotAProblem() throws Exception { GraphNode b = mock(GraphNode.class); GraphNode start = mock(GraphNode.class); setUpSuccessorsForNode(start, b); GraphNode c = mock(GraphNode.class); setUpSuccessorsForNode(b, c); GraphNode d = mock(GraphNode.class); setUpSuccessorsForNode(c, d); setUpSuccessorsForNode(d, start); DepthFirstEnumerator depthFirstEnumerator = getDepthFirstEnumerator(start); verifyFirstElement(depthFirstEnumerator, start); verifyNextElement(depthFirstEnumerator, b); verifyNextElement(depthFirstEnumerator, c); verifyNextElement(depthFirstEnumerator, d); assertThat(depthFirstEnumerator.hasMoreElements(), is(false)); } @Test public void testBiggerGraph() throws Exception { GraphNode start = mock(GraphNode.class); GraphNode b = mock(GraphNode.class); GraphNode h = mock(GraphNode.class); GraphNode j = buildNodeWithoutSuccessor(); setUpSuccessorsForNode(start, b, h, j); GraphNode d = mock(GraphNode.class); GraphNode c = buildNodeWithoutSuccessor(); setUpSuccessorsForNode(b, d, c); GraphNode e = mock(GraphNode.class); setUpSuccessorsForNode(d, e, h); GraphNode f = buildNodeWithoutSuccessor(); GraphNode g = buildNodeWithoutSuccessor(); setUpSuccessorsForNode(e, f, g); GraphNode i = buildNodeWithoutSuccessor(); setUpSuccessorsForNode(h, i); DepthFirstEnumerator enumerator = getDepthFirstEnumerator(start); LinkedList<GraphNode> orderedList = new LinkedList<GraphNode>(); while (enumerator.hasMoreElements()) { orderedList.addLast(enumerator.nextElement()); } assertThat(orderedList.size(), is(10)); assertThat(orderedList.indexOf(start), is(0)); boolean bIsDirectSuccessorOfStart = isDirectSuccessorOf(b, start, orderedList); boolean hIsDirectSuccessorOfStart = isDirectSuccessorOf(h, start, orderedList); boolean jIsDirectSuccessorOfStart = isDirectSuccessorOf(j, start, orderedList); assertThat(bIsDirectSuccessorOfStart || hIsDirectSuccessorOfStart || jIsDirectSuccessorOfStart, is(true)); boolean cIsDirectSuccessorOfB = isDirectSuccessorOf(c, b, orderedList); boolean dIsDirectSuccessorOfB = isDirectSuccessorOf(d, b, orderedList); assertThat(cIsDirectSuccessorOfB || dIsDirectSuccessorOfB, is(true)); boolean eIsDirectSuccessorOfD = isDirectSuccessorOf(e, d, orderedList); boolean hIsDirectSuccessorOfD = isDirectSuccessorOf(h, d, orderedList); assertThat(eIsDirectSuccessorOfD || hIsDirectSuccessorOfD, is(true)); boolean fIsDirectSuccessorofE = isDirectSuccessorOf(f, e, orderedList); boolean gIsDirectSuccessorofE = isDirectSuccessorOf(g, e, orderedList); assertThat(fIsDirectSuccessorofE || gIsDirectSuccessorofE, is(true)); assertThat(isDirectSuccessorOf(i, h, orderedList), is(true)); } private boolean isDirectSuccessorOf(GraphNode second, GraphNode first, LinkedList<GraphNode> orderedList) { return orderedList.indexOf(second) == orderedList.indexOf(first) + 1; } }