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