Ray Milkey

Unit tests for Objective Tracker

- Fixed a bug in ObjectiveTracker turned up by tests, it
  could not handle an emptry list (it was checking for null only)
- Implemented tests for topology, resource and leadership
  events

Change-Id: I1318a0e8655f5b44b30d2ecb527f665f13d54243
...@@ -178,7 +178,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService { ...@@ -178,7 +178,7 @@ public class ObjectiveTracker implements ObjectiveTrackerService {
178 return; 178 return;
179 } 179 }
180 180
181 - if (event.reasons() == null) { 181 + if (event.reasons() == null || event.reasons().isEmpty()) {
182 delegate.triggerCompile(new HashSet<IntentId>(), true); 182 delegate.triggerCompile(new HashSet<IntentId>(), true);
183 183
184 } else { 184 } else {
......
1 +/*
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 + */
16 +package org.onosproject.net.intent.impl;
17 +
18 +import java.util.Collection;
19 +import java.util.HashSet;
20 +import java.util.LinkedList;
21 +import java.util.List;
22 +import java.util.concurrent.CountDownLatch;
23 +import java.util.concurrent.TimeUnit;
24 +
25 +import org.junit.After;
26 +import org.junit.Before;
27 +import org.junit.Test;
28 +import org.onlab.junit.TestUtils;
29 +import org.onosproject.core.IdGenerator;
30 +import org.onosproject.event.Event;
31 +import org.onosproject.net.Link;
32 +import org.onosproject.net.LinkKey;
33 +import org.onosproject.net.NetTestTools;
34 +import org.onosproject.net.NetworkResource;
35 +import org.onosproject.net.intent.Intent;
36 +import org.onosproject.net.intent.IntentBatchLeaderEvent;
37 +import org.onosproject.net.intent.IntentBatchListener;
38 +import org.onosproject.net.intent.IntentId;
39 +import org.onosproject.net.intent.IntentService;
40 +import org.onosproject.net.intent.MockIdGenerator;
41 +import org.onosproject.net.link.LinkEvent;
42 +import org.onosproject.net.resource.LinkResourceEvent;
43 +import org.onosproject.net.resource.LinkResourceListener;
44 +import org.onosproject.net.topology.Topology;
45 +import org.onosproject.net.topology.TopologyEvent;
46 +import org.onosproject.net.topology.TopologyListener;
47 +
48 +import com.google.common.collect.ImmutableList;
49 +import com.google.common.collect.ImmutableSet;
50 +import com.google.common.collect.Lists;
51 +import com.google.common.collect.SetMultimap;
52 +
53 +import static org.easymock.EasyMock.createMock;
54 +import static org.easymock.EasyMock.expect;
55 +import static org.easymock.EasyMock.replay;
56 +import static org.hamcrest.MatcherAssert.assertThat;
57 +import static org.hamcrest.Matchers.equalTo;
58 +import static org.hamcrest.Matchers.hasSize;
59 +import static org.hamcrest.Matchers.is;
60 +import static org.onosproject.net.NetTestTools.link;
61 +import org.onlab.junit.TestUtils.TestUtilsException;
62 +
63 +/**
64 + * Tests for the objective tracker.
65 + */
66 +public class ObjectiveTrackerTest {
67 + private static final int WAIT_TIMEOUT_SECONDS = 2;
68 + private Topology topology;
69 + private ObjectiveTracker tracker;
70 + private TestTopologyChangeDelegate delegate;
71 + private List<Event> reasons;
72 + private TopologyListener listener;
73 + private LinkResourceListener linkResourceListener;
74 + private IntentBatchListener leaderListener;
75 + private IdGenerator mockGenerator;
76 +
77 + /**
78 + * Initialization shared by all test cases.
79 + *
80 + * @throws TestUtilsException if any filed look ups fail
81 + */
82 + @Before
83 + public void setUp() throws TestUtilsException {
84 + topology = createMock(Topology.class);
85 + tracker = new ObjectiveTracker();
86 + delegate = new TestTopologyChangeDelegate();
87 + tracker.setDelegate(delegate);
88 + reasons = new LinkedList<>();
89 + listener = TestUtils.getField(tracker, "listener");
90 + linkResourceListener = TestUtils.getField(tracker, "linkResourceListener");
91 + leaderListener = TestUtils.getField(tracker, "leaderListener");
92 + mockGenerator = new MockIdGenerator();
93 + Intent.bindIdGenerator(mockGenerator);
94 + }
95 +
96 + /**
97 + * Code to clean up shared by all test case.
98 + */
99 + @After
100 + public void tearDown() {
101 + tracker.unsetDelegate(delegate);
102 + Intent.unbindIdGenerator(mockGenerator);
103 + }
104 +
105 + /**
106 + * Topology change delegate mock that tracks the events coming into it
107 + * and saves them. It provides a latch so that tests can wait for events
108 + * to be generated.
109 + */
110 + static class TestTopologyChangeDelegate implements TopologyChangeDelegate {
111 +
112 + CountDownLatch latch = new CountDownLatch(1);
113 + List<IntentId> intentIdsFromEvent;
114 + boolean compileAllFailedFromEvent;
115 +
116 + @Override
117 + public void triggerCompile(Iterable<IntentId> intentIds,
118 + boolean compileAllFailed) {
119 + intentIdsFromEvent = Lists.newArrayList(intentIds);
120 + compileAllFailedFromEvent = compileAllFailed;
121 + latch.countDown();
122 + }
123 + }
124 +
125 + /**
126 + * Mock compilable intent class.
127 + */
128 + private static class MockIntent extends Intent {
129 +
130 + public MockIntent(Collection<NetworkResource> resources) {
131 + super(NetTestTools.APP_ID, resources);
132 + }
133 +
134 + }
135 +
136 + /**
137 + * Mock installable intent class.
138 + */
139 + private static class MockInstallableIntent extends Intent {
140 + public MockInstallableIntent(Collection<NetworkResource> resources) {
141 + super(NetTestTools.APP_ID, resources);
142 + }
143 +
144 + @Override
145 + public boolean isInstallable() {
146 + return true;
147 + }
148 +
149 + }
150 +
151 + /**
152 + * Tests an event with no associated reasons.
153 + *
154 + * @throws InterruptedException if the latch wait fails.
155 + */
156 + @Test
157 + public void testEventNoReasons() throws InterruptedException {
158 + final TopologyEvent event = new TopologyEvent(
159 + TopologyEvent.Type.TOPOLOGY_CHANGED,
160 + topology,
161 + null);
162 +
163 + listener.event(event);
164 + assertThat(
165 + delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
166 + is(true));
167 +
168 + assertThat(delegate.intentIdsFromEvent, hasSize(0));
169 + assertThat(delegate.compileAllFailedFromEvent, is(true));
170 + }
171 +
172 + /**
173 + * Tests an event for a link down where none of the reasons match
174 + * currently installed intents.
175 + *
176 + * @throws InterruptedException if the latch wait fails.
177 + */
178 + @Test
179 + public void testEventLinkDownNoMatches() throws InterruptedException {
180 + final Link link = link("src", 1, "dst", 2);
181 + final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
182 + reasons.add(linkEvent);
183 +
184 + final TopologyEvent event = new TopologyEvent(
185 + TopologyEvent.Type.TOPOLOGY_CHANGED,
186 + topology,
187 + reasons);
188 +
189 + listener.event(event);
190 + assertThat(
191 + delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
192 + is(true));
193 +
194 + assertThat(delegate.intentIdsFromEvent, hasSize(0));
195 + assertThat(delegate.compileAllFailedFromEvent, is(false));
196 + }
197 +
198 + /**
199 + * Tests an event for a link being added.
200 + *
201 + * @throws InterruptedException if the latch wait fails.
202 + */
203 + @Test
204 + public void testEventLinkAdded() throws InterruptedException {
205 + final Link link = link("src", 1, "dst", 2);
206 + final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_ADDED, link);
207 + reasons.add(linkEvent);
208 +
209 + final TopologyEvent event = new TopologyEvent(
210 + TopologyEvent.Type.TOPOLOGY_CHANGED,
211 + topology,
212 + reasons);
213 +
214 + listener.event(event);
215 + assertThat(
216 + delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
217 + is(true));
218 +
219 + assertThat(delegate.intentIdsFromEvent, hasSize(0));
220 + assertThat(delegate.compileAllFailedFromEvent, is(true));
221 + }
222 +
223 + /**
224 + * Tests an event for a link down where the link matches existing intents.
225 + *
226 + * @throws InterruptedException if the latch wait fails.
227 + */
228 + @Test
229 + public void testEventLinkDownMatch() throws Exception {
230 + final Link link = link("src", 1, "dst", 2);
231 + final LinkEvent linkEvent = new LinkEvent(LinkEvent.Type.LINK_REMOVED, link);
232 + reasons.add(linkEvent);
233 +
234 + final TopologyEvent event = new TopologyEvent(
235 + TopologyEvent.Type.TOPOLOGY_CHANGED,
236 + topology,
237 + reasons);
238 +
239 + final IntentId intentId = IntentId.valueOf(0x333L);
240 + Collection<NetworkResource> resources = ImmutableSet.of(link);
241 + tracker.addTrackedResources(intentId, resources);
242 +
243 + listener.event(event);
244 + assertThat(
245 + delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
246 + is(true));
247 +
248 + assertThat(delegate.intentIdsFromEvent, hasSize(1));
249 + assertThat(delegate.compileAllFailedFromEvent, is(false));
250 + assertThat(delegate.intentIdsFromEvent.get(0).toString(),
251 + equalTo("0x333"));
252 + }
253 +
254 + /**
255 + * Tests a resource available event.
256 + *
257 + * @throws InterruptedException if the latch wait fails.
258 + */
259 + @Test
260 + public void testResourceEvent() throws Exception {
261 + LinkResourceEvent event = new LinkResourceEvent(
262 + LinkResourceEvent.Type.ADDITIONAL_RESOURCES_AVAILABLE,
263 + new HashSet<>());
264 + linkResourceListener.event(event);
265 +
266 + assertThat(
267 + delegate.latch.await(WAIT_TIMEOUT_SECONDS, TimeUnit.SECONDS),
268 + is(true));
269 +
270 + assertThat(delegate.intentIdsFromEvent, hasSize(0));
271 + assertThat(delegate.compileAllFailedFromEvent, is(true));
272 + }
273 +
274 + /**
275 + * Tests leadership events.
276 + *
277 + * @throws InterruptedException if the latch wait fails.
278 + */
279 + @Test
280 + public void testLeaderEvents() throws Exception {
281 +
282 + final Link link = link("src", 1, "dst", 2);
283 + final List<NetworkResource> resources = ImmutableList.of(link);
284 +
285 + final List<Intent> intents = new LinkedList<>();
286 + final List<Intent> installableIntents = new LinkedList<>();
287 + installableIntents.add(new MockInstallableIntent(resources));
288 + intents.add(new MockIntent(resources));
289 +
290 + final SetMultimap<LinkKey, IntentId> intentsByLink =
291 + TestUtils.getField(tracker, "intentsByLink");
292 + assertThat(intentsByLink.size(), is(0));
293 +
294 + final IntentService mockIntentManager = createMock(IntentService.class);
295 + expect(mockIntentManager
296 + .getIntents())
297 + .andReturn(intents)
298 + .anyTimes();
299 + expect(mockIntentManager
300 + .getIntent(IntentId.valueOf(0x0)))
301 + .andReturn(intents.get(0))
302 + .anyTimes();
303 + expect(mockIntentManager
304 + .getInstallableIntents(IntentId.valueOf(0x1)))
305 + .andReturn(installableIntents)
306 + .anyTimes();
307 + replay(mockIntentManager);
308 + tracker.bindIntentService(mockIntentManager);
309 +
310 + final IntentBatchLeaderEvent electedEvent = new IntentBatchLeaderEvent(
311 + IntentBatchLeaderEvent.Type.ELECTED, NetTestTools.APP_ID);
312 + leaderListener.event(electedEvent);
313 + assertThat(intentsByLink.size(), is(1));
314 +
315 + final IntentBatchLeaderEvent bootedEvent = new IntentBatchLeaderEvent(
316 + IntentBatchLeaderEvent.Type.BOOTED, NetTestTools.APP_ID);
317 + leaderListener.event(bootedEvent);
318 + assertThat(intentsByLink.size(), is(0));
319 +
320 + tracker.unbindIntentService(mockIntentManager);
321 + }
322 +}