blob: df3c3f390c1d5873cf94f1ee55eab0b37438b403 [file] [log] [blame]
/*******************************************************************************
* 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));
}
}