| /******************************************************************************* |
| * Copyright (c) 2013, 2014 École Polytechnique de Montréal |
| * |
| * All rights reserved. This program and the accompanying materials are made |
| * available under the terms of the Eclipse Public License 2.0 which |
| * accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Geneviève Bastien - Initial implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.tmf.core.tests.synchronization; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.assertNotNull; |
| import static org.junit.Assert.assertTrue; |
| import static org.junit.Assert.fail; |
| |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.ObjectInputStream; |
| import java.io.ObjectOutputStream; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.LinkedList; |
| |
| import org.eclipse.jdt.annotation.NonNull; |
| import org.eclipse.tracecompass.internal.tmf.core.synchronization.SyncAlgorithmFullyIncremental; |
| import org.eclipse.tracecompass.internal.tmf.core.synchronization.TmfTimestampTransformLinearFast; |
| import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventDependency; |
| import org.eclipse.tracecompass.tmf.core.event.matching.TmfEventDependency.DependencyEvent; |
| import org.eclipse.tracecompass.tmf.core.synchronization.ITmfTimestampTransform; |
| import org.eclipse.tracecompass.tmf.core.synchronization.SynchronizationAlgorithm; |
| import org.eclipse.tracecompass.tmf.core.synchronization.SynchronizationAlgorithm.SyncQuality; |
| import org.eclipse.tracecompass.tmf.core.synchronization.SynchronizationAlgorithmFactory; |
| import org.eclipse.tracecompass.tmf.core.synchronization.TimestampTransformFactory; |
| import org.eclipse.tracecompass.tmf.core.timestamp.TmfTimestamp; |
| import org.eclipse.tracecompass.tmf.core.trace.ITmfTrace; |
| import org.eclipse.tracecompass.tmf.tests.stubs.event.TmfSyncEventStub; |
| import org.eclipse.tracecompass.tmf.tests.stubs.trace.TmfTraceStub; |
| import org.junit.After; |
| import org.junit.Before; |
| import org.junit.Test; |
| |
| /** |
| * Tests for {@link SynchronizationAlgorithm} and its descendants |
| * |
| * @author Geneviève Bastien |
| */ |
| @SuppressWarnings("nls") |
| public class SyncTest { |
| |
| private TmfTraceStub t1, t2; |
| private @NonNull Collection<ITmfTrace> fTraces = Collections.emptyList(); |
| |
| /** |
| * Initializing the traces |
| */ |
| @Before |
| public void init() { |
| t1 = new TmfTraceStub(); |
| t1.init("t1"); |
| t2 = new TmfTraceStub(); |
| t2.init("t2"); |
| |
| Collection<ITmfTrace> traces = new LinkedList<>(); |
| traces.add(t1); |
| traces.add(t2); |
| fTraces = traces; |
| } |
| |
| /** |
| * Clean up |
| */ |
| @After |
| public void cleanup() { |
| if (t1 != null) { |
| t1.dispose(); |
| } |
| if (t2 != null) { |
| t2.dispose(); |
| } |
| } |
| |
| /** |
| * Testing fully incremental algorithm with communication between the two |
| * traces |
| */ |
| @Test |
| public void testFullyIncremental() { |
| |
| SynchronizationAlgorithm syncAlgo = SynchronizationAlgorithmFactory.getFullyIncrementalAlgorithm(); |
| |
| syncAlgo.init(fTraces); |
| |
| assertEquals(SyncQuality.ABSENT, syncAlgo.getSynchronizationQuality(t1, t2)); |
| addSyncMatch(syncAlgo, t2, 1, t1, 1); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 0 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 1, t2, 3); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 0 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t2, 2, t1, 3); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 0.5 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.APPROXIMATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 3, t2, 5); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 0.75 beta 1.25 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 4, t2, 8); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 0.75 beta 1.25 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t2, 4, t1, 5); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1.125 beta 0.875 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t2, 4, t1, 6); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1.125 beta 0.875 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 6, t2, 7); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 0.725 beta 1.275 ]]", syncAlgo.toString()); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| ITmfTimestampTransform tt2 = syncAlgo.getTimestampTransform(t2); |
| ITmfTimestampTransform tt1 = syncAlgo.getTimestampTransform(t1); |
| |
| assertEquals(syncAlgo.getTimestampTransform(t1.getHostId()), tt1); |
| assertEquals(TimestampTransformFactory.getDefaultTransform(), tt1); |
| assertEquals(syncAlgo.getTimestampTransform(t2.getHostId()), tt2); |
| assertTrue(tt2 instanceof TmfTimestampTransformLinearFast); |
| |
| /* |
| * Make the two hulls intersect, and make sure the last good formula is |
| * kept after failure |
| */ |
| addSyncMatch(syncAlgo, t1, 7, t2, 4); |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 0.375 beta 1.625 ]]", syncAlgo.toString()); |
| // Last good synchronization |
| tt2 = syncAlgo.getTimestampTransform(t2); |
| tt1 = syncAlgo.getTimestampTransform(t1); |
| assertTrue(tt2 instanceof TmfTimestampTransformLinearFast); |
| |
| addSyncMatch(syncAlgo, t2, 7, t1, 3); |
| assertEquals(SyncQuality.FAIL, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 0.375 beta 1.625 ]]", syncAlgo.toString()); |
| |
| assertEquals(tt2, syncAlgo.getTimestampTransform(t2.getHostId())); |
| assertEquals(tt1, syncAlgo.getTimestampTransform(t1.getHostId())); |
| assertEquals(TimestampTransformFactory.getDefaultTransform(), tt1); |
| } |
| |
| /** |
| * Testing the fully incremental synchronization algorithm when |
| * communication goes in only one direction |
| */ |
| @Test |
| public void testOneHull() { |
| |
| SynchronizationAlgorithm syncAlgo = SynchronizationAlgorithmFactory.getFullyIncrementalAlgorithm(); |
| |
| syncAlgo.init(fTraces); |
| |
| assertEquals(SyncQuality.ABSENT, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 1, t2, 3); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 2, t2, 5); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 3, t2, 5); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 4, t2, 7); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 0 ]]", syncAlgo.toString()); |
| |
| } |
| |
| /** |
| * Testing the fully incremental synchronization algorithm when all |
| * communication from trace1 to trace2 happens before all communication from |
| * trace2 to trace1 |
| */ |
| @Test |
| public void testDisjoint() { |
| |
| SynchronizationAlgorithm syncAlgo = SynchronizationAlgorithmFactory.getFullyIncrementalAlgorithm(); |
| |
| syncAlgo.init(fTraces); |
| |
| assertEquals(SyncQuality.ABSENT, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 1, t2, 3); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 2, t2, 5); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 3, t2, 5); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t1, 4, t2, 7); |
| assertEquals(SyncQuality.INCOMPLETE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 0 ]]", syncAlgo.toString()); |
| |
| addSyncMatch(syncAlgo, t2, 7, t1, 6); |
| assertEquals(SyncQuality.APPROXIMATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t2, 8, t1, 6); |
| assertEquals(SyncQuality.APPROXIMATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| |
| addSyncMatch(syncAlgo, t2, 10, t1, 8); |
| assertEquals(SyncQuality.APPROXIMATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals("SyncAlgorithmFullyIncremental [Between t1 and t2 [ alpha 1 beta 2.5 ]]", syncAlgo.toString()); |
| } |
| |
| private static void addSyncMatch(SynchronizationAlgorithm algo, ITmfTrace sender, long sendTs, ITmfTrace receiver, long receiveTs) { |
| algo.addMatch( |
| new TmfEventDependency( |
| new DependencyEvent(new TmfSyncEventStub(sender, TmfTimestamp.fromSeconds(sendTs))), |
| new DependencyEvent(new TmfSyncEventStub(receiver, TmfTimestamp.fromSeconds(receiveTs))) |
| )); |
| } |
| |
| /** |
| * Testing the serialization of the fully incremental synchronization |
| * algorithm |
| */ |
| @Test |
| public void testFullyIncrementalSerialization() { |
| |
| /* Do a run of synchronization and check the results */ |
| SynchronizationAlgorithm syncAlgo = SynchronizationAlgorithmFactory.getFullyIncrementalAlgorithm(); |
| |
| syncAlgo.init(fTraces); |
| |
| addSyncMatch(syncAlgo, t2, 1, t1, 1); |
| addSyncMatch(syncAlgo, t1, 1, t2, 3); |
| addSyncMatch(syncAlgo, t2, 2, t1, 3); |
| addSyncMatch(syncAlgo, t1, 3, t2, 5); |
| addSyncMatch(syncAlgo, t1, 4, t2, 8); |
| addSyncMatch(syncAlgo, t2, 4, t1, 5); |
| addSyncMatch(syncAlgo, t2, 4, t1, 6); |
| addSyncMatch(syncAlgo, t1, 6, t2, 7); |
| |
| ITmfTimestampTransform tt2 = syncAlgo.getTimestampTransform(t2); |
| ITmfTimestampTransform tt1 = syncAlgo.getTimestampTransform(t1); |
| |
| assertEquals(SyncQuality.ACCURATE, syncAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals(syncAlgo.getTimestampTransform(t1.getHostId()), tt1); |
| assertEquals(TimestampTransformFactory.getDefaultTransform(), tt1); |
| assertEquals(syncAlgo.getTimestampTransform(t2.getHostId()), tt2); |
| |
| /* Serialize the object */ |
| String filePath = null; |
| try { |
| File temp = File.createTempFile("serialSyncAlgo", ".tmp"); |
| filePath = temp.getAbsolutePath(); |
| } catch (IOException e) { |
| fail("Could not create temporary file for serialization"); |
| } |
| assertNotNull(filePath); |
| |
| try (FileOutputStream fileOut = new FileOutputStream(filePath); |
| ObjectOutputStream out = new ObjectOutputStream(fileOut);) { |
| out.writeObject(syncAlgo); |
| |
| } catch (IOException e) { |
| fail("Error serializing the synchronization algorithm " + e.getMessage()); |
| } |
| |
| SynchronizationAlgorithm deserialAlgo = null; |
| /* De-Serialize the object */ |
| try (FileInputStream fileIn = new FileInputStream(filePath); |
| ObjectInputStream in = new ObjectInputStream(fileIn);) { |
| deserialAlgo = (SynchronizationAlgorithm) in.readObject(); |
| } catch (IOException | ClassNotFoundException e) { |
| fail("Error de-serializing the synchronization algorithm " + e.getMessage()); |
| } |
| |
| /* Check that the deserialize algorithm is equivalent to original */ |
| assertNotNull(deserialAlgo); |
| assertTrue(deserialAlgo instanceof SyncAlgorithmFullyIncremental); |
| assertEquals(SyncQuality.ACCURATE, deserialAlgo.getSynchronizationQuality(t1, t2)); |
| assertEquals(tt1, deserialAlgo.getTimestampTransform(t1)); |
| assertEquals(tt2, deserialAlgo.getTimestampTransform(t2)); |
| |
| } |
| |
| } |