2 * Copyright (c) 2015 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
9 package org.opendaylight.controller.cluster.datastore;
11 import static org.junit.Assert.fail;
12 import static org.mockito.Matchers.anyDouble;
13 import static org.mockito.Mockito.doReturn;
14 import static org.mockito.Mockito.never;
15 import static org.mockito.Mockito.verify;
16 import com.codahale.metrics.Snapshot;
17 import com.codahale.metrics.Timer;
18 import java.util.concurrent.TimeUnit;
19 import org.hamcrest.BaseMatcher;
20 import org.hamcrest.Description;
21 import org.hamcrest.Matcher;
22 import org.junit.Before;
23 import org.junit.Test;
24 import org.mockito.Matchers;
25 import org.mockito.Mock;
26 import org.mockito.Mockito;
27 import org.mockito.MockitoAnnotations;
28 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
30 public class TransactionRateLimitingCommitCallbackTest {
33 public ActorContext actorContext;
36 public DatastoreContext datastoreContext;
39 public Timer commitTimer;
42 private Timer.Context commitTimerContext;
45 private Snapshot commitSnapshot;
49 MockitoAnnotations.initMocks(this);
50 doReturn(datastoreContext).when(actorContext).getDatastoreContext();
51 doReturn(30).when(datastoreContext).getShardTransactionCommitTimeoutInSeconds();
52 doReturn(commitTimer).when(actorContext).getOperationTimer("commit");
53 doReturn(commitTimerContext).when(commitTimer).time();
54 doReturn(commitSnapshot).when(commitTimer).getSnapshot();
58 public void testSuccess(){
60 for(int i=1;i<11;i++){
61 // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
62 // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
63 doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
67 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
69 commitCallback.success();
71 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(292)));
75 public void testSuccessPercentileValueZero(){
77 for(int i=1;i<11;i++){
78 // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
79 // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
80 doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
83 doReturn(TimeUnit.MILLISECONDS.toNanos(0) * 1D).when(commitSnapshot).getValue(0.1);
85 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
87 commitCallback.success();
89 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(192)));
93 public void testSuccessOnePercentileValueVeryHigh(){
95 for(int i=1;i<11;i++){
96 // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
97 // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
98 doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
102 doReturn(TimeUnit.MILLISECONDS.toNanos(10000) * 1D).when(commitSnapshot).getValue(1.0);
104 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
105 commitCallback.run();
106 commitCallback.success();
108 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(282)));
112 public void testSuccessWithAllPercentileValueVeryHigh(){
114 for(int i=1;i<11;i++){
115 // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
116 // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
117 doReturn(TimeUnit.MILLISECONDS.toNanos(10000) * 1D).when(commitSnapshot).getValue(i * 0.1);
120 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
121 commitCallback.run();
122 commitCallback.success();
124 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(0)));
128 public void testSuccessWithRealPercentileValues(){
130 for(int i=1;i<11;i++){
131 // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
132 // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
133 doReturn(TimeUnit.MILLISECONDS.toNanos(8) * 1D).when(commitSnapshot).getValue(i * 0.1);
136 doReturn(TimeUnit.MILLISECONDS.toNanos(20) * 1D).when(commitSnapshot).getValue( 0.7);
137 doReturn(TimeUnit.MILLISECONDS.toNanos(100) * 1D).when(commitSnapshot).getValue( 0.9);
138 doReturn(TimeUnit.MILLISECONDS.toNanos(200) * 1D).when(commitSnapshot).getValue( 1.0);
140 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
141 commitCallback.run();
142 commitCallback.success();
144 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(101)));
149 public void testSuccessWithoutRun(){
150 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
153 commitCallback.success();
154 fail("Expected IllegalStateException");
155 } catch(IllegalStateException e){
159 verify(actorContext, never()).setTxCreationLimit(anyDouble());
165 public void testFailure(){
166 TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
167 commitCallback.run();
168 commitCallback.failure();
170 verify(actorContext, never()).setTxCreationLimit(anyDouble());
175 public void testAdjustRateLimitForUnusedTransaction() {
176 doReturn(commitTimer).when(actorContext).getOperationTimer("one", "commit");
177 doReturn("one").when(actorContext).getDataStoreType();
179 Timer commitTimer2 = Mockito.mock(Timer.class);
180 Snapshot commitSnapshot2 = Mockito.mock(Snapshot.class);
182 doReturn(commitSnapshot2).when(commitTimer2).getSnapshot();
184 doReturn(commitTimer2).when(actorContext).getOperationTimer("two", "commit");
186 DatastoreContext.newBuilder().dataStoreType("one").build();
187 DatastoreContext.newBuilder().dataStoreType("two").build();
189 doReturn(TimeUnit.MICROSECONDS.toNanos(500) * 1D).when(commitSnapshot).getValue(1 * 0.1);
191 TransactionRateLimitingCallback.adjustRateLimitForUnusedTransaction(actorContext);
193 verify(actorContext, never()).setTxCreationLimit(anyDouble());
195 Mockito.reset(commitSnapshot);
197 TransactionRateLimitingCallback.adjustRateLimitForUnusedTransaction(actorContext);
199 verify(actorContext, never()).setTxCreationLimit(anyDouble());
201 System.out.println(""+TimeUnit.SECONDS.toNanos(30)/TimeUnit.MICROSECONDS.toNanos(100));
203 doReturn(TimeUnit.MICROSECONDS.toNanos(100) * 1D).when(commitSnapshot2).getValue(1 * 0.1);
205 TransactionRateLimitingCallback.adjustRateLimitForUnusedTransaction(actorContext);
207 verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(1000)));
210 public Matcher<Double> approximately(final double val){
211 return new BaseMatcher<Double>() {
213 public boolean matches(Object o) {
214 Double aDouble = (Double) o;
215 return aDouble >= val && aDouble <= val+1;
219 public void describeTo(Description description) {
220 description.appendText("> " + val +" < " + (val+1));