blob: 4c49d641486ae488370423176965f9be1909656f [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.DropInstruction;
24import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
25import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
26import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModLambdaInstruction;
27import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
28import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
29import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
30import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
32import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
33import org.onosproject.net.flow.instructions.L2ModificationInstruction.PushHeaderInstructions;
34import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
35import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080036
37import com.fasterxml.jackson.databind.JsonNode;
38
Ray Milkeyd03eda02015-01-09 14:58:48 -080039/**
40 * Hamcrest matcher for instructions.
41 */
Ray Milkeydb358082015-01-13 16:34:38 -080042public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
Ray Milkeyd03eda02015-01-09 14:58:48 -080043
44 private final Instruction instruction;
45
Ray Milkeydb358082015-01-13 16:34:38 -080046 private InstructionJsonMatcher(Instruction instructionValue) {
Ray Milkeyd03eda02015-01-09 14:58:48 -080047 instruction = instructionValue;
48 }
49
50 /**
51 * Matches the contents of a push header instruction.
52 *
53 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080054 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -080055 * @return true if contents match, false otherwise
56 */
57 private boolean matchPushHeaderInstruction(JsonNode instructionJson,
58 Description description) {
59 PushHeaderInstructions instructionToMatch =
60 (PushHeaderInstructions) instruction;
61 final String jsonSubtype = instructionJson.get("subtype").textValue();
62 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
63 description.appendText("subtype was " + jsonSubtype);
64 return false;
65 }
66
67 final String jsonType = instructionJson.get("type").textValue();
68 if (!instructionToMatch.type().name().equals(jsonType)) {
69 description.appendText("type was " + jsonType);
70 return false;
71 }
72
73 final JsonNode ethJson = instructionJson.get("ethernetType");
74 if (ethJson == null) {
75 description.appendText("ethernetType was not null");
76 return false;
77 }
78
alshabib7b808c52015-06-26 14:22:24 -070079 if (instructionToMatch.ethernetType().toShort() != ethJson.asInt()) {
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080080 description.appendText("ethernetType was " + ethJson);
Ray Milkeyd03eda02015-01-09 14:58:48 -080081 return false;
82 }
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080083
Ray Milkeyd03eda02015-01-09 14:58:48 -080084 return true;
85 }
86
87 /**
88 * Matches the contents of an output instruction.
89 *
90 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080091 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -080092 * @return true if contents match, false otherwise
93 */
94 private boolean matchOutputInstruction(JsonNode instructionJson,
95 Description description) {
Ray Milkeyd03eda02015-01-09 14:58:48 -080096 final String jsonType = instructionJson.get("type").textValue();
Andrea Campanella5df35952015-12-08 15:46:49 -080097 OutputInstruction instructionToMatch = (OutputInstruction) instruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080098 if (!instructionToMatch.type().name().equals(jsonType)) {
99 description.appendText("type was " + jsonType);
100 return false;
101 }
102
Andrea Campanella5df35952015-12-08 15:46:49 -0800103 if (instructionJson.get("port").isLong() ||
104 instructionJson.get("port").isInt()) {
105 final long jsonPort = instructionJson.get("port").asLong();
106 if (instructionToMatch.port().toLong() != (jsonPort)) {
107 description.appendText("port was " + jsonPort);
108 return false;
109 }
110 } else if (instructionJson.get("port").isTextual()) {
111 final String jsonPort = instructionJson.get("port").textValue();
112 if (!instructionToMatch.port().toString().equals(jsonPort)) {
113 description.appendText("port was " + jsonPort);
114 return false;
115 }
116 } else {
117 final String jsonPort = instructionJson.get("port").toString();
118 description.appendText("Unmathcing types ");
119 description.appendText("instructionToMatch " + instructionToMatch.port().toString());
120 description.appendText("jsonPort " + jsonPort);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800121 }
122
123 return true;
124 }
125
126 /**
127 * Matches the contents of a mod lambda instruction.
128 *
129 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800130 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800131 * @return true if contents match, false otherwise
132 */
133 private boolean matchModLambdaInstruction(JsonNode instructionJson,
134 Description description) {
135 ModLambdaInstruction instructionToMatch =
136 (ModLambdaInstruction) instruction;
137 final String jsonSubtype = instructionJson.get("subtype").textValue();
138 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
139 description.appendText("subtype was " + jsonSubtype);
140 return false;
141 }
142
143 final String jsonType = instructionJson.get("type").textValue();
144 if (!instructionToMatch.type().name().equals(jsonType)) {
145 description.appendText("type was " + jsonType);
146 return false;
147 }
148
149 final long jsonLambda = instructionJson.get("lambda").shortValue();
150 if (instructionToMatch.lambda() != jsonLambda) {
151 description.appendText("lambda was " + jsonLambda);
152 return false;
153 }
154
155 return true;
156 }
157
158 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300159 * Matches the contents of a mod OCh singal instruction.
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700160 *
161 * @param instructionJson JSON instruction to match
162 * @param description Description object used for recording errors
163 * @return true if contents matches, false otherwise
164 */
165 private boolean matchModOchSingalInstruction(JsonNode instructionJson,
166 Description description) {
167 ModOchSignalInstruction instructionToMatch =
168 (ModOchSignalInstruction) instruction;
169
170 String jsonSubType = instructionJson.get("subtype").textValue();
171 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
172 description.appendText("subtype was " + jsonSubType);
173 return false;
174 }
175
176 String jsonType = instructionJson.get("type").textValue();
177 if (!instructionToMatch.type().name().equals(jsonType)) {
178 description.appendText("type was " + jsonType);
179 return false;
180 }
181
182 String jsonGridType = instructionJson.get("gridType").textValue();
183 if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
184 description.appendText("gridType was " + jsonGridType);
185 return false;
186 }
187
188 String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
189 if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
190 description.appendText("channelSpacing was " + jsonChannelSpacing);
191 return false;
192 }
193
194 int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
195 if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
196 description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
197 return false;
198 }
199
200 int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
201 if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
202 description.appendText("slotGranularity was " + jsonSlotGranularity);
203 return false;
204 }
205
206 return true;
207 }
208
209 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300210 * Matches the contents of a mod ODU singal Id instruction.
211 *
212 * @param instructionJson JSON instruction to match
213 * @param description Description object used for recording errors
214 * @return true if contents matches, false otherwise
215 */
216 private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
217 Description description) {
218 ModOduSignalIdInstruction instructionToMatch =
219 (ModOduSignalIdInstruction) instruction;
220 String jsonSubType = instructionJson.get("subtype").textValue();
221 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
222 description.appendText("subtype was " + jsonSubType);
223 return false;
224 }
225 String jsonType = instructionJson.get("type").textValue();
226 if (!instructionToMatch.type().name().equals(jsonType)) {
227 description.appendText("type was " + jsonType);
228 return false;
229 }
230 final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
231 int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
232 int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
233 byte [] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
234 OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
235 if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
236 description.appendText("oduSignalId was " + instructionToMatch);
237 return false;
238 }
239 return true;
240 }
241
242
243 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800244 * Matches the contents of a mod Ethernet instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800245 *
246 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800247 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800248 * @return true if contents match, false otherwise
249 */
250 private boolean matchModEtherInstruction(JsonNode instructionJson,
251 Description description) {
252 ModEtherInstruction instructionToMatch =
253 (ModEtherInstruction) instruction;
254 final String jsonSubtype = instructionJson.get("subtype").textValue();
255 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
256 description.appendText("subtype was " + jsonSubtype);
257 return false;
258 }
259
260 final String jsonType = instructionJson.get("type").textValue();
261 if (!instructionToMatch.type().name().equals(jsonType)) {
262 description.appendText("type was " + jsonType);
263 return false;
264 }
265
266 final String jsonMac = instructionJson.get("mac").textValue();
267 final String mac = instructionToMatch.mac().toString();
268 if (!mac.equals(jsonMac)) {
269 description.appendText("mac was " + jsonMac);
270 return false;
271 }
272
273 return true;
274 }
275
276 /**
277 * Matches the contents of a mod vlan id instruction.
278 *
279 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800280 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800281 * @return true if contents match, false otherwise
282 */
283 private boolean matchModVlanIdInstruction(JsonNode instructionJson,
284 Description description) {
285 ModVlanIdInstruction instructionToMatch =
286 (ModVlanIdInstruction) instruction;
287 final String jsonSubtype = instructionJson.get("subtype").textValue();
288 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
289 description.appendText("subtype was " + jsonSubtype);
290 return false;
291 }
292
293 final String jsonType = instructionJson.get("type").textValue();
294 if (!instructionToMatch.type().name().equals(jsonType)) {
295 description.appendText("type was " + jsonType);
296 return false;
297 }
298
299 final short jsonVlanId = instructionJson.get("vlanId").shortValue();
300 final short vlanId = instructionToMatch.vlanId().toShort();
301 if (jsonVlanId != vlanId) {
302 description.appendText("vlan id was " + jsonVlanId);
303 return false;
304 }
305
306 return true;
307 }
308
309 /**
310 * Matches the contents of a mod vlan pcp instruction.
311 *
312 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800313 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800314 * @return true if contents match, false otherwise
315 */
316 private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
317 Description description) {
318 ModVlanPcpInstruction instructionToMatch =
319 (ModVlanPcpInstruction) instruction;
320 final String jsonSubtype = instructionJson.get("subtype").textValue();
321 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
322 description.appendText("subtype was " + jsonSubtype);
323 return false;
324 }
325
326 final String jsonType = instructionJson.get("type").textValue();
327 if (!instructionToMatch.type().name().equals(jsonType)) {
328 description.appendText("type was " + jsonType);
329 return false;
330 }
331
332 final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
333 final short vlanId = instructionToMatch.vlanPcp();
334 if (jsonVlanPcp != vlanId) {
335 description.appendText("vlan pcp was " + jsonVlanPcp);
336 return false;
337 }
338
339 return true;
340 }
341
342 /**
343 * Matches the contents of a mod ip instruction.
344 *
345 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800346 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800347 * @return true if contents match, false otherwise
348 */
349 private boolean matchModIpInstruction(JsonNode instructionJson,
350 Description description) {
351 ModIPInstruction instructionToMatch =
352 (ModIPInstruction) instruction;
353 final String jsonSubtype = instructionJson.get("subtype").textValue();
354 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
355 description.appendText("subtype was " + jsonSubtype);
356 return false;
357 }
358
359 final String jsonType = instructionJson.get("type").textValue();
360 if (!instructionToMatch.type().name().equals(jsonType)) {
361 description.appendText("type was " + jsonType);
362 return false;
363 }
364
365 final String jsonIp = instructionJson.get("ip").textValue();
366 final String ip = instructionToMatch.ip().toString();
367 if (!ip.equals(jsonIp)) {
368 description.appendText("ip was " + jsonIp);
369 return false;
370 }
371
372 return true;
373 }
374
375 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800376 * Matches the contents of a mod IPv6 Flow Label instruction.
377 *
378 * @param instructionJson JSON instruction to match
379 * @param description Description object used for recording errors
380 * @return true if contents match, false otherwise
381 */
382 private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
383 Description description) {
384 ModIPv6FlowLabelInstruction instructionToMatch =
385 (ModIPv6FlowLabelInstruction) instruction;
386 final String jsonSubtype = instructionJson.get("subtype").textValue();
387 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
388 description.appendText("subtype was " + jsonSubtype);
389 return false;
390 }
391
392 final String jsonType = instructionJson.get("type").textValue();
393 if (!instructionToMatch.type().name().equals(jsonType)) {
394 description.appendText("type was " + jsonType);
395 return false;
396 }
397
398 final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
399 final int flowLabel = instructionToMatch.flowLabel();
400 if (flowLabel != jsonFlowLabel) {
401 description.appendText("IPv6 flow label was " + jsonFlowLabel);
402 return false;
403 }
404
405 return true;
406 }
407
408 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800409 * Matches the contents of a mod MPLS label instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800410 *
411 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800412 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800413 * @return true if contents match, false otherwise
414 */
415 private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
416 Description description) {
417 ModMplsLabelInstruction instructionToMatch =
418 (ModMplsLabelInstruction) instruction;
419 final String jsonSubtype = instructionJson.get("subtype").textValue();
420 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
421 description.appendText("subtype was " + jsonSubtype);
422 return false;
423 }
424
425 final String jsonType = instructionJson.get("type").textValue();
426 if (!instructionToMatch.type().name().equals(jsonType)) {
427 description.appendText("type was " + jsonType);
428 return false;
429 }
430
431 final int jsonLabel = instructionJson.get("label").intValue();
HIGUCHI Yuta04b49fc2015-08-28 09:58:58 -0700432 final int label = instructionToMatch.mplsLabel().toInt();
Ray Milkeyd03eda02015-01-09 14:58:48 -0800433 if (label != jsonLabel) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800434 description.appendText("MPLS label was " + jsonLabel);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800435 return false;
436 }
437
438 return true;
439 }
440
441 @Override
442 public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
443
444 // check type
445 final JsonNode jsonTypeNode = jsonInstruction.get("type");
446 final String jsonType = jsonTypeNode.textValue();
447 final String type = instruction.type().name();
448 if (!jsonType.equals(type)) {
449 description.appendText("type was " + type);
450 return false;
451 }
452
453 if (instruction instanceof PushHeaderInstructions) {
454 return matchPushHeaderInstruction(jsonInstruction, description);
455 } else if (instruction instanceof DropInstruction) {
456 return true;
457 } else if (instruction instanceof OutputInstruction) {
458 return matchOutputInstruction(jsonInstruction, description);
459 } else if (instruction instanceof ModLambdaInstruction) {
460 return matchModLambdaInstruction(jsonInstruction, description);
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700461 } else if (instruction instanceof ModOchSignalInstruction) {
462 return matchModOchSingalInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800463 } else if (instruction instanceof ModEtherInstruction) {
464 return matchModEtherInstruction(jsonInstruction, description);
465 } else if (instruction instanceof ModVlanIdInstruction) {
466 return matchModVlanIdInstruction(jsonInstruction, description);
467 } else if (instruction instanceof ModVlanPcpInstruction) {
468 return matchModVlanPcpInstruction(jsonInstruction, description);
469 } else if (instruction instanceof ModIPInstruction) {
470 return matchModIpInstruction(jsonInstruction, description);
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800471 } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
472 return matchModIPv6FlowLabelInstruction(jsonInstruction,
473 description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800474 } else if (instruction instanceof ModMplsLabelInstruction) {
475 return matchModMplsLabelInstruction(jsonInstruction, description);
Yafit Hadar5796d972015-10-15 13:16:11 +0300476 } else if (instruction instanceof ModOduSignalIdInstruction) {
477 return matchModOduSingalIdInstruction(jsonInstruction, description);
Brian O'Connorb75a67a2015-10-07 14:34:06 -0700478 } else if (instruction instanceof NoActionInstruction) {
479 return true;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800480 }
481
482 return false;
483 }
484
485 @Override
486 public void describeTo(Description description) {
487 description.appendText(instruction.toString());
488 }
489
490 /**
491 * Factory to allocate an instruction matcher.
492 *
493 * @param instruction instruction object we are looking for
494 * @return matcher
495 */
496 public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
497 return new InstructionJsonMatcher(instruction);
498 }
499}