// Copyright 2012 Georg-August-Universität Göttingen, Germany // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package de.ugoe.cs.autoquest.tasktrees.treeimpl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import java.util.HashMap; import java.util.Map; import org.junit.Test; import de.ugoe.cs.autoquest.tasktrees.treeifc.IEventTask; import de.ugoe.cs.autoquest.tasktrees.treeifc.IIteration; import de.ugoe.cs.autoquest.tasktrees.treeifc.ISelection; import de.ugoe.cs.autoquest.tasktrees.treeifc.ISequence; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTree; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeBuilder; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNode; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeFactory; import de.ugoe.cs.autoquest.tasktrees.treeifc.ITaskTreeNodeInfo; import de.ugoe.cs.autoquest.tasktrees.treeimpl.NodeInfo; import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskTreeBuilder; import de.ugoe.cs.autoquest.tasktrees.treeimpl.TaskTreeNodeFactory; import de.ugoe.cs.autoquest.test.DummyGUIElement; import de.ugoe.cs.autoquest.test.DummyInteraction; /** * TODO comment * * @version $Revision: $ $Date: 02.04.2012$ * @author 2012, last modified by $Author: patrick$ */ public class TaskTreeImplTest { /** */ private static final int MAX_TREE_DEPTH = 15; /** */ private ITaskTreeBuilder taskTreeBuilder = new TaskTreeBuilder(); /** */ private ITaskTreeNodeFactory taskTreeNodeFactory = new TaskTreeNodeFactory(); /** * @throws Exception * */ @Test public void testRandomTrees() throws Exception { int noOfTrees = 10; int noOfMaxChildren = 8; int maxDepth = MAX_TREE_DEPTH; for (int i = 0; i < noOfTrees; i++) { System.err.println("iteration " + (i + 1) + ":"); System.err.println(" creating tree"); Map treeInfos = new HashMap(); ITaskTreeNode rootNode = createTree(noOfMaxChildren, maxDepth, treeInfos); System.err.println(" creating task tree"); ITaskTree taskTree = taskTreeNodeFactory.createTaskTree(rootNode); System.err.println(" validating task tree"); assertEquals(rootNode, taskTree.getRoot()); assertMapsEqual(treeInfos, taskTree.getTaskMap()); } } /** * TODO: comment * * @param treeInfos * @param taskMap */ private void assertMapsEqual(Map map1, Map map2) { try { if (map1 == null) { assertNull(map2); return; } assertEquals(map1.size(), map2.size()); for (Map.Entry entry : map1.entrySet()) { ITaskTreeNodeInfo value2 = map2.get(entry.getKey()); assertNotNull(value2); assertEquals(entry.getValue().getTask(), value2.getTask()); //assertEquals(entry.getValue().getNoOfOccurencesInTree(), // value2.getNoOfOccurencesInTree()); } } catch (AssertionError e) { dumpMap(map1); dumpMap(map2); throw e; } } /** * TODO: comment * * @param map2 */ private void dumpMap(Map map) { System.err.println(); if (map == null) { System.err.println("map is null"); } else { System.err.println("map:"); for (Map.Entry entry : map.entrySet()) { System.err.print(" "); System.err.print(entry.getKey()); for (int i = entry.getKey().toString().length(); i < 49; i++) { System.err.print(" "); } System.err.print(" : "); System.err.println(entry.getValue()); } } System.err.println(); } /** * TODO: comment * * @param noOfMaxChildren * @param maxDepth * @param treeInfos * @return */ private ITaskTreeNode createTree(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { /* * for (int i = 0; i < (MAX_TREE_DEPTH + 1 - maxDepth); i++) { System.err.print(" "); } */ ITaskTreeNode tree; // integrating the maximum depth here assures, that either something between 0 and 8 will // be the type, or if the max depth decreases near 0 only event tasks will be created // to finish the tree creation int type = (int) (Math.random() * (Math.min(8, maxDepth))); switch (type) { case 0: { // System.err.print("creating new event task "); tree = createNewEventTask(treeInfos); break; } case 1: { // System.err.print("reusing event task "); tree = reuseEventTask(treeInfos); break; } case 2: { // System.err.println("creating new sequence {"); tree = createNewSequence(maxNoOfChildren, maxDepth, treeInfos); break; } case 3: { // System.err.println("reusing sequence {"); tree = reuseSequence(maxNoOfChildren, maxDepth, treeInfos); break; } case 4: { // System.err.println("creating new selection {"); tree = createNewSelection(maxNoOfChildren, maxDepth, treeInfos); break; } case 5: { // System.err.println("reusing selection {"); tree = reuseSelection(maxNoOfChildren, maxDepth, treeInfos); break; } case 6: { // System.err.println("creating new iteration {"); tree = createNewIteration(maxNoOfChildren, maxDepth, treeInfos); break; } case 7: { // System.err.println("reusing iteration {"); tree = reuseIteration(maxNoOfChildren, maxDepth, treeInfos); break; } default: { // System.err.print("creating new event task per default "); tree = createNewEventTask(treeInfos); } } /* * if (!(tree instanceof InteractionTask)) { for (int i = 0; i < (MAX_TREE_DEPTH + 1 - * maxDepth); i++) { System.err.print(" "); } * * System.err.print("} "); } * * System.err.println(tree); */ return tree; } /** * TODO: comment * * @param treeInfos * @return */ private IEventTask createNewEventTask(Map treeInfos) throws Exception { Thread.sleep(2); long id = System.currentTimeMillis(); IEventTask task = taskTreeNodeFactory.createNewEventTask(new DummyInteraction("interaction" + id, 1), new DummyGUIElement("elem" + id)); treeInfos.put(task, new NodeInfo(task)); return task; } /** * TODO: comment * * @param treeInfos * @return */ private IEventTask reuseEventTask(Map treeInfos) throws Exception { int noOfEventTasks = 0; for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof IEventTask) { noOfEventTasks++; } } if (noOfEventTasks > 0) { noOfEventTasks = (int) (Math.random() * noOfEventTasks); for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof IEventTask) { if (--noOfEventTasks <= 0) { return (IEventTask) entry.getKey(); } } } } else { return createNewEventTask(treeInfos); } throw new RuntimeException("this is an implementation error"); } /** * TODO: comment * * @param treeInfos * @return */ private ISequence createNewSequence(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { ISequence sequence = taskTreeNodeFactory.createNewSequence(); int noOfChildren = (int) (Math.random() * maxNoOfChildren); for (int i = 0; i < noOfChildren; i++) { ITaskTreeNode child = createTree(maxNoOfChildren, maxDepth - 1, treeInfos); // through first removing an existing parent it is assured, that a parent is recorded // only once. This is needed, because parent may be reused in a tree as well, but we // always // iterate the whole tree ((NodeInfo) treeInfos.get(child)).removeParent(sequence); ((NodeInfo) treeInfos.get(child)).addParent(sequence); taskTreeBuilder.addChild(sequence, child); } treeInfos.put(sequence, new NodeInfo(sequence)); return sequence; } /** * TODO: comment * * @param treeInfos * @return */ private ISequence reuseSequence(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { int noOfSequences = 0; for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof ISequence) { noOfSequences++; } } if (noOfSequences > 0) { noOfSequences = (int) (Math.random() * noOfSequences); for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof ISequence) { if (--noOfSequences <= 0) { return (ISequence) entry.getKey(); } } } } else { return createNewSequence(maxNoOfChildren, maxDepth, treeInfos); } throw new RuntimeException("this is an implementation error"); } /** * TODO: comment * * @param treeInfos * @return */ private ISelection createNewSelection(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { ISelection selection = taskTreeNodeFactory.createNewSelection(); int noOfChildren = (int) (Math.random() * maxNoOfChildren); for (int i = 0; i < noOfChildren; i++) { ITaskTreeNode child = createTree(maxNoOfChildren, maxDepth - 1, treeInfos); // through first removing an existing parent it is assured, that a parent is recorded // only once. This is needed, because parent may be reused in a tree as well, but we // always // iterate the whole tree ((NodeInfo) treeInfos.get(child)).removeParent(selection); ((NodeInfo) treeInfos.get(child)).addParent(selection); taskTreeBuilder.addChild(selection, child); } treeInfos.put(selection, new NodeInfo(selection)); return selection; } /** * TODO: comment * * @param treeInfos * @return */ private ISelection reuseSelection(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { int noOfSelections = 0; for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof ISelection) { noOfSelections++; } } if (noOfSelections > 0) { noOfSelections = (int) (Math.random() * noOfSelections); for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof ISelection) { if (--noOfSelections <= 0) { return (ISelection) entry.getKey(); } } } } else { return createNewSelection(maxNoOfChildren, maxDepth, treeInfos); } throw new RuntimeException("this is an implementation error"); } /** * TODO: comment * * @param treeInfos * @return */ private IIteration createNewIteration(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { IIteration iteration = taskTreeNodeFactory.createNewIteration(); ITaskTreeNode child = createTree(maxNoOfChildren, maxDepth - 1, treeInfos); // through first removing an existing parent it is assured, that a parent is recorded // only once. This is needed, because parent may be reused in a tree as well, but we always // iterate the whole tree ((NodeInfo) treeInfos.get(child)).removeParent(iteration); ((NodeInfo) treeInfos.get(child)).addParent(iteration); taskTreeBuilder.setChild(iteration, child); treeInfos.put(iteration, new NodeInfo(iteration)); return iteration; } /** * TODO: comment * * @param treeInfos * @return */ private IIteration reuseIteration(int maxNoOfChildren, int maxDepth, Map treeInfos) throws Exception { int noOfIterations = 0; for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof IIteration) { noOfIterations++; } } if (noOfIterations > 0) { noOfIterations = (int) (Math.random() * noOfIterations); for (Map.Entry entry : treeInfos.entrySet()) { if (entry.getKey() instanceof IIteration) { if (--noOfIterations <= 0) { return (IIteration) entry.getKey(); } } } } else { return createNewIteration(maxNoOfChildren, maxDepth, treeInfos); } throw new RuntimeException("this is an implementation error"); } }