blob: 14fb380370800bb20adbd0a2dae04902e1759296 [file] [log] [blame]
alshabibab984662014-12-04 18:56:18 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2014-present Open Networking Foundation
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;
Ray Milkey39f78b62018-01-05 15:17:37 -080056import org.onosproject.net.intent.PathIntent;
Yi Tseng24d9be72017-05-12 11:28:13 -070057import org.onosproject.net.intent.TopologyChangeDelegate;
Thomas Vachuskac97aa612015-06-23 16:00:18 -070058import org.onosproject.store.trivial.SimpleIntentStore;
Brian O'Connor427a1762014-11-19 18:40:32 -080059
Brian O'Connor3c58e962015-04-28 23:21:51 -070060import java.util.Collection;
61import java.util.Collections;
62import java.util.List;
63import java.util.Map;
64import java.util.Set;
65import java.util.concurrent.CountDownLatch;
66import java.util.concurrent.TimeUnit;
67import java.util.stream.Collectors;
68import java.util.stream.IntStream;
Brian O'Connor427a1762014-11-19 18:40:32 -080069
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -080070import static org.easymock.EasyMock.mock;
Ray Milkeye9a3e222014-12-03 16:46:06 -080071import static org.hamcrest.MatcherAssert.assertThat;
72import static org.hamcrest.Matchers.hasSize;
Ray Milkey77a455f2015-03-27 10:08:17 -070073import static org.hamcrest.Matchers.is;
Brian O'Connor3c58e962015-04-28 23:21:51 -070074import static org.junit.Assert.*;
Ray Milkey9f74c082015-02-11 15:40:16 -080075import static org.onlab.junit.TestTools.assertAfter;
Brian O'Connor427a1762014-11-19 18:40:32 -080076import static org.onlab.util.Tools.delay;
Thomas Vachuska42e8cce2015-07-29 19:25:18 -070077import static org.onosproject.net.NetTestTools.injectEventDispatcher;
Brian O'Connorf0c5a052015-04-27 00:34:53 -070078import static org.onosproject.net.intent.IntentState.*;
Ray Milkey43a28222015-02-23 13:57:58 -080079import static org.onosproject.net.intent.IntentTestsMocks.MockFlowRule;
80import static org.onosproject.net.intent.IntentTestsMocks.MockIntent;
Brian O'Connor427a1762014-11-19 18:40:32 -080081
82/**
83 * Test intent manager and transitions.
84 *
85 * TODO implement the following tests:
86 * - {submit, withdraw, update, replace} intent
Sho SHIMIZU34660962015-01-22 17:58:44 -080087 * - {submit, update, recompiling} intent with failed compilation
Brian O'Connor427a1762014-11-19 18:40:32 -080088 * - failed reservation
89 * - push timeout recovery
90 * - failed items recovery
91 *
92 * in general, verify intents store, flow store, and work queue
93 */
Ray Milkey1c166dc2015-03-02 13:32:39 -080094
Brian O'Connor427a1762014-11-19 18:40:32 -080095public class IntentManagerTest {
96
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -080097 private static final int SUBMIT_TIMEOUT_MS = 1000;
Brian O'Connor427a1762014-11-19 18:40:32 -080098 private static final ApplicationId APPID = new TestApplicationId("manager-test");
99
100 private IntentManager manager;
101 private MockFlowRuleService flowRuleService;
102
103 protected IntentService service;
104 protected IntentExtensionService extensionService;
Yi Tsengc927a062017-05-02 15:02:37 -0700105 protected IntentInstallCoordinator intentInstallCoordinator;
Brian O'Connor427a1762014-11-19 18:40:32 -0800106 protected TestListener listener = new TestListener();
107 protected TestIntentCompiler compiler = new TestIntentCompiler();
Yi Tsengc927a062017-05-02 15:02:37 -0700108 protected TestIntentInstaller installer;
109 protected TestIntentTracker trackerService = new TestIntentTracker();
Brian O'Connor427a1762014-11-19 18:40:32 -0800110
Ray Milkeye9a3e222014-12-03 16:46:06 -0800111 private static class TestListener implements IntentListener {
112 final Multimap<IntentEvent.Type, IntentEvent> events = HashMultimap.create();
113 Map<IntentEvent.Type, CountDownLatch> latchMap = Maps.newHashMap();
114
115 @Override
116 public void event(IntentEvent event) {
117 events.put(event.type(), event);
118 if (latchMap.containsKey(event.type())) {
119 latchMap.get(event.type()).countDown();
120 }
121 }
122
123 public int getCounts(IntentEvent.Type type) {
124 return events.get(type).size();
125 }
126
127 public void setLatch(int count, IntentEvent.Type type) {
128 latchMap.put(type, new CountDownLatch(count));
129 }
130
131 public void await(IntentEvent.Type type) {
132 try {
133 assertTrue("Timed out waiting for: " + type,
134 latchMap.get(type).await(5, TimeUnit.SECONDS));
135 } catch (InterruptedException e) {
136 e.printStackTrace();
137 }
138 }
139 }
140
141 private static class TestIntentTracker implements ObjectiveTrackerService {
142 private TopologyChangeDelegate delegate;
143 @Override
144 public void setDelegate(TopologyChangeDelegate delegate) {
145 this.delegate = delegate;
146 }
147
148 @Override
149 public void unsetDelegate(TopologyChangeDelegate delegate) {
150 if (delegate.equals(this.delegate)) {
151 this.delegate = null;
152 }
153 }
154
155 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800156 public void addTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800157 //TODO
158 }
159
160 @Override
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800161 public void removeTrackedResources(Key key, Collection<NetworkResource> resources) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800162 //TODO
163 }
Thomas Vachuskac46af202015-06-03 16:43:27 -0700164
165 @Override
166 public void trackIntent(IntentData intentData) {
167 //TODO
168 }
Ray Milkeye9a3e222014-12-03 16:46:06 -0800169 }
170
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800171 private static class MockInstallableIntent extends FlowRuleIntent {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800172
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800173 public MockInstallableIntent() {
Ray Milkey39f78b62018-01-05 15:17:37 -0800174 super(APPID, null, Collections.singletonList(new MockFlowRule(100)), Collections.emptyList(),
175 PathIntent.ProtectionType.PRIMARY, null);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800176 }
177 }
178
179 private static class TestIntentCompiler implements IntentCompiler<MockIntent> {
180 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800181 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Sho SHIMIZUee2aa652015-02-25 18:56:43 -0800182 return Lists.newArrayList(new MockInstallableIntent());
Ray Milkeye9a3e222014-12-03 16:46:06 -0800183 }
184 }
185
Ray Milkey77a455f2015-03-27 10:08:17 -0700186 private static class TestIntentCompilerMultipleFlows implements IntentCompiler<MockIntent> {
187 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800188 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkey77a455f2015-03-27 10:08:17 -0700189
190 return IntStream.rangeClosed(1, 5)
191 .mapToObj(mock -> (new MockInstallableIntent()))
192 .collect(Collectors.toList());
193 }
194 }
195
196
Ray Milkeye9a3e222014-12-03 16:46:06 -0800197 private static class TestIntentCompilerError implements IntentCompiler<MockIntent> {
198 @Override
Sho SHIMIZUec07ffd2016-02-22 20:45:21 -0800199 public List<Intent> compile(MockIntent intent, List<Intent> installable) {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800200 throw new IntentCompilationException("Compilation always fails");
201 }
202 }
203
Ray Milkeye9a3e222014-12-03 16:46:06 -0800204 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700205 * Hamcrest matcher to check that a collection of Intents contains an
Ray Milkeye9a3e222014-12-03 16:46:06 -0800206 * Intent with the specified Intent Id.
207 */
208 public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
209 private final IntentId id;
210
211 public EntryForIntentMatcher(IntentId idValue) {
212 id = idValue;
213 }
214
215 @Override
216 public boolean matchesSafely(Collection<Intent> intents) {
217 for (Intent intent : intents) {
218 if (intent.id().equals(id)) {
219 return true;
220 }
221 }
222 return false;
223 }
224
225 @Override
226 public void describeTo(Description description) {
227 description.appendText("an intent with id \" ").
228 appendText(id.toString()).
229 appendText("\"");
230 }
231 }
232
Yi Tsengc927a062017-05-02 15:02:37 -0700233 public static class TestIntentInstaller implements IntentInstaller<MockInstallableIntent> {
234
235 protected IntentExtensionService intentExtensionService;
236 protected ObjectiveTrackerService trackerService;
237 protected IntentInstallCoordinator intentInstallCoordinator;
238 protected FlowRuleService flowRuleService;
239
240 public TestIntentInstaller(IntentExtensionService intentExtensionService,
241 ObjectiveTrackerService trackerService,
242 IntentInstallCoordinator intentInstallCoordinator,
243 FlowRuleService flowRuleService) {
244 this.intentExtensionService = intentExtensionService;
245 this.trackerService = trackerService;
246 this.intentInstallCoordinator = intentInstallCoordinator;
247 this.flowRuleService = flowRuleService;
248 }
249
250 @Override
251 public void apply(IntentOperationContext<MockInstallableIntent> context) {
252 List<MockInstallableIntent> uninstallIntents = context.intentsToUninstall();
253 List<MockInstallableIntent> installIntents = context.intentsToInstall();
254
255 FlowRuleOperations.Builder builder = FlowRuleOperations.builder();
256
257 uninstallIntents.stream()
258 .map(FlowRuleIntent::flowRules)
259 .flatMap(Collection::stream)
260 .forEach(builder::remove);
261
262 installIntents.stream()
263 .map(FlowRuleIntent::flowRules)
264 .flatMap(Collection::stream)
265 .forEach(builder::add);
266
267 FlowRuleOperationsContext ctx = new FlowRuleOperationsContext() {
268 @Override
269 public void onSuccess(FlowRuleOperations ops) {
270 intentInstallCoordinator.intentInstallSuccess(context);
271 }
272
273 @Override
274 public void onError(FlowRuleOperations ops) {
275 intentInstallCoordinator.intentInstallFailed(context);
276 }
277 };
278
279 flowRuleService.apply(builder.build(ctx));
280 }
281 }
282
Ray Milkeye9a3e222014-12-03 16:46:06 -0800283 private static EntryForIntentMatcher hasIntentWithId(IntentId id) {
284 return new EntryForIntentMatcher(id);
285 }
286
Brian O'Connor427a1762014-11-19 18:40:32 -0800287 @Before
288 public void setUp() {
289 manager = new IntentManager();
290 flowRuleService = new MockFlowRuleService();
291 manager.store = new SimpleIntentStore();
Thomas Vachuska42e8cce2015-07-29 19:25:18 -0700292 injectEventDispatcher(manager, new TestEventDispatcher());
Yi Tsengc927a062017-05-02 15:02:37 -0700293 manager.trackerService = trackerService;
Brian O'Connor427a1762014-11-19 18:40:32 -0800294 manager.flowRuleService = flowRuleService;
Brian O'Connor520c0522014-11-23 23:50:47 -0800295 manager.coreService = new TestCoreManager();
Sho SHIMIZUd5bf1062016-02-25 10:26:02 -0800296 manager.configService = mock(ComponentConfigService.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800297 service = manager;
298 extensionService = manager;
Yi Tsengc927a062017-05-02 15:02:37 -0700299 intentInstallCoordinator = manager;
300
Brian O'Connor427a1762014-11-19 18:40:32 -0800301
302 manager.activate();
303 service.addListener(listener);
304 extensionService.registerCompiler(MockIntent.class, compiler);
Brian O'Connor427a1762014-11-19 18:40:32 -0800305
Yi Tsengc927a062017-05-02 15:02:37 -0700306 installer = new TestIntentInstaller(extensionService, trackerService,
307 intentInstallCoordinator, flowRuleService);
308
309 extensionService.registerInstaller(MockInstallableIntent.class, installer);
310
Brian O'Connor427a1762014-11-19 18:40:32 -0800311 assertTrue("store should be empty",
312 Sets.newHashSet(service.getIntents()).isEmpty());
313 assertEquals(0L, flowRuleService.getFlowRuleCount());
314 }
315
Ray Milkey9f74c082015-02-11 15:40:16 -0800316 public void verifyState() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800317 // verify that all intents are parked and the batch operation is unblocked
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700318 Set<IntentState> parked = Sets.newHashSet(INSTALLED, WITHDRAWN, FAILED, CORRUPT);
Brian O'Connor427a1762014-11-19 18:40:32 -0800319 for (Intent i : service.getIntents()) {
Ray Milkeyf9af43c2015-02-09 16:45:48 -0800320 IntentState state = service.getIntentState(i.key());
Brian O'Connor427a1762014-11-19 18:40:32 -0800321 assertTrue("Intent " + i.id() + " is in invalid state " + state,
322 parked.contains(state));
323 }
324 //the batch has not yet been removed when we receive the last event
325 // FIXME: this doesn't guarantee to avoid the race
Brian O'Connorb499b352015-02-03 16:46:15 -0800326
327 //FIXME
328// for (int tries = 0; tries < 10; tries++) {
329// if (manager.batchService.getPendingOperations().isEmpty()) {
330// break;
331// }
332// delay(10);
333// }
334// assertTrue("There are still pending batch operations.",
335// manager.batchService.getPendingOperations().isEmpty());
Brian O'Connor427a1762014-11-19 18:40:32 -0800336
Ray Milkey9f74c082015-02-11 15:40:16 -0800337 }
338
339 @After
340 public void tearDown() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800341 extensionService.unregisterCompiler(MockIntent.class);
Yi Tsengc927a062017-05-02 15:02:37 -0700342 extensionService.unregisterInstaller(MockInstallableIntent.class);
Brian O'Connor427a1762014-11-19 18:40:32 -0800343 service.removeListener(listener);
344 manager.deactivate();
345 // TODO null the other refs?
346 }
347
348 @Test
349 public void submitIntent() {
350 flowRuleService.setFuture(true);
351
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800352 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800353 listener.setLatch(1, Type.INSTALLED);
354 Intent intent = new MockIntent(MockIntent.nextId());
355 service.submit(intent);
Brian O'Connor7a71d5d2014-12-02 00:12:27 -0800356 listener.await(Type.INSTALL_REQ);
Brian O'Connor427a1762014-11-19 18:40:32 -0800357 listener.await(Type.INSTALLED);
358 assertEquals(1L, service.getIntentCount());
359 assertEquals(1L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800360 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800361 }
362
363 @Test
364 public void withdrawIntent() {
365 flowRuleService.setFuture(true);
366
367 listener.setLatch(1, Type.INSTALLED);
368 Intent intent = new MockIntent(MockIntent.nextId());
369 service.submit(intent);
370 listener.await(Type.INSTALLED);
371 assertEquals(1L, service.getIntentCount());
372 assertEquals(1L, flowRuleService.getFlowRuleCount());
373
374 listener.setLatch(1, Type.WITHDRAWN);
375 service.withdraw(intent);
376 listener.await(Type.WITHDRAWN);
Brian O'Connor427a1762014-11-19 18:40:32 -0800377 assertEquals(0L, flowRuleService.getFlowRuleCount());
Ray Milkey9f74c082015-02-11 15:40:16 -0800378 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800379 }
380
381 @Test
Ray Milkey0811bdd2015-03-11 10:21:55 -0700382 @Ignore("This is disabled because we are seeing intermittent failures on Jenkins")
Ray Milkey9f74c082015-02-11 15:40:16 -0800383 public void stressSubmitWithdrawUnique() {
Brian O'Connor427a1762014-11-19 18:40:32 -0800384 flowRuleService.setFuture(true);
385
386 int count = 500;
Ray Milkey9f74c082015-02-11 15:40:16 -0800387 Intent[] intents = new Intent[count];
Brian O'Connor427a1762014-11-19 18:40:32 -0800388
Brian O'Connor427a1762014-11-19 18:40:32 -0800389 listener.setLatch(count, Type.WITHDRAWN);
390
Ray Milkey9f74c082015-02-11 15:40:16 -0800391 for (int i = 0; i < count; i++) {
392 intents[i] = new MockIntent(MockIntent.nextId());
393 service.submit(intents[i]);
394 }
395
396 for (int i = 0; i < count; i++) {
397 service.withdraw(intents[i]);
398 }
399
400 listener.await(Type.WITHDRAWN);
401 assertEquals(0L, flowRuleService.getFlowRuleCount());
402 verifyState();
403 }
404
405 @Test
406 public void stressSubmitWithdrawSame() {
407 flowRuleService.setFuture(true);
408
409 int count = 50;
410
Brian O'Connor427a1762014-11-19 18:40:32 -0800411 Intent intent = new MockIntent(MockIntent.nextId());
412 for (int i = 0; i < count; i++) {
413 service.submit(intent);
414 service.withdraw(intent);
415 }
416
Pavlin Radoslavov35b4ecb2015-03-03 15:06:04 -0800417 assertAfter(SUBMIT_TIMEOUT_MS, () -> {
Ray Milkey9f74c082015-02-11 15:40:16 -0800418 assertEquals(1L, service.getIntentCount());
419 assertEquals(0L, flowRuleService.getFlowRuleCount());
420 });
421 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800422 }
423
Ray Milkey9f74c082015-02-11 15:40:16 -0800424
Ray Milkey93508c22014-12-02 11:35:56 -0800425 /**
426 * Tests for proper behavior of installation of an intent that triggers
427 * a compilation error.
428 */
429 @Test
430 public void errorIntentCompile() {
431 final TestIntentCompilerError errorCompiler = new TestIntentCompilerError();
432 extensionService.registerCompiler(MockIntent.class, errorCompiler);
433 MockIntent intent = new MockIntent(MockIntent.nextId());
434 listener.setLatch(1, Type.INSTALL_REQ);
435 listener.setLatch(1, Type.FAILED);
436 service.submit(intent);
437 listener.await(Type.INSTALL_REQ);
438 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800439 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800440 }
441
442 /**
443 * Tests handling a future that contains an error as a result of
444 * installing an intent.
445 */
Ray Milkey9f74c082015-02-11 15:40:16 -0800446 @Ignore("skipping until we fix update ordering problem")
Ray Milkey93508c22014-12-02 11:35:56 -0800447 @Test
448 public void errorIntentInstallFromFlows() {
449 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800450 flowRuleService.setFuture(false);
Ray Milkey93508c22014-12-02 11:35:56 -0800451 MockIntent intent = new MockIntent(id);
452 listener.setLatch(1, Type.FAILED);
453 listener.setLatch(1, Type.INSTALL_REQ);
454 service.submit(intent);
455 listener.await(Type.INSTALL_REQ);
Ray Milkey93508c22014-12-02 11:35:56 -0800456 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800457 // FIXME the intent will be moved into INSTALLED immediately which overrides FAILED
458 // ... the updates come out of order
459 verifyState();
Ray Milkey93508c22014-12-02 11:35:56 -0800460 }
461
462 /**
Ray Milkeye9a3e222014-12-03 16:46:06 -0800463 * Tests handling a future that contains an unresolvable error as a result of
464 * installing an intent.
Brian O'Connor427a1762014-11-19 18:40:32 -0800465 */
Ray Milkeye9a3e222014-12-03 16:46:06 -0800466 @Test
467 public void errorIntentInstallNeverTrue() {
468 final Long id = MockIntent.nextId();
Brian O'Connor5811ac22015-02-09 19:17:07 -0800469 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800470 MockIntent intent = new MockIntent(id);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700471 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800472 listener.setLatch(1, Type.INSTALL_REQ);
473 service.submit(intent);
474 listener.await(Type.INSTALL_REQ);
475 // The delay here forces the retry loop in the intent manager to time out
476 delay(100);
Brian O'Connor5811ac22015-02-09 19:17:07 -0800477 flowRuleService.setFuture(false);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800478 service.withdraw(intent);
Brian O'Connorf0c5a052015-04-27 00:34:53 -0700479 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800480 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800481 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800482
Ray Milkeye9a3e222014-12-03 16:46:06 -0800483 /**
484 * Tests that a compiler for a subclass of an intent that already has a
485 * compiler is automatically added.
486 */
487 @Test
488 public void intentSubclassCompile() {
489 class MockIntentSubclass extends MockIntent {
490 public MockIntentSubclass(Long number) {
491 super(number);
492 }
493 }
494 flowRuleService.setFuture(true);
495
496 listener.setLatch(1, Type.INSTALL_REQ);
497 listener.setLatch(1, Type.INSTALLED);
498 Intent intent = new MockIntentSubclass(MockIntent.nextId());
499 service.submit(intent);
500 listener.await(Type.INSTALL_REQ);
501 listener.await(Type.INSTALLED);
502 assertEquals(1L, service.getIntentCount());
503 assertEquals(1L, flowRuleService.getFlowRuleCount());
504
505 final Map<Class<? extends Intent>, IntentCompiler<? extends Intent>> compilers =
506 extensionService.getCompilers();
507 assertEquals(2, compilers.size());
508 assertNotNull(compilers.get(MockIntentSubclass.class));
509 assertNotNull(compilers.get(MockIntent.class));
Ray Milkey9f74c082015-02-11 15:40:16 -0800510 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800511 }
512
513 /**
514 * Tests an intent with no compiler.
515 */
516 @Test
517 public void intentWithoutCompiler() {
518 class IntentNoCompiler extends Intent {
519 IntentNoCompiler() {
Ray Milkeyebc5d222015-03-18 15:45:36 -0700520 super(APPID, null, Collections.emptyList(),
Ray Milkey39f78b62018-01-05 15:17:37 -0800521 Intent.DEFAULT_INTENT_PRIORITY, null);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800522 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800523 }
524
Ray Milkeye9a3e222014-12-03 16:46:06 -0800525 Intent intent = new IntentNoCompiler();
526 listener.setLatch(1, Type.INSTALL_REQ);
527 listener.setLatch(1, Type.FAILED);
528 service.submit(intent);
529 listener.await(Type.INSTALL_REQ);
530 listener.await(Type.FAILED);
Ray Milkey9f74c082015-02-11 15:40:16 -0800531 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800532 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800533
Ray Milkeye9a3e222014-12-03 16:46:06 -0800534 /**
535 * Tests an intent with no installer.
536 */
537 @Test
538 public void intentWithoutInstaller() {
Ray Milkeye9a3e222014-12-03 16:46:06 -0800539 MockIntent intent = new MockIntent(MockIntent.nextId());
540 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700541 listener.setLatch(1, Type.CORRUPT);
Ray Milkeye9a3e222014-12-03 16:46:06 -0800542 service.submit(intent);
543 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700544 listener.await(Type.CORRUPT);
Ray Milkey9f74c082015-02-11 15:40:16 -0800545 verifyState();
Ray Milkeye9a3e222014-12-03 16:46:06 -0800546 }
547
548 /**
549 * Tests that the intent fetching methods are correct.
550 */
551 @Test
552 public void testIntentFetching() {
553 List<Intent> intents;
554
555 flowRuleService.setFuture(true);
556
557 intents = Lists.newArrayList(service.getIntents());
558 assertThat(intents, hasSize(0));
559
560 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
561 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
562
563 listener.setLatch(2, Type.INSTALL_REQ);
564 listener.setLatch(2, Type.INSTALLED);
565 service.submit(intent1);
566 service.submit(intent2);
567 listener.await(Type.INSTALL_REQ);
568 listener.await(Type.INSTALL_REQ);
569 listener.await(Type.INSTALLED);
570 listener.await(Type.INSTALLED);
571
572 intents = Lists.newArrayList(service.getIntents());
573 assertThat(intents, hasSize(2));
574
575 assertThat(intents, hasIntentWithId(intent1.id()));
576 assertThat(intents, hasIntentWithId(intent2.id()));
Ray Milkey9f74c082015-02-11 15:40:16 -0800577 verifyState();
Brian O'Connor427a1762014-11-19 18:40:32 -0800578 }
Ray Milkey77a455f2015-03-27 10:08:17 -0700579
580 /**
581 * Tests that removing all intents results in no flows remaining.
582 */
583 @Test
584 public void testFlowRemoval() {
585 List<Intent> intents;
586
587 flowRuleService.setFuture(true);
588
589 intents = Lists.newArrayList(service.getIntents());
590 assertThat(intents, hasSize(0));
591
592 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
593 final MockIntent intent2 = new MockIntent(MockIntent.nextId());
594
595 listener.setLatch(1, Type.INSTALL_REQ);
596 listener.setLatch(1, Type.INSTALLED);
597
598 service.submit(intent1);
599 listener.await(Type.INSTALL_REQ);
600 listener.await(Type.INSTALLED);
601
602
603 listener.setLatch(1, Type.INSTALL_REQ);
604 listener.setLatch(1, Type.INSTALLED);
605
606 service.submit(intent2);
607 listener.await(Type.INSTALL_REQ);
608 listener.await(Type.INSTALLED);
609
610 assertThat(listener.getCounts(Type.INSTALLED), is(2));
611 assertThat(flowRuleService.getFlowRuleCount(), is(2));
612
613 listener.setLatch(1, Type.WITHDRAWN);
614 service.withdraw(intent1);
615 listener.await(Type.WITHDRAWN);
616
617 listener.setLatch(1, Type.WITHDRAWN);
618 service.withdraw(intent2);
619 listener.await(Type.WITHDRAWN);
620
621 assertThat(listener.getCounts(Type.WITHDRAWN), is(2));
622 assertThat(flowRuleService.getFlowRuleCount(), is(0));
623 }
624
625 /**
Brian O'Connor3c58e962015-04-28 23:21:51 -0700626 * Test failure to install an intent, then succeed on retry via IntentCleanup.
627 */
628 @Test
629 public void testCorruptCleanup() {
630 IntentCleanup cleanup = new IntentCleanup();
631 cleanup.service = manager;
632 cleanup.store = manager.store;
633 cleanup.cfgService = new ComponentConfigAdapter();
634
635 try {
636 cleanup.activate();
637
638 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
639 extensionService.registerCompiler(MockIntent.class, errorCompiler);
640 List<Intent> intents;
641
642 flowRuleService.setFuture(false);
643
644 intents = Lists.newArrayList(service.getIntents());
645 assertThat(intents, hasSize(0));
646
647 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
648
649 listener.setLatch(1, Type.INSTALL_REQ);
650 listener.setLatch(1, Type.CORRUPT);
651 listener.setLatch(1, Type.INSTALLED);
652
653 service.submit(intent1);
654
655 listener.await(Type.INSTALL_REQ);
656 listener.await(Type.CORRUPT);
657
658 flowRuleService.setFuture(true);
659
660 listener.await(Type.INSTALLED);
661
662 assertThat(listener.getCounts(Type.CORRUPT), is(1));
663 assertThat(listener.getCounts(Type.INSTALLED), is(1));
664 assertEquals(INSTALLED, manager.getIntentState(intent1.key()));
665 assertThat(flowRuleService.getFlowRuleCount(), is(5));
666 } finally {
667 cleanup.deactivate();
668 }
669 }
670
671 /**
Brian O'Connoreba4e342015-04-30 22:50:13 -0700672 * Test failure to install an intent, and verify retries.
673 */
674 @Test
675 public void testCorruptRetry() {
676 IntentCleanup cleanup = new IntentCleanup();
677 cleanup.service = manager;
678 cleanup.store = manager.store;
679 cleanup.cfgService = new ComponentConfigAdapter();
680 cleanup.period = 1_000_000;
681 cleanup.retryThreshold = 3;
682
683 try {
684 cleanup.activate();
685
686 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
687 extensionService.registerCompiler(MockIntent.class, errorCompiler);
688 List<Intent> intents;
689
690 flowRuleService.setFuture(false);
691
692 intents = Lists.newArrayList(service.getIntents());
693 assertThat(intents, hasSize(0));
694
695 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
696
697 listener.setLatch(1, Type.INSTALL_REQ);
698 listener.setLatch(cleanup.retryThreshold, Type.CORRUPT);
699 listener.setLatch(1, Type.INSTALLED);
700
701 service.submit(intent1);
702
703 listener.await(Type.INSTALL_REQ);
704 listener.await(Type.CORRUPT);
705 assertEquals(CORRUPT, manager.getIntentState(intent1.key()));
706 assertThat(listener.getCounts(Type.CORRUPT), is(cleanup.retryThreshold));
707
708 } finally {
709 cleanup.deactivate();
710 }
711 }
712
713 /**
Ray Milkey77a455f2015-03-27 10:08:17 -0700714 * Tests that an intent that fails installation results in no flows remaining.
715 */
716 @Test
Brian O'Connor3c58e962015-04-28 23:21:51 -0700717 @Ignore("MockFlowRule numbering issue") //test works if run independently
Ray Milkey77a455f2015-03-27 10:08:17 -0700718 public void testFlowRemovalInstallError() {
719 final TestIntentCompilerMultipleFlows errorCompiler = new TestIntentCompilerMultipleFlows();
720 extensionService.registerCompiler(MockIntent.class, errorCompiler);
721 List<Intent> intents;
722
723 flowRuleService.setFuture(true);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700724 //FIXME relying on "3" is brittle
Ray Milkey77a455f2015-03-27 10:08:17 -0700725 flowRuleService.setErrorFlow(3);
726
727 intents = Lists.newArrayList(service.getIntents());
728 assertThat(intents, hasSize(0));
729
730 final MockIntent intent1 = new MockIntent(MockIntent.nextId());
731
732 listener.setLatch(1, Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700733 listener.setLatch(1, Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700734
735 service.submit(intent1);
736 listener.await(Type.INSTALL_REQ);
Brian O'Connor3c58e962015-04-28 23:21:51 -0700737 listener.await(Type.CORRUPT);
Ray Milkey77a455f2015-03-27 10:08:17 -0700738
Brian O'Connor3c58e962015-04-28 23:21:51 -0700739 assertThat(listener.getCounts(Type.CORRUPT), is(1));
740 // in this test, there will still be flows abandoned on the data plane
741 //assertThat(flowRuleService.getFlowRuleCount(), is(0));
Ray Milkey77a455f2015-03-27 10:08:17 -0700742 }
Brian O'Connor427a1762014-11-19 18:40:32 -0800743}