tmf.core: Introduce TmfTimestamp factory methods
[deliverable/tracecompass.git] / analysis / org.eclipse.tracecompass.analysis.graph.core.tests / src / org / eclipse / tracecompass / analysis / graph / core / tests / graph / TmfGraphTest.java
CommitLineData
1b46d94d
FG
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 * Contributors:
10 * Francis Giraldeau - Initial API and implementation
11 * Geneviève Bastien - Initial API and implementation
12 *******************************************************************************/
13
14package org.eclipse.tracecompass.analysis.graph.core.tests.graph;
15
16import static org.junit.Assert.assertEquals;
17import static org.junit.Assert.assertNotNull;
18import static org.junit.Assert.assertNotSame;
19import static org.junit.Assert.assertNull;
20
732e0744 21import java.util.HashSet;
1b46d94d 22import java.util.List;
732e0744 23import java.util.Set;
1b46d94d
FG
24
25import org.eclipse.jdt.annotation.NonNull;
732e0744 26import org.eclipse.tracecompass.analysis.graph.core.base.CycleDetectedException;
1b46d94d
FG
27import org.eclipse.tracecompass.analysis.graph.core.base.IGraphWorker;
28import org.eclipse.tracecompass.analysis.graph.core.base.ITmfGraphVisitor;
29import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge;
30import org.eclipse.tracecompass.analysis.graph.core.base.TmfEdge.EdgeType;
31import org.eclipse.tracecompass.analysis.graph.core.base.TmfGraph;
32import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex;
33import org.eclipse.tracecompass.analysis.graph.core.base.TmfVertex.EdgeDirection;
34import org.eclipse.tracecompass.analysis.graph.core.tests.stubs.TestGraphWorker;
35import org.eclipse.tracecompass.internal.analysis.graph.core.base.TmfGraphStatistics;
36import org.eclipse.tracecompass.tmf.core.timestamp.ITmfTimestamp;
37import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp;
38import org.junit.Test;
39
40/**
41 * Test the basic functionalities of the {@link TmfGraph}, {@link TmfVertex} and
42 * {@link TmfEdge} classes.
43 *
44 * @author Geneviève Bastien
45 * @author Francis Giraldeau
46 */
47public class TmfGraphTest {
48
49 private static final @NonNull IGraphWorker WORKER1 = new TestGraphWorker(1);
50 private static final @NonNull IGraphWorker WORKER2 = new TestGraphWorker(2);
732e0744 51 private static final @NonNull IGraphWorker WORKER3 = new TestGraphWorker(3);
1b46d94d
FG
52
53 private final @NonNull TmfGraph fGraph = new TmfGraph();
54 private final @NonNull TmfVertex fV0 = new TmfVertex(0);
55 private final @NonNull TmfVertex fV1 = new TmfVertex(1);
56
57 /**
58 * Test the graph constructor
59 */
60 @Test
61 public void testDefaultConstructor() {
62 TmfGraph g = new TmfGraph();
63 assertEquals(0, g.size());
64 }
65
66 /**
67 * Test the {@link TmfGraph#add(IGraphWorker, TmfVertex)} method: vertices are
68 * added, but no edge between them is created
69 */
70 @Test
71 public void testAddVertex() {
72 fGraph.add(WORKER1, fV0);
73 fGraph.add(WORKER1, fV1);
74 List<TmfVertex> list = fGraph.getNodesOf(WORKER1);
75 assertEquals(2, list.size());
76 for (int i = 0; i < list.size() - 1; i++) {
77 TmfVertex vertex = list.get(i);
78 assertEquals(i, vertex.getTs());
79 assertNull(vertex.getEdge(EdgeDirection.OUTGOING_HORIZONTAL_EDGE));
80 assertNull(vertex.getEdge(EdgeDirection.INCOMING_HORIZONTAL_EDGE));
81 assertNull(vertex.getEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE));
82 assertNull(vertex.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE));
83 }
84 }
85
86 /**
87 * Test the {@link TmfGraph#append(IGraphWorker, TmfVertex)} and
88 * {@link TmfGraph#append(IGraphWorker, TmfVertex, EdgeType)} methods: vertices
89 * are added and links are created between them.
90 */
91 @Test
92 public void testAppendVertex() {
93 /* Append without type */
94 fGraph.append(WORKER1, fV0);
95 TmfEdge edge = fGraph.append(WORKER1, fV1);
96 assertNotNull(edge);
97 assertEquals(EdgeType.DEFAULT, edge.getType());
98 assertEquals(fV1, edge.getVertexTo());
99 assertEquals(fV0, edge.getVertexFrom());
100 assertEquals(fV1.getTs() - fV0.getTs(), edge.getDuration());
101
102 List<TmfVertex> list = fGraph.getNodesOf(WORKER1);
103 assertEquals(2, list.size());
104 checkLinkHorizontal(list);
105 assertEquals(fV0, fGraph.getHead(WORKER1));
106 assertEquals(fV1, fGraph.getTail(WORKER1));
107
108 /* Append with a type */
109 TmfVertex v2 = new TmfVertex(2);
110 edge = fGraph.append(WORKER1, v2, EdgeType.BLOCKED);
111 assertNotNull(edge);
112 assertEquals(EdgeType.BLOCKED, edge.getType());
113 assertEquals(v2, edge.getVertexTo());
114 assertEquals(fV1, edge.getVertexFrom());
115 assertEquals(v2.getTs() - fV1.getTs(), edge.getDuration());
116
117 list = fGraph.getNodesOf(WORKER1);
118 assertEquals(3, list.size());
119 checkLinkHorizontal(list);
120 assertEquals(fV0, fGraph.getHead(WORKER1));
121 assertEquals(v2, fGraph.getTail(WORKER1));
122 }
123
124 /**
125 * Test that appending vertices in non chronological order gives error
126 */
127 @Test(expected = IllegalArgumentException.class)
128 public void testIllegalVertex() {
129 fGraph.append(WORKER1, fV1);
130 fGraph.append(WORKER1, fV0);
131 }
132
133 /**
134 * Test the {@link TmfGraph#link(TmfVertex, TmfVertex)} and
135 * {@link TmfGraph#link(TmfVertex, TmfVertex, EdgeType)} methods
136 */
137 @Test
138 public void testLink() {
139 // Start with a first node
140 fGraph.add(WORKER1, fV0);
141
142 // Link with second node not in graph
143 TmfEdge edge = fGraph.link(fV0, fV1);
144 assertEquals(fV1, edge.getVertexTo());
145 assertEquals(fV0, edge.getVertexFrom());
146 assertEquals(EdgeType.DEFAULT, edge.getType());
147 assertEquals(fV1.getTs() - fV0.getTs(), edge.getDuration());
148
149 List<TmfVertex> list = fGraph.getNodesOf(WORKER1);
150 assertEquals(2, list.size());
151 edge = fV1.getEdge(EdgeDirection.INCOMING_HORIZONTAL_EDGE);
152 assertNotNull(edge);
153 assertEquals(fV0, edge.getVertexFrom());
154 edge = fV0.getEdge(EdgeDirection.OUTGOING_HORIZONTAL_EDGE);
155 assertNotNull(edge);
156 assertEquals(fV1, edge.getVertexTo());
157
158 // Link with second node for the same object
159 TmfVertex v2 = new TmfVertex(2);
160 fGraph.add(WORKER1, v2);
161 edge = fGraph.link(fV1, v2, EdgeType.NETWORK);
162 assertEquals(v2, edge.getVertexTo());
163 assertEquals(fV1, edge.getVertexFrom());
164 assertEquals(EdgeType.NETWORK, edge.getType());
165
166 list = fGraph.getNodesOf(WORKER1);
167 assertEquals(3, list.size());
168 edge = fV1.getEdge(EdgeDirection.OUTGOING_HORIZONTAL_EDGE);
169 assertNotNull(edge);
170 assertEquals(v2, edge.getVertexTo());
171 edge = v2.getEdge(EdgeDirection.INCOMING_HORIZONTAL_EDGE);
172 assertNotNull(edge);
173 assertEquals(fV1, edge.getVertexFrom());
174
175 // Link with second node for another object
176 TmfVertex v3 = new TmfVertex(3);
177 fGraph.add(WORKER2, v3);
178 edge = fGraph.link(v2, v3, EdgeType.NETWORK);
179 assertEquals(v3, edge.getVertexTo());
180 assertEquals(v2, edge.getVertexFrom());
181 assertEquals(EdgeType.NETWORK, edge.getType());
182
183 list = fGraph.getNodesOf(WORKER2);
184 assertEquals(1, list.size());
185
186 list = fGraph.getNodesOf(WORKER1);
187 assertEquals(3, list.size());
188 edge = v3.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE);
189 assertNotNull(edge);
190 assertEquals(v2, edge.getVertexFrom());
191 edge = v2.getEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE);
192 assertNotNull(edge);
193 assertEquals(v3, edge.getVertexTo());
194
195 }
196
197 /**
198 * Verify that vertices in the list form a chain linked by edges and have no
199 * vertical edges
200 */
201 private static void checkLinkHorizontal(List<TmfVertex> list) {
202 if (list.isEmpty()) {
203 return;
204 }
205 for (int i = 0; i < list.size() - 1; i++) {
206 TmfVertex v0 = list.get(i);
207 TmfVertex v1 = list.get(i + 1);
208 TmfEdge edge = v0.getEdge(EdgeDirection.OUTGOING_HORIZONTAL_EDGE);
209 assertNotNull(edge);
210 assertEquals(v0, edge.getVertexFrom());
211 assertEquals(v1, edge.getVertexTo());
212 edge = v1.getEdge(EdgeDirection.INCOMING_HORIZONTAL_EDGE);
213 assertNotNull(edge);
214 assertEquals(v0, edge.getVertexFrom());
215 assertEquals(v1, edge.getVertexTo());
216 assertNull(v1.getEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE));
217 assertNull(v1.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE));
218 assertNull(v0.getEdge(EdgeDirection.OUTGOING_VERTICAL_EDGE));
219 assertNull(v0.getEdge(EdgeDirection.INCOMING_VERTICAL_EDGE));
220 }
221 }
222
223 /**
224 * Test the {@link TmfGraph#getTail(IGraphWorker)} and
225 * {@link TmfGraph#removeTail(IGraphWorker)} methods
226 */
227 @Test
228 public void testTail() {
229 fGraph.append(WORKER1, fV0);
230 fGraph.append(WORKER1, fV1);
231 assertEquals(fV1, fGraph.getTail(WORKER1));
232 assertEquals(fV1, fGraph.removeTail(WORKER1));
233 assertEquals(fV0, fGraph.getTail(WORKER1));
234 }
235
236 /**
237 * Test the {@link TmfGraph#getHead()} methods
238 */
239 @Test
240 public void testHead() {
ce81d501 241 assertNull(fGraph.getHead());
1b46d94d
FG
242 fGraph.append(WORKER1, fV0);
243 fGraph.append(WORKER1, fV1);
244 assertEquals(fV0, fGraph.getHead());
245 assertEquals(fV0, fGraph.getHead(WORKER1));
246 assertEquals(fV0, fGraph.getHead(fV1));
247 assertEquals(fV0, fGraph.getHead(fV0));
248 }
249
ce81d501
GB
250 /**
251 * Test the {@link TmfGraph#getHead()} methods with 2 workers
252 */
253 @Test
254 public void testHead2() {
255 fGraph.append(WORKER1, fV1);
256 fGraph.append(WORKER2, fV0);
257 assertEquals(fV0, fGraph.getHead());
258 assertEquals(fV1, fGraph.getHead(WORKER1));
259 assertEquals(fV0, fGraph.getHead(WORKER2));
260 assertEquals(fV1, fGraph.getHead(fV1));
261 assertEquals(fV0, fGraph.getHead(fV0));
262 }
263
1b46d94d
FG
264 /**
265 * The test {@link TmfGraph#getParentOf(TmfVertex)} method
266 */
267 @Test
268 public void testParent() {
269 fGraph.append(WORKER1, fV0);
270 fGraph.append(WORKER2, fV1);
271 assertEquals(WORKER1, fGraph.getParentOf(fV0));
272 assertNotSame(WORKER1, fGraph.getParentOf(fV1));
273 assertEquals(WORKER2, fGraph.getParentOf(fV1));
274 }
275
276 /**
277 * Test the {@link TmfGraph#getVertexAt(ITmfTimestamp, IGraphWorker)} method
278 */
279 @Test
280 public void testVertexAt() {
281 TmfVertex[] vertices = new TmfVertex[5];
282 for (int i = 0; i < 5; i++) {
283 TmfVertex v = new TmfVertex((i + 1) * 5);
284 vertices[i] = v;
285 fGraph.append(WORKER1, v);
286 }
b2c971ec
MK
287 assertEquals(vertices[0], fGraph.getVertexAt(TmfTimestamp.fromSeconds(5), WORKER1));
288 assertEquals(vertices[0], fGraph.getVertexAt(TmfTimestamp.fromSeconds(0), WORKER1));
289 assertEquals(vertices[1], fGraph.getVertexAt(TmfTimestamp.fromSeconds(6), WORKER1));
290 assertEquals(vertices[3], fGraph.getVertexAt(TmfTimestamp.fromSeconds(19), WORKER1));
291 assertNull(fGraph.getVertexAt(TmfTimestamp.fromSeconds(19), WORKER2));
292 assertEquals(vertices[3], fGraph.getVertexAt(TmfTimestamp.fromSeconds(20), WORKER1));
293 assertEquals(vertices[4], fGraph.getVertexAt(TmfTimestamp.fromSeconds(21), WORKER1));
294 assertNull(fGraph.getVertexAt(TmfTimestamp.fromSeconds(26), WORKER1));
1b46d94d
FG
295 }
296
297 /**
298 * Test the {@link TmfVertex#linkHorizontal(TmfVertex)} with non
299 * chronological timestamps
300 */
301 @Test(expected = IllegalArgumentException.class)
302 public void testCheckHorizontal() {
303 TmfVertex n0 = new TmfVertex(10);
304 TmfVertex n1 = new TmfVertex(0);
305 n0.linkHorizontal(n1);
306 }
307
308 /**
309 * Test the {@link TmfVertex#linkVertical(TmfVertex)} with non chronological
310 * timestamps
311 */
312 @Test(expected = IllegalArgumentException.class)
313 public void testCheckVertical() {
314 TmfVertex n0 = new TmfVertex(10);
315 TmfVertex n1 = new TmfVertex(0);
316 n0.linkVertical(n1);
317 }
318
319 private class ScanCountVertex implements ITmfGraphVisitor {
320 public int nbVertex = 0;
321 public int nbVLink = 0;
322 public int nbHLink = 0;
323 public int nbStartVertex = 0;
324
325 @Override
326 public void visitHead(TmfVertex node) {
327 nbStartVertex++;
328 }
329
330 @Override
331 public void visit(TmfVertex node) {
332 nbVertex++;
333
334 }
335
336 @Override
337 public void visit(TmfEdge edge, boolean horizontal) {
338 if (horizontal) {
339 nbHLink++;
340 } else {
341 nbVLink++;
342 }
343 }
344 }
345
346 /**
347 * The following graph will be used
348 *
349 * <pre>
350 * ____0___1___2___3___4___5___6___7___8___9___10___11___12___13___14___15
351 *
352 * A *-------* *---*-------*---*---* *---*----*----*---------*
353 * | | | | |
354 * B *---*---*-------* *-------*------------* *----------*
355 * </pre>
356 */
357 @SuppressWarnings("null")
358 private static @NonNull TmfGraph buildFullGraph() {
359 TmfGraph graph = new TmfGraph();
360 TmfVertex[] vertexA;
361 TmfVertex[] vertexB;
362 long[] timesA = { 0, 2, 4, 5, 7, 8, 9, 10, 11, 12, 13, 15 };
363 long[] timesB = { 1, 2, 3, 5, 6, 8, 11, 12, 14 };
364 vertexA = new TmfVertex[timesA.length];
365 vertexB = new TmfVertex[timesB.length];
366 for (int i = 0; i < timesA.length; i++) {
367 vertexA[i] = new TmfVertex(timesA[i]);
368 }
369 for (int i = 0; i < timesB.length; i++) {
370 vertexB[i] = new TmfVertex(timesB[i]);
371 }
372 graph.append(WORKER1, vertexA[0]);
373 graph.append(WORKER1, vertexA[1]);
374 graph.add(WORKER1, vertexA[2]);
375 graph.append(WORKER1, vertexA[3]);
376 graph.append(WORKER1, vertexA[4]);
377 graph.append(WORKER1, vertexA[5]);
378 graph.append(WORKER1, vertexA[6]);
379 graph.add(WORKER1, vertexA[7]);
380 graph.append(WORKER1, vertexA[8]);
381 graph.append(WORKER1, vertexA[9]);
382 graph.append(WORKER1, vertexA[10]);
383 graph.append(WORKER1, vertexA[11]);
384 graph.append(WORKER2, vertexB[0]);
385 graph.append(WORKER2, vertexB[1]);
386 graph.append(WORKER2, vertexB[2]);
387 graph.append(WORKER2, vertexB[3]);
388 graph.add(WORKER2, vertexB[4]);
389 graph.append(WORKER2, vertexB[5]);
390 graph.append(WORKER2, vertexB[6]);
391 graph.add(WORKER2, vertexB[7]);
392 graph.append(WORKER2, vertexB[8]);
393 vertexA[1].linkVertical(vertexB[1]);
394 vertexB[3].linkVertical(vertexA[3]);
395 vertexA[5].linkVertical(vertexB[5]);
396 vertexB[6].linkVertical(vertexA[8]);
397 vertexA[9].linkVertical(vertexB[7]);
398 return graph;
399 }
400
401 /**
402 * Test the {@link TmfGraph#scanLineTraverse(IGraphWorker, ITmfGraphVisitor)} method
403 */
404 @Test
405 public void testScanCount() {
406 TmfGraph graph = buildFullGraph();
407 ScanCountVertex visitor = new ScanCountVertex();
408 graph.scanLineTraverse(graph.getHead(WORKER1), visitor);
409 assertEquals(21, visitor.nbVertex);
410 assertEquals(6, visitor.nbStartVertex);
411 assertEquals(5, visitor.nbVLink);
412 assertEquals(15, visitor.nbHLink);
413 }
414
415 /**
416 * Test the {@link TmfGraphStatistics} class
417 */
418 @Test
419 public void testGraphStatistics() {
420 TmfGraph graph = buildFullGraph();
421 TmfGraphStatistics stats = new TmfGraphStatistics();
49a4b360 422 stats.computeGraphStatistics(graph, WORKER1);
1b46d94d
FG
423 assertEquals(12, stats.getSum(WORKER1).longValue());
424 assertEquals(11, stats.getSum(WORKER2).longValue());
425 assertEquals(23, stats.getSum().longValue());
426 }
427
732e0744
FG
428 /**
429 * This visitor throws an exception if it visits twice the same vertex
430 *
431 * @author Francis Giraldeau
432 *
433 */
434 private class DuplicateDetectorVisitor implements ITmfGraphVisitor {
435 private final Set<TmfVertex> set = new HashSet<>();
436 @Override
437 public void visitHead(TmfVertex vertex) {
438 }
439 @Override
440 public void visit(TmfEdge edge, boolean horizontal) {
441 }
442 @Override
443 public void visit(TmfVertex vertex) {
444 if (set.contains(vertex)) {
445 throw new RuntimeException("node already visited");
446 }
447 set.add(vertex);
448 }
449 }
450
451 /**
452 * Test that exception is thrown if a node is linked horizontally to itself
453 */
454 @Test(expected = IllegalArgumentException.class)
455 public void testHorizontalSelfLink() {
456 TmfVertex n0 = new TmfVertex(0);
457 n0.linkHorizontal(n0);
458 }
459
460 /**
461 * Test that exception is thrown if a node is linked vertically to itself.
462 */
463 @Test(expected = IllegalArgumentException.class)
464 public void testVerticalSelfLink() {
465 TmfVertex n0 = new TmfVertex(0);
466 n0.linkVertical(n0);
467 }
468
469 /**
470 * Test that the visitor detect a cycle in horizontal links. A cycle may
471 * exists only between vertices with equal timetstamps.
472 */
473 @Test(expected = CycleDetectedException.class)
474 public void testHorizontalCycle() {
475 TmfVertex n0 = new TmfVertex(0);
476 TmfVertex n1 = new TmfVertex(0);
477 n0.linkHorizontal(n1);
478 n1.linkHorizontal(n0);
479 TmfGraph graph = new TmfGraph();
480 graph.add(WORKER1, n0);
481 graph.add(WORKER1, n1);
482 graph.scanLineTraverse(n0, new DuplicateDetectorVisitor());
483 }
484
485 /**
486 * Test that scanLineTraverse terminates with the following graph:
487 *
488 * <pre>
489 * ^
490 * |
491 * +----->
492 * ^
493 * |
494 * +
495 *
496 * </pre>
497 */
498 @Test
499 public void testScanLineTerminates() {
500 TmfVertex n10 = new TmfVertex(0);
501 TmfVertex n20 = new TmfVertex(0);
502 TmfVertex n21 = new TmfVertex(1);
503 TmfVertex n30 = new TmfVertex(1);
504 TmfGraph graph = new TmfGraph();
505 n10.linkVertical(n20);
506 n20.linkHorizontal(n21);
507 n21.linkVertical(n30);
508 graph.add(WORKER1, n10);
509 graph.add(WORKER2, n20);
510 graph.add(WORKER2, n21);
511 graph.add(WORKER3, n30);
512 graph.scanLineTraverse(n20, new DuplicateDetectorVisitor());
513 }
514
1b46d94d 515}
This page took 0.052751 seconds and 5 git commands to generate.