Ray Milkey
Committed by Gerrit Code Review

Add some test cases to Intent Manager tests

- test that getIntents() returns the proper items
- test that subclass compilers work
- test the behavior of intents with no compiler
- test the behavior of intents with no installer
- test the behavior of installs that never finish

Change-Id: If0bff389e7fce2f71eb7a97051547dbd05ab588c
1 package org.onosproject.net.intent.impl; 1 package org.onosproject.net.intent.impl;
2 2
3 -import com.google.common.collect.HashMultimap; 3 +import java.util.Collection;
4 -import com.google.common.collect.Lists; 4 +import java.util.List;
5 -import com.google.common.collect.Maps; 5 +import java.util.Map;
6 -import com.google.common.collect.Multimap; 6 +import java.util.Set;
7 -import com.google.common.collect.Sets; 7 +import java.util.concurrent.CountDownLatch;
8 +import java.util.concurrent.TimeUnit;
9 +import java.util.concurrent.atomic.AtomicLong;
8 10
9 import org.hamcrest.Description; 11 import org.hamcrest.Description;
10 -import org.hamcrest.Matchers;
11 import org.hamcrest.TypeSafeMatcher; 12 import org.hamcrest.TypeSafeMatcher;
12 import org.junit.After; 13 import org.junit.After;
13 import org.junit.Before; 14 import org.junit.Before;
...@@ -36,20 +37,21 @@ import org.onosproject.net.resource.LinkResourceAllocations; ...@@ -36,20 +37,21 @@ import org.onosproject.net.resource.LinkResourceAllocations;
36 import org.onosproject.store.trivial.impl.SimpleIntentBatchQueue; 37 import org.onosproject.store.trivial.impl.SimpleIntentBatchQueue;
37 import org.onosproject.store.trivial.impl.SimpleIntentStore; 38 import org.onosproject.store.trivial.impl.SimpleIntentStore;
38 39
39 -import java.util.Collection; 40 +import com.google.common.collect.HashMultimap;
40 -import java.util.List; 41 +import com.google.common.collect.Lists;
41 -import java.util.Map; 42 +import com.google.common.collect.Maps;
42 -import java.util.Set; 43 +import com.google.common.collect.Multimap;
43 -import java.util.concurrent.CountDownLatch; 44 +import com.google.common.collect.Sets;
44 -import java.util.concurrent.TimeUnit;
45 -import java.util.concurrent.atomic.AtomicLong;
46 45
47 -import static org.hamcrest.Matchers.equalTo; 46 +import static org.hamcrest.MatcherAssert.assertThat;
48 -import static org.hamcrest.Matchers.hasItem; 47 +import static org.hamcrest.Matchers.hasSize;
49 import static org.junit.Assert.assertEquals; 48 import static org.junit.Assert.assertEquals;
49 +import static org.junit.Assert.assertNotNull;
50 import static org.junit.Assert.assertTrue; 50 import static org.junit.Assert.assertTrue;
51 -import static org.onosproject.net.intent.IntentState.*;
52 import static org.onlab.util.Tools.delay; 51 import static org.onlab.util.Tools.delay;
52 +import static org.onosproject.net.intent.IntentState.FAILED;
53 +import static org.onosproject.net.intent.IntentState.INSTALLED;
54 +import static org.onosproject.net.intent.IntentState.WITHDRAWN;
53 55
54 /** 56 /**
55 * Test intent manager and transitions. 57 * Test intent manager and transitions.
...@@ -76,6 +78,185 @@ public class IntentManagerTest { ...@@ -76,6 +78,185 @@ public class IntentManagerTest {
76 protected TestIntentCompiler compiler = new TestIntentCompiler(); 78 protected TestIntentCompiler compiler = new TestIntentCompiler();
77 protected TestIntentInstaller installer = new TestIntentInstaller(); 79 protected TestIntentInstaller installer = new TestIntentInstaller();
78 80
81 + private static class TestListener implements IntentListener {
82 + final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
83 + Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();
84 +
85 + @Override
86 + public void event(IntentEvent event) {
87 + events.put(event.type(), event);
88 + if (latchMap.containsKey(event.type())) {
89 + latchMap.get(event.type()).countDown();
90 + }
91 + }
92 +
93 + public int getCounts(IntentEvent.Type type) {
94 + return events.get(type).size();
95 + }
96 +
97 + public void setLatch(int count, IntentEvent.Type type) {
98 + latchMap.put(type, new CountDownLatch(count));
99 + }
100 +
101 + public void await(IntentEvent.Type type) {
102 + try {
103 + assertTrue("Timed out waiting for: " + type,
104 + latchMap.get(type).await(5, TimeUnit.SECONDS));
105 + } catch (InterruptedException e) {
106 + e.printStackTrace();
107 + }
108 + }
109 + }
110 +
111 + private static class TestIntentTracker implements ObjectiveTrackerService {
112 + private TopologyChangeDelegate delegate;
113 + @Override
114 + public void setDelegate(TopologyChangeDelegate delegate) {
115 + this.delegate = delegate;
116 + }
117 +
118 + @Override
119 + public void unsetDelegate(TopologyChangeDelegate delegate) {
120 + if (delegate.equals(this.delegate)) {
121 + this.delegate = null;
122 + }
123 + }
124 +
125 + @Override
126 + public void addTrackedResources(IntentId intentId, Collection<NetworkResource> resources) {
127 + //TODO
128 + }
129 +
130 + @Override
131 + public void removeTrackedResources(IntentId intentId, Collection<NetworkResource> resources) {
132 + //TODO
133 + }
134 + }
135 +
136 + private static class MockIntent extends Intent {
137 + private static AtomicLong counter = new AtomicLong(0);
138 +
139 + private final Long number;
140 + // Nothing new here
141 + public MockIntent(Long number) {
142 + super(APPID, null);
143 + this.number = number;
144 + }
145 +
146 + public Long number() {
147 + return number;
148 + }
149 +
150 + public static Long nextId() {
151 + return counter.getAndIncrement();
152 + }
153 + }
154 +
155 + private static class MockInstallableIntent extends MockIntent {
156 + public MockInstallableIntent(Long number) {
157 + super(number);
158 + }
159 +
160 + @Override
161 + public boolean isInstallable() {
162 + return true;
163 + }
164 + }
165 +
166 + private static class TestIntentCompiler implements IntentCompiler<MockIntent> {
167 + @Override
168 + public List<Intent> compile(MockIntent intent, List<Intent> installable,
169 + Set<LinkResourceAllocations> resources) {
170 + return Lists.newArrayList(new MockInstallableIntent(intent.number()));
171 + }
172 + }
173 +
174 + private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
175 + @Override
176 + public List<Intent> compile(MockIntent intent, List<Intent> installable,
177 + Set<LinkResourceAllocations> resources) {
178 + throw new IntentCompilationException("Compilation always fails");
179 + }
180 + }
181 +
182 + private static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
183 + @Override
184 + public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) {
185 + FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue());
186 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
187 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr));
188 + return Lists.newArrayList(new FlowRuleBatchOperation(rules));
189 + }
190 +
191 + @Override
192 + public List<FlowRuleBatchOperation> uninstall(MockInstallableIntent intent) {
193 + FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue());
194 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
195 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr));
196 + return Lists.newArrayList(new FlowRuleBatchOperation(rules));
197 + }
198 +
199 + @Override
200 + public List<FlowRuleBatchOperation> replace(MockInstallableIntent oldIntent, MockInstallableIntent newIntent) {
201 + FlowRule fr = new IntentTestsMocks.MockFlowRule(oldIntent.number().intValue());
202 + FlowRule fr2 = new IntentTestsMocks.MockFlowRule(newIntent.number().intValue());
203 + List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
204 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr));
205 + rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr2));
206 + return Lists.newArrayList(new FlowRuleBatchOperation(rules));
207 + }
208 + }
209 +
210 + private static class TestIntentErrorInstaller implements IntentInstaller<MockInstallableIntent> {
211 + @Override
212 + public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) {
213 + throw new IntentInstallationException("install() always fails");
214 + }
215 +
216 + @Override
217 + public List<FlowRuleBatchOperation> uninstall(MockInstallableIntent intent) {
218 + throw new IntentRemovalException("uninstall() always fails");
219 + }
220 +
221 + @Override
222 + public List<FlowRuleBatchOperation> replace(MockInstallableIntent oldIntent, MockInstallableIntent newIntent) {
223 + throw new IntentInstallationException("replace() always fails");
224 + }
225 + }
226 +
227 + /**
228 + * Hamcrest matcher to check that a conllection of Intents contains an
229 + * Intent with the specified Intent Id.
230 + */
231 + public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
232 + private final IntentId id;
233 +
234 + public EntryForIntentMatcher(IntentId idValue) {
235 + id = idValue;
236 + }
237 +
238 + @Override
239 + public boolean matchesSafely(Collection<Intent> intents) {
240 + for (Intent intent : intents) {
241 + if (intent.id().equals(id)) {
242 + return true;
243 + }
244 + }
245 + return false;
246 + }
247 +
248 + @Override
249 + public void describeTo(Description description) {
250 + description.appendText("an intent with id \" ").
251 + appendText(id.toString()).
252 + appendText("\"");
253 + }
254 + }
255 +
256 + private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
257 + return new EntryForIntentMatcher(id);
258 + }
259 +
79 @Before 260 @Before
80 public void setUp() { 261 public void setUp() {
81 manager = new IntentManager(); 262 manager = new IntentManager();
...@@ -253,176 +434,120 @@ public class IntentManagerTest { ...@@ -253,176 +434,120 @@ public class IntentManagerTest {
253 service.submit(intent); 434 service.submit(intent);
254 listener.await(Type.INSTALL_REQ); 435 listener.await(Type.INSTALL_REQ);
255 listener.await(Type.FAILED); 436 listener.await(Type.FAILED);
256 -
257 } 437 }
258 438
259 - private static class TestListener implements IntentListener { 439 + /**
260 - final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create(); 440 + * Tests handling a future that contains an unresolvable error as a result of
261 - Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap(); 441 + * installing an intent.
262 - 442 + */
263 - @Override 443 + @Test
264 - public void event(IntentEvent event) { 444 + public void errorIntentInstallNeverTrue() {
265 - events.put(event.type(), event); 445 + final Long id = MockIntent.nextId();
266 - if (latchMap.containsKey(event.type())) { 446 + flowRuleService.setFuture(false, 1);
267 - latchMap.get(event.type()).countDown(); 447 + MockIntent intent = new MockIntent(id);
268 - } 448 + listener.setLatch(1, Type.WITHDRAWN);
269 - } 449 + listener.setLatch(1, Type.INSTALL_REQ);
270 - 450 + service.submit(intent);
271 - public int getCounts(IntentEvent.Type type) { 451 + listener.await(Type.INSTALL_REQ);
272 - return events.get(type).size(); 452 + // The delay here forces the retry loop in the intent manager to time out
273 - } 453 + delay(100);
274 - 454 + flowRuleService.setFuture(false, 1);
275 - public void setLatch(int count, IntentEvent.Type type) { 455 + service.withdraw(intent);
276 - latchMap.put(type, new CountDownLatch(count)); 456 + listener.await(Type.WITHDRAWN);
277 - }
278 -
279 - public void await(IntentEvent.Type type) {
280 - try {
281 - assertTrue("Timed out waiting for: " + type,
282 - latchMap.get(type).await(5, TimeUnit.SECONDS));
283 - } catch (InterruptedException e) {
284 - e.printStackTrace();
285 - }
286 - }
287 } 457 }
288 458
289 - private static class TestIntentTracker implements ObjectiveTrackerService { 459 + /**
290 - private TopologyChangeDelegate delegate; 460 + * Tests that a compiler for a subclass of an intent that already has a
291 - @Override 461 + * compiler is automatically added.
292 - public void setDelegate(TopologyChangeDelegate delegate) { 462 + */
293 - this.delegate = delegate; 463 + @Test
294 - } 464 + public void intentSubclassCompile() {
295 - 465 + class MockIntentSubclass extends MockIntent {
296 - @Override 466 + public MockIntentSubclass(Long number) {
297 - public void unsetDelegate(TopologyChangeDelegate delegate) { 467 + super(number);
298 - if (delegate.equals(this.delegate)) {
299 - this.delegate = null;
300 } 468 }
301 } 469 }
470 + flowRuleService.setFuture(true);
302 471
303 - @Override 472 + listener.setLatch(1, Type.INSTALL_REQ);
304 - public void addTrackedResources(IntentId intentId, Collection<NetworkResource> resources) { 473 + listener.setLatch(1, Type.INSTALLED);
305 - //TODO 474 + Intent intent = new MockIntentSubclass(MockIntent.nextId());
306 - } 475 + service.submit(intent);
307 - 476 + listener.await(Type.INSTALL_REQ);
308 - @Override 477 + listener.await(Type.INSTALLED);
309 - public void removeTrackedResources(IntentId intentId, Collection<NetworkResource> resources) { 478 + assertEquals(1L, service.getIntentCount());
310 - //TODO 479 + assertEquals(1L, flowRuleService.getFlowRuleCount());
311 - }
312 - }
313 -
314 - private static class MockIntent extends Intent {
315 - private static AtomicLong counter = new AtomicLong(0);
316 -
317 - private final Long number;
318 - // Nothing new here
319 - public MockIntent(Long number) {
320 - super(APPID, null);
321 - this.number = number;
322 - }
323 -
324 - public Long number() {
325 - return number;
326 - }
327 -
328 - public static Long nextId() {
329 - return counter.getAndIncrement();
330 - }
331 - }
332 -
333 - private static class MockInstallableIntent extends MockIntent {
334 - public MockInstallableIntent(Long number) {
335 - super(number);
336 - }
337 480
338 - @Override 481 + final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers =
339 - public boolean isInstallable() { 482 + extensionService.getCompilers();
340 - return true; 483 + assertEquals(2, compilers.size());
341 - } 484 + assertNotNull(compilers.get(MockIntentSubclass.class));
485 + assertNotNull(compilers.get(MockIntent.class));
342 } 486 }
343 487
344 - private static class TestIntentCompiler implements IntentCompiler<MockIntent> { 488 + /**
345 - @Override 489 + * Tests an intent with no compiler.
346 - public List<Intent> compile(MockIntent intent, List<Intent> installable, 490 + */
347 - Set<LinkResourceAllocations> resources) { 491 + @Test
348 - return Lists.newArrayList(new MockInstallableIntent(intent.number())); 492 + public void intentWithoutCompiler() {
493 + class IntentNoCompiler extends Intent {
494 + IntentNoCompiler() {
495 + super(APPID, null);
496 + }
349 } 497 }
350 - }
351 498
352 - private static class TestIntentCompilerError implements IntentCompiler<MockIntent> { 499 + Intent intent = new IntentNoCompiler();
353 - @Override 500 + listener.setLatch(1, Type.INSTALL_REQ);
354 - public List<Intent> compile(MockIntent intent, List<Intent> installable, 501 + listener.setLatch(1, Type.FAILED);
355 - Set<LinkResourceAllocations> resources) { 502 + service.submit(intent);
356 - throw new IntentCompilationException("Compilation always fails"); 503 + listener.await(Type.INSTALL_REQ);
357 - } 504 + listener.await(Type.FAILED);
358 } 505 }
359 506
360 - private static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> { 507 + /**
361 - @Override 508 + * Tests an intent with no installer.
362 - public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) { 509 + */
363 - FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue()); 510 + @Test
364 - List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); 511 + public void intentWithoutInstaller() {
365 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr));
366 - return Lists.newArrayList(new FlowRuleBatchOperation(rules));
367 - }
368 512
369 - @Override 513 + extensionService.unregisterInstaller(MockInstallableIntent.class);
370 - public List<FlowRuleBatchOperation> uninstall(MockInstallableIntent intent) {
371 - FlowRule fr = new IntentTestsMocks.MockFlowRule(intent.number().intValue());
372 - List<FlowRuleBatchEntry> rules = Lists.newLinkedList();
373 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr));
374 - return Lists.newArrayList(new FlowRuleBatchOperation(rules));
375 - }
376 514
377 - @Override 515 + MockIntent intent = new MockIntent(MockIntent.nextId());
378 - public List<FlowRuleBatchOperation> replace(MockInstallableIntent oldIntent, MockInstallableIntent newIntent) { 516 + listener.setLatch(1, Type.INSTALL_REQ);
379 - FlowRule fr = new IntentTestsMocks.MockFlowRule(oldIntent.number().intValue()); 517 + listener.setLatch(1, Type.FAILED);
380 - FlowRule fr2 = new IntentTestsMocks.MockFlowRule(newIntent.number().intValue()); 518 + service.submit(intent);
381 - List<FlowRuleBatchEntry> rules = Lists.newLinkedList(); 519 + listener.await(Type.INSTALL_REQ);
382 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.REMOVE, fr)); 520 + listener.await(Type.FAILED);
383 - rules.add(new FlowRuleBatchEntry(FlowRuleOperation.ADD, fr2));
384 - return Lists.newArrayList(new FlowRuleBatchOperation(rules));
385 - }
386 } 521 }
387 522
388 - private static class TestIntentErrorInstaller implements IntentInstaller<MockInstallableIntent> { 523 + /**
389 - @Override 524 + * Tests that the intent fetching methods are correct.
390 - public List<FlowRuleBatchOperation> install(MockInstallableIntent intent) { 525 + */
391 - throw new IntentInstallationException("install() always fails"); 526 + @Test
392 - } 527 + public void testIntentFetching() {
528 + List<Intent> intents;
393 529
394 - @Override 530 + flowRuleService.setFuture(true);
395 - public List<FlowRuleBatchOperation> uninstall(MockInstallableIntent intent) {
396 - throw new IntentRemovalException("uninstall() always fails");
397 - }
398 531
399 - @Override 532 + intents = Lists.newArrayList(service.getIntents());
400 - public List<FlowRuleBatchOperation> replace(MockInstallableIntent oldIntent, MockInstallableIntent newIntent) { 533 + assertThat(intents, hasSize(0));
401 - throw new IntentInstallationException("replace() always fails");
402 - }
403 - }
404 534
405 - /** 535 + final MockIntent intent1 = new MockIntent(MockIntent.nextId());
406 - * Hamcrest matcher to check that a conllection of Intents contains an 536 + final MockIntent intent2 = new MockIntent(MockIntent.nextId());
407 - * Intent with the specified Intent Id.
408 - */
409 - public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
410 - private final String id;
411 537
412 - public EntryForIntentMatcher(String idValue) { 538 + listener.setLatch(2, Type.INSTALL_REQ);
413 - id = idValue; 539 + listener.setLatch(2, Type.INSTALLED);
414 - } 540 + service.submit(intent1);
541 + service.submit(intent2);
542 + listener.await(Type.INSTALL_REQ);
543 + listener.await(Type.INSTALL_REQ);
544 + listener.await(Type.INSTALLED);
545 + listener.await(Type.INSTALLED);
415 546
416 - @Override 547 + intents = Lists.newArrayList(service.getIntents());
417 - public boolean matchesSafely(Collection<Intent> intents) { 548 + assertThat(intents, hasSize(2));
418 - return hasItem(Matchers.<Intent>hasProperty("id", equalTo(id))).matches(intents);
419 - }
420 549
421 - @Override 550 + assertThat(intents, hasIntentWithId(intent1.id()));
422 - public void describeTo(Description description) { 551 + assertThat(intents, hasIntentWithId(intent2.id()));
423 - description.appendText("an intent with id \" ").
424 - appendText(id).
425 - appendText("\"");
426 - }
427 } 552 }
428 } 553 }
......