Time Bucket DS for handeling SB mapping timeout
[lispflowmapping.git] / mappingservice / implementation / src / test / java / org / opendaylight / lispflowmapping / implementation / timebucket / TimeBucketWheelUnitTest.java
1 /*
2  * Copyright (c) 2016 Cisco Systems, Inc.  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.lispflowmapping.implementation.timebucket;
10
11 import java.util.ArrayList;
12 import java.util.Date;
13 import java.util.List;
14 import java.util.concurrent.ConcurrentHashMap;
15
16 import org.junit.Assert;
17 import org.junit.Test;
18 import org.junit.runner.RunWith;
19 import org.mockito.Mockito;
20 import org.mockito.runners.MockitoJUnitRunner;
21 import org.opendaylight.lispflowmapping.config.ConfigIni;
22 import org.opendaylight.lispflowmapping.implementation.MappingSystem;
23 import org.opendaylight.lispflowmapping.implementation.timebucket.containers.TimeBucket;
24 import org.opendaylight.lispflowmapping.implementation.timebucket.containers.TimeBucketWheel;
25 import org.opendaylight.lispflowmapping.interfaces.dao.ILispDAO;
26 import org.opendaylight.lispflowmapping.lisp.type.MappingData;
27 import org.opendaylight.lispflowmapping.lisp.util.LispAddressUtil;
28 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.IpAddressBinary;
29 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.inet.binary.types.rev160303.Ipv4AddressBinary;
30 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.SiteId;
31 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.XtrId;
32 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.eid.container.Eid;
33 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecord;
34 import org.opendaylight.yang.gen.v1.urn.opendaylight.lfm.lisp.proto.rev151105.mapping.record.container.MappingRecordBuilder;
35 import org.powermock.api.mockito.PowerMockito;
36 import org.powermock.core.classloader.annotations.PrepareForTest;
37 import org.powermock.modules.junit4.PowerMockRunner;
38 import org.powermock.modules.junit4.PowerMockRunnerDelegate;
39 import org.powermock.reflect.Whitebox;
40
41 /**
42  * Created by Shakib Ahmed on 12/13/16.
43  */
44
45 @RunWith(PowerMockRunner.class)
46 @PowerMockRunnerDelegate(MockitoJUnitRunner.class)
47 @PrepareForTest(TimeBucketWheel.class)
48 public class TimeBucketWheelUnitTest {
49
50     private static final String IPV4_STRING_1 =         "1.2.3.0";
51     private static final String IPV4_STRING_2 =         "1.2.4.0";
52     private static final String IPV4_STRING_3 =         "1.2.5.0";
53     private static final String IPV4_STRING_4 =         "1.2.6.0";
54     private static final String IPV4_STRING_5 =         "1.2.7.0";
55     private static final Eid IPV4_EID_1 = LispAddressUtil.asIpv4Eid(IPV4_STRING_1);
56     private static final Eid IPV4_EID_2 = LispAddressUtil.asIpv4Eid(IPV4_STRING_2);
57     private static final Eid IPV4_EID_3 = LispAddressUtil.asIpv4Eid(IPV4_STRING_3);
58     private static final Eid IPV4_EID_4 = LispAddressUtil.asIpv4Eid(IPV4_STRING_4);
59     private static final Eid IPV4_EID_5 = LispAddressUtil.asIpv4Eid(IPV4_STRING_5);
60     private static final IpAddressBinary IPV4_SOURCE_RLOC_1 = new IpAddressBinary(
61             new Ipv4AddressBinary(new byte[] {1, 1, 1, 1}));
62
63     private static final int NUMBER_OF_BUCKETS = 4;
64
65     private static final XtrId XTR_ID_1 = new XtrId(new byte[] {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
66
67     private static final SiteId SITE_ID_1 = new SiteId(new byte[]{1, 1, 1, 1, 1, 1, 1, 1});
68
69     private static final long REGISTRATION_VALIDITY = ConfigIni.getInstance().getRegistrationValiditySb();
70
71     private static ILispDAO daoMock = Mockito.mock(ILispDAO.class);
72     private static MappingSystem mappingSystem = Mockito.mock(MappingSystem.class);
73
74     /**
75      * Tests {@link TimeBucketWheel#add(Eid, MappingData, long)} method for general case.
76      */
77     @Test
78     public void mappingAddedInTheProperBucketGeneralTest() {
79         PowerMockito.mockStatic(System.class);
80
81         long frozenTimeStamp = System.currentTimeMillis();
82         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
83
84         TimeBucketWheel timeBucketWheel = getDefaultTimeBucketWheel();
85
86         final int bucketId1 = timeBucketWheel.add(IPV4_EID_1, getDefaultMappingData(IPV4_EID_1),
87                 System.currentTimeMillis());
88
89         frozenTimeStamp += 1000;
90         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
91
92         final int bucketId2 = timeBucketWheel.add(IPV4_EID_2, getDefaultMappingData(IPV4_EID_2),
93                 System.currentTimeMillis());
94
95         frozenTimeStamp += 1000;
96         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
97
98         final int bucketId3 = timeBucketWheel.add(IPV4_EID_3, getDefaultMappingData(IPV4_EID_3),
99                 System.currentTimeMillis());
100
101         frozenTimeStamp += 1000;
102         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
103
104         final int bucketId4 = timeBucketWheel.add(IPV4_EID_4, getDefaultMappingData(IPV4_EID_4),
105                 System.currentTimeMillis());
106
107         frozenTimeStamp += 1000;
108         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
109
110         final int bucketId5 = timeBucketWheel.add(IPV4_EID_5, getDefaultMappingData(IPV4_EID_5),
111                 System.currentTimeMillis());
112
113         Assert.assertEquals((bucketId1 - 1 + NUMBER_OF_BUCKETS) % NUMBER_OF_BUCKETS, bucketId2);
114         Assert.assertEquals((bucketId2 - 1 + NUMBER_OF_BUCKETS) % NUMBER_OF_BUCKETS, bucketId3);
115         Assert.assertEquals((bucketId3 - 1 + NUMBER_OF_BUCKETS) % NUMBER_OF_BUCKETS, bucketId4);
116         Assert.assertEquals((bucketId4 - 1 + NUMBER_OF_BUCKETS) % NUMBER_OF_BUCKETS, bucketId5);
117     }
118
119     /**
120      * Tests {@link TimeBucketWheel#add(Eid, MappingData, long)} method for add in some bucket in the middle.
121      */
122     @Test
123     public void mappingAddedInTheProperBucketAddInMiddleTest() throws Exception {
124         PowerMockito.mockStatic(System.class);
125
126         long frozenTimeStamp = System.currentTimeMillis();
127         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
128
129         TimeBucketWheel timeBucketWheel = getDefaultTimeBucketWheel();
130
131         checkTooOldMappingCase(timeBucketWheel);
132
133         checkOlderThanCurrentCase(timeBucketWheel);
134
135     }
136
137     private void checkTooOldMappingCase(TimeBucketWheel timeBucketWheel) throws Exception {
138         long frozenTimeStamp = System.currentTimeMillis() - 10000;
139         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
140
141         int bucketId = timeBucketWheel.add(IPV4_EID_1, getDefaultMappingData(IPV4_EID_1),
142                 System.currentTimeMillis());
143
144         int idOfLastBucketInBucketWheel = Whitebox.invokeMethod(timeBucketWheel,
145                 "getLastBucketId");
146
147         Assert.assertEquals(idOfLastBucketInBucketWheel, bucketId);
148
149         //Time resetting to old frozen time
150         frozenTimeStamp = System.currentTimeMillis() + 10000;
151         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
152     }
153
154     private void checkOlderThanCurrentCase(TimeBucketWheel timeBucketWheel) {
155         long frozenTimeStamp = System.currentTimeMillis();
156
157         int bucketId1 = timeBucketWheel.add(IPV4_EID_1, getDefaultMappingData(IPV4_EID_1),
158                 frozenTimeStamp);
159
160         MappingData toBeExpiredMappingData = getDefaultMappingData(IPV4_EID_2);
161
162         int bucketId2 = timeBucketWheel.add(IPV4_EID_2, toBeExpiredMappingData,
163                 frozenTimeStamp - 1000);
164
165         Assert.assertEquals((bucketId1 + 1) % NUMBER_OF_BUCKETS, bucketId2);
166
167         //expired at proper time
168         frozenTimeStamp = frozenTimeStamp + 3000;
169         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
170
171         timeBucketWheel.clearExpiredMappingAndRotate();
172
173         Mockito.verify(mappingSystem).handleSbExpiredMapping(IPV4_EID_2, null, toBeExpiredMappingData);
174     }
175
176
177     /**
178      * Tests {@link TimeBucketWheel#refreshMappping(Eid, MappingData, long, int)} method.
179      * {@link ClassCastException} can be thrown.
180      */
181     @Test
182     public void mappingRefreshedProperlyTest() {
183         PowerMockito.mockStatic(System.class);
184
185         long frozenTimeStamp = System.currentTimeMillis();
186         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
187
188         TimeBucketWheel timeBucketWheel = getDefaultTimeBucketWheel();
189
190         final int bucketId1 = timeBucketWheel.add(IPV4_EID_1, getDefaultMappingData(IPV4_EID_1),
191                 System.currentTimeMillis());
192
193         frozenTimeStamp += 2000;
194         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
195
196         MappingData newMappingData = getDefaultMappingData(IPV4_EID_1);
197
198         int currentBucketId = timeBucketWheel.refreshMappping(IPV4_EID_1, newMappingData,
199                 System.currentTimeMillis(), bucketId1);
200
201         List<TimeBucket> bucketList = extractBucketList(timeBucketWheel);
202
203         TimeBucket pastTimeBucket = bucketList.get(bucketId1);
204
205         MappingData oldStoredMappingData = getMappingDataFromTimeBucket(pastTimeBucket, IPV4_EID_1);
206
207         Assert.assertNull(oldStoredMappingData);
208
209         TimeBucket presentTimeBucket = bucketList.get(currentBucketId);
210
211         MappingData newStoredMappingData = getMappingDataFromTimeBucket(presentTimeBucket, IPV4_EID_1);
212
213         Assert.assertEquals(newMappingData, newStoredMappingData);
214     }
215
216     private List<TimeBucket> extractBucketList(TimeBucketWheel timeBucketWheel) {
217         List<TimeBucket> bucketList;
218         try {
219             bucketList = (List<TimeBucket>) Whitebox.getInternalState(timeBucketWheel, "bucketList");
220         } catch (ClassCastException e) {
221             throw e;
222         }
223         return bucketList;
224     }
225
226     private MappingData getMappingDataFromTimeBucket(TimeBucket timeBucket, Eid eid) {
227         ConcurrentHashMap<Eid, MappingData> bucketElements;
228
229         try {
230             bucketElements = (ConcurrentHashMap<Eid, MappingData>) Whitebox.getInternalState(timeBucket,
231                     "bucketElements");
232         } catch (ClassCastException e) {
233             throw e;
234         }
235
236         return bucketElements.get(eid);
237     }
238
239     /**
240      * Tests {@link TimeBucketWheel#clearExpiredMappingAndRotate(long)} method.
241      * {@link ClassCastException} can be thrown.
242      */
243     @Test
244     public void expiredMappingClearedProperlyTest() {
245         PowerMockito.mockStatic(System.class);
246
247         long frozenTimeStamp = System.currentTimeMillis();
248         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
249
250         TimeBucketWheel timeBucketWheel = getDefaultTimeBucketWheel();
251
252         MappingData mappingData = getDefaultMappingData(IPV4_EID_1);
253         timeBucketWheel.add(IPV4_EID_1, mappingData,
254                 System.currentTimeMillis());
255
256         frozenTimeStamp = System.currentTimeMillis() + 4000;
257         PowerMockito.when(System.currentTimeMillis()).thenReturn(frozenTimeStamp);
258
259         timeBucketWheel.clearExpiredMappingAndRotate(frozenTimeStamp);
260
261         Mockito.verify(mappingSystem).handleSbExpiredMapping(IPV4_EID_1, null, mappingData);
262     }
263
264
265     private MappingData getDefaultMappingDataWithProperTimestamp(Eid eid, long timeStamp) {
266         MappingData mappingData = getDefaultMappingData(eid);
267         Date date = new Date();
268         date.setTime(timeStamp);
269         mappingData.setTimestamp(date);
270         return mappingData;
271     }
272
273     private static TimeBucketWheel getDefaultTimeBucketWheel() {
274         return new TimeBucketWheel(4, 3000, mappingSystem);
275     }
276
277     private static MappingData getDefaultMappingData(Eid eid) {
278         return getDefaultMappingData(eid,null);
279     }
280
281     private static MappingData getDefaultMappingData(Eid eid, MappingRecord mappingRecord) {
282         if (mappingRecord == null) {
283             mappingRecord = getDefaultMappingRecordBuilder(eid).build();
284         }
285         return new MappingData(mappingRecord, System.currentTimeMillis());
286     }
287
288     private static MappingRecordBuilder getDefaultMappingRecordBuilder(Eid eid) {
289         return new MappingRecordBuilder()
290                 .setEid(eid)
291                 .setLocatorRecord(new ArrayList<>())
292                 .setRecordTtl(2)
293                 .setAction(MappingRecord.Action.NativelyForward)
294                 .setAuthoritative(true)
295                 .setMapVersion((short) 1)
296                 .setSiteId(SITE_ID_1)
297                 .setSourceRloc(IPV4_SOURCE_RLOC_1)
298                 .setTimestamp(new Date().getTime())
299                 .setXtrId(XTR_ID_1);
300     }
301 }