ss: Move selectNextChildren to CoreNode and return sequenceNumber
[deliverable/tracecompass.git] / statesystem / org.eclipse.tracecompass.statesystem.core.tests / stubs / org / eclipse / tracecompass / statesystem / core / tests / stubs / backend / HistoryTreeClassicStub.java
1 /*******************************************************************************
2 * Copyright (c) 2015 École Polytechnique de Montréal
3 *
4 * All rights reserved. This program and the accompanying materials are
5 * made available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9
10 package org.eclipse.tracecompass.statesystem.core.tests.stubs.backend;
11
12 import static org.eclipse.tracecompass.common.core.NonNullUtils.checkNotNull;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertTrue;
15 import static org.junit.Assert.fail;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.io.PrintWriter;
20 import java.nio.channels.ClosedChannelException;
21 import java.util.Collection;
22 import java.util.List;
23
24 import org.eclipse.tracecompass.internal.statesystem.core.Activator;
25 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTConfig;
26 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.HTNode;
27 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.IHistoryTree;
28 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.ParentNode;
29 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.classic.CoreNode;
30 import org.eclipse.tracecompass.internal.statesystem.core.backend.historytree.classic.HistoryTreeClassic;
31
32 import com.google.common.collect.Iterables;
33
34 /**
35 * Stub class to unit test the history tree. You can set the size of the
36 * interval section before using the tree, in order to fine-tune the test.
37 *
38 * Note to developers: This tree is not meant to be used with a backend. It just
39 * exposes some info from the history tree.
40 *
41 * @author Geneviève Bastien
42 */
43 public class HistoryTreeClassicStub extends HistoryTreeClassic {
44
45 /**
46 * Minimum size a block of this tree should have
47 */
48 public static final int MINIMUM_BLOCK_SIZE = IHistoryTree.TREE_HEADER_SIZE;
49
50 /**
51 * Constructor for this history tree stub
52 *
53 * @param conf
54 * The config to use for this History Tree.
55 * @throws IOException
56 * If an error happens trying to open/write to the file
57 * specified in the config
58 */
59 public HistoryTreeClassicStub(HTConfig conf) throws IOException {
60 super(conf);
61 }
62
63 /**
64 * "Reader" constructor : instantiate a SHTree from an existing tree file on
65 * disk
66 *
67 * @param existingStateFile
68 * Path/filename of the history-file we are to open
69 * @param expProviderVersion
70 * The expected version of the state provider
71 * @throws IOException
72 * If an error happens reading the file
73 */
74 public HistoryTreeClassicStub(File existingStateFile, int expProviderVersion) throws IOException {
75 super(existingStateFile, expProviderVersion);
76 }
77
78 // ------------------------------------------------------------------------
79 // Extra test accessors
80 // ------------------------------------------------------------------------
81
82 @Override
83 public List<HTNode> getLatestBranch() {
84 /* Super method is not public */
85 return checkNotNull(super.getLatestBranch());
86 }
87
88 /**
89 * Get the latest leaf of the tree
90 *
91 * @return The current leaf node of the tree
92 */
93 public HTNode getLatestLeaf() {
94 List<HTNode> latest = getLatestBranch();
95 return Iterables.getLast(latest);
96 }
97
98 /**
99 * Get the node from the latest branch at a given position, 0 being the root
100 * and <size of latest branch - 1> being a leaf node.
101 *
102 * @param pos
103 * The position at which to return the node
104 * @return The node at position pos
105 */
106 public HTNode getNodeAt(int pos) {
107 List<HTNode> latest = getLatestBranch();
108 return latest.get(pos);
109 }
110
111 /**
112 * Get the depth of the tree
113 *
114 * @return The depth of the tree
115 */
116 public int getDepth() {
117 return getLatestBranch().size();
118 }
119
120 // ------------------------------------------------------------------------
121 // Debug printing methods
122 // ------------------------------------------------------------------------
123
124 /**
125 * Print out the full tree for debugging purposes
126 *
127 * @param writer
128 * PrintWriter in which to write the output
129 * @param printIntervals
130 * Flag to enable full output of the interval information
131 * @param ts
132 * The timestamp that nodes have to intersect for intervals to be
133 * printed. A negative value will print intervals for all nodes.
134 * The timestamp only applies if printIntervals is true.
135 */
136 public void debugPrintFullTree(PrintWriter writer, boolean printIntervals, long ts) {
137 preOrderPrint(writer, false, getLatestBranch().get(0), 0, ts);
138
139 if (printIntervals) {
140 preOrderPrint(writer, true, getLatestBranch().get(0), 0, ts);
141 }
142 writer.println('\n');
143 }
144
145 /**
146 * Start at currentNode and print the contents of all its children, in
147 * pre-order. Give the root node in parameter to visit the whole tree, and
148 * have a nice overview.
149 */
150 private void preOrderPrint(PrintWriter writer, boolean printIntervals,
151 HTNode currentNode, int curDepth, long ts) {
152
153 writer.println(currentNode.toString());
154 /*
155 * Print intervals only if timestamp is negative or within the range of
156 * the node
157 */
158 if (printIntervals &&
159 (ts <= 0 ||
160 (ts >= currentNode.getNodeStart() && ts <= currentNode.getNodeEnd()))) {
161 currentNode.debugPrintIntervals(writer);
162 }
163
164 switch (currentNode.getNodeType()) {
165 case LEAF:
166 /* Stop if it's the leaf node */
167 return;
168
169 case CORE:
170 try {
171 final CoreNode node = (CoreNode) currentNode;
172 /* If node extensions were used, they would be printed here. */
173
174 /* Print the child nodes */
175 for (int i = 0; i < node.getNbChildren(); i++) {
176 HTNode nextNode = getTreeIO().readNode(node.getChild(i));
177 for (int j = 0; j < curDepth; j++) {
178 writer.print(" ");
179 }
180 writer.print("+-");
181 preOrderPrint(writer, printIntervals, nextNode, curDepth + 1, ts);
182 }
183 } catch (ClosedChannelException e) {
184 Activator.getDefault().logError(e.getMessage());
185 }
186 break;
187
188 default:
189 break;
190 }
191 }
192
193 // ------------------------------------------------------------------------
194 // Assertion methods, for use with JUnit tests
195 // ------------------------------------------------------------------------
196
197 /**
198 * Check the integrity of all the nodes in the tree. Calls
199 * {@link #assertNodeIntegrity} for every node in the tree.
200 */
201 public void assertIntegrity() {
202 try {
203 for (int i = 0; i < getNodeCount(); i++) {
204 assertNodeIntegrity(getNode(i));
205 }
206 } catch (ClosedChannelException e) {
207 fail(e.getMessage());
208 }
209 }
210
211 /**
212 * Debugging method to make sure all intervals contained in the given node
213 * have valid start and end times.
214 *
215 * @param node
216 * The node to check
217 */
218 private void assertNodeIntegrity(HTNode node) {
219 if (node instanceof ParentNode) {
220 assertChildrenIntegrity((ParentNode) node);
221 }
222
223 /* Check that all intervals are within the node's range */
224 // TODO: Get the intervals of a node
225
226 }
227
228 private void assertChildrenIntegrity(ParentNode node) {
229 try {
230 /*
231 * Test that this node's start and end times match the start of the
232 * first child and the end of the last child, respectively
233 */
234 if (node.getNbChildren() > 0) {
235 HTNode childNode = getNode(node.getChild(0));
236 assertEquals("Equals start time of parent " + node.getSequenceNumber() + " and first child " + childNode.getSequenceNumber(),
237 node.getNodeStart(), childNode.getNodeStart());
238 if (node.isOnDisk()) {
239 childNode = getNode(node.getLatestChild());
240 assertEquals("Equals end time of parent " + node.getSequenceNumber() + " and last child " + childNode.getSequenceNumber(),
241 node.getNodeEnd(), childNode.getNodeEnd());
242 }
243 }
244
245 /*
246 * Test that the childStartTimes[] array matches the real nodes'
247 * start times
248 *
249 * Also test that children range is within the parent's range
250 */
251 for (int i = 0; i < node.getNbChildren(); i++) {
252 HTNode childNode = getNode(node.getChild(i));
253 assertEquals("Start time in parent " + node.getSequenceNumber() + " of child at index " + i,
254 childNode.getNodeStart(), node.getChildStart(i));
255 assertTrue("Child at index " + i + " of parent " + node.getSequenceNumber() + " has correct start time",
256 node.getNodeStart() <= childNode.getNodeStart());
257 if (node.isOnDisk() && childNode.isOnDisk()) {
258 assertTrue("Child at index " + i + " of parent " + node.getSequenceNumber() + " has correct start time",
259 childNode.getNodeEnd() <= childNode.getNodeEnd());
260 }
261 testIntersectingChildren(node, childNode);
262 }
263
264 } catch (ClosedChannelException e) {
265 fail(e.getMessage());
266 }
267 }
268
269 private static void testIntersectingChildren(ParentNode parent, HTNode child) {
270 int childSequence = child.getSequenceNumber();
271 boolean shouldBeInCollection;
272 Collection<Integer> nextChildren;
273 for (long t = parent.getNodeStart(); t < parent.getNodeEnd(); t++) {
274 shouldBeInCollection = (t >= child.getNodeStart() && t <= child.getNodeEnd());
275 nextChildren = parent.selectNextChildren(t);
276 assertEquals(shouldBeInCollection, nextChildren.contains(childSequence));
277 }
278 }
279
280 }
This page took 0.037225 seconds and 5 git commands to generate.