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.apache.omid.transaction.AbstractTransactionManager;
23  import org.mockito.InjectMocks;
24  import org.mockito.Mock;
25  import org.mockito.MockitoAnnotations;
26  import org.mockito.invocation.InvocationOnMock;
27  import org.mockito.stubbing.Answer;
28  import org.slf4j.Logger;
29  import org.slf4j.LoggerFactory;
30  import org.testng.annotations.BeforeMethod;
31  import org.testng.annotations.Test;
32  
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      @Mock
55      TSOServerConfig config;
56  
57      // Component under test
58      @InjectMocks
59      private TimestampOracleImpl timestampOracle;
60  
61      @BeforeMethod(alwaysRun = true, timeOut = 30_000)
62      public void initMocksAndComponents() {
63          MockitoAnnotations.initMocks(this);
64      }
65  
66      @Test(timeOut = 10_000)
67      public void testMonotonicTimestampGrowth() throws Exception {
68  
69          // Intialize component under test
70          timestampOracle.initialize();
71  
72          long last = timestampOracle.next();
73          for (int i = 0; i < (3 * TimestampOracleImpl.TIMESTAMP_BATCH); i++) {
74              long current = timestampOracle.next();
75              assertEquals(current, last + AbstractTransactionManager.MAX_CHECKPOINTS_PER_TXN, "Not monotonic growth");
76              last = current;
77          }
78          assertTrue(timestampOracle.getLast() == last);
79          LOG.info("Last timestamp: {}", last);
80      }
81  
82      @Test(timeOut = 10_000)
83      public void testTimestampOraclePanicsWhenTheStorageHasProblems() throws Exception {
84  
85          // Intialize component under test
86          timestampOracle.initialize();
87  
88          // Cause an exception when updating the max timestamp
89          final CountDownLatch updateMaxTimestampMethodCalled = new CountDownLatch(1);
90          doAnswer(new Answer() {
91              @Override
92              public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
93                  updateMaxTimestampMethodCalled.countDown();
94                  throw new RuntimeException("Out of memory or something");
95              }
96          }).when(timestampStorage).updateMaxTimestamp(anyLong(), anyLong());
97  
98          // Make the previous exception to be thrown
99          Thread allocThread = new Thread("AllocThread") {
100             @Override
101             public void run() {
102                 while (true) {
103                     timestampOracle.next();
104                 }
105             }
106         };
107         allocThread.start();
108 
109         updateMaxTimestampMethodCalled.await();
110 
111         // Verify that it has blown up
112         verify(panicker, atLeastOnce()).panic(anyString(), any(Throwable.class));
113     }
114 
115 }