blob: f3416284b2b0b163112645b83ef949ad9d44a2e6 [file] [log] [blame]
Jonathan Hartaa380972014-04-03 10:24:46 -07001package net.onrc.onos.core.intent.runtime;
Ray Milkey6688cd82014-03-11 16:40:46 -07002
Jonathan Harta88fd242014-04-03 11:24:54 -07003import static org.hamcrest.MatcherAssert.assertThat;
4import static org.hamcrest.Matchers.equalTo;
5import static org.hamcrest.Matchers.hasItem;
6import static org.hamcrest.Matchers.hasSize;
Pavlin Radoslavove2238bc2014-06-09 18:05:23 -07007import static org.hamcrest.Matchers.not;
Jonathan Harta88fd242014-04-03 11:24:54 -07008import static org.hamcrest.Matchers.notNullValue;
9
10import java.util.Collection;
11import java.util.LinkedList;
12import java.util.List;
13
Ray Milkey6688cd82014-03-11 16:40:46 -070014import net.floodlightcontroller.core.module.FloodlightModuleContext;
Jonathan Hartaa380972014-04-03 10:24:46 -070015import net.onrc.onos.core.intent.Intent;
Jonathan Harta88fd242014-04-03 11:24:54 -070016import net.onrc.onos.core.intent.Intent.IntentState;
Jonathan Hartaa380972014-04-03 10:24:46 -070017import net.onrc.onos.core.intent.IntentMap;
Jonathan Harta88fd242014-04-03 11:24:54 -070018import net.onrc.onos.core.intent.IntentOperation.Operator;
Jonathan Hartaa380972014-04-03 10:24:46 -070019import net.onrc.onos.core.intent.IntentOperationList;
Jonathan Harte37e4e22014-05-13 19:12:02 -070020import net.onrc.onos.core.intent.MockTopology;
Jonathan Hartaa380972014-04-03 10:24:46 -070021import net.onrc.onos.core.intent.ShortestPathIntent;
Jonathan Hart472062d2014-04-03 10:56:48 -070022import net.onrc.onos.core.topology.DeviceEvent;
Jonathan Hart472062d2014-04-03 10:56:48 -070023import net.onrc.onos.core.topology.LinkEvent;
24import net.onrc.onos.core.topology.PortEvent;
25import net.onrc.onos.core.topology.SwitchEvent;
Ray Milkey6688cd82014-03-11 16:40:46 -070026
Jonathan Harta88fd242014-04-03 11:24:54 -070027import org.hamcrest.Description;
28import org.hamcrest.Factory;
29import org.hamcrest.Matcher;
30import org.hamcrest.Matchers;
31import org.hamcrest.TypeSafeMatcher;
Ray Milkey6688cd82014-03-11 16:40:46 -070032import org.junit.After;
33import org.junit.Before;
34import org.junit.Test;
35import org.junit.runner.RunWith;
Ray Milkey6688cd82014-03-11 16:40:46 -070036import org.powermock.core.classloader.annotations.PrepareForTest;
37import org.powermock.modules.junit4.PowerMockRunner;
38
Ray Milkey6688cd82014-03-11 16:40:46 -070039/**
40 * @author Ray Milkey (ray@onlab.us)
Ray Milkey269ffb92014-04-03 14:43:30 -070041 * <p/>
42 * Unit tests for the Path Calculation Runtime module (PathCalcRuntimeModule).
43 * These test cases check the results of creating paths, deleting paths, and
Jonathan Harte37e4e22014-05-13 19:12:02 -070044 * rerouting paths. The topology, controller registry, and data grid are
Ray Milkey269ffb92014-04-03 14:43:30 -070045 * mocked out. The individual tests check the high level intents and the
46 * resulting operation lists to be sure they match the intended APIs.
Ray Milkey6688cd82014-03-11 16:40:46 -070047 */
48@RunWith(PowerMockRunner.class)
49@PrepareForTest(PathCalcRuntimeModule.class)
50public class PathCalcRuntimeModuleTest {
Ray Milkeydc659c42014-03-28 16:30:42 -070051 private static final Long LOCAL_PORT = 0xFFFEL;
52
Ray Milkey9d671002014-05-29 17:24:29 -070053 private IntentTestMocks mocks;
54 private PathCalcRuntimeModule runtime;
Ray Milkey6688cd82014-03-11 16:40:46 -070055
Ray Milkey6688cd82014-03-11 16:40:46 -070056 @Before
57 public void setUp() throws Exception {
Ray Milkey9d671002014-05-29 17:24:29 -070058 mocks = new IntentTestMocks();
59 mocks.setUpIntentMocks();
Ray Milkey6688cd82014-03-11 16:40:46 -070060
Ray Milkey9d671002014-05-29 17:24:29 -070061 runtime = new PathCalcRuntimeModule();
62 final FloodlightModuleContext moduleContext = mocks.getModuleContext();
63 runtime.init(moduleContext);
64 runtime.startUp(moduleContext);
Ray Milkey6688cd82014-03-11 16:40:46 -070065 }
66
Ray Milkeydc659c42014-03-28 16:30:42 -070067
68 /**
69 * Hamcrest matcher to check that a collection of Intents contains an
70 * Intent with the specified Intent Id.
71 */
72 public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070073 private final String id;
Ray Milkeydc659c42014-03-28 16:30:42 -070074
75 public EntryForIntentMatcher(String idValue) {
76 id = idValue;
77 }
78
79 @Override
80 public boolean matchesSafely(Collection<Intent> intents) {
Pavlin Radoslavove2238bc2014-06-09 18:05:23 -070081 return hasItem(Matchers.<Intent>hasProperty("id", equalTo(id))).matches(intents);
Ray Milkeydc659c42014-03-28 16:30:42 -070082 }
83
84 @Override
85 public void describeTo(Description description) {
86 description.appendText("an intent with id \" ").
87 appendText(id).
88 appendText("\"");
89 }
90 }
91
92
93 /**
94 * Factory method to create an Intent entry Matcher. Returns a matcher
95 * for the Intent with the given id.
Ray Milkey269ffb92014-04-03 14:43:30 -070096 *
Ray Milkeydc659c42014-03-28 16:30:42 -070097 * @param id id of the intent to match
98 * @return Matcher object
99 */
100 @Factory
101 public static Matcher<Collection<Intent>> hasIntentWithId(String id) {
102 return new EntryForIntentMatcher(id);
103 }
104
105
106 /**
107 * Matcher to determine if an IntentMap contains an entry with a given id,
108 * and that entry has a given state.
109 */
110 public static class IntentsHaveIntentWithStateMatcher extends TypeSafeMatcher<IntentMap> {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700111 private final String id;
112 private final IntentState state;
Ray Milkeydc659c42014-03-28 16:30:42 -0700113 private Intent intent;
114
115 public IntentsHaveIntentWithStateMatcher(String idValue,
116 IntentState stateValue) {
117 id = idValue;
118 state = stateValue;
119 }
120
121 @Override
122 public boolean matchesSafely(IntentMap intents) {
123 intent = intents.getIntent(id);
124
125 return intent != null && intent.getState() == state;
126 }
127
128 @Override
129 public void describeTo(Description description) {
130 if (intent == null) {
131 description.appendText("intent lookup for id \"");
132 description.appendText(id);
133 description.appendText("\"");
134 } else {
135 description.appendText("state ");
136 description.appendText(state.toString());
137 }
138 }
139
140 @Override
141 public void describeMismatchSafely(IntentMap intents,
142 Description mismatchDescription) {
143 if (intent != null) {
144 mismatchDescription.appendText("was ").
Ray Milkey269ffb92014-04-03 14:43:30 -0700145 appendText(intent.getState().toString());
Ray Milkeydc659c42014-03-28 16:30:42 -0700146 } else {
147 mismatchDescription.appendText("that intent was not found");
148 }
149 }
150 }
151
152
153 /**
154 * Factory method to create a Matcher for an IntentMap that looks for an
155 * Intent with a given id and state.
156 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700157 * @param id id of the Intent to match
Ray Milkeydc659c42014-03-28 16:30:42 -0700158 * @param state if the Intent is found, its state must match this
159 * @return Matcher object
160 */
161 @Factory
162 public static Matcher<IntentMap> hasIntentWithIdAndState(String id,
163 IntentState state) {
164 return new IntentsHaveIntentWithStateMatcher(id, state);
165 }
166
167
Ray Milkey6688cd82014-03-11 16:40:46 -0700168 @After
169 public void tearDown() {
Ray Milkey9d671002014-05-29 17:24:29 -0700170 mocks.tearDownIntentMocks();
Ray Milkey6688cd82014-03-11 16:40:46 -0700171 }
172
173 /**
174 * Test the result of executing a path calculation on an
175 * Intent Operation List which contains a path that references a
176 * non-existent switch.
Ray Milkey269ffb92014-04-03 14:43:30 -0700177 * <p/>
Ray Milkey6688cd82014-03-11 16:40:46 -0700178 * A 3 path list is created where one of the paths references a switch
179 * that is not in the topology. The test checks that the resulting
180 * Operation List has entries for the 2 correct paths, and that the
181 * high level intents contain a proper error entry for the bad path.
182 */
183 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700184 public void testInvalidSwitchName() {
Ray Milkey6688cd82014-03-11 16:40:46 -0700185 final String BAD_SWITCH_INTENT_NAME = "No Such Switch Intent";
186
187 // create shortest path intents
188 final IntentOperationList opList = new IntentOperationList();
189 opList.add(Operator.ADD,
190 new ShortestPathIntent(BAD_SWITCH_INTENT_NAME, 111L, 12L,
191 LOCAL_PORT, 2L, 21L, LOCAL_PORT));
192 opList.add(Operator.ADD,
193 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
194 LOCAL_PORT));
195 opList.add(Operator.ADD,
196 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
197 LOCAL_PORT));
198
199 // compile high-level intent operations into low-level intent
200 // operations (calculate paths)
Ray Milkey6688cd82014-03-11 16:40:46 -0700201 final IntentOperationList pathIntentOpList =
202 runtime.executeIntentOperations(opList);
203 assertThat(pathIntentOpList, notNullValue());
204
205 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
206 assertThat(highLevelIntents, notNullValue());
207
208 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
209 assertThat(allIntents, notNullValue());
210
211 // One intent had an error and should not create a path list entry
212 assertThat(pathIntentOpList, hasSize(opList.size() - 1));
213
214 // Should be a high level intent for each operation
Ray Milkeydc659c42014-03-28 16:30:42 -0700215 assertThat(allIntents, hasSize(opList.size()));
Ray Milkey6688cd82014-03-11 16:40:46 -0700216
217 // Check that we got a high level intent for each operation
Ray Milkeydc659c42014-03-28 16:30:42 -0700218 assertThat(allIntents, hasIntentWithId("3"));
219 assertThat(allIntents, hasIntentWithId("2"));
220 assertThat(allIntents, hasIntentWithId(BAD_SWITCH_INTENT_NAME));
Ray Milkey6688cd82014-03-11 16:40:46 -0700221
222 // Check that the non existent switch was NACKed
Ray Milkeydc659c42014-03-28 16:30:42 -0700223 assertThat(highLevelIntents, hasIntentWithIdAndState(BAD_SWITCH_INTENT_NAME, IntentState.INST_NACK));
Ray Milkey6688cd82014-03-11 16:40:46 -0700224
225 // Check that switch 2 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700226 assertThat(highLevelIntents, hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkey6688cd82014-03-11 16:40:46 -0700227
228 // Check that switch 3 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700229 assertThat(highLevelIntents, hasIntentWithIdAndState("3", IntentState.INST_REQ));
230
231 }
232
233
234 /**
235 * Test the result of executing a path calculation on an
236 * Intent Operation List and then removing one of the switches.
Ray Milkey269ffb92014-04-03 14:43:30 -0700237 * <p/>
Ray Milkeydc659c42014-03-28 16:30:42 -0700238 * A 3 path list is created and then one of the paths is removed.
239 * The test checks that the resulting Operation List is correct,
240 * and that the high level intents contain a proper "delete requested"
241 * entry for the deleted path.
242 */
243 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700244 public void testIntentRemoval() {
Ray Milkeydc659c42014-03-28 16:30:42 -0700245 // create shortest path intents
246 final IntentOperationList opList = new IntentOperationList();
247 opList.add(Operator.ADD,
248 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700249 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700250 opList.add(Operator.ADD,
251 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700252 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700253 opList.add(Operator.ADD,
254 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700255 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700256
257 // compile high-level intent operations into low-level intent
258 // operations (calculate paths)
Ray Milkeydc659c42014-03-28 16:30:42 -0700259 final IntentOperationList pathIntentOpList =
260 runtime.executeIntentOperations(opList);
261 assertThat(pathIntentOpList, notNullValue());
262
263 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
264 assertThat(highLevelIntents, notNullValue());
265
266 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
267 assertThat(allIntents, notNullValue());
268
269 // Should be one operation per path
270 assertThat(pathIntentOpList, hasSize(opList.size()));
271
272 // Should be a high level intent for each operation
273 assertThat(allIntents, hasSize(opList.size()));
274
275 // Check that we got a high level intent for each operation
276 assertThat(allIntents, hasIntentWithId("3"));
277 assertThat(allIntents, hasIntentWithId("2"));
278 assertThat(allIntents, hasIntentWithId("1"));
279
280 // Check that switch 1 was correctly processed
281 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700282 hasIntentWithIdAndState("1", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700283
284 // Check that switch 2 was correctly processed
285 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700286 hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700287
288 // Check that switch 3 was correctly processed
289 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700290 hasIntentWithIdAndState("3", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700291
292 // Now delete one path and check the results
293 final IntentOperationList opListForRemoval = new IntentOperationList();
294 opListForRemoval.add(Operator.REMOVE,
295 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
296 LOCAL_PORT));
297
298 final IntentOperationList pathIntentOpListAfterRemoval =
299 runtime.executeIntentOperations(opListForRemoval);
300 assertThat(pathIntentOpListAfterRemoval, notNullValue());
301 assertThat(pathIntentOpListAfterRemoval, hasSize(1));
302
303 // Check the high level intents.
304 final IntentMap highLevelIntentsAfterRemoval = runtime.getHighLevelIntents();
305 assertThat(highLevelIntentsAfterRemoval, notNullValue());
306
307 final Collection<Intent> allIntentsAfterRemoval = highLevelIntentsAfterRemoval.getAllIntents();
308 assertThat(allIntentsAfterRemoval, notNullValue());
309 assertThat(allIntentsAfterRemoval, hasSize(3));
310
311 // Check that we got a high level intent for each operation
312 assertThat(allIntentsAfterRemoval, hasIntentWithId("3"));
313 assertThat(allIntentsAfterRemoval, hasIntentWithId("2"));
314 assertThat(allIntentsAfterRemoval, hasIntentWithId("1"));
315
316 // Check the states of the high level intents
317 // Check that switch 1 was correctly processed
318 assertThat(highLevelIntents,
319 hasIntentWithIdAndState("1", IntentState.DEL_REQ));
320
321 // Check that switch 2 was correctly processed
322 assertThat(highLevelIntents,
323 hasIntentWithIdAndState("2", IntentState.INST_REQ));
324
325 // Check that switch 3 was correctly processed
326 assertThat(highLevelIntents,
327 hasIntentWithIdAndState("3", IntentState.INST_REQ));
328 }
329
330 /**
331 * Test the result of executing a path calculation on an
332 * Intent Operation List and then forcing a reroute.
Ray Milkey269ffb92014-04-03 14:43:30 -0700333 * <p/>
Ray Milkeydc659c42014-03-28 16:30:42 -0700334 * A 3 path list is created and then one of the links is removed.
335 * The test checks that the resulting Operation List is correct,
336 * and that the high level intents contain a proper "reroute requested"
337 * entry for the deleted link.
338 */
339 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700340 public void testIntentReroute() {
Ray Milkeydc659c42014-03-28 16:30:42 -0700341 // create shortest path intents
342 final IntentOperationList opList = new IntentOperationList();
Toshio Koideee698952014-06-11 13:35:30 -0700343 opList.add(Operator.ADD,
Ray Milkeydc659c42014-03-28 16:30:42 -0700344 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
Toshio Koideee698952014-06-11 13:35:30 -0700345 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700346 opList.add(Operator.ADD,
347 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700348 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700349 opList.add(Operator.ADD,
350 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700351 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700352
353 // compile high-level intent operations into low-level intent
354 // operations (calculate paths)
Ray Milkeydc659c42014-03-28 16:30:42 -0700355 final IntentOperationList pathIntentOpList =
356 runtime.executeIntentOperations(opList);
357 assertThat(pathIntentOpList, notNullValue());
358
359 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
360 assertThat(highLevelIntents, notNullValue());
361
362 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
363 assertThat(allIntents, notNullValue());
364
365 // Should be one operation per path
366 assertThat(pathIntentOpList, hasSize(opList.size()));
367
368 // Should be a high level intent for each operation
369 assertThat(allIntents, hasSize(opList.size()));
370
371 // Check that we got a high level intent for each operation
372 assertThat(allIntents, hasIntentWithId("3"));
373 assertThat(allIntents, hasIntentWithId("2"));
374 assertThat(allIntents, hasIntentWithId("1"));
375
Toshio Koidec2112c22014-06-05 19:59:15 -0700376 // Check that the high level intent 1 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700377 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700378 hasIntentWithIdAndState("1", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700379
Toshio Koidec2112c22014-06-05 19:59:15 -0700380 // Check that the high level intent 2 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700381 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700382 hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700383
Toshio Koidec2112c22014-06-05 19:59:15 -0700384 // Check that the high level intent 3 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700385 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700386 hasIntentWithIdAndState("3", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700387
Toshio Koidec2112c22014-06-05 19:59:15 -0700388 final IntentMap pathIntents = runtime.getPathIntents();
389 assertThat(pathIntents, notNullValue());
Ray Milkeydc659c42014-03-28 16:30:42 -0700390
Toshio Koidec2112c22014-06-05 19:59:15 -0700391 final Collection<Intent> allPathIntents = pathIntents.getAllIntents();
392 assertThat(allPathIntents, notNullValue());
393
394 // Check that we got a low level intent for each operation
395 assertThat(allPathIntents, hasIntentWithId("3___0"));
396 assertThat(allPathIntents, hasIntentWithId("2___0"));
397 assertThat(allPathIntents, hasIntentWithId("1___0"));
398
399 // Check that the low level intent 1 was correctly processed
400 assertThat(pathIntents,
401 hasIntentWithIdAndState("1___0", IntentState.INST_REQ));
402
403 // Check that the low level intent 2 was correctly processed
404 assertThat(pathIntents,
405 hasIntentWithIdAndState("2___0", IntentState.INST_REQ));
406
407 // Check that the low level intent 3 was correctly processed
408 assertThat(pathIntents,
409 hasIntentWithIdAndState("3___0", IntentState.INST_REQ));
410
411 // Receive notification from south-bound
412 IntentStateList isl = new IntentStateList();
413 isl.put("1___0", IntentState.INST_ACK);
414 isl.put("2___0", IntentState.INST_ACK);
415 isl.put("3___0", IntentState.INST_ACK);
416 isl.domainSwitchDpids.add(1L);
417 isl.domainSwitchDpids.add(2L);
418 isl.domainSwitchDpids.add(3L);
419 isl.domainSwitchDpids.add(4L);
420 runtime.entryUpdated(isl);
421
422 // Now check the results
423 final IntentMap processedHighLevelIntents = runtime.getHighLevelIntents();
424 assertThat(processedHighLevelIntents, notNullValue());
425
426 // Check that the high level intent 1 was correctly processed
427 assertThat(processedHighLevelIntents,
428 hasIntentWithIdAndState("1", IntentState.INST_ACK));
429
430 // Check that the high level intent 2 was correctly processed
431 assertThat(processedHighLevelIntents,
432 hasIntentWithIdAndState("2", IntentState.INST_ACK));
433
434 // Check that the high level intent 3 was correctly processed
435 assertThat(processedHighLevelIntents,
436 hasIntentWithIdAndState("3", IntentState.INST_ACK));
437
438 final IntentMap processedPathIntents = runtime.getPathIntents();
439 assertThat(processedPathIntents, notNullValue());
440
441 // Check that the low level intent 1 was correctly processed
442 assertThat(processedPathIntents,
443 hasIntentWithIdAndState("1___0", IntentState.INST_ACK));
444
445 // Check that the low level intent 2 was correctly processed
446 assertThat(processedPathIntents,
447 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
448
449 // Check that the low level intent 3 was correctly processed
450 assertThat(processedPathIntents,
451 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
452
453
454 // Remove one of the links and check results
Ray Milkeydc659c42014-03-28 16:30:42 -0700455 final List<SwitchEvent> emptySwitchEvents = new LinkedList<>();
456 final List<PortEvent> emptyPortEvents = new LinkedList<>();
457 final List<DeviceEvent> emptyDeviceEvents = new LinkedList<>();
458 final List<LinkEvent> addedLinkEvents = new LinkedList<>();
459 final List<LinkEvent> removedLinkEvents = new LinkedList<>();
460
Ray Milkey9d671002014-05-29 17:24:29 -0700461 final MockTopology topology = mocks.getTopology();
Jonathan Harte37e4e22014-05-13 19:12:02 -0700462 topology.removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
463 topology.removeLink(2L, 21L, 1L, 12L);
Ray Milkeydc659c42014-03-28 16:30:42 -0700464 LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
465 LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
466 removedLinkEvents.add(linkEvent1);
467 removedLinkEvents.add(linkEvent2);
Jonathan Harte37e4e22014-05-13 19:12:02 -0700468 runtime.topologyEvents(
Ray Milkeydc659c42014-03-28 16:30:42 -0700469 emptySwitchEvents,
470 emptySwitchEvents,
471 emptyPortEvents,
472 emptyPortEvents,
473 addedLinkEvents,
474 removedLinkEvents,
475 emptyDeviceEvents,
476 emptyDeviceEvents);
Ray Milkeydc659c42014-03-28 16:30:42 -0700477
478 // Check the high level intents.
479 final IntentMap highLevelIntentsAfterReroute = runtime.getHighLevelIntents();
480 assertThat(highLevelIntentsAfterReroute, notNullValue());
481
Ray Milkeydc659c42014-03-28 16:30:42 -0700482 // Check the states of the high level intents
Toshio Koidec2112c22014-06-05 19:59:15 -0700483 // Check that the high level intent 1 was correctly processed
484 assertThat(highLevelIntentsAfterReroute,
485 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700486
Toshio Koidec2112c22014-06-05 19:59:15 -0700487 // Check that the high level intent 2 was not affected
488 assertThat(highLevelIntentsAfterReroute,
Ray Milkeydc659c42014-03-28 16:30:42 -0700489 hasIntentWithIdAndState("2", IntentState.INST_ACK));
490
Toshio Koidec2112c22014-06-05 19:59:15 -0700491 // Check that the high level intent 3 was not affected
492 assertThat(highLevelIntentsAfterReroute,
Ray Milkeydc659c42014-03-28 16:30:42 -0700493 hasIntentWithIdAndState("3", IntentState.INST_ACK));
494
Toshio Koidec2112c22014-06-05 19:59:15 -0700495 final IntentMap pathIntentsAfterReroute = runtime.getPathIntents();
496 assertThat(pathIntentsAfterReroute, notNullValue());
Ray Milkey6688cd82014-03-11 16:40:46 -0700497
Toshio Koidec2112c22014-06-05 19:59:15 -0700498 // Check that the low level intent 1 was correctly processed
499 assertThat(pathIntentsAfterReroute,
500 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
501 assertThat(pathIntentsAfterReroute,
502 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
503
504 // Check that the low level intent 2 was not affected
505 assertThat(pathIntentsAfterReroute,
506 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
507
508 // Check that the low level intent 3 was not affected
509 assertThat(pathIntentsAfterReroute,
510 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
511
512 // Receive notification from south-bound
513 isl = new IntentStateList();
514 isl.put("1___0", IntentState.DEL_ACK);
515 isl.put("1___1", IntentState.INST_ACK);
516 isl.domainSwitchDpids.add(1L);
517 isl.domainSwitchDpids.add(2L);
518 isl.domainSwitchDpids.add(4L);
519 runtime.entryUpdated(isl);
520
521 // Now check the results
522 final IntentMap reroutedHighLevelIntents = runtime.getHighLevelIntents();
523 assertThat(reroutedHighLevelIntents, notNullValue());
524
525 // Check that the high level intent 1 was correctly processed
526 assertThat(reroutedHighLevelIntents,
527 hasIntentWithIdAndState("1", IntentState.INST_ACK));
528
529 // Check that the high level intent 2 was not affected
530 assertThat(reroutedHighLevelIntents,
531 hasIntentWithIdAndState("2", IntentState.INST_ACK));
532
533 // Check that the high level intent 3 was not affected
534 assertThat(reroutedHighLevelIntents,
535 hasIntentWithIdAndState("3", IntentState.INST_ACK));
536
537 final IntentMap reroutedPathIntents = runtime.getPathIntents();
538 assertThat(processedPathIntents, notNullValue());
539
540 // Check that the low level intent 1 was correctly processed
Pavlin Radoslavove2238bc2014-06-09 18:05:23 -0700541 assertThat(reroutedPathIntents.getAllIntents(),
542 not(hasIntentWithId("1___0")));
Toshio Koidec2112c22014-06-05 19:59:15 -0700543 assertThat(reroutedPathIntents,
544 hasIntentWithIdAndState("1___1", IntentState.INST_ACK));
545
546 // Check that the low level intent 2 was not affected
547 assertThat(reroutedPathIntents,
548 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
549
550 // Check that the low level intent 3 was not affected
551 assertThat(reroutedPathIntents,
552 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
Ray Milkey6688cd82014-03-11 16:40:46 -0700553 }
Toshio Koideee698952014-06-11 13:35:30 -0700554
555 /**
556 * Test the result of executing a path calculation on an
557 * Intent Operation List and then forcing a reroute and
558 * an interrupt of a topology change event while the reroute
559 * is processed.
560 * <p/>
561 * A 3 path list is created, one of the links is removed, then
562 * the removed link is restored.
563 * The test checks that if the high level intent was marked
564 * as stale when a topology changed event was received while
565 * processing reroute then the stale high level intent is executed
566 * once again after completion of its reroute.
567 */
568 @Test
569 public void testIntentRerouteWithTopologyEventInterrupt() {
570
571 // create shortest path intents
572 final IntentOperationList opList = new IntentOperationList();
573 opList.add(Operator.ADD,
574 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
575 LOCAL_PORT));
576 opList.add(Operator.ADD,
577 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
578 LOCAL_PORT));
579 opList.add(Operator.ADD,
580 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
581 LOCAL_PORT));
582
583 // compile high-level intent operations into low-level intent
584 // operations (calculate paths)
585 final IntentOperationList pathIntentOpList =
586 runtime.executeIntentOperations(opList);
587 assertThat(pathIntentOpList, notNullValue());
588
589 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
590 assertThat(highLevelIntents, notNullValue());
591
592 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
593 assertThat(allIntents, notNullValue());
594
595 // Should be one operation per path
596 assertThat(pathIntentOpList, hasSize(opList.size()));
597
598 // Should be a high level intent for each operation
599 assertThat(allIntents, hasSize(opList.size()));
600
601 // Check that we got a high level intent for each operation
602 assertThat(allIntents, hasIntentWithId("3"));
603 assertThat(allIntents, hasIntentWithId("2"));
604 assertThat(allIntents, hasIntentWithId("1"));
605
606 // Check that the high level intent 1 was correctly processed
607 assertThat(highLevelIntents,
608 hasIntentWithIdAndState("1", IntentState.INST_REQ));
609
610 // Check that the high level intent 2 was correctly processed
611 assertThat(highLevelIntents,
612 hasIntentWithIdAndState("2", IntentState.INST_REQ));
613
614 // Check that the high level intent 3 was correctly processed
615 assertThat(highLevelIntents,
616 hasIntentWithIdAndState("3", IntentState.INST_REQ));
617
618 final IntentMap pathIntents = runtime.getPathIntents();
619 assertThat(pathIntents, notNullValue());
620
621 final Collection<Intent> allPathIntents = pathIntents.getAllIntents();
622 assertThat(allPathIntents, notNullValue());
623
624 // Check that we got a low level intent for each operation
625 assertThat(allPathIntents, hasIntentWithId("3___0"));
626 assertThat(allPathIntents, hasIntentWithId("2___0"));
627 assertThat(allPathIntents, hasIntentWithId("1___0"));
628
629 // Check that the low level intent 1 was correctly processed
630 assertThat(pathIntents,
631 hasIntentWithIdAndState("1___0", IntentState.INST_REQ));
632
633 // Check that the low level intent 2 was correctly processed
634 assertThat(pathIntents,
635 hasIntentWithIdAndState("2___0", IntentState.INST_REQ));
636
637 // Check that the low level intent 3 was correctly processed
638 assertThat(pathIntents,
639 hasIntentWithIdAndState("3___0", IntentState.INST_REQ));
640
641 // Receive notification from south-bound
642 IntentStateList isl = new IntentStateList();
643 isl.put("1___0", IntentState.INST_ACK);
644 isl.put("2___0", IntentState.INST_ACK);
645 isl.put("3___0", IntentState.INST_ACK);
646 isl.domainSwitchDpids.add(1L);
647 isl.domainSwitchDpids.add(2L);
648 isl.domainSwitchDpids.add(3L);
649 isl.domainSwitchDpids.add(4L);
650 runtime.entryUpdated(isl);
651
652 // Now check the results
653 final IntentMap processedHighLevelIntents = runtime.getHighLevelIntents();
654 assertThat(processedHighLevelIntents, notNullValue());
655
656 // Check that the high level intent 1 was correctly processed
657 assertThat(processedHighLevelIntents,
658 hasIntentWithIdAndState("1", IntentState.INST_ACK));
659
660 // Check that the high level intent 2 was correctly processed
661 assertThat(processedHighLevelIntents,
662 hasIntentWithIdAndState("2", IntentState.INST_ACK));
663
664 // Check that the high level intent 3 was correctly processed
665 assertThat(processedHighLevelIntents,
666 hasIntentWithIdAndState("3", IntentState.INST_ACK));
667
668 final IntentMap processedPathIntents = runtime.getPathIntents();
669 assertThat(processedPathIntents, notNullValue());
670
671 // Check that the low level intent 1 was correctly processed
672 assertThat(processedPathIntents,
673 hasIntentWithIdAndState("1___0", IntentState.INST_ACK));
674
675 // Check that the low level intent 2 was correctly processed
676 assertThat(processedPathIntents,
677 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
678
679 // Check that the low level intent 3 was correctly processed
680 assertThat(processedPathIntents,
681 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
682
683
684 // Remove one of the links and check results
685 final List<SwitchEvent> emptySwitchEvents = new LinkedList<>();
686 final List<PortEvent> emptyPortEvents = new LinkedList<>();
687 final List<DeviceEvent> emptyDeviceEvents = new LinkedList<>();
688 final List<LinkEvent> addedLinkEvents = new LinkedList<>();
689 final List<LinkEvent> removedLinkEvents = new LinkedList<>();
690
691 final MockTopology topology = mocks.getTopology();
692 topology.removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
693 topology.removeLink(2L, 21L, 1L, 12L);
694 final LinkEvent linkEvent1 = new LinkEvent(1L, 12L, 2L, 21L);
695 final LinkEvent linkEvent2 = new LinkEvent(2L, 21L, 1L, 12L);
696 removedLinkEvents.add(linkEvent1);
697 removedLinkEvents.add(linkEvent2);
698 runtime.topologyEvents(
699 emptySwitchEvents,
700 emptySwitchEvents,
701 emptyPortEvents,
702 emptyPortEvents,
703 addedLinkEvents,
704 removedLinkEvents,
705 emptyDeviceEvents,
706 emptyDeviceEvents);
707
708 // Check the high level intents.
709 final IntentMap highLevelIntentsAfterReroute = runtime.getHighLevelIntents();
710 assertThat(highLevelIntentsAfterReroute, notNullValue());
711
712 // Check the states of the high level intents
713 // Check that the high level intent 1 was correctly processed
714 assertThat(highLevelIntentsAfterReroute,
715 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
716
717 // Check that the high level intent 2 was not affected
718 assertThat(highLevelIntentsAfterReroute,
719 hasIntentWithIdAndState("2", IntentState.INST_ACK));
720
721 // Check that the high level intent 3 was not affected
722 assertThat(highLevelIntentsAfterReroute,
723 hasIntentWithIdAndState("3", IntentState.INST_ACK));
724
725 final IntentMap pathIntentsAfterReroute = runtime.getPathIntents();
726 assertThat(pathIntentsAfterReroute, notNullValue());
727
728 // Check that the low level intent 1 was correctly processed
729 assertThat(pathIntentsAfterReroute,
730 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
731 assertThat(pathIntentsAfterReroute,
732 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
733
734 // Check that the low level intent 2 was not affected
735 assertThat(pathIntentsAfterReroute,
736 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
737
738 // Check that the low level intent 3 was not affected
739 assertThat(pathIntentsAfterReroute,
740 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
741
742 // Interrupt by topology changed event while the reroute
743 removedLinkEvents.clear();
744 addedLinkEvents.clear();
745 topology.addBidirectionalLinks(1L, 12L, 2L, 21L); // Restoration of the failure
746 addedLinkEvents.add(linkEvent1);
747 addedLinkEvents.add(linkEvent2);
748 runtime.topologyEvents(
749 emptySwitchEvents,
750 emptySwitchEvents,
751 emptyPortEvents,
752 emptyPortEvents,
753 addedLinkEvents,
754 removedLinkEvents,
755 emptyDeviceEvents,
756 emptyDeviceEvents);
757
758 // Check the high level intents.
759 final IntentMap highLevelIntentsAfterInterrupt = runtime.getHighLevelIntents();
760 assertThat(highLevelIntentsAfterInterrupt, notNullValue());
761
762 // Check the states of the high level intents
763 // Check that the high level intent 1 was not affected
764 assertThat(highLevelIntentsAfterInterrupt,
765 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
766
767 final IntentMap pathIntentsAfterInterrupt = runtime.getPathIntents();
768 assertThat(pathIntentsAfterInterrupt, notNullValue());
769
770 // Check that the low level intent 1 was not affected
771 assertThat(pathIntentsAfterInterrupt,
772 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
773 assertThat(pathIntentsAfterInterrupt,
774 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
775
776 // Receive notification from south-bound
777 isl = new IntentStateList();
778 isl.put("1___0", IntentState.DEL_ACK);
779 isl.put("1___1", IntentState.INST_ACK);
780 isl.domainSwitchDpids.add(1L);
781 isl.domainSwitchDpids.add(2L);
782 isl.domainSwitchDpids.add(4L);
783 runtime.entryUpdated(isl);
784
785 // Now check the results
786 final IntentMap reroutedHighLevelIntents = runtime.getHighLevelIntents();
787 assertThat(reroutedHighLevelIntents, notNullValue());
788
789 // Check that the high level intent 1 was correctly processed
790 // It should be rerouted once again
791 assertThat(reroutedHighLevelIntents,
792 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
793
794 // Check that the high level intent 2 was not affected
795 assertThat(reroutedHighLevelIntents,
796 hasIntentWithIdAndState("2", IntentState.INST_ACK));
797
798 // Check that the high level intent 3 was not affected
799 assertThat(reroutedHighLevelIntents,
800 hasIntentWithIdAndState("3", IntentState.INST_ACK));
801
802 final IntentMap reroutedPathIntents = runtime.getPathIntents();
803 assertThat(processedPathIntents, notNullValue());
804
805 // Check that the low level intent 1 was correctly processed
806 assertThat(reroutedPathIntents.getAllIntents(),
807 not(hasIntentWithId("1___0")));
808 assertThat(reroutedPathIntents,
809 hasIntentWithIdAndState("1___1", IntentState.DEL_REQ));
810 assertThat(reroutedPathIntents,
811 hasIntentWithIdAndState("1___2", IntentState.INST_REQ));
812
813 // Check that the low level intent 2 was not affected
814 assertThat(reroutedPathIntents,
815 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
816
817 // Check that the low level intent 3 was not affected
818 assertThat(reroutedPathIntents,
819 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
820 }
Ray Milkey6688cd82014-03-11 16:40:46 -0700821}