blob: 119acc6f63e98d46ac39841750bdd95e30f16a43 [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 Hartaa380972014-04-03 10:24:46 -070020import net.onrc.onos.core.intent.ShortestPathIntent;
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -070021import net.onrc.onos.core.topology.HostEvent;
Jonathan Hart472062d2014-04-03 10:56:48 -070022import net.onrc.onos.core.topology.LinkEvent;
TeruU5d2c9392014-06-09 20:02:02 -070023import net.onrc.onos.core.topology.MockTopology;
Jonathan Hart472062d2014-04-03 10:56:48 -070024import net.onrc.onos.core.topology.PortEvent;
25import net.onrc.onos.core.topology.SwitchEvent;
Yuta HIGUCHIb8093642014-07-16 13:17:07 -070026import net.onrc.onos.core.topology.TopologyElement;
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -070027import net.onrc.onos.core.topology.TopologyEvents;
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -070028import net.onrc.onos.core.util.SwitchPort;
Ray Milkey6688cd82014-03-11 16:40:46 -070029
Jonathan Harta88fd242014-04-03 11:24:54 -070030import org.hamcrest.Description;
31import org.hamcrest.Factory;
32import org.hamcrest.Matcher;
33import org.hamcrest.Matchers;
34import org.hamcrest.TypeSafeMatcher;
Ray Milkey6688cd82014-03-11 16:40:46 -070035import org.junit.After;
36import org.junit.Before;
37import org.junit.Test;
38import org.junit.runner.RunWith;
Ray Milkey6688cd82014-03-11 16:40:46 -070039import org.powermock.core.classloader.annotations.PrepareForTest;
40import org.powermock.modules.junit4.PowerMockRunner;
41
Ray Milkey6688cd82014-03-11 16:40:46 -070042/**
Ray Milkey269ffb92014-04-03 14:43:30 -070043 * Unit tests for the Path Calculation Runtime module (PathCalcRuntimeModule).
44 * These test cases check the results of creating paths, deleting paths, and
Jonathan Harte37e4e22014-05-13 19:12:02 -070045 * rerouting paths. The topology, controller registry, and data grid are
Ray Milkey269ffb92014-04-03 14:43:30 -070046 * mocked out. The individual tests check the high level intents and the
47 * resulting operation lists to be sure they match the intended APIs.
Ray Milkey6688cd82014-03-11 16:40:46 -070048 */
49@RunWith(PowerMockRunner.class)
50@PrepareForTest(PathCalcRuntimeModule.class)
51public class PathCalcRuntimeModuleTest {
Ray Milkeydc659c42014-03-28 16:30:42 -070052 private static final Long LOCAL_PORT = 0xFFFEL;
53
Ray Milkey9d671002014-05-29 17:24:29 -070054 private IntentTestMocks mocks;
55 private PathCalcRuntimeModule runtime;
Ray Milkey6688cd82014-03-11 16:40:46 -070056
Ray Milkey6688cd82014-03-11 16:40:46 -070057 @Before
58 public void setUp() throws Exception {
Ray Milkey9d671002014-05-29 17:24:29 -070059 mocks = new IntentTestMocks();
60 mocks.setUpIntentMocks();
Ray Milkey6688cd82014-03-11 16:40:46 -070061
Ray Milkey9d671002014-05-29 17:24:29 -070062 runtime = new PathCalcRuntimeModule();
63 final FloodlightModuleContext moduleContext = mocks.getModuleContext();
64 runtime.init(moduleContext);
65 runtime.startUp(moduleContext);
Ray Milkey6688cd82014-03-11 16:40:46 -070066 }
67
Ray Milkeydc659c42014-03-28 16:30:42 -070068
69 /**
70 * Hamcrest matcher to check that a collection of Intents contains an
71 * Intent with the specified Intent Id.
72 */
73 public static class EntryForIntentMatcher extends TypeSafeMatcher<Collection<Intent>> {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -070074 private final String id;
Ray Milkeydc659c42014-03-28 16:30:42 -070075
76 public EntryForIntentMatcher(String idValue) {
77 id = idValue;
78 }
79
80 @Override
81 public boolean matchesSafely(Collection<Intent> intents) {
Pavlin Radoslavove2238bc2014-06-09 18:05:23 -070082 return hasItem(Matchers.<Intent>hasProperty("id", equalTo(id))).matches(intents);
Ray Milkeydc659c42014-03-28 16:30:42 -070083 }
84
85 @Override
86 public void describeTo(Description description) {
87 description.appendText("an intent with id \" ").
88 appendText(id).
89 appendText("\"");
90 }
91 }
92
93
94 /**
95 * Factory method to create an Intent entry Matcher. Returns a matcher
96 * for the Intent with the given id.
Ray Milkey269ffb92014-04-03 14:43:30 -070097 *
Ray Milkeydc659c42014-03-28 16:30:42 -070098 * @param id id of the intent to match
99 * @return Matcher object
100 */
101 @Factory
102 public static Matcher<Collection<Intent>> hasIntentWithId(String id) {
103 return new EntryForIntentMatcher(id);
104 }
105
106
107 /**
108 * Matcher to determine if an IntentMap contains an entry with a given id,
109 * and that entry has a given state.
110 */
111 public static class IntentsHaveIntentWithStateMatcher extends TypeSafeMatcher<IntentMap> {
Yuta HIGUCHI44a0b352014-05-14 21:32:48 -0700112 private final String id;
113 private final IntentState state;
Ray Milkeydc659c42014-03-28 16:30:42 -0700114 private Intent intent;
115
116 public IntentsHaveIntentWithStateMatcher(String idValue,
117 IntentState stateValue) {
118 id = idValue;
119 state = stateValue;
120 }
121
122 @Override
123 public boolean matchesSafely(IntentMap intents) {
124 intent = intents.getIntent(id);
125
126 return intent != null && intent.getState() == state;
127 }
128
129 @Override
130 public void describeTo(Description description) {
131 if (intent == null) {
132 description.appendText("intent lookup for id \"");
133 description.appendText(id);
134 description.appendText("\"");
135 } else {
136 description.appendText("state ");
137 description.appendText(state.toString());
138 }
139 }
140
141 @Override
142 public void describeMismatchSafely(IntentMap intents,
143 Description mismatchDescription) {
144 if (intent != null) {
145 mismatchDescription.appendText("was ").
Ray Milkey269ffb92014-04-03 14:43:30 -0700146 appendText(intent.getState().toString());
Ray Milkeydc659c42014-03-28 16:30:42 -0700147 } else {
148 mismatchDescription.appendText("that intent was not found");
149 }
150 }
151 }
152
153
154 /**
155 * Factory method to create a Matcher for an IntentMap that looks for an
156 * Intent with a given id and state.
157 *
Ray Milkey269ffb92014-04-03 14:43:30 -0700158 * @param id id of the Intent to match
Ray Milkeydc659c42014-03-28 16:30:42 -0700159 * @param state if the Intent is found, its state must match this
160 * @return Matcher object
161 */
162 @Factory
163 public static Matcher<IntentMap> hasIntentWithIdAndState(String id,
164 IntentState state) {
165 return new IntentsHaveIntentWithStateMatcher(id, state);
166 }
167
168
Ray Milkey6688cd82014-03-11 16:40:46 -0700169 @After
170 public void tearDown() {
Ray Milkey9d671002014-05-29 17:24:29 -0700171 mocks.tearDownIntentMocks();
Ray Milkey6688cd82014-03-11 16:40:46 -0700172 }
173
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700174 private static final String BAD_SWITCH_INTENT_NAME = "No Such Switch Intent";
175
Ray Milkey6688cd82014-03-11 16:40:46 -0700176 /**
177 * Test the result of executing a path calculation on an
178 * Intent Operation List which contains a path that references a
179 * non-existent switch.
Ray Milkey269ffb92014-04-03 14:43:30 -0700180 * <p/>
Ray Milkey6688cd82014-03-11 16:40:46 -0700181 * A 3 path list is created where one of the paths references a switch
182 * that is not in the topology. The test checks that the resulting
183 * Operation List has entries for the 2 correct paths, and that the
184 * high level intents contain a proper error entry for the bad path.
185 */
186 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700187 public void testInvalidSwitchName() {
Ray Milkey6688cd82014-03-11 16:40:46 -0700188
189 // create shortest path intents
190 final IntentOperationList opList = new IntentOperationList();
191 opList.add(Operator.ADD,
192 new ShortestPathIntent(BAD_SWITCH_INTENT_NAME, 111L, 12L,
193 LOCAL_PORT, 2L, 21L, LOCAL_PORT));
194 opList.add(Operator.ADD,
195 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
196 LOCAL_PORT));
197 opList.add(Operator.ADD,
198 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
199 LOCAL_PORT));
200
201 // compile high-level intent operations into low-level intent
202 // operations (calculate paths)
Ray Milkey6688cd82014-03-11 16:40:46 -0700203 final IntentOperationList pathIntentOpList =
204 runtime.executeIntentOperations(opList);
205 assertThat(pathIntentOpList, notNullValue());
206
207 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
208 assertThat(highLevelIntents, notNullValue());
209
210 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
211 assertThat(allIntents, notNullValue());
212
213 // One intent had an error and should not create a path list entry
214 assertThat(pathIntentOpList, hasSize(opList.size() - 1));
215
216 // Should be a high level intent for each operation
Ray Milkeydc659c42014-03-28 16:30:42 -0700217 assertThat(allIntents, hasSize(opList.size()));
Ray Milkey6688cd82014-03-11 16:40:46 -0700218
219 // Check that we got a high level intent for each operation
Ray Milkeydc659c42014-03-28 16:30:42 -0700220 assertThat(allIntents, hasIntentWithId("3"));
221 assertThat(allIntents, hasIntentWithId("2"));
222 assertThat(allIntents, hasIntentWithId(BAD_SWITCH_INTENT_NAME));
Ray Milkey6688cd82014-03-11 16:40:46 -0700223
224 // Check that the non existent switch was NACKed
Ray Milkeydc659c42014-03-28 16:30:42 -0700225 assertThat(highLevelIntents, hasIntentWithIdAndState(BAD_SWITCH_INTENT_NAME, IntentState.INST_NACK));
Ray Milkey6688cd82014-03-11 16:40:46 -0700226
227 // Check that switch 2 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700228 assertThat(highLevelIntents, hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkey6688cd82014-03-11 16:40:46 -0700229
230 // Check that switch 3 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700231 assertThat(highLevelIntents, hasIntentWithIdAndState("3", IntentState.INST_REQ));
232
233 }
234
235
236 /**
237 * Test the result of executing a path calculation on an
238 * Intent Operation List and then removing one of the switches.
Ray Milkey269ffb92014-04-03 14:43:30 -0700239 * <p/>
Ray Milkeydc659c42014-03-28 16:30:42 -0700240 * A 3 path list is created and then one of the paths is removed.
241 * The test checks that the resulting Operation List is correct,
242 * and that the high level intents contain a proper "delete requested"
243 * entry for the deleted path.
244 */
245 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700246 public void testIntentRemoval() {
Ray Milkeydc659c42014-03-28 16:30:42 -0700247 // create shortest path intents
248 final IntentOperationList opList = new IntentOperationList();
249 opList.add(Operator.ADD,
250 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700251 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700252 opList.add(Operator.ADD,
253 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700254 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700255 opList.add(Operator.ADD,
256 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700257 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700258
259 // compile high-level intent operations into low-level intent
260 // operations (calculate paths)
Ray Milkeydc659c42014-03-28 16:30:42 -0700261 final IntentOperationList pathIntentOpList =
262 runtime.executeIntentOperations(opList);
263 assertThat(pathIntentOpList, notNullValue());
264
265 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
266 assertThat(highLevelIntents, notNullValue());
267
268 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
269 assertThat(allIntents, notNullValue());
270
271 // Should be one operation per path
272 assertThat(pathIntentOpList, hasSize(opList.size()));
273
274 // Should be a high level intent for each operation
275 assertThat(allIntents, hasSize(opList.size()));
276
277 // Check that we got a high level intent for each operation
278 assertThat(allIntents, hasIntentWithId("3"));
279 assertThat(allIntents, hasIntentWithId("2"));
280 assertThat(allIntents, hasIntentWithId("1"));
281
282 // Check that switch 1 was correctly processed
283 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700284 hasIntentWithIdAndState("1", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700285
286 // Check that switch 2 was correctly processed
287 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700288 hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700289
290 // Check that switch 3 was correctly processed
291 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700292 hasIntentWithIdAndState("3", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700293
294 // Now delete one path and check the results
295 final IntentOperationList opListForRemoval = new IntentOperationList();
296 opListForRemoval.add(Operator.REMOVE,
297 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
298 LOCAL_PORT));
299
300 final IntentOperationList pathIntentOpListAfterRemoval =
301 runtime.executeIntentOperations(opListForRemoval);
302 assertThat(pathIntentOpListAfterRemoval, notNullValue());
303 assertThat(pathIntentOpListAfterRemoval, hasSize(1));
304
305 // Check the high level intents.
306 final IntentMap highLevelIntentsAfterRemoval = runtime.getHighLevelIntents();
307 assertThat(highLevelIntentsAfterRemoval, notNullValue());
308
309 final Collection<Intent> allIntentsAfterRemoval = highLevelIntentsAfterRemoval.getAllIntents();
310 assertThat(allIntentsAfterRemoval, notNullValue());
311 assertThat(allIntentsAfterRemoval, hasSize(3));
312
313 // Check that we got a high level intent for each operation
314 assertThat(allIntentsAfterRemoval, hasIntentWithId("3"));
315 assertThat(allIntentsAfterRemoval, hasIntentWithId("2"));
316 assertThat(allIntentsAfterRemoval, hasIntentWithId("1"));
317
318 // Check the states of the high level intents
319 // Check that switch 1 was correctly processed
320 assertThat(highLevelIntents,
321 hasIntentWithIdAndState("1", IntentState.DEL_REQ));
322
323 // Check that switch 2 was correctly processed
324 assertThat(highLevelIntents,
325 hasIntentWithIdAndState("2", IntentState.INST_REQ));
326
327 // Check that switch 3 was correctly processed
328 assertThat(highLevelIntents,
329 hasIntentWithIdAndState("3", IntentState.INST_REQ));
330 }
331
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700332 // CHECKSTYLE:OFF method too long
Ray Milkeydc659c42014-03-28 16:30:42 -0700333 /**
334 * Test the result of executing a path calculation on an
335 * Intent Operation List and then forcing a reroute.
Ray Milkey269ffb92014-04-03 14:43:30 -0700336 * <p/>
Ray Milkeydc659c42014-03-28 16:30:42 -0700337 * A 3 path list is created and then one of the links is removed.
338 * The test checks that the resulting Operation List is correct,
339 * and that the high level intents contain a proper "reroute requested"
340 * entry for the deleted link.
341 */
342 @Test
Toshio Koideee698952014-06-11 13:35:30 -0700343 public void testIntentReroute() {
Ray Milkeydc659c42014-03-28 16:30:42 -0700344 // create shortest path intents
345 final IntentOperationList opList = new IntentOperationList();
Toshio Koideee698952014-06-11 13:35:30 -0700346 opList.add(Operator.ADD,
Ray Milkeydc659c42014-03-28 16:30:42 -0700347 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
Toshio Koideee698952014-06-11 13:35:30 -0700348 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700349 opList.add(Operator.ADD,
350 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700351 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700352 opList.add(Operator.ADD,
353 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
Ray Milkey269ffb92014-04-03 14:43:30 -0700354 LOCAL_PORT));
Ray Milkeydc659c42014-03-28 16:30:42 -0700355
356 // compile high-level intent operations into low-level intent
357 // operations (calculate paths)
Ray Milkeydc659c42014-03-28 16:30:42 -0700358 final IntentOperationList pathIntentOpList =
359 runtime.executeIntentOperations(opList);
360 assertThat(pathIntentOpList, notNullValue());
361
362 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
363 assertThat(highLevelIntents, notNullValue());
364
365 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
366 assertThat(allIntents, notNullValue());
367
368 // Should be one operation per path
369 assertThat(pathIntentOpList, hasSize(opList.size()));
370
371 // Should be a high level intent for each operation
372 assertThat(allIntents, hasSize(opList.size()));
373
374 // Check that we got a high level intent for each operation
375 assertThat(allIntents, hasIntentWithId("3"));
376 assertThat(allIntents, hasIntentWithId("2"));
377 assertThat(allIntents, hasIntentWithId("1"));
378
Toshio Koidec2112c22014-06-05 19:59:15 -0700379 // Check that the high level intent 1 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700380 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700381 hasIntentWithIdAndState("1", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700382
Toshio Koidec2112c22014-06-05 19:59:15 -0700383 // Check that the high level intent 2 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700384 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700385 hasIntentWithIdAndState("2", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700386
Toshio Koidec2112c22014-06-05 19:59:15 -0700387 // Check that the high level intent 3 was correctly processed
Ray Milkeydc659c42014-03-28 16:30:42 -0700388 assertThat(highLevelIntents,
Ray Milkey269ffb92014-04-03 14:43:30 -0700389 hasIntentWithIdAndState("3", IntentState.INST_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700390
Toshio Koidec2112c22014-06-05 19:59:15 -0700391 final IntentMap pathIntents = runtime.getPathIntents();
392 assertThat(pathIntents, notNullValue());
Ray Milkeydc659c42014-03-28 16:30:42 -0700393
Toshio Koidec2112c22014-06-05 19:59:15 -0700394 final Collection<Intent> allPathIntents = pathIntents.getAllIntents();
395 assertThat(allPathIntents, notNullValue());
396
397 // Check that we got a low level intent for each operation
398 assertThat(allPathIntents, hasIntentWithId("3___0"));
399 assertThat(allPathIntents, hasIntentWithId("2___0"));
400 assertThat(allPathIntents, hasIntentWithId("1___0"));
401
402 // Check that the low level intent 1 was correctly processed
403 assertThat(pathIntents,
404 hasIntentWithIdAndState("1___0", IntentState.INST_REQ));
405
406 // Check that the low level intent 2 was correctly processed
407 assertThat(pathIntents,
408 hasIntentWithIdAndState("2___0", IntentState.INST_REQ));
409
410 // Check that the low level intent 3 was correctly processed
411 assertThat(pathIntents,
412 hasIntentWithIdAndState("3___0", IntentState.INST_REQ));
413
414 // Receive notification from south-bound
415 IntentStateList isl = new IntentStateList();
416 isl.put("1___0", IntentState.INST_ACK);
417 isl.put("2___0", IntentState.INST_ACK);
418 isl.put("3___0", IntentState.INST_ACK);
419 isl.domainSwitchDpids.add(1L);
420 isl.domainSwitchDpids.add(2L);
421 isl.domainSwitchDpids.add(3L);
422 isl.domainSwitchDpids.add(4L);
423 runtime.entryUpdated(isl);
424
425 // Now check the results
426 final IntentMap processedHighLevelIntents = runtime.getHighLevelIntents();
427 assertThat(processedHighLevelIntents, notNullValue());
428
429 // Check that the high level intent 1 was correctly processed
430 assertThat(processedHighLevelIntents,
431 hasIntentWithIdAndState("1", IntentState.INST_ACK));
432
433 // Check that the high level intent 2 was correctly processed
434 assertThat(processedHighLevelIntents,
435 hasIntentWithIdAndState("2", IntentState.INST_ACK));
436
437 // Check that the high level intent 3 was correctly processed
438 assertThat(processedHighLevelIntents,
439 hasIntentWithIdAndState("3", IntentState.INST_ACK));
440
441 final IntentMap processedPathIntents = runtime.getPathIntents();
442 assertThat(processedPathIntents, notNullValue());
443
444 // Check that the low level intent 1 was correctly processed
445 assertThat(processedPathIntents,
446 hasIntentWithIdAndState("1___0", IntentState.INST_ACK));
447
448 // Check that the low level intent 2 was correctly processed
449 assertThat(processedPathIntents,
450 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
451
452 // Check that the low level intent 3 was correctly processed
453 assertThat(processedPathIntents,
454 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
455
Toshio Koidec2112c22014-06-05 19:59:15 -0700456 // Remove one of the links and check results
Ray Milkeydc659c42014-03-28 16:30:42 -0700457 final List<SwitchEvent> emptySwitchEvents = new LinkedList<>();
458 final List<PortEvent> emptyPortEvents = new LinkedList<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700459 final List<HostEvent> emptyHostEvents = new LinkedList<>();
Ray Milkeydc659c42014-03-28 16:30:42 -0700460 final List<LinkEvent> addedLinkEvents = new LinkedList<>();
461 final List<LinkEvent> removedLinkEvents = new LinkedList<>();
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700462 TopologyEvents topologyEvents;
Ray Milkeydc659c42014-03-28 16:30:42 -0700463
Ray Milkey9d671002014-05-29 17:24:29 -0700464 final MockTopology topology = mocks.getTopology();
Jonathan Harte37e4e22014-05-13 19:12:02 -0700465 topology.removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
466 topology.removeLink(2L, 21L, 1L, 12L);
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -0700467 LinkEvent linkEvent1 = new LinkEvent(new SwitchPort(1L, 12L), new SwitchPort(2L, 21L));
468 LinkEvent linkEvent2 = new LinkEvent(new SwitchPort(2L, 21L), new SwitchPort(1L, 12L));
Yuta HIGUCHIb8093642014-07-16 13:17:07 -0700469 linkEvent1.createStringAttribute(TopologyElement.TYPE, TopologyElement.TYPE_PACKET_LAYER);
470 linkEvent2.createStringAttribute(TopologyElement.TYPE, TopologyElement.TYPE_PACKET_LAYER);
Ray Milkeydc659c42014-03-28 16:30:42 -0700471 removedLinkEvents.add(linkEvent1);
472 removedLinkEvents.add(linkEvent2);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700473
474 topologyEvents = new TopologyEvents(0,
475 emptySwitchEvents,
476 emptySwitchEvents,
477 emptyPortEvents,
478 emptyPortEvents,
479 addedLinkEvents,
480 removedLinkEvents,
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700481 emptyHostEvents,
482 emptyHostEvents);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700483
484 runtime.topologyEvents(topologyEvents);
Ray Milkeydc659c42014-03-28 16:30:42 -0700485
486 // Check the high level intents.
487 final IntentMap highLevelIntentsAfterReroute = runtime.getHighLevelIntents();
488 assertThat(highLevelIntentsAfterReroute, notNullValue());
489
Ray Milkeydc659c42014-03-28 16:30:42 -0700490 // Check the states of the high level intents
Toshio Koidec2112c22014-06-05 19:59:15 -0700491 // Check that the high level intent 1 was correctly processed
492 assertThat(highLevelIntentsAfterReroute,
493 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
Ray Milkeydc659c42014-03-28 16:30:42 -0700494
Toshio Koidec2112c22014-06-05 19:59:15 -0700495 // Check that the high level intent 2 was not affected
496 assertThat(highLevelIntentsAfterReroute,
Ray Milkeydc659c42014-03-28 16:30:42 -0700497 hasIntentWithIdAndState("2", IntentState.INST_ACK));
498
Toshio Koidec2112c22014-06-05 19:59:15 -0700499 // Check that the high level intent 3 was not affected
500 assertThat(highLevelIntentsAfterReroute,
Ray Milkeydc659c42014-03-28 16:30:42 -0700501 hasIntentWithIdAndState("3", IntentState.INST_ACK));
502
Toshio Koidec2112c22014-06-05 19:59:15 -0700503 final IntentMap pathIntentsAfterReroute = runtime.getPathIntents();
504 assertThat(pathIntentsAfterReroute, notNullValue());
Ray Milkey6688cd82014-03-11 16:40:46 -0700505
Toshio Koidec2112c22014-06-05 19:59:15 -0700506 // Check that the low level intent 1 was correctly processed
507 assertThat(pathIntentsAfterReroute,
508 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
509 assertThat(pathIntentsAfterReroute,
510 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
511
512 // Check that the low level intent 2 was not affected
513 assertThat(pathIntentsAfterReroute,
514 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
515
516 // Check that the low level intent 3 was not affected
517 assertThat(pathIntentsAfterReroute,
518 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
519
520 // Receive notification from south-bound
521 isl = new IntentStateList();
522 isl.put("1___0", IntentState.DEL_ACK);
523 isl.put("1___1", IntentState.INST_ACK);
524 isl.domainSwitchDpids.add(1L);
525 isl.domainSwitchDpids.add(2L);
526 isl.domainSwitchDpids.add(4L);
527 runtime.entryUpdated(isl);
528
529 // Now check the results
530 final IntentMap reroutedHighLevelIntents = runtime.getHighLevelIntents();
531 assertThat(reroutedHighLevelIntents, notNullValue());
532
533 // Check that the high level intent 1 was correctly processed
534 assertThat(reroutedHighLevelIntents,
535 hasIntentWithIdAndState("1", IntentState.INST_ACK));
536
537 // Check that the high level intent 2 was not affected
538 assertThat(reroutedHighLevelIntents,
539 hasIntentWithIdAndState("2", IntentState.INST_ACK));
540
541 // Check that the high level intent 3 was not affected
542 assertThat(reroutedHighLevelIntents,
543 hasIntentWithIdAndState("3", IntentState.INST_ACK));
544
545 final IntentMap reroutedPathIntents = runtime.getPathIntents();
546 assertThat(processedPathIntents, notNullValue());
547
548 // Check that the low level intent 1 was correctly processed
Pavlin Radoslavove2238bc2014-06-09 18:05:23 -0700549 assertThat(reroutedPathIntents.getAllIntents(),
550 not(hasIntentWithId("1___0")));
Toshio Koidec2112c22014-06-05 19:59:15 -0700551 assertThat(reroutedPathIntents,
552 hasIntentWithIdAndState("1___1", IntentState.INST_ACK));
553
554 // Check that the low level intent 2 was not affected
555 assertThat(reroutedPathIntents,
556 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
557
558 // Check that the low level intent 3 was not affected
559 assertThat(reroutedPathIntents,
560 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
Ray Milkey6688cd82014-03-11 16:40:46 -0700561 }
Toshio Koideee698952014-06-11 13:35:30 -0700562
563 /**
564 * Test the result of executing a path calculation on an
565 * Intent Operation List and then forcing a reroute and
566 * an interrupt of a topology change event while the reroute
567 * is processed.
568 * <p/>
569 * A 3 path list is created, one of the links is removed, then
570 * the removed link is restored.
571 * The test checks that if the high level intent was marked
572 * as stale when a topology changed event was received while
573 * processing reroute then the stale high level intent is executed
574 * once again after completion of its reroute.
575 */
576 @Test
577 public void testIntentRerouteWithTopologyEventInterrupt() {
578
579 // create shortest path intents
580 final IntentOperationList opList = new IntentOperationList();
581 opList.add(Operator.ADD,
582 new ShortestPathIntent("1", 1L, 12L, LOCAL_PORT, 2L, 21L,
583 LOCAL_PORT));
584 opList.add(Operator.ADD,
585 new ShortestPathIntent("2", 1L, 14L, LOCAL_PORT, 4L, 41L,
586 LOCAL_PORT));
587 opList.add(Operator.ADD,
588 new ShortestPathIntent("3", 2L, 23L, LOCAL_PORT, 3L, 32L,
589 LOCAL_PORT));
590
591 // compile high-level intent operations into low-level intent
592 // operations (calculate paths)
593 final IntentOperationList pathIntentOpList =
594 runtime.executeIntentOperations(opList);
595 assertThat(pathIntentOpList, notNullValue());
596
597 final IntentMap highLevelIntents = runtime.getHighLevelIntents();
598 assertThat(highLevelIntents, notNullValue());
599
600 final Collection<Intent> allIntents = highLevelIntents.getAllIntents();
601 assertThat(allIntents, notNullValue());
602
603 // Should be one operation per path
604 assertThat(pathIntentOpList, hasSize(opList.size()));
605
606 // Should be a high level intent for each operation
607 assertThat(allIntents, hasSize(opList.size()));
608
609 // Check that we got a high level intent for each operation
610 assertThat(allIntents, hasIntentWithId("3"));
611 assertThat(allIntents, hasIntentWithId("2"));
612 assertThat(allIntents, hasIntentWithId("1"));
613
614 // Check that the high level intent 1 was correctly processed
615 assertThat(highLevelIntents,
616 hasIntentWithIdAndState("1", IntentState.INST_REQ));
617
618 // Check that the high level intent 2 was correctly processed
619 assertThat(highLevelIntents,
620 hasIntentWithIdAndState("2", IntentState.INST_REQ));
621
622 // Check that the high level intent 3 was correctly processed
623 assertThat(highLevelIntents,
624 hasIntentWithIdAndState("3", IntentState.INST_REQ));
625
626 final IntentMap pathIntents = runtime.getPathIntents();
627 assertThat(pathIntents, notNullValue());
628
629 final Collection<Intent> allPathIntents = pathIntents.getAllIntents();
630 assertThat(allPathIntents, notNullValue());
631
632 // Check that we got a low level intent for each operation
633 assertThat(allPathIntents, hasIntentWithId("3___0"));
634 assertThat(allPathIntents, hasIntentWithId("2___0"));
635 assertThat(allPathIntents, hasIntentWithId("1___0"));
636
637 // Check that the low level intent 1 was correctly processed
638 assertThat(pathIntents,
639 hasIntentWithIdAndState("1___0", IntentState.INST_REQ));
640
641 // Check that the low level intent 2 was correctly processed
642 assertThat(pathIntents,
643 hasIntentWithIdAndState("2___0", IntentState.INST_REQ));
644
645 // Check that the low level intent 3 was correctly processed
646 assertThat(pathIntents,
647 hasIntentWithIdAndState("3___0", IntentState.INST_REQ));
648
649 // Receive notification from south-bound
650 IntentStateList isl = new IntentStateList();
651 isl.put("1___0", IntentState.INST_ACK);
652 isl.put("2___0", IntentState.INST_ACK);
653 isl.put("3___0", IntentState.INST_ACK);
654 isl.domainSwitchDpids.add(1L);
655 isl.domainSwitchDpids.add(2L);
656 isl.domainSwitchDpids.add(3L);
657 isl.domainSwitchDpids.add(4L);
658 runtime.entryUpdated(isl);
659
660 // Now check the results
661 final IntentMap processedHighLevelIntents = runtime.getHighLevelIntents();
662 assertThat(processedHighLevelIntents, notNullValue());
663
664 // Check that the high level intent 1 was correctly processed
665 assertThat(processedHighLevelIntents,
666 hasIntentWithIdAndState("1", IntentState.INST_ACK));
667
668 // Check that the high level intent 2 was correctly processed
669 assertThat(processedHighLevelIntents,
670 hasIntentWithIdAndState("2", IntentState.INST_ACK));
671
672 // Check that the high level intent 3 was correctly processed
673 assertThat(processedHighLevelIntents,
674 hasIntentWithIdAndState("3", IntentState.INST_ACK));
675
676 final IntentMap processedPathIntents = runtime.getPathIntents();
677 assertThat(processedPathIntents, notNullValue());
678
679 // Check that the low level intent 1 was correctly processed
680 assertThat(processedPathIntents,
681 hasIntentWithIdAndState("1___0", IntentState.INST_ACK));
682
683 // Check that the low level intent 2 was correctly processed
684 assertThat(processedPathIntents,
685 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
686
687 // Check that the low level intent 3 was correctly processed
688 assertThat(processedPathIntents,
689 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
690
691
692 // Remove one of the links and check results
693 final List<SwitchEvent> emptySwitchEvents = new LinkedList<>();
694 final List<PortEvent> emptyPortEvents = new LinkedList<>();
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700695 final List<HostEvent> emptyHostEvents = new LinkedList<>();
Toshio Koideee698952014-06-11 13:35:30 -0700696 final List<LinkEvent> addedLinkEvents = new LinkedList<>();
697 final List<LinkEvent> removedLinkEvents = new LinkedList<>();
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700698 TopologyEvents topologyEvents;
Toshio Koideee698952014-06-11 13:35:30 -0700699
700 final MockTopology topology = mocks.getTopology();
701 topology.removeLink(1L, 12L, 2L, 21L); // This link is used by the intent "1"
702 topology.removeLink(2L, 21L, 1L, 12L);
Yuta HIGUCHIe2a4e172014-07-03 10:50:39 -0700703 final LinkEvent linkEvent1 = new LinkEvent(new SwitchPort(1L, 12L), new SwitchPort(2L, 21L));
704 final LinkEvent linkEvent2 = new LinkEvent(new SwitchPort(2L, 21L), new SwitchPort(1L, 12L));
Yuta HIGUCHIb8093642014-07-16 13:17:07 -0700705 linkEvent1.createStringAttribute(TopologyElement.TYPE, TopologyElement.TYPE_PACKET_LAYER);
706 linkEvent2.createStringAttribute(TopologyElement.TYPE, TopologyElement.TYPE_PACKET_LAYER);
Toshio Koideee698952014-06-11 13:35:30 -0700707 removedLinkEvents.add(linkEvent1);
708 removedLinkEvents.add(linkEvent2);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700709
710 topologyEvents = new TopologyEvents(0,
711 emptySwitchEvents,
712 emptySwitchEvents,
713 emptyPortEvents,
714 emptyPortEvents,
715 addedLinkEvents,
716 removedLinkEvents,
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700717 emptyHostEvents,
718 emptyHostEvents);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700719
720 runtime.topologyEvents(topologyEvents);
Toshio Koideee698952014-06-11 13:35:30 -0700721
722 // Check the high level intents.
723 final IntentMap highLevelIntentsAfterReroute = runtime.getHighLevelIntents();
724 assertThat(highLevelIntentsAfterReroute, notNullValue());
725
726 // Check the states of the high level intents
727 // Check that the high level intent 1 was correctly processed
728 assertThat(highLevelIntentsAfterReroute,
729 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
730
731 // Check that the high level intent 2 was not affected
732 assertThat(highLevelIntentsAfterReroute,
733 hasIntentWithIdAndState("2", IntentState.INST_ACK));
734
735 // Check that the high level intent 3 was not affected
736 assertThat(highLevelIntentsAfterReroute,
737 hasIntentWithIdAndState("3", IntentState.INST_ACK));
738
739 final IntentMap pathIntentsAfterReroute = runtime.getPathIntents();
740 assertThat(pathIntentsAfterReroute, notNullValue());
741
742 // Check that the low level intent 1 was correctly processed
743 assertThat(pathIntentsAfterReroute,
744 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
745 assertThat(pathIntentsAfterReroute,
746 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
747
748 // Check that the low level intent 2 was not affected
749 assertThat(pathIntentsAfterReroute,
750 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
751
752 // Check that the low level intent 3 was not affected
753 assertThat(pathIntentsAfterReroute,
754 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
755
756 // Interrupt by topology changed event while the reroute
757 removedLinkEvents.clear();
758 addedLinkEvents.clear();
759 topology.addBidirectionalLinks(1L, 12L, 2L, 21L); // Restoration of the failure
760 addedLinkEvents.add(linkEvent1);
761 addedLinkEvents.add(linkEvent2);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700762
763 topologyEvents = new TopologyEvents(0,
764 emptySwitchEvents,
765 emptySwitchEvents,
766 emptyPortEvents,
767 emptyPortEvents,
768 addedLinkEvents,
769 removedLinkEvents,
Yuta HIGUCHIbfc77f02014-07-14 22:50:25 -0700770 emptyHostEvents,
771 emptyHostEvents);
Pavlin Radoslavov4eaab992014-07-03 18:39:42 -0700772
773 runtime.topologyEvents(topologyEvents);
Toshio Koideee698952014-06-11 13:35:30 -0700774
775 // Check the high level intents.
776 final IntentMap highLevelIntentsAfterInterrupt = runtime.getHighLevelIntents();
777 assertThat(highLevelIntentsAfterInterrupt, notNullValue());
778
779 // Check the states of the high level intents
780 // Check that the high level intent 1 was not affected
781 assertThat(highLevelIntentsAfterInterrupt,
782 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
783
784 final IntentMap pathIntentsAfterInterrupt = runtime.getPathIntents();
785 assertThat(pathIntentsAfterInterrupt, notNullValue());
786
787 // Check that the low level intent 1 was not affected
788 assertThat(pathIntentsAfterInterrupt,
789 hasIntentWithIdAndState("1___0", IntentState.DEL_REQ));
790 assertThat(pathIntentsAfterInterrupt,
791 hasIntentWithIdAndState("1___1", IntentState.INST_REQ));
792
793 // Receive notification from south-bound
794 isl = new IntentStateList();
795 isl.put("1___0", IntentState.DEL_ACK);
796 isl.put("1___1", IntentState.INST_ACK);
797 isl.domainSwitchDpids.add(1L);
798 isl.domainSwitchDpids.add(2L);
799 isl.domainSwitchDpids.add(4L);
800 runtime.entryUpdated(isl);
801
802 // Now check the results
803 final IntentMap reroutedHighLevelIntents = runtime.getHighLevelIntents();
804 assertThat(reroutedHighLevelIntents, notNullValue());
805
806 // Check that the high level intent 1 was correctly processed
807 // It should be rerouted once again
808 assertThat(reroutedHighLevelIntents,
809 hasIntentWithIdAndState("1", IntentState.REROUTE_REQ));
810
811 // Check that the high level intent 2 was not affected
812 assertThat(reroutedHighLevelIntents,
813 hasIntentWithIdAndState("2", IntentState.INST_ACK));
814
815 // Check that the high level intent 3 was not affected
816 assertThat(reroutedHighLevelIntents,
817 hasIntentWithIdAndState("3", IntentState.INST_ACK));
818
819 final IntentMap reroutedPathIntents = runtime.getPathIntents();
820 assertThat(processedPathIntents, notNullValue());
821
822 // Check that the low level intent 1 was correctly processed
823 assertThat(reroutedPathIntents.getAllIntents(),
824 not(hasIntentWithId("1___0")));
825 assertThat(reroutedPathIntents,
826 hasIntentWithIdAndState("1___1", IntentState.DEL_REQ));
827 assertThat(reroutedPathIntents,
828 hasIntentWithIdAndState("1___2", IntentState.INST_REQ));
829
830 // Check that the low level intent 2 was not affected
831 assertThat(reroutedPathIntents,
832 hasIntentWithIdAndState("2___0", IntentState.INST_ACK));
833
834 // Check that the low level intent 3 was not affected
835 assertThat(reroutedPathIntents,
836 hasIntentWithIdAndState("3___0", IntentState.INST_ACK));
837 }
Yuta HIGUCHI91a8f502014-06-17 10:15:29 -0700838 // CHECKSTYLE:ON method too long
839
Ray Milkey6688cd82014-03-11 16:40:46 -0700840}