blob: 45c90e74bdf53a286434c2dc2c319779d15bcd9f [file] [log] [blame]
alshabibab984662014-12-04 18:56:18 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2014-present Open Networking Laboratory
alshabibab984662014-12-04 18:56:18 -08003 *
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 */
Brian O'Connorabafb502014-12-02 22:26:20 -080016package org.onosproject.net.intent.impl;
Brian O'Connor427a1762014-11-19 18:40:32 -080017
Brian O'Connor3c58e962015-04-28 23:21:51 -070018import com.google.common.collect.HashMultimap;
19import com.google.common.collect.Lists;
20import com.google.common.collect.Maps;
21import com.google.common.collect.Multimap;
22import com.google.common.collect.Sets;
Brian O'Connor427a1762014-11-19 18:40:32 -080023import org.hamcrest.Description;
Brian O'Connor427a1762014-11-19 18:40:32 -080024import org.hamcrest.TypeSafeMatcher;
25import org.junit.After;
26import org.junit.Before;
Jonathan Hart4fd4ebb2015-02-04 17:38:48 -080027import org.junit.Ignore;
Brian O'Connor427a1762014-11-19 18:40:32 -080028import org.junit.Test;
Brian O'Connorabafb502014-12-02 22:26:20 -080029import org.onosproject.TestApplicationId;
Brian O'Connor3c58e962015-04-28 23:21:51 -070030import org.onosproject.cfg.ComponentConfigAdapter;
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -080031import org.onosproject.cfg.ComponentConfigService;
Thomas Vachuskac46af202015-06-03 16:43:27 -070032import org.onosproject.common.event.impl.TestEventDispatcher;
Brian O'Connorabafb502014-12-02 22:26:20 -080033import org.onosproject.core.ApplicationId;
34import org.onosproject.core.impl.TestCoreManager;
Brian O'Connorabafb502014-12-02 22:26:20 -080035import org.onosproject.net.NetworkResource;
Yi Tsengc927a062017-05-02 15:02:37 -070036import org.onosproject.net.flow.FlowRuleOperations;
37import org.onosproject.net.flow.FlowRuleOperationsContext;
38import org.onosproject.net.flow.FlowRuleService;
Sho SHIMIZUee2aa652015-02-25 18:56:43 -080039import org.onosproject.net.intent.FlowRuleIntent;
Brian O'Connorabafb502014-12-02 22:26:20 -080040import org.onosproject.net.intent.Intent;
Yuta HIGUCHId95d5902016-06-27 00:18:45 -070041import org.onosproject.net.intent.IntentCompilationException;
Brian O'Connorabafb502014-12-02 22:26:20 -080042import org.onosproject.net.intent.IntentCompiler;
Thomas Vachuskac46af202015-06-03 16:43:27 -070043import org.onosproject.net.intent.IntentData;
Brian O'Connorabafb502014-12-02 22:26:20 -080044import org.onosproject.net.intent.IntentEvent;
45import org.onosproject.net.intent.IntentEvent.Type;
46import org.onosproject.net.intent.IntentExtensionService;
47import org.onosproject.net.intent.IntentId;
Yi Tsengc927a062017-05-02 15:02:37 -070048import org.onosproject.net.intent.IntentInstallCoordinator;
49import org.onosproject.net.intent.IntentInstaller;
Brian O'Connorabafb502014-12-02 22:26:20 -080050import org.onosproject.net.intent.IntentListener;
Yi Tsengc927a062017-05-02 15:02:37 -070051import org.onosproject.net.intent.IntentOperationContext;
Brian O'Connorabafb502014-12-02 22:26:20 -080052import org.onosproject.net.intent.IntentService;
53import org.onosproject.net.intent.IntentState;
Ray Milkeyf9af43c2015-02-09 16:45:48 -080054import org.onosproject.net.intent.Key;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070055import org.onosproject.store.trivial.SimpleIntentStore;
Brian O'Connor427a1762014-11-19 18:40:32 -080056
Brian O'Connor3c58e962015-04-28 23:21:51 -070057import java.util.Collection;
58import java.util.Collections;
59import java.util.List;
60import java.util.Map;
61import java.util.Set;
62import java.util.concurrent.CountDownLatch;
63import java.util.concurrent.TimeUnit;
64import java.util.stream.Collectors;
65import java.util.stream.IntStream;
Brian O'Connor427a1762014-11-19 18:40:32 -080066
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -080067import static org.easymock.EasyMock.mock;
Ray Milkeye9a3e222014-12-03 16:46:06 -080068import static org.hamcrest.MatcherAssert.assertThat;
69import static org.hamcrest.Matchers.hasSize;
Ray Milkey77a455f2015-03-27 10:08:17 -070070import static org.hamcrest.Matchers.is;
Brian O'Connor3c58e962015-04-28 23:21:51 -070071import static org.junit.Assert.*;
Ray Milkey9f74c082015-02-11 15:40:16 -080072import static org.onlab.junit.TestTools.assertAfter;
Brian O'Connor427a1762014-11-19 18:40:32 -080073import static org.onlab.util.Tools.delay;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070074import static org.onosproject.net.NetTestTools.injectEventDispatcher;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070075import static org.onosproject.net.intent.IntentState.*;
Ray Milkey43a28222015-02-23 13:57:58 -080076import static org.onosproject.net.intent.IntentTestsMocks.MockFlowRule;
77import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Brian O'Connor427a1762014-11-19 18:40:32 -080078
79/**
80 * Test intent manager and transitions.
81 *
82 * TODO implement the following tests:
83 * - {submit, withdraw, update, replace} intent
Sho SHIMIZU34660962015-01-22 17:58:44 -080084 * - {submit, update, recompiling} intent with failed compilation
Brian O'Connor427a1762014-11-19 18:40:32 -080085 * - failed reservation
86 * - push timeout recovery
87 * - failed items recovery
88 *
89 * in general, verify intents store, flow store, and work queue
90 */
Ray Milkey1c166dc2015-03-02 13:32:39 -080091
Brian O'Connor427a1762014-11-19 18:40:32 -080092public class IntentManagerTest {
93
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -080094 private static final int SUBMIT_TIMEOUT_MS = 1000;
Brian O'Connor427a1762014-11-19 18:40:32 -080095 private static final ApplicationId APPID = new TestApplicationId("manager-test");
96
97 private IntentManager manager;
98 private MockFlowRuleService flowRuleService;
99
100 protected IntentService service;
101 protected IntentExtensionService extensionService;
Yi Tsengc927a062017-05-02 15:02:37 -0700102 protected IntentInstallCoordinator intentInstallCoordinator;
Brian O'Connor427a1762014-11-19 18:40:32 -0800103 protected TestListener listener = new TestListener();
104 protected TestIntentCompiler compiler = new TestIntentCompiler();
Yi Tsengc927a062017-05-02 15:02:37 -0700105 protected TestIntentInstaller installer;
106 protected TestIntentTracker trackerService = new TestIntentTracker();
Brian O'Connor427a1762014-11-19 18:40:32 -0800107
Ray Milkeye9a3e222014-12-03 16:46:06 -0800108 private static class TestListener implements IntentListener {
109 final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
110 Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();
111
112 @Override
113 public void event(IntentEvent event) {
114 events.put(event.type(), event);
115 if (latchMap.containsKey(event.type())) {
116 latchMap.get(event.type()).countDown();
117 }
118 }
119
120 public int getCounts(IntentEvent.Type type) {
121 return events.get(type).size();
122 }
123
124 public void setLatch(int count, IntentEvent.Type type) {
125 latchMap.put(type, new CountDownLatch(count));
126 }
127
128 public void await(IntentEvent.Type type) {
129 try {
130 assertTrue("Timed out waiting for: " + type,
131 latchMap.get(type).await(5, TimeUnit.SECONDS));
132 } catch (InterruptedException e) {
133 e.printStackTrace();
134 }
135 }
136 }
137
138 private static class TestIntentTracker implements ObjectiveTrackerService {
139 private TopologyChangeDelegate delegate;
140 @Override
141 public void setDelegate(TopologyChangeDelegate delegate) {
142 this.delegate = delegate;
143 }
144
145 @Override
146 public void unsetDelegate(TopologyChangeDelegate delegate) {
147 if (delegate.equals(this.delegate)) {
148 this.delegate = null;
149 }
150 }
151
152 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800153 public void addTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800154 //TODO
155 }
156
157 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800158 public void removeTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800159 //TODO
160 }
Thomas Vachuskac46af202015-06-03 16:43:27 -0700161
162 @Override
163 public void trackIntent(IntentData intentData) {
164 //TODO
165 }
Ray Milkeye9a3e222014-12-03 16:46:06 -0800166 }
167
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800168 private static class MockInstallableIntent extends FlowRuleIntent {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800169
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800170 public MockInstallableIntent() {
Sho SHIMIZUc3cf5bc2015-09-24 14:46:40 -0700171 super(APPID, Collections.singletonList(new MockFlowRule(100)), Collections.emptyList());
Ray Milkeye9a3e222014-12-03 16:46:06 -0800172 }
173 }
174
175 private static class TestIntentCompiler implements IntentCompiler<MockIntent> {
176 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800177 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800178 return Lists.newArrayList(new MockInstallableIntent());
Ray Milkeye9a3e222014-12-03 16:46:06 -0800179 }
180 }
181
Ray Milkey77a455f2015-03-27 10:08:17 -0700182 private static class TestIntentCompilerMultipleFlows implements IntentCompiler<MockIntent> {
183 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800184 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkey77a455f2015-03-27 10:08:17 -0700185
186 return IntStream.rangeClosed(1, 5)
187 .mapToObj(mock -> (new MockInstallableIntent()))
188 .collect(Collectors.toList());
189 }
190 }
191
192
Ray Milkeye9a3e222014-12-03 16:46:06 -0800193 private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
194 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800195 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800196 throw new IntentCompilationException("Compilation always fails");
197 }
198 }
199
Ray Milkeye9a3e222014-12-03 16:46:06 -0800200 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700201 * Hamcrest matcher to check that a collection of Intents contains an
Ray Milkeye9a3e222014-12-03 16:46:06 -0800202 * Intent with the specified Intent Id.
203 */
204 public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
205 private final IntentId id;
206
207 public EntryForIntentMatcher(IntentId idValue) {
208 id = idValue;
209 }
210
211 @Override
212 public boolean matchesSafely(Collection<Intent> intents) {
213 for (Intent intent : intents) {
214 if (intent.id().equals(id)) {
215 return true;
216 }
217 }
218 return false;
219 }
220
221 @Override
222 public void describeTo(Description description) {
223 description.appendText("an intent with id \" ").
224 appendText(id.toString()).
225 appendText("\"");
226 }
227 }
228
Yi Tsengc927a062017-05-02 15:02:37 -0700229 public static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
230
231 protected IntentExtensionService intentExtensionService;
232 protected ObjectiveTrackerService trackerService;
233 protected IntentInstallCoordinator intentInstallCoordinator;
234 protected FlowRuleService flowRuleService;
235
236 public TestIntentInstaller(IntentExtensionService intentExtensionService,
237 ObjectiveTrackerService trackerService,
238 IntentInstallCoordinator intentInstallCoordinator,
239 FlowRuleService flowRuleService) {
240 this.intentExtensionService = intentExtensionService;
241 this.trackerService = trackerService;
242 this.intentInstallCoordinator = intentInstallCoordinator;
243 this.flowRuleService = flowRuleService;
244 }
245
246 @Override
247 public void apply(IntentOperationContext<MockInstallableIntent> context) {
248 List<MockInstallableIntent> uninstallIntents = context.intentsToUninstall();
249 List<MockInstallableIntent> installIntents = context.intentsToInstall();
250
251 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
252
253 uninstallIntents.stream()
254 .map(FlowRuleIntent::flowRules)
255 .flatMap(Collection::stream)
256 .forEach(builder::remove);
257
258 installIntents.stream()
259 .map(FlowRuleIntent::flowRules)
260 .flatMap(Collection::stream)
261 .forEach(builder::add);
262
263 FlowRuleOperationsContext ctx = new FlowRuleOperationsContext() {
264 @Override
265 public void onSuccess(FlowRuleOperations ops) {
266 intentInstallCoordinator.intentInstallSuccess(context);
267 }
268
269 @Override
270 public void onError(FlowRuleOperations ops) {
271 intentInstallCoordinator.intentInstallFailed(context);
272 }
273 };
274
275 flowRuleService.apply(builder.build(ctx));
276 }
277 }
278
Ray Milkeye9a3e222014-12-03 16:46:06 -0800279 private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
280 return new EntryForIntentMatcher(id);
281 }
282
Brian O'Connor427a1762014-11-19 18:40:32 -0800283 @Before
284 public void setUp() {
285 manager = new IntentManager();
286 flowRuleService = new MockFlowRuleService();
287 manager.store = new SimpleIntentStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700288 injectEventDispatcher(manager, new TestEventDispatcher());
Yi Tsengc927a062017-05-02 15:02:37 -0700289 manager.trackerService = trackerService;
Brian O'Connor427a1762014-11-19 18:40:32 -0800290 manager.flowRuleService = flowRuleService;
Brian O'Connor520c0522014-11-23 23:50:47 -0800291 manager.coreService = new TestCoreManager();
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800292 manager.configService = mock(ComponentConfigService.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800293 service = manager;
294 extensionService = manager;
Yi Tsengc927a062017-05-02 15:02:37 -0700295 intentInstallCoordinator = manager;
296
Brian O'Connor427a1762014-11-19 18:40:32 -0800297
298 manager.activate();
299 service.addListener(listener);
300 extensionService.registerCompiler(MockIntent.class, compiler);
Brian O'Connor427a1762014-11-19 18:40:32 -0800301
Yi Tsengc927a062017-05-02 15:02:37 -0700302 installer = new TestIntentInstaller(extensionService, trackerService,
303 intentInstallCoordinator, flowRuleService);
304
305 extensionService.registerInstaller(MockInstallableIntent.class, installer);
306
Brian O'Connor427a1762014-11-19 18:40:32 -0800307 assertTrue("store should be empty",
308 Sets.newHashSet(service.getIntents()).isEmpty());
309 assertEquals(0L, flowRuleService.getFlowRuleCount());
310 }
311
Ray Milkey9f74c082015-02-11 15:40:16 -0800312 public void verifyState() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800313 // verify that all intents are parked and the batch operation is unblocked
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700314 Set<IntentState> parked = Sets.newHashSet(INSTALLED, WITHDRAWN, FAILED, CORRUPT);
Brian O'Connor427a1762014-11-19 18:40:32 -0800315 for (Intent i : service.getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800316 IntentState state = service.getIntentState(i.key());
Brian O'Connor427a1762014-11-19 18:40:32 -0800317 assertTrue("Intent " + i.id() + " is in invalid state " + state,
318 parked.contains(state));
319 }
320 //the batch has not yet been removed when we receive the last event
321 // FIXME: this doesn't guarantee to avoid the race
Brian O'Connorb499b352015-02-03 16:46:15 -0800322
323 //FIXME
324// for (int tries = 0; tries < 10; tries++) {
325// if (manager.batchService.getPendingOperations().isEmpty()) {
326// break;
327// }
328// delay(10);
329// }
330// assertTrue("There are still pending batch operations.",
331// manager.batchService.getPendingOperations().isEmpty());
Brian O'Connor427a1762014-11-19 18:40:32 -0800332
Ray Milkey9f74c082015-02-11 15:40:16 -0800333 }
334
335 @After
336 public void tearDown() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800337 extensionService.unregisterCompiler(MockIntent.class);
Yi Tsengc927a062017-05-02 15:02:37 -0700338 extensionService.unregisterInstaller(MockInstallableIntent.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800339 service.removeListener(listener);
340 manager.deactivate();
341 // TODO null the other refs?
342 }
343
344 @Test
345 public void submitIntent() {
346 flowRuleService.setFuture(true);
347
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800348 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800349 listener.setLatch(1, Type.INSTALLED);
350 Intent intent = new MockIntent(MockIntent.nextId());
351 service.submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800352 listener.await(Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800353 listener.await(Type.INSTALLED);
354 assertEquals(1L, service.getIntentCount());
355 assertEquals(1L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800356 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800357 }
358
359 @Test
360 public void withdrawIntent() {
361 flowRuleService.setFuture(true);
362
363 listener.setLatch(1, Type.INSTALLED);
364 Intent intent = new MockIntent(MockIntent.nextId());
365 service.submit(intent);
366 listener.await(Type.INSTALLED);
367 assertEquals(1L, service.getIntentCount());
368 assertEquals(1L, flowRuleService.getFlowRuleCount());
369
370 listener.setLatch(1, Type.WITHDRAWN);
371 service.withdraw(intent);
372 listener.await(Type.WITHDRAWN);
Brian O'Connor427a1762014-11-19 18:40:32 -0800373 assertEquals(0L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800374 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800375 }
376
377 @Test
Ray Milkey0811bdd2015-03-11 10:21:55 -0700378 @Ignore("This is disabled because we are seeing intermittent failures on Jenkins")
Ray Milkey9f74c082015-02-11 15:40:16 -0800379 public void stressSubmitWithdrawUnique() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800380 flowRuleService.setFuture(true);
381
382 int count = 500;
Ray Milkey9f74c082015-02-11 15:40:16 -0800383 Intent[] intents = new Intent[count];
Brian O'Connor427a1762014-11-19 18:40:32 -0800384
Brian O'Connor427a1762014-11-19 18:40:32 -0800385 listener.setLatch(count, Type.WITHDRAWN);
386
Ray Milkey9f74c082015-02-11 15:40:16 -0800387 for (int i = 0; i < count; i++) {
388 intents[i] = new MockIntent(MockIntent.nextId());
389 service.submit(intents[i]);
390 }
391
392 for (int i = 0; i < count; i++) {
393 service.withdraw(intents[i]);
394 }
395
396 listener.await(Type.WITHDRAWN);
397 assertEquals(0L, flowRuleService.getFlowRuleCount());
398 verifyState();
399 }
400
401 @Test
402 public void stressSubmitWithdrawSame() {
403 flowRuleService.setFuture(true);
404
405 int count = 50;
406
Brian O'Connor427a1762014-11-19 18:40:32 -0800407 Intent intent = new MockIntent(MockIntent.nextId());
408 for (int i = 0; i < count; i++) {
409 service.submit(intent);
410 service.withdraw(intent);
411 }
412
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -0800413 assertAfter(SUBMIT_TIMEOUT_MS, () -> {
Ray Milkey9f74c082015-02-11 15:40:16 -0800414 assertEquals(1L, service.getIntentCount());
415 assertEquals(0L, flowRuleService.getFlowRuleCount());
416 });
417 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800418 }
419
Ray Milkey9f74c082015-02-11 15:40:16 -0800420
Ray Milkey93508c22014-12-02 11:35:56 -0800421 /**
422 * Tests for proper behavior of installation of an intent that triggers
423 * a compilation error.
424 */
425 @Test
426 public void errorIntentCompile() {
427 final TestIntentCompilerError errorCompiler = new TestIntentCompilerError();
428 extensionService.registerCompiler(MockIntent.class, errorCompiler);
429 MockIntent intent = new MockIntent(MockIntent.nextId());
430 listener.setLatch(1, Type.INSTALL_REQ);
431 listener.setLatch(1, Type.FAILED);
432 service.submit(intent);
433 listener.await(Type.INSTALL_REQ);
434 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800435 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800436 }
437
438 /**
439 * Tests handling a future that contains an error as a result of
440 * installing an intent.
441 */
Ray Milkey9f74c082015-02-11 15:40:16 -0800442 @Ignore("skipping until we fix update ordering problem")
Ray Milkey93508c22014-12-02 11:35:56 -0800443 @Test
444 public void errorIntentInstallFromFlows() {
445 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800446 flowRuleService.setFuture(false);
Ray Milkey93508c22014-12-02 11:35:56 -0800447 MockIntent intent = new MockIntent(id);
448 listener.setLatch(1, Type.FAILED);
449 listener.setLatch(1, Type.INSTALL_REQ);
450 service.submit(intent);
451 listener.await(Type.INSTALL_REQ);
Ray Milkey93508c22014-12-02 11:35:56 -0800452 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800453 // FIXME the intent will be moved into INSTALLED immediately which overrides FAILED
454 // ... the updates come out of order
455 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800456 }
457
458 /**
Ray Milkeye9a3e222014-12-03 16:46:06 -0800459 * Tests handling a future that contains an unresolvable error as a result of
460 * installing an intent.
Brian O'Connor427a1762014-11-19 18:40:32 -0800461 */
Ray Milkeye9a3e222014-12-03 16:46:06 -0800462 @Test
463 public void errorIntentInstallNeverTrue() {
464 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800465 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800466 MockIntent intent = new MockIntent(id);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700467 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800468 listener.setLatch(1, Type.INSTALL_REQ);
469 service.submit(intent);
470 listener.await(Type.INSTALL_REQ);
471 // The delay here forces the retry loop in the intent manager to time out
472 delay(100);
Brian O'Connor5811ac22015-02-09 19:17:07 -0800473 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800474 service.withdraw(intent);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700475 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800476 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800477 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800478
Ray Milkeye9a3e222014-12-03 16:46:06 -0800479 /**
480 * Tests that a compiler for a subclass of an intent that already has a
481 * compiler is automatically added.
482 */
483 @Test
484 public void intentSubclassCompile() {
485 class MockIntentSubclass extends MockIntent {
486 public MockIntentSubclass(Long number) {
487 super(number);
488 }
489 }
490 flowRuleService.setFuture(true);
491
492 listener.setLatch(1, Type.INSTALL_REQ);
493 listener.setLatch(1, Type.INSTALLED);
494 Intent intent = new MockIntentSubclass(MockIntent.nextId());
495 service.submit(intent);
496 listener.await(Type.INSTALL_REQ);
497 listener.await(Type.INSTALLED);
498 assertEquals(1L, service.getIntentCount());
499 assertEquals(1L, flowRuleService.getFlowRuleCount());
500
501 final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers =
502 extensionService.getCompilers();
503 assertEquals(2, compilers.size());
504 assertNotNull(compilers.get(MockIntentSubclass.class));
505 assertNotNull(compilers.get(MockIntent.class));
Ray Milkey9f74c082015-02-11 15:40:16 -0800506 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800507 }
508
509 /**
510 * Tests an intent with no compiler.
511 */
512 @Test
513 public void intentWithoutCompiler() {
514 class IntentNoCompiler extends Intent {
515 IntentNoCompiler() {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700516 super(APPID, null, Collections.emptyList(),
517 Intent.DEFAULT_INTENT_PRIORITY);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800518 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800519 }
520
Ray Milkeye9a3e222014-12-03 16:46:06 -0800521 Intent intent = new IntentNoCompiler();
522 listener.setLatch(1, Type.INSTALL_REQ);
523 listener.setLatch(1, Type.FAILED);
524 service.submit(intent);
525 listener.await(Type.INSTALL_REQ);
526 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800527 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800528 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800529
Ray Milkeye9a3e222014-12-03 16:46:06 -0800530 /**
531 * Tests an intent with no installer.
532 */
533 @Test
534 public void intentWithoutInstaller() {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800535 MockIntent intent = new MockIntent(MockIntent.nextId());
536 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700537 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800538 service.submit(intent);
539 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700540 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800541 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800542 }
543
544 /**
545 * Tests that the intent fetching methods are correct.
546 */
547 @Test
548 public void testIntentFetching() {
549 List<Intent> intents;
550
551 flowRuleService.setFuture(true);
552
553 intents = Lists.newArrayList(service.getIntents());
554 assertThat(intents, hasSize(0));
555
556 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
557 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
558
559 listener.setLatch(2, Type.INSTALL_REQ);
560 listener.setLatch(2, Type.INSTALLED);
561 service.submit(intent1);
562 service.submit(intent2);
563 listener.await(Type.INSTALL_REQ);
564 listener.await(Type.INSTALL_REQ);
565 listener.await(Type.INSTALLED);
566 listener.await(Type.INSTALLED);
567
568 intents = Lists.newArrayList(service.getIntents());
569 assertThat(intents, hasSize(2));
570
571 assertThat(intents, hasIntentWithId(intent1.id()));
572 assertThat(intents, hasIntentWithId(intent2.id()));
Ray Milkey9f74c082015-02-11 15:40:16 -0800573 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800574 }
Ray Milkey77a455f2015-03-27 10:08:17 -0700575
576 /**
577 * Tests that removing all intents results in no flows remaining.
578 */
579 @Test
580 public void testFlowRemoval() {
581 List<Intent> intents;
582
583 flowRuleService.setFuture(true);
584
585 intents = Lists.newArrayList(service.getIntents());
586 assertThat(intents, hasSize(0));
587
588 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
589 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
590
591 listener.setLatch(1, Type.INSTALL_REQ);
592 listener.setLatch(1, Type.INSTALLED);
593
594 service.submit(intent1);
595 listener.await(Type.INSTALL_REQ);
596 listener.await(Type.INSTALLED);
597
598
599 listener.setLatch(1, Type.INSTALL_REQ);
600 listener.setLatch(1, Type.INSTALLED);
601
602 service.submit(intent2);
603 listener.await(Type.INSTALL_REQ);
604 listener.await(Type.INSTALLED);
605
606 assertThat(listener.getCounts(Type.INSTALLED), is(2));
607 assertThat(flowRuleService.getFlowRuleCount(), is(2));
608
609 listener.setLatch(1, Type.WITHDRAWN);
610 service.withdraw(intent1);
611 listener.await(Type.WITHDRAWN);
612
613 listener.setLatch(1, Type.WITHDRAWN);
614 service.withdraw(intent2);
615 listener.await(Type.WITHDRAWN);
616
617 assertThat(listener.getCounts(Type.WITHDRAWN), is(2));
618 assertThat(flowRuleService.getFlowRuleCount(), is(0));
619 }
620
621 /**
Brian O'Connor3c58e962015-04-28 23:21:51 -0700622 * Test failure to install an intent, then succeed on retry via IntentCleanup.
623 */
624 @Test
625 public void testCorruptCleanup() {
626 IntentCleanup cleanup = new IntentCleanup();
627 cleanup.service = manager;
628 cleanup.store = manager.store;
629 cleanup.cfgService = new ComponentConfigAdapter();
630
631 try {
632 cleanup.activate();
633
634 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
635 extensionService.registerCompiler(MockIntent.class, errorCompiler);
636 List<Intent> intents;
637
638 flowRuleService.setFuture(false);
639
640 intents = Lists.newArrayList(service.getIntents());
641 assertThat(intents, hasSize(0));
642
643 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
644
645 listener.setLatch(1, Type.INSTALL_REQ);
646 listener.setLatch(1, Type.CORRUPT);
647 listener.setLatch(1, Type.INSTALLED);
648
649 service.submit(intent1);
650
651 listener.await(Type.INSTALL_REQ);
652 listener.await(Type.CORRUPT);
653
654 flowRuleService.setFuture(true);
655
656 listener.await(Type.INSTALLED);
657
658 assertThat(listener.getCounts(Type.CORRUPT), is(1));
659 assertThat(listener.getCounts(Type.INSTALLED), is(1));
660 assertEquals(INSTALLED, manager.getIntentState(intent1.key()));
661 assertThat(flowRuleService.getFlowRuleCount(), is(5));
662 } finally {
663 cleanup.deactivate();
664 }
665 }
666
667 /**
Brian O'Connoreba4e342015-04-30 22:50:13 -0700668 * Test failure to install an intent, and verify retries.
669 */
670 @Test
671 public void testCorruptRetry() {
672 IntentCleanup cleanup = new IntentCleanup();
673 cleanup.service = manager;
674 cleanup.store = manager.store;
675 cleanup.cfgService = new ComponentConfigAdapter();
676 cleanup.period = 1_000_000;
677 cleanup.retryThreshold = 3;
678
679 try {
680 cleanup.activate();
681
682 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
683 extensionService.registerCompiler(MockIntent.class, errorCompiler);
684 List<Intent> intents;
685
686 flowRuleService.setFuture(false);
687
688 intents = Lists.newArrayList(service.getIntents());
689 assertThat(intents, hasSize(0));
690
691 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
692
693 listener.setLatch(1, Type.INSTALL_REQ);
694 listener.setLatch(cleanup.retryThreshold, Type.CORRUPT);
695 listener.setLatch(1, Type.INSTALLED);
696
697 service.submit(intent1);
698
699 listener.await(Type.INSTALL_REQ);
700 listener.await(Type.CORRUPT);
701 assertEquals(CORRUPT, manager.getIntentState(intent1.key()));
702 assertThat(listener.getCounts(Type.CORRUPT), is(cleanup.retryThreshold));
703
704 } finally {
705 cleanup.deactivate();
706 }
707 }
708
709 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700710 * Tests that an intent that fails installation results in no flows remaining.
711 */
712 @Test
Brian O'Connor3c58e962015-04-28 23:21:51 -0700713 @Ignore("MockFlowRule numbering issue") //test works if run independently
Ray Milkey77a455f2015-03-27 10:08:17 -0700714 public void testFlowRemovalInstallError() {
715 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
716 extensionService.registerCompiler(MockIntent.class, errorCompiler);
717 List<Intent> intents;
718
719 flowRuleService.setFuture(true);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700720 //FIXME relying on "3" is brittle
Ray Milkey77a455f2015-03-27 10:08:17 -0700721 flowRuleService.setErrorFlow(3);
722
723 intents = Lists.newArrayList(service.getIntents());
724 assertThat(intents, hasSize(0));
725
726 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
727
728 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700729 listener.setLatch(1, Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700730
731 service.submit(intent1);
732 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700733 listener.await(Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700734
Brian O'Connor3c58e962015-04-28 23:21:51 -0700735 assertThat(listener.getCounts(Type.CORRUPT), is(1));
736 // in this test, there will still be flows abandoned on the data plane
737 //assertThat(flowRuleService.getFlowRuleCount(), is(0));
Ray Milkey77a455f2015-03-27 10:08:17 -0700738 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800739}