blob: a6871c870e9350ea742f801940be9f6d3962b3e3 [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
18import org.hamcrest.Description;
Ray Milkeyd03eda02015-01-09 14:58:48 -080019import org.hamcrest.TypeSafeDiagnosingMatcher;
Yafit Hadar5796d972015-10-15 13:16:11 +030020import org.onlab.util.HexString;
21import org.onosproject.net.OduSignalId;
Ray Milkeyd03eda02015-01-09 14:58:48 -080022import org.onosproject.net.flow.instructions.Instruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030023import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
24import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
25import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
26import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
27import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
28import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
29import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
32import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
33import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
34import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080035
36import com.fasterxml.jackson.databind.JsonNode;
37
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 /**
126 * Matches the contents of a mod lambda instruction.
127 *
128 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800129 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800130 * @return true if contents match, false otherwise
131 */
132 private boolean matchModLambdaInstruction(JsonNode instructionJson,
133 Description description) {
134 ModLambdaInstruction instructionToMatch =
135 (ModLambdaInstruction) instruction;
136 final String jsonSubtype = instructionJson.get("subtype").textValue();
137 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
138 description.appendText("subtype was " + jsonSubtype);
139 return false;
140 }
141
142 final String jsonType = instructionJson.get("type").textValue();
143 if (!instructionToMatch.type().name().equals(jsonType)) {
144 description.appendText("type was " + jsonType);
145 return false;
146 }
147
148 final long jsonLambda = instructionJson.get("lambda").shortValue();
149 if (instructionToMatch.lambda() != jsonLambda) {
150 description.appendText("lambda was " + jsonLambda);
151 return false;
152 }
153
154 return true;
155 }
156
157 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300158 * Matches the contents of a mod OCh singal instruction.
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700159 *
160 * @param instructionJson JSON instruction to match
161 * @param description Description object used for recording errors
162 * @return true if contents matches, false otherwise
163 */
164 private boolean matchModOchSingalInstruction(JsonNode instructionJson,
165 Description description) {
166 ModOchSignalInstruction instructionToMatch =
167 (ModOchSignalInstruction) instruction;
168
169 String jsonSubType = instructionJson.get("subtype").textValue();
170 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
171 description.appendText("subtype was " + jsonSubType);
172 return false;
173 }
174
175 String jsonType = instructionJson.get("type").textValue();
176 if (!instructionToMatch.type().name().equals(jsonType)) {
177 description.appendText("type was " + jsonType);
178 return false;
179 }
180
181 String jsonGridType = instructionJson.get("gridType").textValue();
182 if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
183 description.appendText("gridType was " + jsonGridType);
184 return false;
185 }
186
187 String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
188 if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
189 description.appendText("channelSpacing was " + jsonChannelSpacing);
190 return false;
191 }
192
193 int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
194 if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
195 description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
196 return false;
197 }
198
199 int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
200 if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
201 description.appendText("slotGranularity was " + jsonSlotGranularity);
202 return false;
203 }
204
205 return true;
206 }
207
208 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300209 * Matches the contents of a mod ODU singal Id instruction.
210 *
211 * @param instructionJson JSON instruction to match
212 * @param description Description object used for recording errors
213 * @return true if contents matches, false otherwise
214 */
215 private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
216 Description description) {
217 ModOduSignalIdInstruction instructionToMatch =
218 (ModOduSignalIdInstruction) instruction;
219 String jsonSubType = instructionJson.get("subtype").textValue();
220 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
221 description.appendText("subtype was " + jsonSubType);
222 return false;
223 }
224 String jsonType = instructionJson.get("type").textValue();
225 if (!instructionToMatch.type().name().equals(jsonType)) {
226 description.appendText("type was " + jsonType);
227 return false;
228 }
229 final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
230 int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
231 int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
Jian Li68c4fc42016-01-11 16:07:03 -0800232 byte[] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
Yafit Hadar5796d972015-10-15 13:16:11 +0300233 OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
234 if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
235 description.appendText("oduSignalId was " + instructionToMatch);
236 return false;
237 }
238 return true;
239 }
240
241
242 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800243 * Matches the contents of a mod Ethernet instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800244 *
245 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800246 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800247 * @return true if contents match, false otherwise
248 */
249 private boolean matchModEtherInstruction(JsonNode instructionJson,
250 Description description) {
251 ModEtherInstruction instructionToMatch =
252 (ModEtherInstruction) instruction;
253 final String jsonSubtype = instructionJson.get("subtype").textValue();
254 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
255 description.appendText("subtype was " + jsonSubtype);
256 return false;
257 }
258
259 final String jsonType = instructionJson.get("type").textValue();
260 if (!instructionToMatch.type().name().equals(jsonType)) {
261 description.appendText("type was " + jsonType);
262 return false;
263 }
264
265 final String jsonMac = instructionJson.get("mac").textValue();
266 final String mac = instructionToMatch.mac().toString();
267 if (!mac.equals(jsonMac)) {
268 description.appendText("mac was " + jsonMac);
269 return false;
270 }
271
272 return true;
273 }
274
275 /**
276 * Matches the contents of a mod vlan id instruction.
277 *
278 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800279 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800280 * @return true if contents match, false otherwise
281 */
282 private boolean matchModVlanIdInstruction(JsonNode instructionJson,
283 Description description) {
284 ModVlanIdInstruction instructionToMatch =
285 (ModVlanIdInstruction) instruction;
286 final String jsonSubtype = instructionJson.get("subtype").textValue();
287 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
288 description.appendText("subtype was " + jsonSubtype);
289 return false;
290 }
291
292 final String jsonType = instructionJson.get("type").textValue();
293 if (!instructionToMatch.type().name().equals(jsonType)) {
294 description.appendText("type was " + jsonType);
295 return false;
296 }
297
298 final short jsonVlanId = instructionJson.get("vlanId").shortValue();
299 final short vlanId = instructionToMatch.vlanId().toShort();
300 if (jsonVlanId != vlanId) {
301 description.appendText("vlan id was " + jsonVlanId);
302 return false;
303 }
304
305 return true;
306 }
307
308 /**
309 * Matches the contents of a mod vlan pcp instruction.
310 *
311 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800312 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800313 * @return true if contents match, false otherwise
314 */
315 private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
316 Description description) {
317 ModVlanPcpInstruction instructionToMatch =
318 (ModVlanPcpInstruction) instruction;
319 final String jsonSubtype = instructionJson.get("subtype").textValue();
320 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
321 description.appendText("subtype was " + jsonSubtype);
322 return false;
323 }
324
325 final String jsonType = instructionJson.get("type").textValue();
326 if (!instructionToMatch.type().name().equals(jsonType)) {
327 description.appendText("type was " + jsonType);
328 return false;
329 }
330
331 final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
332 final short vlanId = instructionToMatch.vlanPcp();
333 if (jsonVlanPcp != vlanId) {
334 description.appendText("vlan pcp was " + jsonVlanPcp);
335 return false;
336 }
337
338 return true;
339 }
340
341 /**
342 * Matches the contents of a mod ip instruction.
343 *
344 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800345 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800346 * @return true if contents match, false otherwise
347 */
348 private boolean matchModIpInstruction(JsonNode instructionJson,
349 Description description) {
350 ModIPInstruction instructionToMatch =
351 (ModIPInstruction) instruction;
352 final String jsonSubtype = instructionJson.get("subtype").textValue();
353 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
354 description.appendText("subtype was " + jsonSubtype);
355 return false;
356 }
357
358 final String jsonType = instructionJson.get("type").textValue();
359 if (!instructionToMatch.type().name().equals(jsonType)) {
360 description.appendText("type was " + jsonType);
361 return false;
362 }
363
364 final String jsonIp = instructionJson.get("ip").textValue();
365 final String ip = instructionToMatch.ip().toString();
366 if (!ip.equals(jsonIp)) {
367 description.appendText("ip was " + jsonIp);
368 return false;
369 }
370
371 return true;
372 }
373
374 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800375 * Matches the contents of a mod IPv6 Flow Label instruction.
376 *
377 * @param instructionJson JSON instruction to match
378 * @param description Description object used for recording errors
379 * @return true if contents match, false otherwise
380 */
381 private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
382 Description description) {
383 ModIPv6FlowLabelInstruction instructionToMatch =
384 (ModIPv6FlowLabelInstruction) instruction;
385 final String jsonSubtype = instructionJson.get("subtype").textValue();
386 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
387 description.appendText("subtype was " + jsonSubtype);
388 return false;
389 }
390
391 final String jsonType = instructionJson.get("type").textValue();
392 if (!instructionToMatch.type().name().equals(jsonType)) {
393 description.appendText("type was " + jsonType);
394 return false;
395 }
396
397 final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
398 final int flowLabel = instructionToMatch.flowLabel();
399 if (flowLabel != jsonFlowLabel) {
400 description.appendText("IPv6 flow label was " + jsonFlowLabel);
401 return false;
402 }
403
404 return true;
405 }
406
407 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800408 * Matches the contents of a mod MPLS label instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800409 *
410 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800411 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800412 * @return true if contents match, false otherwise
413 */
414 private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
415 Description description) {
416 ModMplsLabelInstruction instructionToMatch =
417 (ModMplsLabelInstruction) instruction;
418 final String jsonSubtype = instructionJson.get("subtype").textValue();
419 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
420 description.appendText("subtype was " + jsonSubtype);
421 return false;
422 }
423
424 final String jsonType = instructionJson.get("type").textValue();
425 if (!instructionToMatch.type().name().equals(jsonType)) {
426 description.appendText("type was " + jsonType);
427 return false;
428 }
429
430 final int jsonLabel = instructionJson.get("label").intValue();
Ray Milkey125572b2016-02-22 16:48:17 -0800431 final int label = instructionToMatch.label().toInt();
Ray Milkeyd03eda02015-01-09 14:58:48 -0800432 if (label != jsonLabel) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800433 description.appendText("MPLS label was " + jsonLabel);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800434 return false;
435 }
436
437 return true;
438 }
439
440 @Override
441 public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
442
443 // check type
444 final JsonNode jsonTypeNode = jsonInstruction.get("type");
445 final String jsonType = jsonTypeNode.textValue();
446 final String type = instruction.type().name();
447 if (!jsonType.equals(type)) {
448 description.appendText("type was " + type);
449 return false;
450 }
451
452 if (instruction instanceof PushHeaderInstructions) {
453 return matchPushHeaderInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800454 } else if (instruction instanceof OutputInstruction) {
455 return matchOutputInstruction(jsonInstruction, description);
456 } else if (instruction instanceof ModLambdaInstruction) {
457 return matchModLambdaInstruction(jsonInstruction, description);
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700458 } else if (instruction instanceof ModOchSignalInstruction) {
459 return matchModOchSingalInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800460 } else if (instruction instanceof ModEtherInstruction) {
461 return matchModEtherInstruction(jsonInstruction, description);
462 } else if (instruction instanceof ModVlanIdInstruction) {
463 return matchModVlanIdInstruction(jsonInstruction, description);
464 } else if (instruction instanceof ModVlanPcpInstruction) {
465 return matchModVlanPcpInstruction(jsonInstruction, description);
466 } else if (instruction instanceof ModIPInstruction) {
467 return matchModIpInstruction(jsonInstruction, description);
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800468 } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
469 return matchModIPv6FlowLabelInstruction(jsonInstruction,
470 description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800471 } else if (instruction instanceof ModMplsLabelInstruction) {
472 return matchModMplsLabelInstruction(jsonInstruction, description);
Yafit Hadar5796d972015-10-15 13:16:11 +0300473 } else if (instruction instanceof ModOduSignalIdInstruction) {
474 return matchModOduSingalIdInstruction(jsonInstruction, description);
Brian O'Connorb75a67a2015-10-07 14:34:06 -0700475 } else if (instruction instanceof NoActionInstruction) {
476 return true;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800477 }
478
479 return false;
480 }
481
482 @Override
483 public void describeTo(Description description) {
484 description.appendText(instruction.toString());
485 }
486
487 /**
488 * Factory to allocate an instruction matcher.
489 *
490 * @param instruction instruction object we are looking for
491 * @return matcher
492 */
493 public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
494 return new InstructionJsonMatcher(instruction);
495 }
496}