View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
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      // Component under test
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          // Intialize component under test
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          // Intialize component under test
88          worldClockOracle.initialize();
89  
90          // Cause an exception when updating the max timestamp
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         // Make the previous exception to be thrown
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         // Verify that it has blown up
114         verify(panicker, atLeastOnce()).panic(anyString(), any(Throwable.class));
115     }
116 
117 }