blob: 66f8473d2317dde3433a76aa6f0b2c0b81bfcfc8 [file] [log] [blame]
Ray Milkeyd03eda02015-01-09 14:58:48 -08001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2015-present Open Networking Foundation
Ray Milkeyd03eda02015-01-09 14:58:48 -08003 *
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;
Jian Li47b26232016-03-07 09:59:59 -080025import org.onosproject.net.flow.instructions.Instructions.MeterInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030026import org.onosproject.net.flow.instructions.Instructions.NoActionInstruction;
27import org.onosproject.net.flow.instructions.Instructions.OutputInstruction;
Jian Li70dffe42016-03-08 22:23:02 -080028import org.onosproject.net.flow.instructions.Instructions.SetQueueInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030029import org.onosproject.net.flow.instructions.L0ModificationInstruction.ModOchSignalInstruction;
30import org.onosproject.net.flow.instructions.L1ModificationInstruction.ModOduSignalIdInstruction;
31import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
Jian Li11260a02016-05-19 13:07:22 -070032import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsHeaderInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030033import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModMplsLabelInstruction;
34import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
35import org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanPcpInstruction;
Yafit Hadar5796d972015-10-15 13:16:11 +030036import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPInstruction;
37import org.onosproject.net.flow.instructions.L3ModificationInstruction.ModIPv6FlowLabelInstruction;
Frank Wang74ce2c12018-04-11 20:26:45 +080038import org.onosproject.net.flow.instructions.PiInstruction;
39import org.onosproject.net.pi.runtime.PiAction;
Frank Wang74ce2c12018-04-11 20:26:45 +080040import org.onosproject.net.pi.runtime.PiActionParam;
Carmelo Casconecb4327a2018-09-11 15:17:23 -070041import org.onosproject.net.pi.runtime.PiActionProfileGroupId;
42import org.onosproject.net.pi.runtime.PiActionProfileMemberId;
Frank Wang74ce2c12018-04-11 20:26:45 +080043
44import java.util.Collection;
45import java.util.Objects;
46
47import static org.onlab.util.ImmutableByteSequence.copyFrom;
Ray Milkeyd03eda02015-01-09 14:58:48 -080048
Ray Milkeyd03eda02015-01-09 14:58:48 -080049/**
50 * Hamcrest matcher for instructions.
51 */
Ray Milkeydb358082015-01-13 16:34:38 -080052public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
Ray Milkeyd03eda02015-01-09 14:58:48 -080053
54 private final Instruction instruction;
55
Ray Milkeydb358082015-01-13 16:34:38 -080056 private InstructionJsonMatcher(Instruction instructionValue) {
Ray Milkeyd03eda02015-01-09 14:58:48 -080057 instruction = instructionValue;
58 }
59
60 /**
61 * Matches the contents of a push header instruction.
62 *
63 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -080064 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -080065 * @return true if contents match, false otherwise
66 */
Jian Li11260a02016-05-19 13:07:22 -070067 private boolean matchModMplsHeaderInstruction(JsonNode instructionJson,
68 Description description) {
69 ModMplsHeaderInstruction instructionToMatch =
70 (ModMplsHeaderInstruction) instruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -080071 final String jsonSubtype = instructionJson.get("subtype").textValue();
72 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
73 description.appendText("subtype was " + jsonSubtype);
74 return false;
75 }
76
77 final String jsonType = instructionJson.get("type").textValue();
78 if (!instructionToMatch.type().name().equals(jsonType)) {
79 description.appendText("type was " + jsonType);
80 return false;
81 }
82
83 final JsonNode ethJson = instructionJson.get("ethernetType");
84 if (ethJson == null) {
85 description.appendText("ethernetType was not null");
86 return false;
87 }
88
alshabib7b808c52015-06-26 14:22:24 -070089 if (instructionToMatch.ethernetType().toShort() != ethJson.asInt()) {
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080090 description.appendText("ethernetType was " + ethJson);
Ray Milkeyd03eda02015-01-09 14:58:48 -080091 return false;
92 }
Yuta HIGUCHI32a53c52015-02-08 01:25:40 -080093
Ray Milkeyd03eda02015-01-09 14:58:48 -080094 return true;
95 }
96
Jian Li11260a02016-05-19 13:07:22 -070097 // TODO: need to add matchModVlanHeaderInstruction
98
Ray Milkeyd03eda02015-01-09 14:58:48 -080099 /**
100 * Matches the contents of an output instruction.
101 *
102 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800103 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800104 * @return true if contents match, false otherwise
105 */
106 private boolean matchOutputInstruction(JsonNode instructionJson,
107 Description description) {
Ray Milkeyd03eda02015-01-09 14:58:48 -0800108 final String jsonType = instructionJson.get("type").textValue();
Andrea Campanella5df35952015-12-08 15:46:49 -0800109 OutputInstruction instructionToMatch = (OutputInstruction) instruction;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800110 if (!instructionToMatch.type().name().equals(jsonType)) {
111 description.appendText("type was " + jsonType);
112 return false;
113 }
114
Andrea Campanella5df35952015-12-08 15:46:49 -0800115 if (instructionJson.get("port").isLong() ||
116 instructionJson.get("port").isInt()) {
117 final long jsonPort = instructionJson.get("port").asLong();
118 if (instructionToMatch.port().toLong() != (jsonPort)) {
119 description.appendText("port was " + jsonPort);
120 return false;
121 }
122 } else if (instructionJson.get("port").isTextual()) {
123 final String jsonPort = instructionJson.get("port").textValue();
124 if (!instructionToMatch.port().toString().equals(jsonPort)) {
125 description.appendText("port was " + jsonPort);
126 return false;
127 }
128 } else {
129 final String jsonPort = instructionJson.get("port").toString();
Jian Li70dffe42016-03-08 22:23:02 -0800130 description.appendText("Unmatching types ");
Andrea Campanella5df35952015-12-08 15:46:49 -0800131 description.appendText("instructionToMatch " + instructionToMatch.port().toString());
132 description.appendText("jsonPort " + jsonPort);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800133 }
134
135 return true;
136 }
137
138 /**
Jian Lice8c5602016-03-03 21:43:24 -0800139 * Matches the contents of a group instruction.
140 *
141 * @param instructionJson JSON instruction to match
142 * @param description Description object used for recording errors
143 * @return true if contents match, false otherwise
144 */
145 private boolean matchGroupInstruction(JsonNode instructionJson,
146 Description description) {
147 final String jsonType = instructionJson.get("type").textValue();
148 GroupInstruction instructionToMatch = (GroupInstruction) instruction;
149 if (!instructionToMatch.type().name().equals(jsonType)) {
150 description.appendText("type was " + jsonType);
151 return false;
152 }
153
Jian Li47b26232016-03-07 09:59:59 -0800154 final int jsonGroupId = instructionJson.get("groupId").intValue();
155 if (instructionToMatch.groupId().id() != jsonGroupId) {
156 description.appendText("groupId was " + jsonGroupId);
157 return false;
158 }
159
160 return true;
161 }
162
163 /**
164 * Matches the contents of a meter instruction.
165 *
166 * @param instructionJson JSON instruction to match
167 * @param description Description object used for recording errors
168 * @return true if contents match, false otherwise
169 */
170 private boolean matchMeterInstruction(JsonNode instructionJson,
171 Description description) {
172 final String jsonType = instructionJson.get("type").textValue();
173 MeterInstruction instructionToMatch = (MeterInstruction) instruction;
174 if (!instructionToMatch.type().name().equals(jsonType)) {
175 description.appendText("type was " + jsonType);
176 return false;
177 }
178
179 final long jsonMeterId = instructionJson.get("meterId").longValue();
180 if (instructionToMatch.meterId().id() != jsonMeterId) {
181 description.appendText("meterId was " + jsonMeterId);
182 return false;
Jian Lice8c5602016-03-03 21:43:24 -0800183 }
184
185 return true;
186 }
187
188 /**
Jian Li70dffe42016-03-08 22:23:02 -0800189 * Matches the contents of a set queue instruction.
190 *
191 * @param instructionJson JSON instruction to match
192 * @param description Description object used for recording errors
193 * @return true if contents match, false otherwise
194 */
195 private boolean matchSetQueueInstruction(JsonNode instructionJson,
196 Description description) {
197 final String jsonType = instructionJson.get("type").textValue();
198 SetQueueInstruction instructionToMatch = (SetQueueInstruction) instruction;
199 if (!instructionToMatch.type().name().equals(jsonType)) {
200 description.appendText("type was " + jsonType);
201 return false;
202 }
203
204 final long jsonQueueId = instructionJson.get("queueId").longValue();
205 if (instructionToMatch.queueId() != jsonQueueId) {
206 description.appendText("queueId was " + jsonQueueId);
207 return false;
208 }
209
210 if (instructionJson.get("port").isLong() ||
211 instructionJson.get("port").isInt()) {
212 final long jsonPort = instructionJson.get("port").asLong();
213 if (instructionToMatch.port().toLong() != (jsonPort)) {
214 description.appendText("port was " + jsonPort);
215 return false;
216 }
217 } else if (instructionJson.get("port").isTextual()) {
218 final String jsonPort = instructionJson.get("port").textValue();
219 if (!instructionToMatch.port().toString().equals(jsonPort)) {
220 description.appendText("port was " + jsonPort);
221 return false;
222 }
223 } else {
224 final String jsonPort = instructionJson.get("port").toString();
225 description.appendText("Unmatching types ");
226 description.appendText("instructionToMatch " + instructionToMatch.port().toString());
227 description.appendText("jsonPort " + jsonPort);
228 }
229
230 return true;
231 }
232
233 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300234 * Matches the contents of a mod OCh singal instruction.
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700235 *
236 * @param instructionJson JSON instruction to match
237 * @param description Description object used for recording errors
238 * @return true if contents matches, false otherwise
239 */
240 private boolean matchModOchSingalInstruction(JsonNode instructionJson,
241 Description description) {
242 ModOchSignalInstruction instructionToMatch =
243 (ModOchSignalInstruction) instruction;
244
245 String jsonSubType = instructionJson.get("subtype").textValue();
246 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
247 description.appendText("subtype was " + jsonSubType);
248 return false;
249 }
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
257 String jsonGridType = instructionJson.get("gridType").textValue();
258 if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
259 description.appendText("gridType was " + jsonGridType);
260 return false;
261 }
262
263 String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
264 if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
265 description.appendText("channelSpacing was " + jsonChannelSpacing);
266 return false;
267 }
268
269 int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
270 if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
271 description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
272 return false;
273 }
274
275 int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
276 if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
277 description.appendText("slotGranularity was " + jsonSlotGranularity);
278 return false;
279 }
280
281 return true;
282 }
283
284 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300285 * Matches the contents of a mod ODU singal Id instruction.
286 *
287 * @param instructionJson JSON instruction to match
288 * @param description Description object used for recording errors
289 * @return true if contents matches, false otherwise
290 */
291 private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
292 Description description) {
293 ModOduSignalIdInstruction instructionToMatch =
294 (ModOduSignalIdInstruction) instruction;
295 String jsonSubType = instructionJson.get("subtype").textValue();
296 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
297 description.appendText("subtype was " + jsonSubType);
298 return false;
299 }
300 String jsonType = instructionJson.get("type").textValue();
301 if (!instructionToMatch.type().name().equals(jsonType)) {
302 description.appendText("type was " + jsonType);
303 return false;
304 }
305 final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
306 int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
307 int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
Jian Li68c4fc42016-01-11 16:07:03 -0800308 byte[] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
Yafit Hadar5796d972015-10-15 13:16:11 +0300309 OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
310 if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
311 description.appendText("oduSignalId was " + instructionToMatch);
312 return false;
313 }
314 return true;
315 }
316
317
318 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800319 * Matches the contents of a mod Ethernet instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800320 *
321 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800322 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800323 * @return true if contents match, false otherwise
324 */
325 private boolean matchModEtherInstruction(JsonNode instructionJson,
326 Description description) {
327 ModEtherInstruction instructionToMatch =
328 (ModEtherInstruction) instruction;
329 final String jsonSubtype = instructionJson.get("subtype").textValue();
330 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
331 description.appendText("subtype was " + jsonSubtype);
332 return false;
333 }
334
335 final String jsonType = instructionJson.get("type").textValue();
336 if (!instructionToMatch.type().name().equals(jsonType)) {
337 description.appendText("type was " + jsonType);
338 return false;
339 }
340
341 final String jsonMac = instructionJson.get("mac").textValue();
342 final String mac = instructionToMatch.mac().toString();
343 if (!mac.equals(jsonMac)) {
344 description.appendText("mac was " + jsonMac);
345 return false;
346 }
347
348 return true;
349 }
350
351 /**
352 * Matches the contents of a mod vlan id instruction.
353 *
354 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800355 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800356 * @return true if contents match, false otherwise
357 */
358 private boolean matchModVlanIdInstruction(JsonNode instructionJson,
359 Description description) {
360 ModVlanIdInstruction instructionToMatch =
361 (ModVlanIdInstruction) instruction;
362 final String jsonSubtype = instructionJson.get("subtype").textValue();
363 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
364 description.appendText("subtype was " + jsonSubtype);
365 return false;
366 }
367
368 final String jsonType = instructionJson.get("type").textValue();
369 if (!instructionToMatch.type().name().equals(jsonType)) {
370 description.appendText("type was " + jsonType);
371 return false;
372 }
373
374 final short jsonVlanId = instructionJson.get("vlanId").shortValue();
375 final short vlanId = instructionToMatch.vlanId().toShort();
376 if (jsonVlanId != vlanId) {
377 description.appendText("vlan id was " + jsonVlanId);
378 return false;
379 }
380
381 return true;
382 }
383
384 /**
385 * Matches the contents of a mod vlan pcp instruction.
386 *
387 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800388 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800389 * @return true if contents match, false otherwise
390 */
391 private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
392 Description description) {
393 ModVlanPcpInstruction instructionToMatch =
394 (ModVlanPcpInstruction) instruction;
395 final String jsonSubtype = instructionJson.get("subtype").textValue();
396 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
397 description.appendText("subtype was " + jsonSubtype);
398 return false;
399 }
400
401 final String jsonType = instructionJson.get("type").textValue();
402 if (!instructionToMatch.type().name().equals(jsonType)) {
403 description.appendText("type was " + jsonType);
404 return false;
405 }
406
407 final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
408 final short vlanId = instructionToMatch.vlanPcp();
409 if (jsonVlanPcp != vlanId) {
410 description.appendText("vlan pcp was " + jsonVlanPcp);
411 return false;
412 }
413
414 return true;
415 }
416
417 /**
418 * Matches the contents of a mod ip instruction.
419 *
420 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800421 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800422 * @return true if contents match, false otherwise
423 */
424 private boolean matchModIpInstruction(JsonNode instructionJson,
425 Description description) {
426 ModIPInstruction instructionToMatch =
427 (ModIPInstruction) instruction;
428 final String jsonSubtype = instructionJson.get("subtype").textValue();
429 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
430 description.appendText("subtype was " + jsonSubtype);
431 return false;
432 }
433
434 final String jsonType = instructionJson.get("type").textValue();
435 if (!instructionToMatch.type().name().equals(jsonType)) {
436 description.appendText("type was " + jsonType);
437 return false;
438 }
439
440 final String jsonIp = instructionJson.get("ip").textValue();
441 final String ip = instructionToMatch.ip().toString();
442 if (!ip.equals(jsonIp)) {
443 description.appendText("ip was " + jsonIp);
444 return false;
445 }
446
447 return true;
448 }
449
450 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800451 * Matches the contents of a mod IPv6 Flow Label instruction.
452 *
453 * @param instructionJson JSON instruction to match
454 * @param description Description object used for recording errors
455 * @return true if contents match, false otherwise
456 */
457 private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
458 Description description) {
459 ModIPv6FlowLabelInstruction instructionToMatch =
460 (ModIPv6FlowLabelInstruction) instruction;
461 final String jsonSubtype = instructionJson.get("subtype").textValue();
462 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
463 description.appendText("subtype was " + jsonSubtype);
464 return false;
465 }
466
467 final String jsonType = instructionJson.get("type").textValue();
468 if (!instructionToMatch.type().name().equals(jsonType)) {
469 description.appendText("type was " + jsonType);
470 return false;
471 }
472
473 final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
474 final int flowLabel = instructionToMatch.flowLabel();
475 if (flowLabel != jsonFlowLabel) {
476 description.appendText("IPv6 flow label was " + jsonFlowLabel);
477 return false;
478 }
479
480 return true;
481 }
482
483 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800484 * Matches the contents of a mod MPLS label instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800485 *
486 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800487 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800488 * @return true if contents match, false otherwise
489 */
490 private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
491 Description description) {
492 ModMplsLabelInstruction instructionToMatch =
493 (ModMplsLabelInstruction) instruction;
494 final String jsonSubtype = instructionJson.get("subtype").textValue();
495 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
496 description.appendText("subtype was " + jsonSubtype);
497 return false;
498 }
499
500 final String jsonType = instructionJson.get("type").textValue();
501 if (!instructionToMatch.type().name().equals(jsonType)) {
502 description.appendText("type was " + jsonType);
503 return false;
504 }
505
506 final int jsonLabel = instructionJson.get("label").intValue();
Ray Milkey125572b2016-02-22 16:48:17 -0800507 final int label = instructionToMatch.label().toInt();
Ray Milkeyd03eda02015-01-09 14:58:48 -0800508 if (label != jsonLabel) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800509 description.appendText("MPLS label was " + jsonLabel);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800510 return false;
511 }
512
513 return true;
514 }
515
Frank Wang74ce2c12018-04-11 20:26:45 +0800516 /**
517 * Matches the contents of a protocol-independent instruction.
518 *
519 * @param instructionJson JSON instruction to match
520 * @param description Description object used for recording errors
521 * @return true if contents match, false otherwise
522 */
523 private boolean matchPiInstruction(JsonNode instructionJson,
524 Description description) {
525 PiInstruction instructionToMatch = (PiInstruction) instruction;
526
527 final String jsonSubtype = instructionJson.get("subtype").textValue();
528 if (!instructionToMatch.action().type().name().equals(jsonSubtype)) {
529 description.appendText("subtype was " + jsonSubtype);
530 return false;
531 }
532
533 final String jsonType = instructionJson.get("type").textValue();
534 if (!instructionToMatch.type().name().equals(jsonType)) {
535 description.appendText("type was " + jsonType);
536 return false;
537 }
538
539 switch (instructionToMatch.action().type()) {
540 case ACTION:
541 if (!Objects.equals(instructionJson.get("actionId").textValue(),
542 ((PiAction) instructionToMatch.action()).id().id())) {
543 description.appendText("action was " + ((PiAction) instructionToMatch.action()).id().id());
544 return false;
545 }
546 Collection<PiActionParam> piActionParams = ((PiAction) instructionToMatch.action()).parameters();
547 JsonNode jsonParams = instructionJson.get("actionParams");
548 for (PiActionParam actionParam : piActionParams) {
549 if (!Objects.equals(copyFrom(HexString.fromHexString(jsonParams.get(actionParam.id().id())
550 .textValue(), null)),
551 actionParam.value())) {
552 description.appendText("action param value was " + actionParam.value());
553 return false;
554 }
555 }
556 break;
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700557 case ACTION_PROFILE_GROUP_ID:
Frank Wang74ce2c12018-04-11 20:26:45 +0800558 if (!Objects.equals(instructionJson.get("groupId").asInt(),
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700559 ((PiActionProfileGroupId) instructionToMatch.action()).id())) {
560 description.appendText("action profile group id was " +
561 ((PiActionProfileGroupId) instructionToMatch.action()).id());
Frank Wang74ce2c12018-04-11 20:26:45 +0800562 return false;
563 }
564 break;
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700565 case ACTION_PROFILE_MEMBER_ID:
Frank Wang74ce2c12018-04-11 20:26:45 +0800566 if (!Objects.equals(instructionJson.get("memberId").asInt(),
Carmelo Casconecb4327a2018-09-11 15:17:23 -0700567 ((PiActionProfileMemberId) instructionToMatch.action()).id())) {
568 description.appendText("action profile member id was " +
569 ((PiActionProfileMemberId) instructionToMatch.action()).id());
Frank Wang74ce2c12018-04-11 20:26:45 +0800570 return false;
571 }
572 break;
573 default:
574 description.appendText("type was " + jsonType);
575 return false;
576 }
577
578 return true;
579 }
580
Ray Milkeyd03eda02015-01-09 14:58:48 -0800581 @Override
582 public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
583
584 // check type
585 final JsonNode jsonTypeNode = jsonInstruction.get("type");
586 final String jsonType = jsonTypeNode.textValue();
587 final String type = instruction.type().name();
588 if (!jsonType.equals(type)) {
589 description.appendText("type was " + type);
590 return false;
591 }
592
Jian Li11260a02016-05-19 13:07:22 -0700593 if (instruction instanceof ModMplsHeaderInstruction) {
594 return matchModMplsHeaderInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800595 } else if (instruction instanceof OutputInstruction) {
596 return matchOutputInstruction(jsonInstruction, description);
Jian Lice8c5602016-03-03 21:43:24 -0800597 } else if (instruction instanceof GroupInstruction) {
598 return matchGroupInstruction(jsonInstruction, description);
Jian Li47b26232016-03-07 09:59:59 -0800599 } else if (instruction instanceof MeterInstruction) {
600 return matchMeterInstruction(jsonInstruction, description);
Jian Li70dffe42016-03-08 22:23:02 -0800601 } else if (instruction instanceof SetQueueInstruction) {
602 return matchSetQueueInstruction(jsonInstruction, description);
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700603 } else if (instruction instanceof ModOchSignalInstruction) {
604 return matchModOchSingalInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800605 } else if (instruction instanceof ModEtherInstruction) {
606 return matchModEtherInstruction(jsonInstruction, description);
607 } else if (instruction instanceof ModVlanIdInstruction) {
608 return matchModVlanIdInstruction(jsonInstruction, description);
609 } else if (instruction instanceof ModVlanPcpInstruction) {
610 return matchModVlanPcpInstruction(jsonInstruction, description);
611 } else if (instruction instanceof ModIPInstruction) {
612 return matchModIpInstruction(jsonInstruction, description);
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800613 } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
Jian Li70dffe42016-03-08 22:23:02 -0800614 return matchModIPv6FlowLabelInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800615 } else if (instruction instanceof ModMplsLabelInstruction) {
616 return matchModMplsLabelInstruction(jsonInstruction, description);
Yafit Hadar5796d972015-10-15 13:16:11 +0300617 } else if (instruction instanceof ModOduSignalIdInstruction) {
618 return matchModOduSingalIdInstruction(jsonInstruction, description);
Frank Wang74ce2c12018-04-11 20:26:45 +0800619 } else if (instruction instanceof PiInstruction) {
620 return matchPiInstruction(jsonInstruction, description);
Brian O'Connorb75a67a2015-10-07 14:34:06 -0700621 } else if (instruction instanceof NoActionInstruction) {
622 return true;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800623 }
624
625 return false;
626 }
627
628 @Override
629 public void describeTo(Description description) {
630 description.appendText(instruction.toString());
631 }
632
633 /**
634 * Factory to allocate an instruction matcher.
635 *
636 * @param instruction instruction object we are looking for
637 * @return matcher
638 */
639 public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
640 return new InstructionJsonMatcher(instruction);
641 }
642}