blob: b015f24c6661ff26170efa19b99f184482e74d91 [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;
Yi Tseng24d9be72017-05-12 11:28:13 -070055import org.onosproject.net.intent.ObjectiveTrackerService;
56import org.onosproject.net.intent.TopologyChangeDelegate;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070057import org.onosproject.store.trivial.SimpleIntentStore;
Brian O'Connor427a1762014-11-19 18:40:32 -080058
Brian O'Connor3c58e962015-04-28 23:21:51 -070059import java.util.Collection;
60import java.util.Collections;
61import java.util.List;
62import java.util.Map;
63import java.util.Set;
64import java.util.concurrent.CountDownLatch;
65import java.util.concurrent.TimeUnit;
66import java.util.stream.Collectors;
67import java.util.stream.IntStream;
Brian O'Connor427a1762014-11-19 18:40:32 -080068
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -080069import static org.easymock.EasyMock.mock;
Ray Milkeye9a3e222014-12-03 16:46:06 -080070import static org.hamcrest.MatcherAssert.assertThat;
71import static org.hamcrest.Matchers.hasSize;
Ray Milkey77a455f2015-03-27 10:08:17 -070072import static org.hamcrest.Matchers.is;
Brian O'Connor3c58e962015-04-28 23:21:51 -070073import static org.junit.Assert.*;
Ray Milkey9f74c082015-02-11 15:40:16 -080074import static org.onlab.junit.TestTools.assertAfter;
Brian O'Connor427a1762014-11-19 18:40:32 -080075import static org.onlab.util.Tools.delay;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070076import static org.onosproject.net.NetTestTools.injectEventDispatcher;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070077import static org.onosproject.net.intent.IntentState.*;
Ray Milkey43a28222015-02-23 13:57:58 -080078import static org.onosproject.net.intent.IntentTestsMocks.MockFlowRule;
79import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Brian O'Connor427a1762014-11-19 18:40:32 -080080
81/**
82 * Test intent manager and transitions.
83 *
84 * TODO implement the following tests:
85 * - {submit, withdraw, update, replace} intent
Sho SHIMIZU34660962015-01-22 17:58:44 -080086 * - {submit, update, recompiling} intent with failed compilation
Brian O'Connor427a1762014-11-19 18:40:32 -080087 * - failed reservation
88 * - push timeout recovery
89 * - failed items recovery
90 *
91 * in general, verify intents store, flow store, and work queue
92 */
Ray Milkey1c166dc2015-03-02 13:32:39 -080093
Brian O'Connor427a1762014-11-19 18:40:32 -080094public class IntentManagerTest {
95
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -080096 private static final int SUBMIT_TIMEOUT_MS = 1000;
Brian O'Connor427a1762014-11-19 18:40:32 -080097 private static final ApplicationId APPID = new TestApplicationId("manager-test");
98
99 private IntentManager manager;
100 private MockFlowRuleService flowRuleService;
101
102 protected IntentService service;
103 protected IntentExtensionService extensionService;
Yi Tsengc927a062017-05-02 15:02:37 -0700104 protected IntentInstallCoordinator intentInstallCoordinator;
Brian O'Connor427a1762014-11-19 18:40:32 -0800105 protected TestListener listener = new TestListener();
106 protected TestIntentCompiler compiler = new TestIntentCompiler();
Yi Tsengc927a062017-05-02 15:02:37 -0700107 protected TestIntentInstaller installer;
108 protected TestIntentTracker trackerService = new TestIntentTracker();
Brian O'Connor427a1762014-11-19 18:40:32 -0800109
Ray Milkeye9a3e222014-12-03 16:46:06 -0800110 private static class TestListener implements IntentListener {
111 final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
112 Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();
113
114 @Override
115 public void event(IntentEvent event) {
116 events.put(event.type(), event);
117 if (latchMap.containsKey(event.type())) {
118 latchMap.get(event.type()).countDown();
119 }
120 }
121
122 public int getCounts(IntentEvent.Type type) {
123 return events.get(type).size();
124 }
125
126 public void setLatch(int count, IntentEvent.Type type) {
127 latchMap.put(type, new CountDownLatch(count));
128 }
129
130 public void await(IntentEvent.Type type) {
131 try {
132 assertTrue("Timed out waiting for: " + type,
133 latchMap.get(type).await(5, TimeUnit.SECONDS));
134 } catch (InterruptedException e) {
135 e.printStackTrace();
136 }
137 }
138 }
139
140 private static class TestIntentTracker implements ObjectiveTrackerService {
141 private TopologyChangeDelegate delegate;
142 @Override
143 public void setDelegate(TopologyChangeDelegate delegate) {
144 this.delegate = delegate;
145 }
146
147 @Override
148 public void unsetDelegate(TopologyChangeDelegate delegate) {
149 if (delegate.equals(this.delegate)) {
150 this.delegate = null;
151 }
152 }
153
154 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800155 public void addTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800156 //TODO
157 }
158
159 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800160 public void removeTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800161 //TODO
162 }
Thomas Vachuskac46af202015-06-03 16:43:27 -0700163
164 @Override
165 public void trackIntent(IntentData intentData) {
166 //TODO
167 }
Ray Milkeye9a3e222014-12-03 16:46:06 -0800168 }
169
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800170 private static class MockInstallableIntent extends FlowRuleIntent {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800171
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800172 public MockInstallableIntent() {
Sho SHIMIZUc3cf5bc2015-09-24 14:46:40 -0700173 super(APPID, Collections.singletonList(new MockFlowRule(100)), Collections.emptyList());
Ray Milkeye9a3e222014-12-03 16:46:06 -0800174 }
175 }
176
177 private static class TestIntentCompiler implements IntentCompiler<MockIntent> {
178 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800179 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800180 return Lists.newArrayList(new MockInstallableIntent());
Ray Milkeye9a3e222014-12-03 16:46:06 -0800181 }
182 }
183
Ray Milkey77a455f2015-03-27 10:08:17 -0700184 private static class TestIntentCompilerMultipleFlows implements IntentCompiler<MockIntent> {
185 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800186 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkey77a455f2015-03-27 10:08:17 -0700187
188 return IntStream.rangeClosed(1, 5)
189 .mapToObj(mock -> (new MockInstallableIntent()))
190 .collect(Collectors.toList());
191 }
192 }
193
194
Ray Milkeye9a3e222014-12-03 16:46:06 -0800195 private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
196 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800197 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800198 throw new IntentCompilationException("Compilation always fails");
199 }
200 }
201
Ray Milkeye9a3e222014-12-03 16:46:06 -0800202 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700203 * Hamcrest matcher to check that a collection of Intents contains an
Ray Milkeye9a3e222014-12-03 16:46:06 -0800204 * Intent with the specified Intent Id.
205 */
206 public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
207 private final IntentId id;
208
209 public EntryForIntentMatcher(IntentId idValue) {
210 id = idValue;
211 }
212
213 @Override
214 public boolean matchesSafely(Collection<Intent> intents) {
215 for (Intent intent : intents) {
216 if (intent.id().equals(id)) {
217 return true;
218 }
219 }
220 return false;
221 }
222
223 @Override
224 public void describeTo(Description description) {
225 description.appendText("an intent with id \" ").
226 appendText(id.toString()).
227 appendText("\"");
228 }
229 }
230
Yi Tsengc927a062017-05-02 15:02:37 -0700231 public static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
232
233 protected IntentExtensionService intentExtensionService;
234 protected ObjectiveTrackerService trackerService;
235 protected IntentInstallCoordinator intentInstallCoordinator;
236 protected FlowRuleService flowRuleService;
237
238 public TestIntentInstaller(IntentExtensionService intentExtensionService,
239 ObjectiveTrackerService trackerService,
240 IntentInstallCoordinator intentInstallCoordinator,
241 FlowRuleService flowRuleService) {
242 this.intentExtensionService = intentExtensionService;
243 this.trackerService = trackerService;
244 this.intentInstallCoordinator = intentInstallCoordinator;
245 this.flowRuleService = flowRuleService;
246 }
247
248 @Override
249 public void apply(IntentOperationContext<MockInstallableIntent> context) {
250 List<MockInstallableIntent> uninstallIntents = context.intentsToUninstall();
251 List<MockInstallableIntent> installIntents = context.intentsToInstall();
252
253 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
254
255 uninstallIntents.stream()
256 .map(FlowRuleIntent::flowRules)
257 .flatMap(Collection::stream)
258 .forEach(builder::remove);
259
260 installIntents.stream()
261 .map(FlowRuleIntent::flowRules)
262 .flatMap(Collection::stream)
263 .forEach(builder::add);
264
265 FlowRuleOperationsContext ctx = new FlowRuleOperationsContext() {
266 @Override
267 public void onSuccess(FlowRuleOperations ops) {
268 intentInstallCoordinator.intentInstallSuccess(context);
269 }
270
271 @Override
272 public void onError(FlowRuleOperations ops) {
273 intentInstallCoordinator.intentInstallFailed(context);
274 }
275 };
276
277 flowRuleService.apply(builder.build(ctx));
278 }
279 }
280
Ray Milkeye9a3e222014-12-03 16:46:06 -0800281 private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
282 return new EntryForIntentMatcher(id);
283 }
284
Brian O'Connor427a1762014-11-19 18:40:32 -0800285 @Before
286 public void setUp() {
287 manager = new IntentManager();
288 flowRuleService = new MockFlowRuleService();
289 manager.store = new SimpleIntentStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700290 injectEventDispatcher(manager, new TestEventDispatcher());
Yi Tsengc927a062017-05-02 15:02:37 -0700291 manager.trackerService = trackerService;
Brian O'Connor427a1762014-11-19 18:40:32 -0800292 manager.flowRuleService = flowRuleService;
Brian O'Connor520c0522014-11-23 23:50:47 -0800293 manager.coreService = new TestCoreManager();
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800294 manager.configService = mock(ComponentConfigService.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800295 service = manager;
296 extensionService = manager;
Yi Tsengc927a062017-05-02 15:02:37 -0700297 intentInstallCoordinator = manager;
298
Brian O'Connor427a1762014-11-19 18:40:32 -0800299
300 manager.activate();
301 service.addListener(listener);
302 extensionService.registerCompiler(MockIntent.class, compiler);
Brian O'Connor427a1762014-11-19 18:40:32 -0800303
Yi Tsengc927a062017-05-02 15:02:37 -0700304 installer = new TestIntentInstaller(extensionService, trackerService,
305 intentInstallCoordinator, flowRuleService);
306
307 extensionService.registerInstaller(MockInstallableIntent.class, installer);
308
Brian O'Connor427a1762014-11-19 18:40:32 -0800309 assertTrue("store should be empty",
310 Sets.newHashSet(service.getIntents()).isEmpty());
311 assertEquals(0L, flowRuleService.getFlowRuleCount());
312 }
313
Ray Milkey9f74c082015-02-11 15:40:16 -0800314 public void verifyState() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800315 // verify that all intents are parked and the batch operation is unblocked
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700316 Set<IntentState> parked = Sets.newHashSet(INSTALLED, WITHDRAWN, FAILED, CORRUPT);
Brian O'Connor427a1762014-11-19 18:40:32 -0800317 for (Intent i : service.getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800318 IntentState state = service.getIntentState(i.key());
Brian O'Connor427a1762014-11-19 18:40:32 -0800319 assertTrue("Intent " + i.id() + " is in invalid state " + state,
320 parked.contains(state));
321 }
322 //the batch has not yet been removed when we receive the last event
323 // FIXME: this doesn't guarantee to avoid the race
Brian O'Connorb499b352015-02-03 16:46:15 -0800324
325 //FIXME
326// for (int tries = 0; tries < 10; tries++) {
327// if (manager.batchService.getPendingOperations().isEmpty()) {
328// break;
329// }
330// delay(10);
331// }
332// assertTrue("There are still pending batch operations.",
333// manager.batchService.getPendingOperations().isEmpty());
Brian O'Connor427a1762014-11-19 18:40:32 -0800334
Ray Milkey9f74c082015-02-11 15:40:16 -0800335 }
336
337 @After
338 public void tearDown() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800339 extensionService.unregisterCompiler(MockIntent.class);
Yi Tsengc927a062017-05-02 15:02:37 -0700340 extensionService.unregisterInstaller(MockInstallableIntent.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800341 service.removeListener(listener);
342 manager.deactivate();
343 // TODO null the other refs?
344 }
345
346 @Test
347 public void submitIntent() {
348 flowRuleService.setFuture(true);
349
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800350 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800351 listener.setLatch(1, Type.INSTALLED);
352 Intent intent = new MockIntent(MockIntent.nextId());
353 service.submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800354 listener.await(Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800355 listener.await(Type.INSTALLED);
356 assertEquals(1L, service.getIntentCount());
357 assertEquals(1L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800358 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800359 }
360
361 @Test
362 public void withdrawIntent() {
363 flowRuleService.setFuture(true);
364
365 listener.setLatch(1, Type.INSTALLED);
366 Intent intent = new MockIntent(MockIntent.nextId());
367 service.submit(intent);
368 listener.await(Type.INSTALLED);
369 assertEquals(1L, service.getIntentCount());
370 assertEquals(1L, flowRuleService.getFlowRuleCount());
371
372 listener.setLatch(1, Type.WITHDRAWN);
373 service.withdraw(intent);
374 listener.await(Type.WITHDRAWN);
Brian O'Connor427a1762014-11-19 18:40:32 -0800375 assertEquals(0L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800376 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800377 }
378
379 @Test
Ray Milkey0811bdd2015-03-11 10:21:55 -0700380 @Ignore("This is disabled because we are seeing intermittent failures on Jenkins")
Ray Milkey9f74c082015-02-11 15:40:16 -0800381 public void stressSubmitWithdrawUnique() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800382 flowRuleService.setFuture(true);
383
384 int count = 500;
Ray Milkey9f74c082015-02-11 15:40:16 -0800385 Intent[] intents = new Intent[count];
Brian O'Connor427a1762014-11-19 18:40:32 -0800386
Brian O'Connor427a1762014-11-19 18:40:32 -0800387 listener.setLatch(count, Type.WITHDRAWN);
388
Ray Milkey9f74c082015-02-11 15:40:16 -0800389 for (int i = 0; i < count; i++) {
390 intents[i] = new MockIntent(MockIntent.nextId());
391 service.submit(intents[i]);
392 }
393
394 for (int i = 0; i < count; i++) {
395 service.withdraw(intents[i]);
396 }
397
398 listener.await(Type.WITHDRAWN);
399 assertEquals(0L, flowRuleService.getFlowRuleCount());
400 verifyState();
401 }
402
403 @Test
404 public void stressSubmitWithdrawSame() {
405 flowRuleService.setFuture(true);
406
407 int count = 50;
408
Brian O'Connor427a1762014-11-19 18:40:32 -0800409 Intent intent = new MockIntent(MockIntent.nextId());
410 for (int i = 0; i < count; i++) {
411 service.submit(intent);
412 service.withdraw(intent);
413 }
414
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -0800415 assertAfter(SUBMIT_TIMEOUT_MS, () -> {
Ray Milkey9f74c082015-02-11 15:40:16 -0800416 assertEquals(1L, service.getIntentCount());
417 assertEquals(0L, flowRuleService.getFlowRuleCount());
418 });
419 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800420 }
421
Ray Milkey9f74c082015-02-11 15:40:16 -0800422
Ray Milkey93508c22014-12-02 11:35:56 -0800423 /**
424 * Tests for proper behavior of installation of an intent that triggers
425 * a compilation error.
426 */
427 @Test
428 public void errorIntentCompile() {
429 final TestIntentCompilerError errorCompiler = new TestIntentCompilerError();
430 extensionService.registerCompiler(MockIntent.class, errorCompiler);
431 MockIntent intent = new MockIntent(MockIntent.nextId());
432 listener.setLatch(1, Type.INSTALL_REQ);
433 listener.setLatch(1, Type.FAILED);
434 service.submit(intent);
435 listener.await(Type.INSTALL_REQ);
436 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800437 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800438 }
439
440 /**
441 * Tests handling a future that contains an error as a result of
442 * installing an intent.
443 */
Ray Milkey9f74c082015-02-11 15:40:16 -0800444 @Ignore("skipping until we fix update ordering problem")
Ray Milkey93508c22014-12-02 11:35:56 -0800445 @Test
446 public void errorIntentInstallFromFlows() {
447 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800448 flowRuleService.setFuture(false);
Ray Milkey93508c22014-12-02 11:35:56 -0800449 MockIntent intent = new MockIntent(id);
450 listener.setLatch(1, Type.FAILED);
451 listener.setLatch(1, Type.INSTALL_REQ);
452 service.submit(intent);
453 listener.await(Type.INSTALL_REQ);
Ray Milkey93508c22014-12-02 11:35:56 -0800454 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800455 // FIXME the intent will be moved into INSTALLED immediately which overrides FAILED
456 // ... the updates come out of order
457 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800458 }
459
460 /**
Ray Milkeye9a3e222014-12-03 16:46:06 -0800461 * Tests handling a future that contains an unresolvable error as a result of
462 * installing an intent.
Brian O'Connor427a1762014-11-19 18:40:32 -0800463 */
Ray Milkeye9a3e222014-12-03 16:46:06 -0800464 @Test
465 public void errorIntentInstallNeverTrue() {
466 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800467 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800468 MockIntent intent = new MockIntent(id);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700469 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800470 listener.setLatch(1, Type.INSTALL_REQ);
471 service.submit(intent);
472 listener.await(Type.INSTALL_REQ);
473 // The delay here forces the retry loop in the intent manager to time out
474 delay(100);
Brian O'Connor5811ac22015-02-09 19:17:07 -0800475 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800476 service.withdraw(intent);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700477 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800478 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800479 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800480
Ray Milkeye9a3e222014-12-03 16:46:06 -0800481 /**
482 * Tests that a compiler for a subclass of an intent that already has a
483 * compiler is automatically added.
484 */
485 @Test
486 public void intentSubclassCompile() {
487 class MockIntentSubclass extends MockIntent {
488 public MockIntentSubclass(Long number) {
489 super(number);
490 }
491 }
492 flowRuleService.setFuture(true);
493
494 listener.setLatch(1, Type.INSTALL_REQ);
495 listener.setLatch(1, Type.INSTALLED);
496 Intent intent = new MockIntentSubclass(MockIntent.nextId());
497 service.submit(intent);
498 listener.await(Type.INSTALL_REQ);
499 listener.await(Type.INSTALLED);
500 assertEquals(1L, service.getIntentCount());
501 assertEquals(1L, flowRuleService.getFlowRuleCount());
502
503 final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers =
504 extensionService.getCompilers();
505 assertEquals(2, compilers.size());
506 assertNotNull(compilers.get(MockIntentSubclass.class));
507 assertNotNull(compilers.get(MockIntent.class));
Ray Milkey9f74c082015-02-11 15:40:16 -0800508 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800509 }
510
511 /**
512 * Tests an intent with no compiler.
513 */
514 @Test
515 public void intentWithoutCompiler() {
516 class IntentNoCompiler extends Intent {
517 IntentNoCompiler() {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700518 super(APPID, null, Collections.emptyList(),
519 Intent.DEFAULT_INTENT_PRIORITY);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800520 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800521 }
522
Ray Milkeye9a3e222014-12-03 16:46:06 -0800523 Intent intent = new IntentNoCompiler();
524 listener.setLatch(1, Type.INSTALL_REQ);
525 listener.setLatch(1, Type.FAILED);
526 service.submit(intent);
527 listener.await(Type.INSTALL_REQ);
528 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800529 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800530 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800531
Ray Milkeye9a3e222014-12-03 16:46:06 -0800532 /**
533 * Tests an intent with no installer.
534 */
535 @Test
536 public void intentWithoutInstaller() {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800537 MockIntent intent = new MockIntent(MockIntent.nextId());
538 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700539 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800540 service.submit(intent);
541 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700542 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800543 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800544 }
545
546 /**
547 * Tests that the intent fetching methods are correct.
548 */
549 @Test
550 public void testIntentFetching() {
551 List<Intent> intents;
552
553 flowRuleService.setFuture(true);
554
555 intents = Lists.newArrayList(service.getIntents());
556 assertThat(intents, hasSize(0));
557
558 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
559 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
560
561 listener.setLatch(2, Type.INSTALL_REQ);
562 listener.setLatch(2, Type.INSTALLED);
563 service.submit(intent1);
564 service.submit(intent2);
565 listener.await(Type.INSTALL_REQ);
566 listener.await(Type.INSTALL_REQ);
567 listener.await(Type.INSTALLED);
568 listener.await(Type.INSTALLED);
569
570 intents = Lists.newArrayList(service.getIntents());
571 assertThat(intents, hasSize(2));
572
573 assertThat(intents, hasIntentWithId(intent1.id()));
574 assertThat(intents, hasIntentWithId(intent2.id()));
Ray Milkey9f74c082015-02-11 15:40:16 -0800575 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800576 }
Ray Milkey77a455f2015-03-27 10:08:17 -0700577
578 /**
579 * Tests that removing all intents results in no flows remaining.
580 */
581 @Test
582 public void testFlowRemoval() {
583 List<Intent> intents;
584
585 flowRuleService.setFuture(true);
586
587 intents = Lists.newArrayList(service.getIntents());
588 assertThat(intents, hasSize(0));
589
590 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
591 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
592
593 listener.setLatch(1, Type.INSTALL_REQ);
594 listener.setLatch(1, Type.INSTALLED);
595
596 service.submit(intent1);
597 listener.await(Type.INSTALL_REQ);
598 listener.await(Type.INSTALLED);
599
600
601 listener.setLatch(1, Type.INSTALL_REQ);
602 listener.setLatch(1, Type.INSTALLED);
603
604 service.submit(intent2);
605 listener.await(Type.INSTALL_REQ);
606 listener.await(Type.INSTALLED);
607
608 assertThat(listener.getCounts(Type.INSTALLED), is(2));
609 assertThat(flowRuleService.getFlowRuleCount(), is(2));
610
611 listener.setLatch(1, Type.WITHDRAWN);
612 service.withdraw(intent1);
613 listener.await(Type.WITHDRAWN);
614
615 listener.setLatch(1, Type.WITHDRAWN);
616 service.withdraw(intent2);
617 listener.await(Type.WITHDRAWN);
618
619 assertThat(listener.getCounts(Type.WITHDRAWN), is(2));
620 assertThat(flowRuleService.getFlowRuleCount(), is(0));
621 }
622
623 /**
Brian O'Connor3c58e962015-04-28 23:21:51 -0700624 * Test failure to install an intent, then succeed on retry via IntentCleanup.
625 */
626 @Test
627 public void testCorruptCleanup() {
628 IntentCleanup cleanup = new IntentCleanup();
629 cleanup.service = manager;
630 cleanup.store = manager.store;
631 cleanup.cfgService = new ComponentConfigAdapter();
632
633 try {
634 cleanup.activate();
635
636 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
637 extensionService.registerCompiler(MockIntent.class, errorCompiler);
638 List<Intent> intents;
639
640 flowRuleService.setFuture(false);
641
642 intents = Lists.newArrayList(service.getIntents());
643 assertThat(intents, hasSize(0));
644
645 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
646
647 listener.setLatch(1, Type.INSTALL_REQ);
648 listener.setLatch(1, Type.CORRUPT);
649 listener.setLatch(1, Type.INSTALLED);
650
651 service.submit(intent1);
652
653 listener.await(Type.INSTALL_REQ);
654 listener.await(Type.CORRUPT);
655
656 flowRuleService.setFuture(true);
657
658 listener.await(Type.INSTALLED);
659
660 assertThat(listener.getCounts(Type.CORRUPT), is(1));
661 assertThat(listener.getCounts(Type.INSTALLED), is(1));
662 assertEquals(INSTALLED, manager.getIntentState(intent1.key()));
663 assertThat(flowRuleService.getFlowRuleCount(), is(5));
664 } finally {
665 cleanup.deactivate();
666 }
667 }
668
669 /**
Brian O'Connoreba4e342015-04-30 22:50:13 -0700670 * Test failure to install an intent, and verify retries.
671 */
672 @Test
673 public void testCorruptRetry() {
674 IntentCleanup cleanup = new IntentCleanup();
675 cleanup.service = manager;
676 cleanup.store = manager.store;
677 cleanup.cfgService = new ComponentConfigAdapter();
678 cleanup.period = 1_000_000;
679 cleanup.retryThreshold = 3;
680
681 try {
682 cleanup.activate();
683
684 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
685 extensionService.registerCompiler(MockIntent.class, errorCompiler);
686 List<Intent> intents;
687
688 flowRuleService.setFuture(false);
689
690 intents = Lists.newArrayList(service.getIntents());
691 assertThat(intents, hasSize(0));
692
693 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
694
695 listener.setLatch(1, Type.INSTALL_REQ);
696 listener.setLatch(cleanup.retryThreshold, Type.CORRUPT);
697 listener.setLatch(1, Type.INSTALLED);
698
699 service.submit(intent1);
700
701 listener.await(Type.INSTALL_REQ);
702 listener.await(Type.CORRUPT);
703 assertEquals(CORRUPT, manager.getIntentState(intent1.key()));
704 assertThat(listener.getCounts(Type.CORRUPT), is(cleanup.retryThreshold));
705
706 } finally {
707 cleanup.deactivate();
708 }
709 }
710
711 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700712 * Tests that an intent that fails installation results in no flows remaining.
713 */
714 @Test
Brian O'Connor3c58e962015-04-28 23:21:51 -0700715 @Ignore("MockFlowRule numbering issue") //test works if run independently
Ray Milkey77a455f2015-03-27 10:08:17 -0700716 public void testFlowRemovalInstallError() {
717 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
718 extensionService.registerCompiler(MockIntent.class, errorCompiler);
719 List<Intent> intents;
720
721 flowRuleService.setFuture(true);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700722 //FIXME relying on "3" is brittle
Ray Milkey77a455f2015-03-27 10:08:17 -0700723 flowRuleService.setErrorFlow(3);
724
725 intents = Lists.newArrayList(service.getIntents());
726 assertThat(intents, hasSize(0));
727
728 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
729
730 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700731 listener.setLatch(1, Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700732
733 service.submit(intent1);
734 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700735 listener.await(Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700736
Brian O'Connor3c58e962015-04-28 23:21:51 -0700737 assertThat(listener.getCounts(Type.CORRUPT), is(1));
738 // in this test, there will still be flows abandoned on the data plane
739 //assertThat(flowRuleService.getFlowRuleCount(), is(0));
Ray Milkey77a455f2015-03-27 10:08:17 -0700740 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800741}