blob: cd5b009856b5efa8cfab2e1374c5d9a60c348bee [file] [log] [blame]
Thomas Vachuska4f1a60c2014-10-28 13:39:07 -07001/*
2 * Copyright 2014 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 */
Yuta HIGUCHI4d187952014-10-16 19:59:35 -070016package org.onlab.onos.store.flow.impl;
17
18import static com.google.common.base.Preconditions.checkState;
19import static org.junit.Assert.*;
20
21import java.util.Collections;
22import java.util.Map;
Ayaka Koshibefc981cf2014-10-21 12:44:17 -070023import java.util.LinkedList;
Yuta HIGUCHI4d187952014-10-16 19:59:35 -070024import java.util.concurrent.CountDownLatch;
25import java.util.concurrent.TimeUnit;
26
27import org.junit.After;
28import org.junit.Before;
29import org.junit.Test;
30import org.onlab.onos.cluster.NodeId;
Ayaka Koshibefc981cf2014-10-21 12:44:17 -070031import org.onlab.onos.cluster.RoleInfo;
Yuta HIGUCHI4d187952014-10-16 19:59:35 -070032import org.onlab.onos.event.AbstractListenerRegistry;
33import org.onlab.onos.event.DefaultEventSinkRegistry;
34import org.onlab.onos.event.Event;
35import org.onlab.onos.event.EventDeliveryService;
36import org.onlab.onos.event.EventSink;
37import org.onlab.onos.mastership.MastershipEvent;
38import org.onlab.onos.mastership.MastershipEvent.Type;
39import org.onlab.onos.mastership.MastershipListener;
40import org.onlab.onos.mastership.MastershipService;
41import org.onlab.onos.mastership.MastershipServiceAdapter;
42import org.onlab.onos.net.DeviceId;
43import org.onlab.onos.store.flow.ReplicaInfo;
44import org.onlab.onos.store.flow.ReplicaInfoEvent;
45import org.onlab.onos.store.flow.ReplicaInfoEventListener;
46import org.onlab.onos.store.flow.ReplicaInfoService;
47
48import com.google.common.base.Optional;
49import com.google.common.collect.Maps;
50
51public class ReplicaInfoManagerTest {
52
53
54 private static final DeviceId DID1 = DeviceId.deviceId("of:1");
55 private static final DeviceId DID2 = DeviceId.deviceId("of:2");
56 private static final NodeId NID1 = new NodeId("foo");
57
58 private ReplicaInfoManager mgr;
59 private ReplicaInfoService service;
60
61 private AbstractListenerRegistry<MastershipEvent, MastershipListener>
62 mastershipListenerRegistry;
63 private TestEventDispatcher eventDispatcher;
64
65
66 @Before
67 public void setUp() throws Exception {
68 mastershipListenerRegistry = new AbstractListenerRegistry<>();
69
70 mgr = new ReplicaInfoManager();
71 service = mgr;
72
73 eventDispatcher = new TestEventDispatcher();
74 mgr.eventDispatcher = eventDispatcher;
75 mgr.mastershipService = new TestMastershipService();
76
77 // register dummy mastership event source
78 mgr.eventDispatcher.addSink(MastershipEvent.class, mastershipListenerRegistry);
79
80 mgr.activate();
81 }
82
83 @After
84 public void tearDown() throws Exception {
85 mgr.deactivate();
86 }
87
88 @Test
89 public void testGetReplicaInfoFor() {
90 ReplicaInfo info1 = service.getReplicaInfoFor(DID1);
91 assertEquals(Optional.of(NID1), info1.master());
92 // backups are always empty for now
93 assertEquals(Collections.emptyList(), info1.backups());
94
95 ReplicaInfo info2 = service.getReplicaInfoFor(DID2);
96 assertEquals("There's no master", Optional.absent(), info2.master());
97 // backups are always empty for now
98 assertEquals(Collections.emptyList(), info2.backups());
99 }
100
101 @Test
102 public void testReplicaInfoEvent() throws InterruptedException {
103 final CountDownLatch latch = new CountDownLatch(1);
104 service.addListener(new MasterNodeCheck(latch, DID1, NID1));
105
106 // fake MastershipEvent
Ayaka Koshibefc981cf2014-10-21 12:44:17 -0700107 eventDispatcher.post(new MastershipEvent(Type.MASTER_CHANGED, DID1,
108 new RoleInfo(NID1, new LinkedList<NodeId>())));
Yuta HIGUCHI4d187952014-10-16 19:59:35 -0700109
110 assertTrue(latch.await(1, TimeUnit.SECONDS));
111 }
112
113
114 private final class MasterNodeCheck implements ReplicaInfoEventListener {
115 private final CountDownLatch latch;
116 private Optional<NodeId> expectedMaster;
117 private DeviceId expectedDevice;
118
119
120 MasterNodeCheck(CountDownLatch latch, DeviceId did,
121 NodeId nid) {
122 this.latch = latch;
123 this.expectedMaster = Optional.fromNullable(nid);
124 this.expectedDevice = did;
125 }
126
127 @Override
128 public void event(ReplicaInfoEvent event) {
129 assertEquals(expectedDevice, event.subject());
130 assertEquals(expectedMaster, event.replicaInfo().master());
131 // backups are always empty for now
132 assertEquals(Collections.emptyList(), event.replicaInfo().backups());
133 latch.countDown();
134 }
135 }
136
137
138 private final class TestMastershipService
139 extends MastershipServiceAdapter
140 implements MastershipService {
141
142 private Map<DeviceId, NodeId> masters;
143
144 TestMastershipService() {
145 masters = Maps.newHashMap();
146 masters.put(DID1, NID1);
147 // DID2 has no master
148 }
149
150 @Override
151 public NodeId getMasterFor(DeviceId deviceId) {
152 return masters.get(deviceId);
153 }
154
155 @Override
156 public void addListener(MastershipListener listener) {
157 mastershipListenerRegistry.addListener(listener);
158 }
159
160 @Override
161 public void removeListener(MastershipListener listener) {
162 mastershipListenerRegistry.removeListener(listener);
163 }
164 }
165
166
167 // code clone
168 /**
169 * Implements event delivery system that delivers events synchronously, or
170 * in-line with the post method invocation.
171 */
172 private static class TestEventDispatcher extends DefaultEventSinkRegistry
173 implements EventDeliveryService {
174
175 @SuppressWarnings({ "rawtypes", "unchecked" })
176 @Override
177 public void post(Event event) {
178 EventSink sink = getSink(event.getClass());
179 checkState(sink != null, "No sink for event %s", event);
180 sink.process(event);
181 }
182 }
183}