1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.omid.tso;
19
20 import org.apache.omid.metrics.MetricsRegistry;
21 import org.apache.omid.timestamp.storage.TimestampStorage;
22 import org.mockito.InjectMocks;
23 import org.mockito.Mock;
24 import org.mockito.MockitoAnnotations;
25 import org.mockito.invocation.InvocationOnMock;
26 import org.mockito.stubbing.Answer;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.testng.annotations.BeforeMethod;
30 import org.testng.annotations.Test;
31
32 import java.util.concurrent.CountDownLatch;
33
34 import static org.mockito.Matchers.any;
35 import static org.mockito.Matchers.anyLong;
36 import static org.mockito.Matchers.anyString;
37 import static org.mockito.Mockito.atLeastOnce;
38 import static org.mockito.Mockito.doAnswer;
39 import static org.mockito.Mockito.verify;
40 import static org.testng.Assert.assertTrue;
41
42 public class TestWorldTimeOracle {
43
44 private static final Logger LOG = LoggerFactory.getLogger(TestWorldTimeOracle.class);
45
46 @Mock
47 private MetricsRegistry metrics;
48 @Mock
49 private Panicker panicker;
50 @Mock
51 private TimestampStorage timestampStorage;
52 @Mock
53 private TSOServerConfig config;
54
55
56 @InjectMocks
57 private WorldClockOracleImpl worldClockOracle;
58
59 @BeforeMethod(alwaysRun = true, timeOut = 30_000)
60 public void initMocksAndComponents() {
61 MockitoAnnotations.initMocks(this);
62 }
63
64 @Test(timeOut = 30_000)
65 public void testMonotonicTimestampGrowth() throws Exception {
66
67
68 worldClockOracle.initialize();
69
70 long last = worldClockOracle.next();
71
72 int timestampIntervalSec = (int) (WorldClockOracleImpl.TIMESTAMP_INTERVAL_MS / 1000) * 2;
73 for (int i = 0; i < timestampIntervalSec; i++) {
74 long current = worldClockOracle.next();
75 assertTrue(current > last+1 , "Timestamp should be based on world time");
76 last = current;
77 Thread.sleep(1000);
78 }
79
80 assertTrue(worldClockOracle.getLast() == last);
81 LOG.info("Last timestamp: {}", last);
82 }
83
84 @Test(timeOut = 10_000)
85 public void testTimestampOraclePanicsWhenTheStorageHasProblems() throws Exception {
86
87
88 worldClockOracle.initialize();
89
90
91 final CountDownLatch updateMaxTimestampMethodCalled = new CountDownLatch(1);
92 doAnswer(new Answer() {
93 @Override
94 public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
95 updateMaxTimestampMethodCalled.countDown();
96 throw new RuntimeException("Out of memory or something");
97 }
98 }).when(timestampStorage).updateMaxTimestamp(anyLong(), anyLong());
99
100
101 Thread allocThread = new Thread("AllocThread") {
102 @Override
103 public void run() {
104 while (true) {
105 worldClockOracle.next();
106 }
107 }
108 };
109 allocThread.start();
110
111 updateMaxTimestampMethodCalled.await();
112
113
114 verify(panicker, atLeastOnce()).panic(anyString(), any(Throwable.class));
115 }
116
117 }