1 /*******************************************************************************
2 * Copyright (c) 2015 École Polytechnique de Montréal
4 * All rights reserved. This program and the accompanying materials are made
5 * 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
10 * Francis Giraldeau - Initial implementation and API
11 * Geneviève Bastien - Fixes and improvements
12 *******************************************************************************/
14 package org
.eclipse
.tracecompass
.tmf
.core
.tests
.synchronization
;
16 import static org
.junit
.Assert
.assertEquals
;
17 import static org
.junit
.Assert
.assertNotNull
;
18 import static org
.junit
.Assert
.assertTrue
;
19 import static org
.junit
.Assert
.fail
;
22 import java
.io
.FileInputStream
;
23 import java
.io
.FileOutputStream
;
24 import java
.io
.IOException
;
25 import java
.io
.ObjectInputStream
;
26 import java
.io
.ObjectOutputStream
;
27 import java
.util
.Arrays
;
29 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.synchronization
.TmfTimestampTransformLinear
;
30 import org
.eclipse
.tracecompass
.internal
.tmf
.core
.synchronization
.TmfTimestampTransformLinearFast
;
31 import org
.eclipse
.tracecompass
.tmf
.core
.synchronization
.ITmfTimestampTransform
;
32 import org
.junit
.Test
;
33 import org
.junit
.runner
.RunWith
;
34 import org
.junit
.runners
.Parameterized
;
35 import org
.junit
.runners
.Parameterized
.Parameters
;
38 * Tests for {@link TmfTimestampTransformLinearFast}
40 * @author Geneviève Bastien
42 @RunWith(Parameterized
.class)
43 public class TsTransformFastTest
{
45 private static final long ts
= 1361657893526374091L;
47 private static interface IFastTransformFactory
{
48 public TmfTimestampTransformLinearFast
create(double alpha
, double beta
);
51 private static final IFastTransformFactory fNewObject
= (a
, b
) -> {
52 return new TmfTimestampTransformLinearFast(a
, b
);
55 private static final IFastTransformFactory fDeserialized
= (a
, b
) -> {
56 TmfTimestampTransformLinearFast tt
= new TmfTimestampTransformLinearFast(a
, b
);
57 /* Serialize the object */
58 String filePath
= null;
60 File temp
= File
.createTempFile("serialSyncAlgo", ".tmp");
61 filePath
= temp
.getAbsolutePath();
62 } catch (IOException e
) {
63 fail("Could not create temporary file for serialization");
65 assertNotNull(filePath
);
67 try (FileOutputStream fileOut
= new FileOutputStream(filePath
);
68 ObjectOutputStream out
= new ObjectOutputStream(fileOut
);) {
70 } catch (IOException e
) {
71 fail("Error serializing the synchronization algorithm " + e
.getMessage());
74 TmfTimestampTransformLinearFast deserialTt
= null;
75 /* De-Serialize the object */
76 try (FileInputStream fileIn
= new FileInputStream(filePath
);
77 ObjectInputStream in
= new ObjectInputStream(fileIn
);) {
78 deserialTt
= (TmfTimestampTransformLinearFast
) in
.readObject();
79 } catch (IOException
| ClassNotFoundException e
) {
80 fail("Error de-serializing the synchronization algorithm " + e
.getMessage());
85 private final IFastTransformFactory fTransformFactory
;
91 * The name of this parameterized test
93 * Factory to create the timestamp transform
95 public TsTransformFastTest(String name
, IFastTransformFactory factory
) {
96 fTransformFactory
= factory
;
100 * @return the test parameters
102 @Parameters(name
= "Factory={0}")
103 public static Iterable
<Object
[]> parameters() {
104 return Arrays
.asList(new Object
[][] {
105 { "Object", fNewObject
},
106 { "Deserialized", fDeserialized
}
111 * Test whether the fast linear transform always yields the same value for
115 public void testFLTRepeatability() {
116 TmfTimestampTransformLinearFast fast
= fTransformFactory
.create(Math
.PI
, 0);
117 // Access fDeltaMax to compute the cache range boundaries
118 long deltaMax
= fast
.getDeltaMax();
119 // Initialize the transform
120 long timestamp
= ts
- (ts
% deltaMax
);
121 fast
.transform(timestamp
);
122 long tsMiss
= timestamp
+ deltaMax
;
123 long tsNoMiss
= timestamp
+ deltaMax
- 1;
125 // Get the transformed value to a timestamp without cache miss
126 long tsTNoMiss
= fast
.transform(tsNoMiss
);
127 assertEquals(1, fast
.getCacheMisses());
129 // Cause a cache miss
130 fast
.transform(tsMiss
);
131 assertEquals(2, fast
.getCacheMisses());
134 * Get the transformed value of the same previous timestamp after the
137 long tsTAfterMiss
= fast
.transform(tsNoMiss
);
138 assertEquals(tsTNoMiss
, tsTAfterMiss
);
142 * Test that 2 equal fast transform always give the same results for the
146 public void testFLTEquivalence() {
147 TmfTimestampTransformLinearFast fast
= fTransformFactory
.create(Math
.PI
, 0);
148 TmfTimestampTransformLinearFast fast2
= fTransformFactory
.create(Math
.PI
, 0);
150 long deltaMax
= fast
.getDeltaMax();
152 long start
= (ts
- (ts
% deltaMax
) - 10);
153 checkTime(fast
, fast2
, 20, start
, 1);
157 * Test the precision of the fast timestamp transform compared to the
158 * original transform.
161 public void testFastTransformPrecision() {
162 TmfTimestampTransformLinear precise
= new TmfTimestampTransformLinear(Math
.PI
, 0);
163 TmfTimestampTransformLinearFast fast
= fTransformFactory
.create(Math
.PI
, 0);
165 long start
= (long) Math
.pow(10, 18);
166 long end
= Long
.MAX_VALUE
;
167 int step
= (int) ((end
- start
) / (samples
* Math
.PI
));
168 checkTime(precise
, fast
, samples
, start
, step
);
169 assertEquals(samples
, fast
.getCacheMisses());
171 // check that rescale is done only when required
172 // assumes tsBitWidth == 30
173 // test forward and backward timestamps
175 int[] directions
= new int[] { 1, -1 };
176 for (Integer direction
: directions
) {
177 for (int i
= 0; i
<= 30; i
++) {
178 fast
.resetScaleStats();
179 step
= (1 << i
) * direction
;
180 checkTime(precise
, fast
, samples
, start
, step
);
181 assertTrue(String
.format("samples: %d scale misses: %d",
182 samples
, fast
.getCacheMisses()), samples
>= fast
.getCacheMisses());
188 * Test that fast transform produces the same result for small and large
192 public void testFastTransformSlope() {
193 int[] dir
= new int[] { 1, -1 };
194 long start
= (1 << 30);
195 for (int ex
= -9; ex
<= 9; ex
++) {
196 for (int d
= 0; d
< dir
.length
; d
++) {
197 double slope
= Math
.pow(10.0, ex
);
198 TmfTimestampTransformLinear precise
= new TmfTimestampTransformLinear(slope
, 0);
199 TmfTimestampTransformLinearFast fast
= fTransformFactory
.create(slope
, 0);
200 checkTime(precise
, fast
, 1000, start
, dir
[d
]);
206 * Test that fast transform produces the same result with a slope and
207 * offset, for small and large values
210 public void testFastTransformSlopeAndOffset() {
211 double offset
= 54321.0;
212 double slope
= Math
.pow(10.0, 4);
213 for (int ex
= 0; ex
<= Long
.SIZE
- 1; ex
++) {
214 long start
= 1 << ex
;
215 TmfTimestampTransformLinear precise
= new TmfTimestampTransformLinear(slope
, offset
);
216 TmfTimestampTransformLinearFast fast
= fTransformFactory
.create(slope
, offset
);
217 checkTime(precise
, fast
, 5, start
, 1);
222 * Check that the proper exception are raised for illegal slopes
225 public void testFastTransformArguments() {
226 double[] slopes
= new double[] { -1.0, ((double) Integer
.MAX_VALUE
) + 1, 1e-10 };
227 for (double slope
: slopes
) {
228 Exception exception
= null;
230 fTransformFactory
.create(slope
, 0.0);
231 } catch (IllegalArgumentException e
) {
234 assertNotNull(exception
);
238 private static void checkTime(ITmfTimestampTransform precise
, ITmfTimestampTransform fast
,
239 int samples
, long start
, long step
) {
241 for (int i
= 0; i
< samples
; i
++) {
242 long time
= start
+ i
* step
;
243 long exp
= precise
.transform(time
);
244 long act
= fast
.transform(time
);
245 long err
= act
- exp
;
246 // allow only two ns of error
247 assertTrue("start: " + start
+ " [" + err
+ "]", Math
.abs(err
) < 3);
250 assertTrue("monotonic error" + act
+ " " + prev
, act
>= prev
);
251 } else if (step
< 0) {
252 assertTrue("monotonic ", act
<= prev
);