1 /*******************************************************************************
2 * Copyright (c) 2014 Ericsson
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
10 * Bernd Hufmann - Initial API and implementation
11 *******************************************************************************/
13 package org
.eclipse
.tracecompass
.tmf
.core
.tests
.signal
;
15 import static org
.junit
.Assert
.assertEquals
;
16 import static org
.junit
.Assert
.fail
;
18 import java
.util
.ArrayList
;
19 import java
.util
.List
;
20 import java
.util
.concurrent
.CountDownLatch
;
22 import org
.eclipse
.tracecompass
.tmf
.core
.component
.TmfComponent
;
23 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfEndSynchSignal
;
24 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignal
;
25 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalHandler
;
26 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfSignalManager
;
27 import org
.eclipse
.tracecompass
.tmf
.core
.signal
.TmfStartSynchSignal
;
28 import org
.junit
.After
;
29 import org
.junit
.Before
;
30 import org
.junit
.Test
;
33 * Test suite for {@link TmfSignalManager}
35 * @author Bernd Hufmann
37 public class TmfSignalManagerTest
{
39 private TestSignalSender signalSender
;
46 signalSender
= new TestSignalSender();
53 public void tearDown() {
54 signalSender
.dispose();
57 // ------------------------------------------------------------------------
59 // ------------------------------------------------------------------------
62 * Test send and receive including synch signals.
65 public void testSendReceive() {
66 final int NB_HANDLERS
= 10;
67 TestSignalHandler
[] signalReceivers
= new TestSignalHandler
[NB_HANDLERS
];
68 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
69 signalReceivers
[i
] = new TestSignalHandler();
71 final TestSignal1 firstSignal
= new TestSignal1(signalSender
);
72 final TestSignal2 secondSignal
= new TestSignal2(signalSender
);
74 final Class
<?
>[] expectedOrder
= new Class
[] {
75 TmfStartSynchSignal
.class, TestSignal1
.class, TmfEndSynchSignal
.class,
76 TmfStartSynchSignal
.class, TestSignal2
.class, TmfEndSynchSignal
.class };
79 signalSender
.sendSignal(firstSignal
);
80 signalSender
.sendSignal(secondSignal
);
82 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
83 assertEquals(expectedOrder
.length
, signalReceivers
[i
].receivedSignals
.size());
85 for (int k
= 0; k
< expectedOrder
.length
; k
++) {
86 assertEquals(signalReceivers
[i
].receivedSignals
.get(k
).getClass(), expectedOrder
[k
]);
89 for (int k
= 0; k
< expectedOrder
.length
; k
+= 3) {
91 int startSyncId
= signalReceivers
[i
].receivedSignals
.get(k
).getReference();
92 int signalId
= signalReceivers
[i
].receivedSignals
.get(k
+ 1).getReference();
93 int endSyncId
= signalReceivers
[i
].receivedSignals
.get(k
+ 2).getReference();
95 assertEquals(startSyncId
, signalId
);
96 assertEquals(startSyncId
, endSyncId
);
100 // Make sure that handlers are disposed in any case (success or not success)
101 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
102 signalReceivers
[i
].dispose();
108 * Test nesting signals. Verify that they are handled in the same thread.
111 public void testNestedSignals() {
112 TestSignalHandlerNested signalResender
= new TestSignalHandlerNested();
113 TestSignalHandler signalReceiver
= new TestSignalHandler();
115 final TestSignal1 mainSignal
= new TestSignal1(signalSender
);
117 final Class
<?
>[] expectedOrder
= new Class
[] {
118 TmfStartSynchSignal
.class,
119 TmfStartSynchSignal
.class,
121 TmfEndSynchSignal
.class,
122 TmfStartSynchSignal
.class,
123 TmfStartSynchSignal
.class,
125 TmfEndSynchSignal
.class,
127 TmfEndSynchSignal
.class,
129 TmfEndSynchSignal
.class
133 * Index of signals in array signalReceiver.receivedSignals which have
134 * to have the same signal ID.
137 final int[] sameSigNoIndex
= new int[] {
138 0, 10, 11, 1, 2, 3, 4, 8, 9, 5, 6, 7
142 signalSender
.sendSignal(mainSignal
);
144 assertEquals(expectedOrder
.length
, signalReceiver
.receivedSignals
.size());
146 for (int i
= 0; i
< expectedOrder
.length
; i
++) {
147 assertEquals(signalReceiver
.receivedSignals
.get(i
).getClass(), expectedOrder
[i
]);
150 for (int i
= 0; i
< sameSigNoIndex
.length
; i
+=3) {
152 int startSyncId
= signalReceiver
.receivedSignals
.get(sameSigNoIndex
[i
]).getReference();
153 int signalId
= signalReceiver
.receivedSignals
.get(sameSigNoIndex
[i
+ 1]).getReference();
154 int endSyncId
= signalReceiver
.receivedSignals
.get(sameSigNoIndex
[i
+ 2]).getReference();
155 assertEquals(startSyncId
, signalId
);
156 assertEquals(startSyncId
, endSyncId
);
159 // Make sure that handlers are disposed in any case (success or not success)
160 signalResender
.dispose();
161 signalReceiver
.dispose();
166 * Test concurrent signals. Verify that they are handled one after each
170 public void testConcurrentSignals() {
172 TestSignalHandlerNested signalResender
= new TestSignalHandlerNested();
173 TestSignalHandler signalReceiver
= new TestSignalHandler(false, null);
176 * Test of synchronization of signal manager.
178 * The order of received signals is either set of signals triggered by
179 * thread1 before set of signals triggered by thread2 or the other way
182 * If both received sets were interleaved then the synchronization of
183 * the signal manager would be not working.
186 final Class
<?
>[] expectedOrder1
= new Class
[] {
187 TestSignal2
.class, TestSignal4
.class, TestSignal3
.class, TestSignal1
.class, // signals triggered by thread 1
188 TestSignal4
.class // signal triggered by thread2
191 final Class
<?
>[] expectedOrder2
= new Class
[] {
192 TestSignal4
.class, // signal triggered by thread2
193 TestSignal2
.class, TestSignal4
.class, TestSignal3
.class, TestSignal1
.class // signals triggered by thread 1
197 * Run it multiple times so that both expected order are triggered
200 for (int k
= 0; k
< 10; k
++) {
201 // Latch to ensure that both threads are started
202 final CountDownLatch startLatch
= new CountDownLatch(2);
203 // Latch to ensure that signals are send roughly at the same time
204 final CountDownLatch sendLatch
= new CountDownLatch(1);
205 // Latch to ensure that both treads are finished
206 final CountDownLatch endLatch
= new CountDownLatch(2);
208 signalReceiver
.receivedSignals
.clear();
210 Thread senderThread1
= new Thread() {
213 startLatch
.countDown();
216 } catch (InterruptedException e
) {
218 signalSender
.sendSignal(new TestSignal1(signalSender
));
219 endLatch
.countDown();
223 Thread senderThread2
= new Thread() {
226 startLatch
.countDown();
229 } catch (InterruptedException e
) {
231 signalSender
.sendSignal(new TestSignal4(signalSender
));
232 endLatch
.countDown();
236 senderThread1
.start();
237 senderThread2
.start();
240 } catch (InterruptedException e
) {
242 sendLatch
.countDown();
246 } catch (InterruptedException e
) {
249 assertEquals(expectedOrder1
.length
, signalReceiver
.receivedSignals
.size());
251 for (int i
= 0; i
< expectedOrder1
.length
; i
++) {
252 if (!signalReceiver
.receivedSignals
.get(i
).getClass().equals(expectedOrder1
[i
])) {
259 for (int i
= 0; i
< expectedOrder2
.length
; i
++) {
260 if (!signalReceiver
.receivedSignals
.get(i
).getClass().equals(expectedOrder2
[i
])) {
261 fail("Concurrent signal test failure!");
267 // Make sure that handlers are disposed in any case (success or not success)
268 signalResender
.dispose();
269 signalReceiver
.dispose();
274 * Test broadcastAsync()
277 public void testBroadcastAsync() {
278 TestSignalHandlerNested signalResender
= new TestSignalHandlerNested(false);
280 final int NB_HANDLERS
= 10;
281 final CountDownLatch latch
= new CountDownLatch(NB_HANDLERS
);
282 TestSignalHandler
[] signalReceivers
= new TestSignalHandler
[NB_HANDLERS
];
283 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
284 signalReceivers
[i
] = new TestSignalHandler(false, latch
);
287 final Class
<?
>[] expectedOrder
= new Class
[] {
288 TestSignal1
.class, TestSignal2
.class, TestSignal3
.class, TestSignal4
.class
292 final TestSignal1 mainSignal
= new TestSignal1(signalSender
);
293 signalSender
.sendSignal(mainSignal
);
297 } catch (InterruptedException e
) {
300 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
301 assertEquals(expectedOrder
.length
, signalReceivers
[i
].receivedSignals
.size());
302 for (int k
= 0; k
< expectedOrder
.length
; k
++) {
303 assertEquals(signalReceivers
[i
].receivedSignals
.get(k
).getClass(), expectedOrder
[k
]);
307 // Make sure that handlers are disposed in any case (success or not success)
308 for (int i
= 0; i
< NB_HANDLERS
; i
++) {
309 signalReceivers
[i
].dispose();
311 signalResender
.dispose();
315 // ------------------------------------------------------------------------
317 // ------------------------------------------------------------------------
322 private class TestSignalSender
extends TmfComponent
{
325 super("TestSignalSender");
332 * main signal to send
334 public void sendSignal(TmfSignal signal
) {
340 * Signal handler implementation for testing nested signals.
341 * Needs to be public so TmfSignalManager can see it.
343 public class TestSignalHandlerNested
extends AbstractBaseSignalHandler
{
345 private boolean sync
;
350 private TestSignalHandlerNested() {
361 private TestSignalHandlerNested(boolean sync
) {
362 super("TestSignalHandlerNested", false);
364 TmfSignalManager
.deregister(this);
365 TmfSignalManager
.registerVIP(this);
369 * Receive a signal of type TestSignal1.
375 public void receiveSignal1(final TestSignal1 signal
) {
377 broadcast(new TestSignal2(signal
.getSource()));
378 broadcast(new TestSignal3(signal
.getSource()));
380 broadcastAsync(new TestSignal2(signal
.getSource()));
381 broadcastAsync(new TestSignal3(signal
.getSource()));
386 * Receive a signal of type TestSignal3.
392 public void receiveSignal3(final TestSignal3 signal
) {
394 broadcast(new TestSignal4(signal
.getSource()));
396 broadcastAsync(new TestSignal4(signal
.getSource()));
402 * Signal handler implementation for testing of sending and receiving
405 public class TestSignalHandler
extends AbstractBaseSignalHandler
{
407 private CountDownLatch latch
;
413 private TestSignalHandler() {
423 * latch to count down when receiving last signal
426 private TestSignalHandler(boolean logSyncSigs
, CountDownLatch latch
) {
427 super("TestSignalHandler", logSyncSigs
);
432 * Receive a signal of type TestSignal1.
438 public void receiveSignal1(final TestSignal1 signal
) {
439 receivedSignals
.add(signal
);
443 * Receive a signal of type TestSignal2.
449 public void receiveSignal2(final TestSignal2 signal
) {
450 receivedSignals
.add(signal
);
454 * Receive a signal of type TestSignal3.
460 public void receiveSignal3(final TestSignal3 signal
) {
461 receivedSignals
.add(signal
);
465 * Receive a signal of type TestSignal4.
471 public void receiveSignal4(final TestSignal4 signal
) {
472 receivedSignals
.add(signal
);
480 * Base signal handler for start and end sync signals.
482 public abstract class AbstractBaseSignalHandler
extends TmfComponent
{
483 List
<TmfSignal
> receivedSignals
= new ArrayList
<>();
484 private boolean logSyncSigs
;
486 private AbstractBaseSignalHandler(String name
, boolean logSyncSignal
) {
488 this.logSyncSigs
= logSyncSignal
;
492 * Receive a signal of type TmfStartSynchSignal.
498 public void receiveStartSynch(final TmfStartSynchSignal signal
) {
500 receivedSignals
.add(signal
);
505 * Receive a signal of type TmfEndSynchSignal.
511 public void receiveEndSynch(final TmfEndSynchSignal signal
) {
513 receivedSignals
.add(signal
);
522 private class TestSignal1
extends TmfSignal
{
524 public TestSignal1(Object source
) {
532 private class TestSignal2
extends TmfSignal
{
534 public TestSignal2(Object source
) {
542 private class TestSignal3
extends TmfSignal
{
544 public TestSignal3(Object source
) {
552 private class TestSignal4
extends TmfSignal
{
554 public TestSignal4(Object source
) {