blob: 2ed7a8264f023b135bdaea6c9c1624efc6d00866 [file] [log] [blame]
Ray Milkeyd03eda02015-01-09 14:58:48 -08001/*
2 * Copyright 2015 Open Networking Laboratory
3 *
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 */
16package org.onosproject.codec.impl;
17
Jian Lice8c5602016-03-03 21:43:24 -080018import com.fasterxml.jackson.databind.JsonNode;
Ray Milkeyd03eda02015-01-09 14:58:48 -080019import org.hamcrest.Description;
Ray Milkeyd03eda02015-01-09 14:58:48 -080020import org.hamcrest.TypeSafeDiagnosingMatcher;
Yafit Hadar5796d972015-10-15 13:16:11 +030021import org.onlab.util.HexString;
22import org.onosproject.net.OduSignalId;
Ray Milkeyd03eda02015-01-09 14:58:48 -080023import org.onosproject.net.flow.instructions.Instruction;
Jian Lice8c5602016-03-03 21:43:24 -080024import org.onosproject.net.flow.instructions.Instructions.GroupInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030025import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
26import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
27import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
28import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
29import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
32import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
33import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
34import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
35import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
36import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080037
Ray Milkeyd03eda02015-01-09 14:58:48 -080038/**
39 * Hamcrest matcher for instructions.
40 */
Ray Milkeydb358082015-01-13 16:34:38 -080041public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
Ray Milkeyd03eda02015-01-09 14:58:48 -080042
43 private final Instruction instruction;
44
Ray Milkeydb358082015-01-13 16:34:38 -080045 private InstructionJsonMatcher(Instruction instructionValue) {
Ray Milkeyd03eda02015-01-09 14:58:48 -080046 instruction = instructionValue;
47 }
48
49 /**
50 * Matches the contents of a push header instruction.
51 *
52 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080053 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -080054 * @return true if contents match, false otherwise
55 */
56 private boolean matchPushHeaderInstruction(JsonNode instructionJson,
57 Description description) {
58 PushHeaderInstructions instructionToMatch =
59 (PushHeaderInstructions) instruction;
60 final String jsonSubtype = instructionJson.get("subtype").textValue();
61 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
62 description.appendText("subtype was " + jsonSubtype);
63 return false;
64 }
65
66 final String jsonType = instructionJson.get("type").textValue();
67 if (!instructionToMatch.type().name().equals(jsonType)) {
68 description.appendText("type was " + jsonType);
69 return false;
70 }
71
72 final JsonNode ethJson = instructionJson.get("ethernetType");
73 if (ethJson == null) {
74 description.appendText("ethernetType was not null");
75 return false;
76 }
77
alshabib7b808c52015-06-26 14:22:24 -070078 if (instructionToMatch.ethernetType().toShort() != ethJson.asInt()) {
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080079 description.appendText("ethernetType was " + ethJson);
Ray Milkeyd03eda02015-01-09 14:58:48 -080080 return false;
81 }
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080082
Ray Milkeyd03eda02015-01-09 14:58:48 -080083 return true;
84 }
85
86 /**
87 * Matches the contents of an output instruction.
88 *
89 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080090 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -080091 * @return true if contents match, false otherwise
92 */
93 private boolean matchOutputInstruction(JsonNode instructionJson,
94 Description description) {
Ray Milkeyd03eda02015-01-09 14:58:48 -080095 final String jsonType = instructionJson.get("type").textValue();
Andrea Campanella5df35952015-12-08 15:46:49 -080096 OutputInstruction instructionToMatch = (OutputInstruction) instruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080097 if (!instructionToMatch.type().name().equals(jsonType)) {
98 description.appendText("type was " + jsonType);
99 return false;
100 }
101
Andrea Campanella5df35952015-12-08 15:46:49 -0800102 if (instructionJson.get("port").isLong() ||
103 instructionJson.get("port").isInt()) {
104 final long jsonPort = instructionJson.get("port").asLong();
105 if (instructionToMatch.port().toLong() != (jsonPort)) {
106 description.appendText("port was " + jsonPort);
107 return false;
108 }
109 } else if (instructionJson.get("port").isTextual()) {
110 final String jsonPort = instructionJson.get("port").textValue();
111 if (!instructionToMatch.port().toString().equals(jsonPort)) {
112 description.appendText("port was " + jsonPort);
113 return false;
114 }
115 } else {
116 final String jsonPort = instructionJson.get("port").toString();
117 description.appendText("Unmathcing types ");
118 description.appendText("instructionToMatch " + instructionToMatch.port().toString());
119 description.appendText("jsonPort " + jsonPort);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800120 }
121
122 return true;
123 }
124
125 /**
Jian Lice8c5602016-03-03 21:43:24 -0800126 * Matches the contents of a group instruction.
127 *
128 * @param instructionJson JSON instruction to match
129 * @param description Description object used for recording errors
130 * @return true if contents match, false otherwise
131 */
132 private boolean matchGroupInstruction(JsonNode instructionJson,
133 Description description) {
134 final String jsonType = instructionJson.get("type").textValue();
135 GroupInstruction instructionToMatch = (GroupInstruction) instruction;
136 if (!instructionToMatch.type().name().equals(jsonType)) {
137 description.appendText("type was " + jsonType);
138 return false;
139 }
140
141 if (instructionJson.get("groupId").isInt()) {
142 final int jsonGroupId = instructionJson.get("groupId").asInt();
143 if (instructionToMatch.groupId().id() != jsonGroupId) {
144 description.appendText("groupId was " + jsonGroupId);
145 return false;
146 }
147 }
148
149 return true;
150 }
151
152 /**
Ray Milkeyd03eda02015-01-09 14:58:48 -0800153 * Matches the contents of a mod lambda instruction.
154 *
155 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800156 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800157 * @return true if contents match, false otherwise
158 */
159 private boolean matchModLambdaInstruction(JsonNode instructionJson,
160 Description description) {
161 ModLambdaInstruction instructionToMatch =
162 (ModLambdaInstruction) instruction;
163 final String jsonSubtype = instructionJson.get("subtype").textValue();
164 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
165 description.appendText("subtype was " + jsonSubtype);
166 return false;
167 }
168
169 final String jsonType = instructionJson.get("type").textValue();
170 if (!instructionToMatch.type().name().equals(jsonType)) {
171 description.appendText("type was " + jsonType);
172 return false;
173 }
174
175 final long jsonLambda = instructionJson.get("lambda").shortValue();
176 if (instructionToMatch.lambda() != jsonLambda) {
177 description.appendText("lambda was " + jsonLambda);
178 return false;
179 }
180
181 return true;
182 }
183
184 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300185 * Matches the contents of a mod OCh singal instruction.
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700186 *
187 * @param instructionJson JSON instruction to match
188 * @param description Description object used for recording errors
189 * @return true if contents matches, false otherwise
190 */
191 private boolean matchModOchSingalInstruction(JsonNode instructionJson,
192 Description description) {
193 ModOchSignalInstruction instructionToMatch =
194 (ModOchSignalInstruction) instruction;
195
196 String jsonSubType = instructionJson.get("subtype").textValue();
197 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
198 description.appendText("subtype was " + jsonSubType);
199 return false;
200 }
201
202 String jsonType = instructionJson.get("type").textValue();
203 if (!instructionToMatch.type().name().equals(jsonType)) {
204 description.appendText("type was " + jsonType);
205 return false;
206 }
207
208 String jsonGridType = instructionJson.get("gridType").textValue();
209 if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
210 description.appendText("gridType was " + jsonGridType);
211 return false;
212 }
213
214 String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
215 if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
216 description.appendText("channelSpacing was " + jsonChannelSpacing);
217 return false;
218 }
219
220 int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
221 if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
222 description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
223 return false;
224 }
225
226 int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
227 if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
228 description.appendText("slotGranularity was " + jsonSlotGranularity);
229 return false;
230 }
231
232 return true;
233 }
234
235 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300236 * Matches the contents of a mod ODU singal Id instruction.
237 *
238 * @param instructionJson JSON instruction to match
239 * @param description Description object used for recording errors
240 * @return true if contents matches, false otherwise
241 */
242 private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
243 Description description) {
244 ModOduSignalIdInstruction instructionToMatch =
245 (ModOduSignalIdInstruction) instruction;
246 String jsonSubType = instructionJson.get("subtype").textValue();
247 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
248 description.appendText("subtype was " + jsonSubType);
249 return false;
250 }
251 String jsonType = instructionJson.get("type").textValue();
252 if (!instructionToMatch.type().name().equals(jsonType)) {
253 description.appendText("type was " + jsonType);
254 return false;
255 }
256 final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
257 int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
258 int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
Jian Li68c4fc42016-01-11 16:07:03 -0800259 byte[] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
Yafit Hadar5796d972015-10-15 13:16:11 +0300260 OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
261 if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
262 description.appendText("oduSignalId was " + instructionToMatch);
263 return false;
264 }
265 return true;
266 }
267
268
269 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800270 * Matches the contents of a mod Ethernet instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800271 *
272 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800273 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800274 * @return true if contents match, false otherwise
275 */
276 private boolean matchModEtherInstruction(JsonNode instructionJson,
277 Description description) {
278 ModEtherInstruction instructionToMatch =
279 (ModEtherInstruction) instruction;
280 final String jsonSubtype = instructionJson.get("subtype").textValue();
281 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
282 description.appendText("subtype was " + jsonSubtype);
283 return false;
284 }
285
286 final String jsonType = instructionJson.get("type").textValue();
287 if (!instructionToMatch.type().name().equals(jsonType)) {
288 description.appendText("type was " + jsonType);
289 return false;
290 }
291
292 final String jsonMac = instructionJson.get("mac").textValue();
293 final String mac = instructionToMatch.mac().toString();
294 if (!mac.equals(jsonMac)) {
295 description.appendText("mac was " + jsonMac);
296 return false;
297 }
298
299 return true;
300 }
301
302 /**
303 * Matches the contents of a mod vlan id instruction.
304 *
305 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800306 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800307 * @return true if contents match, false otherwise
308 */
309 private boolean matchModVlanIdInstruction(JsonNode instructionJson,
310 Description description) {
311 ModVlanIdInstruction instructionToMatch =
312 (ModVlanIdInstruction) instruction;
313 final String jsonSubtype = instructionJson.get("subtype").textValue();
314 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
315 description.appendText("subtype was " + jsonSubtype);
316 return false;
317 }
318
319 final String jsonType = instructionJson.get("type").textValue();
320 if (!instructionToMatch.type().name().equals(jsonType)) {
321 description.appendText("type was " + jsonType);
322 return false;
323 }
324
325 final short jsonVlanId = instructionJson.get("vlanId").shortValue();
326 final short vlanId = instructionToMatch.vlanId().toShort();
327 if (jsonVlanId != vlanId) {
328 description.appendText("vlan id was " + jsonVlanId);
329 return false;
330 }
331
332 return true;
333 }
334
335 /**
336 * Matches the contents of a mod vlan pcp instruction.
337 *
338 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800339 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800340 * @return true if contents match, false otherwise
341 */
342 private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
343 Description description) {
344 ModVlanPcpInstruction instructionToMatch =
345 (ModVlanPcpInstruction) instruction;
346 final String jsonSubtype = instructionJson.get("subtype").textValue();
347 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
348 description.appendText("subtype was " + jsonSubtype);
349 return false;
350 }
351
352 final String jsonType = instructionJson.get("type").textValue();
353 if (!instructionToMatch.type().name().equals(jsonType)) {
354 description.appendText("type was " + jsonType);
355 return false;
356 }
357
358 final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
359 final short vlanId = instructionToMatch.vlanPcp();
360 if (jsonVlanPcp != vlanId) {
361 description.appendText("vlan pcp was " + jsonVlanPcp);
362 return false;
363 }
364
365 return true;
366 }
367
368 /**
369 * Matches the contents of a mod ip instruction.
370 *
371 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800372 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800373 * @return true if contents match, false otherwise
374 */
375 private boolean matchModIpInstruction(JsonNode instructionJson,
376 Description description) {
377 ModIPInstruction instructionToMatch =
378 (ModIPInstruction) instruction;
379 final String jsonSubtype = instructionJson.get("subtype").textValue();
380 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
381 description.appendText("subtype was " + jsonSubtype);
382 return false;
383 }
384
385 final String jsonType = instructionJson.get("type").textValue();
386 if (!instructionToMatch.type().name().equals(jsonType)) {
387 description.appendText("type was " + jsonType);
388 return false;
389 }
390
391 final String jsonIp = instructionJson.get("ip").textValue();
392 final String ip = instructionToMatch.ip().toString();
393 if (!ip.equals(jsonIp)) {
394 description.appendText("ip was " + jsonIp);
395 return false;
396 }
397
398 return true;
399 }
400
401 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800402 * Matches the contents of a mod IPv6 Flow Label instruction.
403 *
404 * @param instructionJson JSON instruction to match
405 * @param description Description object used for recording errors
406 * @return true if contents match, false otherwise
407 */
408 private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
409 Description description) {
410 ModIPv6FlowLabelInstruction instructionToMatch =
411 (ModIPv6FlowLabelInstruction) instruction;
412 final String jsonSubtype = instructionJson.get("subtype").textValue();
413 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
414 description.appendText("subtype was " + jsonSubtype);
415 return false;
416 }
417
418 final String jsonType = instructionJson.get("type").textValue();
419 if (!instructionToMatch.type().name().equals(jsonType)) {
420 description.appendText("type was " + jsonType);
421 return false;
422 }
423
424 final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
425 final int flowLabel = instructionToMatch.flowLabel();
426 if (flowLabel != jsonFlowLabel) {
427 description.appendText("IPv6 flow label was " + jsonFlowLabel);
428 return false;
429 }
430
431 return true;
432 }
433
434 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800435 * Matches the contents of a mod MPLS label instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800436 *
437 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800438 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800439 * @return true if contents match, false otherwise
440 */
441 private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
442 Description description) {
443 ModMplsLabelInstruction instructionToMatch =
444 (ModMplsLabelInstruction) instruction;
445 final String jsonSubtype = instructionJson.get("subtype").textValue();
446 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
447 description.appendText("subtype was " + jsonSubtype);
448 return false;
449 }
450
451 final String jsonType = instructionJson.get("type").textValue();
452 if (!instructionToMatch.type().name().equals(jsonType)) {
453 description.appendText("type was " + jsonType);
454 return false;
455 }
456
457 final int jsonLabel = instructionJson.get("label").intValue();
Ray Milkey125572b2016-02-22 16:48:17 -0800458 final int label = instructionToMatch.label().toInt();
Ray Milkeyd03eda02015-01-09 14:58:48 -0800459 if (label != jsonLabel) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800460 description.appendText("MPLS label was " + jsonLabel);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800461 return false;
462 }
463
464 return true;
465 }
466
467 @Override
468 public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
469
470 // check type
471 final JsonNode jsonTypeNode = jsonInstruction.get("type");
472 final String jsonType = jsonTypeNode.textValue();
473 final String type = instruction.type().name();
474 if (!jsonType.equals(type)) {
475 description.appendText("type was " + type);
476 return false;
477 }
478
479 if (instruction instanceof PushHeaderInstructions) {
480 return matchPushHeaderInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800481 } else if (instruction instanceof OutputInstruction) {
482 return matchOutputInstruction(jsonInstruction, description);
Jian Lice8c5602016-03-03 21:43:24 -0800483 } else if (instruction instanceof GroupInstruction) {
484 return matchGroupInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800485 } else if (instruction instanceof ModLambdaInstruction) {
486 return matchModLambdaInstruction(jsonInstruction, description);
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700487 } else if (instruction instanceof ModOchSignalInstruction) {
488 return matchModOchSingalInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800489 } else if (instruction instanceof ModEtherInstruction) {
490 return matchModEtherInstruction(jsonInstruction, description);
491 } else if (instruction instanceof ModVlanIdInstruction) {
492 return matchModVlanIdInstruction(jsonInstruction, description);
493 } else if (instruction instanceof ModVlanPcpInstruction) {
494 return matchModVlanPcpInstruction(jsonInstruction, description);
495 } else if (instruction instanceof ModIPInstruction) {
496 return matchModIpInstruction(jsonInstruction, description);
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800497 } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
498 return matchModIPv6FlowLabelInstruction(jsonInstruction,
499 description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800500 } else if (instruction instanceof ModMplsLabelInstruction) {
501 return matchModMplsLabelInstruction(jsonInstruction, description);
Yafit Hadar5796d972015-10-15 13:16:11 +0300502 } else if (instruction instanceof ModOduSignalIdInstruction) {
503 return matchModOduSingalIdInstruction(jsonInstruction, description);
Brian O'Connorb75a67a2015-10-07 14:34:06 -0700504 } else if (instruction instanceof NoActionInstruction) {
505 return true;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800506 }
507
508 return false;
509 }
510
511 @Override
512 public void describeTo(Description description) {
513 description.appendText(instruction.toString());
514 }
515
516 /**
517 * Factory to allocate an instruction matcher.
518 *
519 * @param instruction instruction object we are looking for
520 * @return matcher
521 */
522 public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
523 return new InstructionJsonMatcher(instruction);
524 }
525}