Merge "Bug 2194: Find primary shard on remote ShardManager"
[controller.git] / opendaylight / md-sal / sal-distributed-datastore / src / test / java / org / opendaylight / controller / cluster / datastore / TransactionRateLimitingCommitCallbackTest.java
1 /*
2  * Copyright (c) 2015 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8
9 package org.opendaylight.controller.cluster.datastore;
10
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.MockitoAnnotations;
27 import org.opendaylight.controller.cluster.datastore.utils.ActorContext;
28
29 public class TransactionRateLimitingCommitCallbackTest {
30
31     @Mock
32     public ActorContext actorContext;
33
34     @Mock
35     public DatastoreContext datastoreContext;
36
37     @Mock
38     public Timer commitTimer;
39
40     @Mock
41     private Timer.Context commitTimerContext;
42
43     @Mock
44     private Snapshot commitSnapshot;
45
46     @Before
47     public void setUp(){
48         MockitoAnnotations.initMocks(this);
49         doReturn(datastoreContext).when(actorContext).getDatastoreContext();
50         doReturn(30).when(datastoreContext).getShardTransactionCommitTimeoutInSeconds();
51         doReturn(commitTimer).when(actorContext).getOperationTimer("commit");
52         doReturn(commitTimerContext).when(commitTimer).time();
53         doReturn(commitSnapshot).when(commitTimer).getSnapshot();
54     }
55
56     @Test
57     public void testSuccess(){
58
59         for(int i=1;i<11;i++){
60             // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
61             // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
62             doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
63         }
64
65
66         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
67         commitCallback.run();
68         commitCallback.success();
69
70         verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(292)));
71     }
72
73     @Test
74     public void testSuccessPercentileValueZero(){
75
76         for(int i=1;i<11;i++){
77             // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
78             // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
79             doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
80         }
81
82         doReturn(TimeUnit.MILLISECONDS.toNanos(0) * 1D).when(commitSnapshot).getValue(0.1);
83
84         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
85         commitCallback.run();
86         commitCallback.success();
87
88         verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(192)));
89     }
90
91     @Test
92     public void testSuccessOnePercentileValueVeryHigh(){
93
94         for(int i=1;i<11;i++){
95             // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
96             // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
97             doReturn(TimeUnit.MILLISECONDS.toNanos(i) * 1D).when(commitSnapshot).getValue(i * 0.1);
98         }
99
100         // ten seconds
101         doReturn(TimeUnit.MILLISECONDS.toNanos(10000) * 1D).when(commitSnapshot).getValue(1.0);
102
103         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
104         commitCallback.run();
105         commitCallback.success();
106
107         verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(282)));
108     }
109
110     @Test
111     public void testSuccessWithAllPercentileValueVeryHigh(){
112
113         for(int i=1;i<11;i++){
114             // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
115             // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
116             doReturn(TimeUnit.MILLISECONDS.toNanos(10000) * 1D).when(commitSnapshot).getValue(i * 0.1);
117         }
118
119         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
120         commitCallback.run();
121         commitCallback.success();
122
123         verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(0)));
124     }
125
126     @Test
127     public void testSuccessWithRealPercentileValues(){
128
129         for(int i=1;i<11;i++){
130             // Keep on increasing the amount of time it takes to complete transaction for each tenth of a
131             // percentile. Essentially this would be 1ms for the 10th percentile, 2ms for 20th percentile and so on.
132             doReturn(TimeUnit.MILLISECONDS.toNanos(8) * 1D).when(commitSnapshot).getValue(i * 0.1);
133         }
134
135         doReturn(TimeUnit.MILLISECONDS.toNanos(20) * 1D).when(commitSnapshot).getValue( 0.7);
136         doReturn(TimeUnit.MILLISECONDS.toNanos(100) * 1D).when(commitSnapshot).getValue( 0.9);
137         doReturn(TimeUnit.MILLISECONDS.toNanos(200) * 1D).when(commitSnapshot).getValue( 1.0);
138
139         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
140         commitCallback.run();
141         commitCallback.success();
142
143         verify(actorContext).setTxCreationLimit(Matchers.doubleThat(approximately(101)));
144     }
145
146
147     @Test
148     public void testSuccessWithoutRun(){
149         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
150
151         try {
152             commitCallback.success();
153             fail("Expected IllegalStateException");
154         } catch(IllegalStateException e){
155
156         }
157
158         verify(actorContext, never()).setTxCreationLimit(anyDouble());
159
160     }
161
162
163     @Test
164     public void testFailure(){
165         TransactionRateLimitingCallback commitCallback = new TransactionRateLimitingCallback(actorContext);
166         commitCallback.run();
167         commitCallback.failure();
168
169         verify(actorContext, never()).setTxCreationLimit(anyDouble());
170
171     }
172
173     public Matcher<Double> approximately(final double val){
174         return new BaseMatcher<Double>() {
175             @Override
176             public boolean matches(Object o) {
177                 Double aDouble = (Double) o;
178                 return aDouble > val && aDouble < val+1;
179             }
180
181             @Override
182             public void describeTo(Description description) {
183                 description.appendText("> " + val +" < " + (val+1));
184             }
185         };
186     }
187
188
189 }