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.io.IOException;
33  import java.util.concurrent.CountDownLatch;
34  
35  import static org.mockito.Matchers.any;
36  import static org.mockito.Matchers.anyLong;
37  import static org.mockito.Matchers.anyString;
38  import static org.mockito.Mockito.atLeastOnce;
39  import static org.mockito.Mockito.doAnswer;
40  import static org.mockito.Mockito.verify;
41  import static org.testng.Assert.assertEquals;
42  import static org.testng.Assert.assertTrue;
43  
44  public class TestTimestampOracle {
45  
46      private static final Logger LOG = LoggerFactory.getLogger(TestTimestampOracle.class);
47  
48      @Mock
49      private MetricsRegistry metrics;
50      @Mock
51      private Panicker panicker;
52      @Mock
53      private TimestampStorage timestampStorage;
54  
55      // Component under test
56      @InjectMocks
57      private TimestampOracleImpl timestampOracle;
58  
59      @BeforeMethod(alwaysRun = true, timeOut = 30_000)
60      public void initMocksAndComponents() {
61          MockitoAnnotations.initMocks(this);
62      }
63  
64      @Test(timeOut = 10_000)
65      public void testMonotonicTimestampGrowth() throws Exception {
66  
67          // Intialize component under test
68          timestampOracle.initialize();
69  
70          long last = timestampOracle.next();
71          for (int i = 0; i < (3 * TimestampOracleImpl.TIMESTAMP_BATCH); i++) {
72              long current = timestampOracle.next();
73              assertEquals(current, last + 1, "Not monotonic growth");
74              last = current;
75          }
76          assertTrue(timestampOracle.getLast() == last);
77          LOG.info("Last timestamp: {}", last);
78      }
79  
80      @Test(timeOut = 10_000)
81      public void testTimestampOraclePanicsWhenTheStorageHasProblems() throws Exception {
82  
83          // Intialize component under test
84          timestampOracle.initialize();
85  
86          // Cause an exception when updating the max timestamp
87          final CountDownLatch updateMaxTimestampMethodCalled = new CountDownLatch(1);
88          doAnswer(new Answer() {
89              @Override
90              public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
91                  updateMaxTimestampMethodCalled.countDown();
92                  throw new RuntimeException("Out of memory or something");
93              }
94          }).when(timestampStorage).updateMaxTimestamp(anyLong(), anyLong());
95  
96          // Make the previous exception to be thrown
97          Thread allocThread = new Thread("AllocThread") {
98              @Override
99              public void run() {
100                 try {
101                     while (true) {
102                         timestampOracle.next();
103                     }
104                 } catch (IOException ioe) {
105                     LOG.error("Shouldn't occur");
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 }