blob: b014bcf884748b708e958ec1756e9331b35c8b69 [file] [log] [blame]
Jian Li96b47d92016-05-16 17:59:06 -07001/*
Brian O'Connora09fe5b2017-08-03 21:12:30 -07002 * Copyright 2016-present Open Networking Foundation
Jian Li96b47d92016-05-16 17:59:06 -07003 *
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 com.fasterxml.jackson.databind.JsonNode;
19import com.fasterxml.jackson.databind.node.ObjectNode;
20import com.google.common.collect.ImmutableSet;
21import org.apache.commons.lang3.StringUtils;
22import org.hamcrest.Description;
23import org.hamcrest.TypeSafeDiagnosingMatcher;
24import org.junit.Before;
25import org.junit.Test;
26import org.onlab.packet.MacAddress;
27import org.onosproject.codec.JsonCodec;
28import org.onosproject.net.PortNumber;
29import org.onosproject.net.flow.DefaultTrafficTreatment;
30import org.onosproject.net.flow.TrafficTreatment;
31import org.onosproject.net.flow.instructions.Instruction;
32import org.onosproject.net.flow.instructions.Instructions;
33import org.onosproject.net.meter.MeterId;
34
35import java.io.IOException;
36import java.io.InputStream;
37import java.util.List;
cansu.toprak409289d2017-10-27 10:04:05 +030038import java.util.Optional;
Jian Li96b47d92016-05-16 17:59:06 -070039
40import static org.hamcrest.MatcherAssert.assertThat;
41import static org.hamcrest.Matchers.is;
42import static org.hamcrest.Matchers.notNullValue;
43
44/**
45 * Unit tests for traffic treatment codec.
46 */
47public class TrafficTreatmentCodecTest {
48
49 private MockCodecContext context;
50 private JsonCodec<TrafficTreatment> trafficTreatmentCodec;
51
52 @Before
53 public void setUp() {
54 context = new MockCodecContext();
55 trafficTreatmentCodec = context.codec(TrafficTreatment.class);
56 assertThat(trafficTreatmentCodec, notNullValue());
57 }
58
59 /**
60 * Tests encoding of a traffic treatment object.
61 */
62 @Test
63 public void testTrafficTreatmentEncode() {
64
65 Instruction output = Instructions.createOutput(PortNumber.portNumber(0));
66 Instruction modL2Src = Instructions.modL2Src(MacAddress.valueOf("11:22:33:44:55:66"));
67 Instruction modL2Dst = Instructions.modL2Dst(MacAddress.valueOf("44:55:66:77:88:99"));
Jordi Ortiz75f5fb92016-10-21 19:26:16 +020068 MeterId meterId = MeterId.meterId(1);
Jian Li96b47d92016-05-16 17:59:06 -070069 Instruction meter = Instructions.meterTraffic(meterId);
70 Instruction transition = Instructions.transition(1);
71 TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
72 TrafficTreatment treatment = tBuilder
73 .add(output)
74 .add(modL2Src)
75 .add(modL2Dst)
76 .add(meter)
77 .add(transition)
78 .build();
79
80 ObjectNode treatmentJson = trafficTreatmentCodec.encode(treatment, context);
81 assertThat(treatmentJson, TrafficTreatmentJsonMatcher.matchesTrafficTreatment(treatment));
82 }
83
84 /**
85 * Tests decoding of a traffic treatment JSON object.
86 */
87 @Test
88 public void testTrafficTreatmentDecode() throws IOException {
89 TrafficTreatment treatment = getTreatment("TrafficTreatment.json");
90
91 List<Instruction> insts = treatment.immediate();
92 assertThat(insts.size(), is(2));
93
94 ImmutableSet<String> types = ImmutableSet.of("OUTPUT", "L2MODIFICATION");
95 assertThat(types.contains(insts.get(0).type().name()), is(true));
96 assertThat(types.contains(insts.get(1).type().name()), is(true));
97 }
98
Jian Lie2a59f42016-05-18 15:15:53 -070099 public static final class TrafficTreatmentJsonMatcher
Jian Li96b47d92016-05-16 17:59:06 -0700100 extends TypeSafeDiagnosingMatcher<JsonNode> {
101
102 private final TrafficTreatment trafficTreatment;
103
104 private TrafficTreatmentJsonMatcher(TrafficTreatment trafficTreatment) {
105 this.trafficTreatment = trafficTreatment;
106 }
107
108 /**
109 * Filtered out the meter and table transition instructions.
110 *
111 * @param node JSON node
112 * @return filtered JSON node
113 */
114 private int filteredSize(JsonNode node) {
115 int counter = 0;
116 for (int idx = 0; idx < node.size(); idx++) {
117 String type = node.get(idx).get("type").asText();
Jon Halla3fcf672017-03-28 16:53:22 -0700118 if (!"METER".equals(type) && !"TABLE".equals(type)) {
Jian Li96b47d92016-05-16 17:59:06 -0700119 counter++;
120 }
121 }
122 return counter;
123 }
124
125 private JsonNode getInstNode(JsonNode node, String name) {
126 for (int idx = 0; idx < node.size(); idx++) {
127 String type = node.get(idx).get("type").asText();
128 if (type.equals(name)) {
129 return node.get(idx);
130 }
131 }
132 return null;
133 }
134
135 @Override
136 protected boolean matchesSafely(JsonNode jsonNode, Description description) {
137
138 // check instructions
139 final JsonNode jsonInstructions = jsonNode.get("instructions");
140
141 if (trafficTreatment.immediate().size() != filteredSize(jsonInstructions)) {
142 description.appendText("instructions array size of " +
143 Integer.toString(trafficTreatment.immediate().size()));
144 return false;
145 }
146
147 for (final Instruction instruction : trafficTreatment.immediate()) {
148 boolean instructionFound = false;
149 for (int instructionIndex = 0; instructionIndex < jsonInstructions.size();
150 instructionIndex++) {
151 final String jsonType =
152 jsonInstructions.get(instructionIndex).get("type").asText();
153 final String instructionType = instruction.type().name();
154 if (jsonType.equals(instructionType)) {
155 instructionFound = true;
156 }
157 }
158 if (!instructionFound) {
159 description.appendText("instruction " + instruction.toString());
160 return false;
161 }
162 }
163
164 // check metered
165 JsonNode meterNode = getInstNode(jsonInstructions, "METER");
166 String jsonMeterId = meterNode != null ? meterNode.get("meterId").asText() : null;
cansu.toprak409289d2017-10-27 10:04:05 +0300167 if (trafficTreatment.metered() != null && !trafficTreatment.meters().isEmpty()) {
168 Optional<Instructions.MeterInstruction> optional = trafficTreatment.meters().stream().filter(
169 meterInstruction -> StringUtils.equals(jsonMeterId, meterInstruction.meterId().toString()))
170 .findAny();
171 if (!optional.isPresent()) {
Jian Lie2a59f42016-05-18 15:15:53 -0700172 description.appendText("meter id was " + jsonMeterId);
173 return false;
174 }
Jian Li96b47d92016-05-16 17:59:06 -0700175 }
176
177 // check table transition
178 JsonNode tableNode = getInstNode(jsonInstructions, "TABLE");
179 String jsonTableId = tableNode != null ? tableNode.get("tableId").asText() : null;
Jian Lie2a59f42016-05-18 15:15:53 -0700180 if (trafficTreatment.tableTransition() != null) {
181 String tableId = trafficTreatment.tableTransition().tableId().toString();
182 if (!StringUtils.equals(jsonTableId, tableId)) {
183 description.appendText("table id was " + jsonMeterId);
184 return false;
185 }
Jian Li96b47d92016-05-16 17:59:06 -0700186 }
187
188 // TODO: check deferred
189
190 return true;
191 }
192
193 @Override
194 public void describeTo(Description description) {
195 description.appendText(trafficTreatment.toString());
196 }
197
198 /**
199 * Factory to allocate a traffic treatment.
200 *
201 * @param trafficTreatment traffic treatment object we are looking for
202 * @return matcher
203 */
204 static TrafficTreatmentJsonMatcher matchesTrafficTreatment(TrafficTreatment trafficTreatment) {
205 return new TrafficTreatmentJsonMatcher(trafficTreatment);
206 }
207 }
208
209 /**
210 * Reads in a traffic treatment from the given resource and decodes it.
211 *
212 * @param resourceName resource to use to read the JSON for the rule
213 * @return decoded trafficTreatment
214 * @throws IOException if processing the resource fails
215 */
216 private TrafficTreatment getTreatment(String resourceName) throws IOException {
217 InputStream jsonStream = TrafficTreatmentCodecTest.class.getResourceAsStream(resourceName);
218 JsonNode json = context.mapper().readTree(jsonStream);
219 assertThat(json, notNullValue());
220 TrafficTreatment treatment = trafficTreatmentCodec.decode((ObjectNode) json, context);
221 assertThat(treatment, notNullValue());
222 return treatment;
223 }
224}