blob: 9ffb3c3addafc6dcf143b83dc6adf73ede004e49 [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) {
96 OutputInstruction instructionToMatch = (OutputInstruction) instruction;
97
98 final String jsonType = instructionJson.get("type").textValue();
99 if (!instructionToMatch.type().name().equals(jsonType)) {
100 description.appendText("type was " + jsonType);
101 return false;
102 }
103
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
110 return true;
111 }
112
113 /**
114 * Matches the contents of a mod lambda instruction.
115 *
116 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800117 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800118 * @return true if contents match, false otherwise
119 */
120 private boolean matchModLambdaInstruction(JsonNode instructionJson,
121 Description description) {
122 ModLambdaInstruction instructionToMatch =
123 (ModLambdaInstruction) instruction;
124 final String jsonSubtype = instructionJson.get("subtype").textValue();
125 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
126 description.appendText("subtype was " + jsonSubtype);
127 return false;
128 }
129
130 final String jsonType = instructionJson.get("type").textValue();
131 if (!instructionToMatch.type().name().equals(jsonType)) {
132 description.appendText("type was " + jsonType);
133 return false;
134 }
135
136 final long jsonLambda = instructionJson.get("lambda").shortValue();
137 if (instructionToMatch.lambda() != jsonLambda) {
138 description.appendText("lambda was " + jsonLambda);
139 return false;
140 }
141
142 return true;
143 }
144
145 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300146 * Matches the contents of a mod OCh singal instruction.
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700147 *
148 * @param instructionJson JSON instruction to match
149 * @param description Description object used for recording errors
150 * @return true if contents matches, false otherwise
151 */
152 private boolean matchModOchSingalInstruction(JsonNode instructionJson,
153 Description description) {
154 ModOchSignalInstruction instructionToMatch =
155 (ModOchSignalInstruction) instruction;
156
157 String jsonSubType = instructionJson.get("subtype").textValue();
158 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
159 description.appendText("subtype was " + jsonSubType);
160 return false;
161 }
162
163 String jsonType = instructionJson.get("type").textValue();
164 if (!instructionToMatch.type().name().equals(jsonType)) {
165 description.appendText("type was " + jsonType);
166 return false;
167 }
168
169 String jsonGridType = instructionJson.get("gridType").textValue();
170 if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
171 description.appendText("gridType was " + jsonGridType);
172 return false;
173 }
174
175 String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
176 if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
177 description.appendText("channelSpacing was " + jsonChannelSpacing);
178 return false;
179 }
180
181 int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
182 if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
183 description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
184 return false;
185 }
186
187 int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
188 if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
189 description.appendText("slotGranularity was " + jsonSlotGranularity);
190 return false;
191 }
192
193 return true;
194 }
195
196 /**
Yafit Hadar5796d972015-10-15 13:16:11 +0300197 * Matches the contents of a mod ODU singal Id instruction.
198 *
199 * @param instructionJson JSON instruction to match
200 * @param description Description object used for recording errors
201 * @return true if contents matches, false otherwise
202 */
203 private boolean matchModOduSingalIdInstruction(JsonNode instructionJson,
204 Description description) {
205 ModOduSignalIdInstruction instructionToMatch =
206 (ModOduSignalIdInstruction) instruction;
207 String jsonSubType = instructionJson.get("subtype").textValue();
208 if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
209 description.appendText("subtype was " + jsonSubType);
210 return false;
211 }
212 String jsonType = instructionJson.get("type").textValue();
213 if (!instructionToMatch.type().name().equals(jsonType)) {
214 description.appendText("type was " + jsonType);
215 return false;
216 }
217 final JsonNode jsonOduSignal = instructionJson.get("oduSignalId");
218 int jsonTpn = jsonOduSignal.get("tributaryPortNumber").intValue();
219 int jsonTsLen = jsonOduSignal.get("tributarySlotLength").intValue();
220 byte [] tributaryBitMap = HexString.fromHexString(jsonOduSignal.get("tributarySlotBitmap").asText());
221 OduSignalId jsonOduSignalId = OduSignalId.oduSignalId(jsonTpn, jsonTsLen, tributaryBitMap);
222 if (!instructionToMatch.oduSignalId().equals(jsonOduSignalId)) {
223 description.appendText("oduSignalId was " + instructionToMatch);
224 return false;
225 }
226 return true;
227 }
228
229
230 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800231 * Matches the contents of a mod Ethernet instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800232 *
233 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800234 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800235 * @return true if contents match, false otherwise
236 */
237 private boolean matchModEtherInstruction(JsonNode instructionJson,
238 Description description) {
239 ModEtherInstruction instructionToMatch =
240 (ModEtherInstruction) instruction;
241 final String jsonSubtype = instructionJson.get("subtype").textValue();
242 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
243 description.appendText("subtype was " + jsonSubtype);
244 return false;
245 }
246
247 final String jsonType = instructionJson.get("type").textValue();
248 if (!instructionToMatch.type().name().equals(jsonType)) {
249 description.appendText("type was " + jsonType);
250 return false;
251 }
252
253 final String jsonMac = instructionJson.get("mac").textValue();
254 final String mac = instructionToMatch.mac().toString();
255 if (!mac.equals(jsonMac)) {
256 description.appendText("mac was " + jsonMac);
257 return false;
258 }
259
260 return true;
261 }
262
263 /**
264 * Matches the contents of a mod vlan id instruction.
265 *
266 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800267 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800268 * @return true if contents match, false otherwise
269 */
270 private boolean matchModVlanIdInstruction(JsonNode instructionJson,
271 Description description) {
272 ModVlanIdInstruction instructionToMatch =
273 (ModVlanIdInstruction) instruction;
274 final String jsonSubtype = instructionJson.get("subtype").textValue();
275 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
276 description.appendText("subtype was " + jsonSubtype);
277 return false;
278 }
279
280 final String jsonType = instructionJson.get("type").textValue();
281 if (!instructionToMatch.type().name().equals(jsonType)) {
282 description.appendText("type was " + jsonType);
283 return false;
284 }
285
286 final short jsonVlanId = instructionJson.get("vlanId").shortValue();
287 final short vlanId = instructionToMatch.vlanId().toShort();
288 if (jsonVlanId != vlanId) {
289 description.appendText("vlan id was " + jsonVlanId);
290 return false;
291 }
292
293 return true;
294 }
295
296 /**
297 * Matches the contents of a mod vlan pcp instruction.
298 *
299 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800300 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800301 * @return true if contents match, false otherwise
302 */
303 private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
304 Description description) {
305 ModVlanPcpInstruction instructionToMatch =
306 (ModVlanPcpInstruction) instruction;
307 final String jsonSubtype = instructionJson.get("subtype").textValue();
308 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
309 description.appendText("subtype was " + jsonSubtype);
310 return false;
311 }
312
313 final String jsonType = instructionJson.get("type").textValue();
314 if (!instructionToMatch.type().name().equals(jsonType)) {
315 description.appendText("type was " + jsonType);
316 return false;
317 }
318
319 final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
320 final short vlanId = instructionToMatch.vlanPcp();
321 if (jsonVlanPcp != vlanId) {
322 description.appendText("vlan pcp was " + jsonVlanPcp);
323 return false;
324 }
325
326 return true;
327 }
328
329 /**
330 * Matches the contents of a mod ip instruction.
331 *
332 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800333 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800334 * @return true if contents match, false otherwise
335 */
336 private boolean matchModIpInstruction(JsonNode instructionJson,
337 Description description) {
338 ModIPInstruction instructionToMatch =
339 (ModIPInstruction) instruction;
340 final String jsonSubtype = instructionJson.get("subtype").textValue();
341 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
342 description.appendText("subtype was " + jsonSubtype);
343 return false;
344 }
345
346 final String jsonType = instructionJson.get("type").textValue();
347 if (!instructionToMatch.type().name().equals(jsonType)) {
348 description.appendText("type was " + jsonType);
349 return false;
350 }
351
352 final String jsonIp = instructionJson.get("ip").textValue();
353 final String ip = instructionToMatch.ip().toString();
354 if (!ip.equals(jsonIp)) {
355 description.appendText("ip was " + jsonIp);
356 return false;
357 }
358
359 return true;
360 }
361
362 /**
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800363 * Matches the contents of a mod IPv6 Flow Label instruction.
364 *
365 * @param instructionJson JSON instruction to match
366 * @param description Description object used for recording errors
367 * @return true if contents match, false otherwise
368 */
369 private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
370 Description description) {
371 ModIPv6FlowLabelInstruction instructionToMatch =
372 (ModIPv6FlowLabelInstruction) instruction;
373 final String jsonSubtype = instructionJson.get("subtype").textValue();
374 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
375 description.appendText("subtype was " + jsonSubtype);
376 return false;
377 }
378
379 final String jsonType = instructionJson.get("type").textValue();
380 if (!instructionToMatch.type().name().equals(jsonType)) {
381 description.appendText("type was " + jsonType);
382 return false;
383 }
384
385 final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
386 final int flowLabel = instructionToMatch.flowLabel();
387 if (flowLabel != jsonFlowLabel) {
388 description.appendText("IPv6 flow label was " + jsonFlowLabel);
389 return false;
390 }
391
392 return true;
393 }
394
395 /**
Ray Milkeydb358082015-01-13 16:34:38 -0800396 * Matches the contents of a mod MPLS label instruction.
Ray Milkeyd03eda02015-01-09 14:58:48 -0800397 *
398 * @param instructionJson JSON instruction to match
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800399 * @param description Description object used for recording errors
Ray Milkeyd03eda02015-01-09 14:58:48 -0800400 * @return true if contents match, false otherwise
401 */
402 private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
403 Description description) {
404 ModMplsLabelInstruction instructionToMatch =
405 (ModMplsLabelInstruction) instruction;
406 final String jsonSubtype = instructionJson.get("subtype").textValue();
407 if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
408 description.appendText("subtype was " + jsonSubtype);
409 return false;
410 }
411
412 final String jsonType = instructionJson.get("type").textValue();
413 if (!instructionToMatch.type().name().equals(jsonType)) {
414 description.appendText("type was " + jsonType);
415 return false;
416 }
417
418 final int jsonLabel = instructionJson.get("label").intValue();
HIGUCHI Yuta04b49fc2015-08-28 09:58:58 -0700419 final int label = instructionToMatch.mplsLabel().toInt();
Ray Milkeyd03eda02015-01-09 14:58:48 -0800420 if (label != jsonLabel) {
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800421 description.appendText("MPLS label was " + jsonLabel);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800422 return false;
423 }
424
425 return true;
426 }
427
428 @Override
429 public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
430
431 // check type
432 final JsonNode jsonTypeNode = jsonInstruction.get("type");
433 final String jsonType = jsonTypeNode.textValue();
434 final String type = instruction.type().name();
435 if (!jsonType.equals(type)) {
436 description.appendText("type was " + type);
437 return false;
438 }
439
440 if (instruction instanceof PushHeaderInstructions) {
441 return matchPushHeaderInstruction(jsonInstruction, description);
442 } else if (instruction instanceof DropInstruction) {
443 return true;
444 } else if (instruction instanceof OutputInstruction) {
445 return matchOutputInstruction(jsonInstruction, description);
446 } else if (instruction instanceof ModLambdaInstruction) {
447 return matchModLambdaInstruction(jsonInstruction, description);
Sho SHIMIZUed7af542015-05-05 19:10:45 -0700448 } else if (instruction instanceof ModOchSignalInstruction) {
449 return matchModOchSingalInstruction(jsonInstruction, description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800450 } else if (instruction instanceof ModEtherInstruction) {
451 return matchModEtherInstruction(jsonInstruction, description);
452 } else if (instruction instanceof ModVlanIdInstruction) {
453 return matchModVlanIdInstruction(jsonInstruction, description);
454 } else if (instruction instanceof ModVlanPcpInstruction) {
455 return matchModVlanPcpInstruction(jsonInstruction, description);
456 } else if (instruction instanceof ModIPInstruction) {
457 return matchModIpInstruction(jsonInstruction, description);
Pavlin Radoslavovfebe82c2015-02-11 19:08:15 -0800458 } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
459 return matchModIPv6FlowLabelInstruction(jsonInstruction,
460 description);
Ray Milkeyd03eda02015-01-09 14:58:48 -0800461 } else if (instruction instanceof ModMplsLabelInstruction) {
462 return matchModMplsLabelInstruction(jsonInstruction, description);
Yafit Hadar5796d972015-10-15 13:16:11 +0300463 } else if (instruction instanceof ModOduSignalIdInstruction) {
464 return matchModOduSingalIdInstruction(jsonInstruction, description);
Brian O'Connorb75a67a2015-10-07 14:34:06 -0700465 } else if (instruction instanceof NoActionInstruction) {
466 return true;
Ray Milkeyd03eda02015-01-09 14:58:48 -0800467 }
468
469 return false;
470 }
471
472 @Override
473 public void describeTo(Description description) {
474 description.appendText(instruction.toString());
475 }
476
477 /**
478 * Factory to allocate an instruction matcher.
479 *
480 * @param instruction instruction object we are looking for
481 * @return matcher
482 */
483 public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
484 return new InstructionJsonMatcher(instruction);
485 }
486}