0b7040119ab75b53ad500b31cae5483f780aebcc
[onosfw.git] /
1 /*
2  * Copyright 2014-2015 Open Networking Laboratory
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package org.onosproject.store.mastership.impl;
17
18 /**
19  * Test of the Hazelcast-based distributed MastershipStore implementation.
20  */
21 public class DistributedMastershipStoreTest {
22 /*
23     private static final DeviceId DID1 = DeviceId.deviceId("of:01");
24     private static final DeviceId DID2 = DeviceId.deviceId("of:02");
25     private static final DeviceId DID3 = DeviceId.deviceId("of:03");
26
27     private static final IpAddress IP = IpAddress.valueOf("127.0.0.1");
28
29     private static final NodeId N1 = new NodeId("node1");
30     private static final NodeId N2 = new NodeId("node2");
31
32     private static final ControllerNode CN1 = new DefaultControllerNode(N1, IP);
33     private static final ControllerNode CN2 = new DefaultControllerNode(N2, IP);
34
35     private DistributedMastershipStore dms;
36     private TestDistributedMastershipStore testStore;
37     private KryoSerializer serializationMgr;
38     private StoreManager storeMgr;
39
40     @BeforeClass
41     public static void setUpBeforeClass() throws Exception {
42     }
43
44     @AfterClass
45     public static void tearDownAfterClass() throws Exception {
46     }
47
48     @Before
49     public void setUp() throws Exception {
50         // TODO should find a way to clean Hazelcast instance without shutdown.
51         TestStoreManager testStoreMgr = new TestStoreManager();
52         testStoreMgr.setHazelcastInstance(testStoreMgr.initSingleInstance());
53         storeMgr = testStoreMgr;
54         storeMgr.activate();
55
56         serializationMgr = new KryoSerializer();
57
58         dms = new TestDistributedMastershipStore(storeMgr, serializationMgr);
59         dms.clusterService = new TestClusterService();
60         dms.activate();
61
62         testStore = (TestDistributedMastershipStore) dms;
63     }
64
65     @After
66     public void tearDown() throws Exception {
67         dms.deactivate();
68
69         storeMgr.deactivate();
70     }
71
72     @Test
73     @Ignore("Disabled this test due to intermittent failures seen on Jenkins runs")
74     public void getRole() {
75         assertEquals("wrong role:", NONE, dms.getRole(N1, DID1));
76         testStore.put(DID1, N1, true, false, true);
77         assertEquals("wrong role:", MASTER, dms.getRole(N1, DID1));
78         testStore.put(DID1, N2, false, true, false);
79         assertEquals("wrong role:", STANDBY, dms.getRole(N2, DID1));
80     }
81
82     @Test
83     public void getMaster() {
84         assertTrue("wrong store state:", dms.roleMap.isEmpty());
85
86         testStore.put(DID1, N1, true, false, false);
87         TestTools.assertAfter(100, () -> //wait for up to 100ms
88             assertEquals("wrong master:", N1, dms.getMaster(DID1)));
89         assertNull("wrong master:", dms.getMaster(DID2));
90     }
91
92     @Test
93     public void getDevices() {
94         assertTrue("wrong store state:", dms.roleMap.isEmpty());
95
96         testStore.put(DID1, N1, true, false, false);
97         testStore.put(DID2, N1, true, false, false);
98         testStore.put(DID3, N2, true, false, false);
99         assertEquals("wrong devices",
100                 Sets.newHashSet(DID1, DID2), dms.getDevices(N1));
101     }
102
103     @Test
104     public void requestRoleAndTerm() {
105         //CN1 is "local"
106         testStore.setCurrent(CN1);
107
108         //if already MASTER, nothing should happen
109         testStore.put(DID2, N1, true, false, true);
110         assertEquals("wrong role for MASTER:", MASTER, Futures.getUnchecked(dms.requestRole(DID2)));
111
112         //populate maps with DID1, N1 thru NONE case
113         assertEquals("wrong role for NONE:", MASTER, Futures.getUnchecked(dms.requestRole(DID1)));
114         assertTrue("wrong state for store:", !dms.terms.isEmpty());
115         assertEquals("wrong term",
116                 MastershipTerm.of(N1, 1), dms.getTermFor(DID1));
117
118         //CN2 now local. DID2 has N1 as MASTER so N2 is STANDBY
119         testStore.setCurrent(CN2);
120         assertEquals("wrong role for STANDBY:", STANDBY, Futures.getUnchecked(dms.requestRole(DID2)));
121         assertEquals("wrong number of entries:", 2, dms.terms.size());
122
123         //change term and requestRole() again; should persist
124         testStore.increment(DID2);
125         assertEquals("wrong role for STANDBY:", STANDBY, Futures.getUnchecked(dms.requestRole(DID2)));
126         assertEquals("wrong term", MastershipTerm.of(N1, 1), dms.getTermFor(DID2));
127     }
128
129     @Test
130     public void setMaster() {
131         //populate maps with DID1, N1 as MASTER thru NONE case
132         testStore.setCurrent(CN1);
133         assertEquals("wrong role for NONE:", MASTER, Futures.getUnchecked(dms.requestRole(DID1)));
134         assertNull("wrong event:", Futures.getUnchecked(dms.setMaster(N1, DID1)));
135
136         //switch over to N2
137         assertEquals("wrong event:", Type.MASTER_CHANGED, Futures.getUnchecked(dms.setMaster(N2, DID1)).type());
138         System.out.println(dms.getTermFor(DID1).master() + ":" + dms.getTermFor(DID1).termNumber());
139         assertEquals("wrong term", MastershipTerm.of(N2, 2), dms.getTermFor(DID1));
140
141         //orphan switch - should be rare case
142         assertEquals("wrong event:", Type.MASTER_CHANGED, Futures.getUnchecked(dms.setMaster(N2, DID2)).type());
143         assertEquals("wrong term", MastershipTerm.of(N2, 1), dms.getTermFor(DID2));
144         //disconnect and reconnect - sign of failing re-election or single-instance channel
145         dms.roleMap.clear();
146         dms.setMaster(N2, DID2);
147         assertEquals("wrong term", MastershipTerm.of(N2, 2), dms.getTermFor(DID2));
148     }
149
150     @Test
151     public void relinquishRole() {
152         //populate maps with DID1, N1 as MASTER thru NONE case
153         testStore.setCurrent(CN1);
154         assertEquals("wrong role for NONE:", MASTER, Futures.getUnchecked(dms.requestRole(DID1)));
155         //no backup, no new MASTER/event
156         assertNull("wrong event:", Futures.getUnchecked(dms.relinquishRole(N1, DID1)));
157
158         dms.requestRole(DID1);
159
160         //add backup CN2, get it elected MASTER by relinquishing
161         testStore.setCurrent(CN2);
162         assertEquals("wrong role for NONE:", STANDBY, Futures.getUnchecked(dms.requestRole(DID1)));
163         assertEquals("wrong event:", Type.MASTER_CHANGED, Futures.getUnchecked(dms.relinquishRole(N1, DID1)).type());
164         assertEquals("wrong master", N2, dms.getMaster(DID1));
165
166         //all nodes "give up" on device, which goes back to NONE.
167         assertNull("wrong event:", Futures.getUnchecked(dms.relinquishRole(N2, DID1)));
168         assertEquals("wrong role for node:", NONE, dms.getRole(N2, DID1));
169
170         assertEquals("wrong number of retired nodes", 2,
171                 dms.roleMap.get(DID1).nodesOfRole(NONE).size());
172
173         //bring nodes back
174         assertEquals("wrong role for NONE:", MASTER, Futures.getUnchecked(dms.requestRole(DID1)));
175         testStore.setCurrent(CN1);
176         assertEquals("wrong role for NONE:", STANDBY, Futures.getUnchecked(dms.requestRole(DID1)));
177         assertEquals("wrong number of backup nodes", 1,
178                 dms.roleMap.get(DID1).nodesOfRole(STANDBY).size());
179
180         //If STANDBY, should drop to NONE
181         assertEquals("wrong event:", Type.BACKUPS_CHANGED, Futures.getUnchecked(dms.relinquishRole(N1, DID1)).type());
182         assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID1));
183
184         //NONE - nothing happens
185         assertEquals("wrong event:", Type.BACKUPS_CHANGED, Futures.getUnchecked(dms.relinquishRole(N1, DID2)).type());
186         assertEquals("wrong role for node:", NONE, dms.getRole(N1, DID2));
187
188     }
189
190     @Ignore("Ignore until Delegate spec. is clear.")
191     @Test
192     public void testEvents() throws InterruptedException {
193         //shamelessly copy other distributed store tests
194         final CountDownLatch addLatch = new CountDownLatch(1);
195
196         MastershipStoreDelegate checkAdd = new MastershipStoreDelegate() {
197             @Override
198             public void notify(MastershipEvent event) {
199                 assertEquals("wrong event:", Type.MASTER_CHANGED, event.type());
200                 assertEquals("wrong subject", DID1, event.subject());
201                 assertEquals("wrong subject", N1, event.roleInfo().master());
202                 addLatch.countDown();
203             }
204         };
205
206         dms.setDelegate(checkAdd);
207         dms.setMaster(N1, DID1);
208         //this will fail until we do something about single-instance-ness
209         assertTrue("Add event fired", addLatch.await(1, TimeUnit.SECONDS));
210     }
211
212     private class TestDistributedMastershipStore extends
213             DistributedMastershipStore {
214         public TestDistributedMastershipStore(StoreService storeService,
215                 KryoSerializer kryoSerialization) {
216             this.storeService = storeService;
217             this.serializer = kryoSerialization;
218         }
219
220         //helper to populate master/backup structures
221         public void put(DeviceId dev, NodeId node,
222                 boolean master, boolean backup, boolean term) {
223             RoleValue rv = dms.roleMap.get(dev);
224             if (rv == null) {
225                 rv = new RoleValue();
226             }
227
228             if (master) {
229                 rv.add(MASTER, node);
230                 rv.reassign(node, STANDBY, NONE);
231             }
232             if (backup) {
233                 rv.add(STANDBY, node);
234                 rv.remove(MASTER, node);
235                 rv.remove(NONE, node);
236             }
237             if (term) {
238                 dms.terms.put(dev, 0);
239             }
240             dms.roleMap.put(dev, rv);
241         }
242
243         //a dumb utility function.
244         public void dump() {
245             for (Map.Entry<DeviceId, RoleValue> el : dms.roleMap.entrySet()) {
246                 System.out.println("DID: " + el.getKey());
247                 for (MastershipRole role : MastershipRole.values()) {
248                     System.out.println("\t" + role.toString() + ":");
249                     for (NodeId n : el.getValue().nodesOfRole(role)) {
250                         System.out.println("\t\t" + n);
251                     }
252                 }
253             }
254         }
255
256         //increment term for a device
257         public void increment(DeviceId dev) {
258             Integer t = dms.terms.get(dev);
259             if (t != null) {
260                 dms.terms.put(dev, ++t);
261             }
262         }
263
264         //sets the "local" node
265         public void setCurrent(ControllerNode node) {
266             ((TestClusterService) clusterService).current = node;
267         }
268     }
269
270     private class TestClusterService extends ClusterServiceAdapter {
271
272         protected ControllerNode current;
273
274         @Override
275         public ControllerNode getLocalNode() {
276             return current;
277         }
278
279         @Override
280         public Set<ControllerNode> getNodes() {
281             return Sets.newHashSet(CN1, CN2);
282         }
283
284     }
285 */
286 }