Ray Milkey

Unit tets for instruction JSON codecs

Fixed several bugs in codecs turned up by unit tests

Change-Id: Icddb31aa3d2cb58612a0578772d24ff5f113d073
...@@ -43,6 +43,13 @@ ...@@ -43,6 +43,13 @@
43 <artifactId>easymock</artifactId> 43 <artifactId>easymock</artifactId>
44 <scope>test</scope> 44 <scope>test</scope>
45 </dependency> 45 </dependency>
46 + <dependency>
47 + <groupId>org.onosproject</groupId>
48 + <artifactId>onos-api</artifactId>
49 + <version>${project.version}</version>
50 + <scope>test</scope>
51 + <classifier>tests</classifier>
52 + </dependency>
46 </dependencies> 53 </dependencies>
47 54
48 <properties> 55 <properties>
......
...@@ -20,8 +20,10 @@ import org.onosproject.codec.JsonCodec; ...@@ -20,8 +20,10 @@ import org.onosproject.codec.JsonCodec;
20 import org.onosproject.net.flow.TrafficSelector; 20 import org.onosproject.net.flow.TrafficSelector;
21 import org.onosproject.net.flow.TrafficTreatment; 21 import org.onosproject.net.flow.TrafficTreatment;
22 import org.onosproject.net.intent.ConnectivityIntent; 22 import org.onosproject.net.intent.ConnectivityIntent;
23 +import org.onosproject.net.intent.Constraint;
23 import org.onosproject.net.intent.Intent; 24 import org.onosproject.net.intent.Intent;
24 25
26 +import com.fasterxml.jackson.databind.node.ArrayNode;
25 import com.fasterxml.jackson.databind.node.ObjectNode; 27 import com.fasterxml.jackson.databind.node.ObjectNode;
26 28
27 import static com.google.common.base.Preconditions.checkNotNull; 29 import static com.google.common.base.Preconditions.checkNotNull;
...@@ -50,6 +52,17 @@ public class ConnectivityIntentCodec extends JsonCodec<ConnectivityIntent> { ...@@ -50,6 +52,17 @@ public class ConnectivityIntentCodec extends JsonCodec<ConnectivityIntent> {
50 result.set("treatment", treatmentCodec.encode(intent.treatment(), context)); 52 result.set("treatment", treatmentCodec.encode(intent.treatment(), context));
51 } 53 }
52 54
55 + if (intent.constraints() != null) {
56 + final ArrayNode jsonConstraints = result.putArray("constraints");
57 +
58 + if (intent.constraints() != null) {
59 + for (final Constraint constraint : intent.constraints()) {
60 + // TODO: constraint should have its own codec
61 + jsonConstraints.add(constraint.toString());
62 + }
63 + }
64 + }
65 +
53 return result; 66 return result;
54 } 67 }
55 } 68 }
......
...@@ -50,6 +50,7 @@ public class CriterionCodec extends JsonCodec<Criterion> { ...@@ -50,6 +50,7 @@ public class CriterionCodec extends JsonCodec<Criterion> {
50 case ETH_SRC: 50 case ETH_SRC:
51 case ETH_DST: 51 case ETH_DST:
52 final Criteria.EthCriterion ethCriterion = (Criteria.EthCriterion) criterion; 52 final Criteria.EthCriterion ethCriterion = (Criteria.EthCriterion) criterion;
53 + result.put("mac", ethCriterion.mac().toString());
53 break; 54 break;
54 55
55 case ETH_TYPE: 56 case ETH_TYPE:
...@@ -60,6 +61,8 @@ public class CriterionCodec extends JsonCodec<Criterion> { ...@@ -60,6 +61,8 @@ public class CriterionCodec extends JsonCodec<Criterion> {
60 61
61 case IPV4_SRC: 62 case IPV4_SRC:
62 case IPV6_SRC: 63 case IPV6_SRC:
64 + case IPV4_DST:
65 + case IPV6_DST:
63 final Criteria.IPCriterion iPCriterion = (Criteria.IPCriterion) criterion; 66 final Criteria.IPCriterion iPCriterion = (Criteria.IPCriterion) criterion;
64 result.put("ip", iPCriterion.ip().toString()); 67 result.put("ip", iPCriterion.ip().toString());
65 break; 68 break;
......
1 +/*
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 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import org.hamcrest.Description;
19 +import org.hamcrest.TypeSafeDiagnosingMatcher;
20 +import org.onosproject.net.ConnectPoint;
21 +
22 +import com.fasterxml.jackson.databind.JsonNode;
23 +
24 +/**
25 + * Hamcrest matcher for connect points.
26 + */
27 +
28 +public final class ConnectPointJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
29 +
30 + private final ConnectPoint connectPoint;
31 +
32 + private ConnectPointJsonMatcher(ConnectPoint connectPointValue) {
33 + connectPoint = connectPointValue;
34 + }
35 +
36 + @Override
37 + public boolean matchesSafely(JsonNode jsonConnectPoint, Description description) {
38 + // check device
39 + final String jsonDevice = jsonConnectPoint.get("device").asText();
40 + final String device = connectPoint.deviceId().toString();
41 + if (!jsonDevice.equals(device)) {
42 + description.appendText("device was " + jsonDevice);
43 + return false;
44 + }
45 +
46 + // check port
47 + final String jsonPort = jsonConnectPoint.get("port").asText();
48 + final String port = connectPoint.port().toString();
49 + if (!jsonPort.equals(port)) {
50 + description.appendText("port was " + jsonPort);
51 + return false;
52 + }
53 +
54 + return true;
55 + }
56 +
57 + @Override
58 + public void describeTo(Description description) {
59 + description.appendText(connectPoint.toString());
60 + }
61 +
62 + /**
63 + * Factory to allocate an connect point matcher.
64 + *
65 + * @param connectPoint connect point object we are looking for
66 + * @return matcher
67 + */
68 + public static ConnectPointJsonMatcher matchesConnectPoint(ConnectPoint connectPoint) {
69 + return new ConnectPointJsonMatcher(connectPoint);
70 + }
71 +}
1 +/*
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 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import org.hamcrest.Description;
19 +import org.hamcrest.TypeSafeDiagnosingMatcher;
20 +import org.onosproject.net.flow.criteria.Criteria;
21 +import org.onosproject.net.flow.criteria.Criterion;
22 +
23 +import com.fasterxml.jackson.databind.JsonNode;
24 +
25 +/**
26 + * Hamcrest matcher for criterion objects.
27 + */
28 +public final class CriterionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
29 +
30 + final Criterion criterion;
31 +
32 + private CriterionJsonMatcher(Criterion criterionValue) {
33 + criterion = criterionValue;
34 + }
35 +
36 + @Override
37 + public boolean matchesSafely(JsonNode jsonCriterion, Description description) {
38 + final String type = criterion.type().name();
39 + final String jsonType = jsonCriterion.get("type").asText();
40 + if (!type.equals(jsonType)) {
41 + description.appendText("type was " + type);
42 + return false;
43 + }
44 +
45 + switch (criterion.type()) {
46 +
47 + case IN_PORT:
48 + final Criteria.PortCriterion portCriterion = (Criteria.PortCriterion) criterion;
49 + final long port = portCriterion.port().toLong();
50 + final long jsonPort = jsonCriterion.get("port").asLong();
51 + if (port != jsonPort) {
52 + description.appendText("port was " + Long.toString(jsonPort));
53 + return false;
54 + }
55 + break;
56 +
57 + case ETH_SRC:
58 + case ETH_DST:
59 + final Criteria.EthCriterion ethCriterion = (Criteria.EthCriterion) criterion;
60 + final String mac = ethCriterion.mac().toString();
61 + final String jsonMac = jsonCriterion.get("mac").textValue();
62 + if (!mac.equals(jsonMac)) {
63 + description.appendText("mac was " + jsonMac);
64 + return false;
65 + }
66 + break;
67 +
68 + case ETH_TYPE:
69 + final Criteria.EthTypeCriterion ethTypeCriterion =
70 + (Criteria.EthTypeCriterion) criterion;
71 + final String ethType = ethTypeCriterion.ethType().toString();
72 + final String jsonEthType = jsonCriterion.get("ethType").textValue();
73 + if (!ethType.equals(jsonEthType)) {
74 + description.appendText("ethType was " + jsonEthType);
75 + return false;
76 + }
77 + break;
78 +
79 + case IPV4_SRC:
80 + case IPV6_SRC:
81 + case IPV4_DST:
82 + case IPV6_DST:
83 + final Criteria.IPCriterion ipCriterion = (Criteria.IPCriterion) criterion;
84 + final String ip = ipCriterion.ip().toString();
85 + final String jsonIp = jsonCriterion.get("ip").textValue();
86 + if (!ip.equals(jsonIp)) {
87 + description.appendText("ip was " + jsonIp);
88 + return false;
89 + }
90 + break;
91 +
92 + case IP_PROTO:
93 + final Criteria.IPProtocolCriterion iPProtocolCriterion =
94 + (Criteria.IPProtocolCriterion) criterion;
95 + final byte protocol = iPProtocolCriterion.protocol();
96 + final byte jsonProtocol = (byte) jsonCriterion.get("protocol").shortValue();
97 + if (protocol != jsonProtocol) {
98 + description.appendText("protocol was " + Byte.toString(jsonProtocol));
99 + return false;
100 + }
101 + break;
102 +
103 + case VLAN_PCP:
104 + final Criteria.VlanPcpCriterion vlanPcpCriterion =
105 + (Criteria.VlanPcpCriterion) criterion;
106 + final byte priority = vlanPcpCriterion.priority();
107 + final byte jsonPriority = (byte) jsonCriterion.get("protocol").shortValue();
108 + if (priority != jsonPriority) {
109 + description.appendText("priority was " + Byte.toString(jsonPriority));
110 + return false;
111 + }
112 + break;
113 +
114 + case VLAN_VID:
115 + final Criteria.VlanIdCriterion vlanIdCriterion =
116 + (Criteria.VlanIdCriterion) criterion;
117 + final short vlanId = vlanIdCriterion.vlanId().toShort();
118 + final short jsonvlanId = jsonCriterion.get("vlanId").shortValue();
119 + if (vlanId != jsonvlanId) {
120 + description.appendText("vlanId was " + Short.toString(jsonvlanId));
121 + return false;
122 + }
123 + break;
124 +
125 + case TCP_SRC:
126 + case TCP_DST:
127 + final Criteria.TcpPortCriterion tcpPortCriterion =
128 + (Criteria.TcpPortCriterion) criterion;
129 + final byte tcpPort = tcpPortCriterion.tcpPort().byteValue();
130 + final byte jsonTcpPort = (byte) jsonCriterion.get("tcpPort").shortValue();
131 + if (tcpPort != jsonTcpPort) {
132 + description.appendText("tcp port was " + Byte.toString(jsonTcpPort));
133 + return false;
134 + }
135 + break;
136 +
137 + case MPLS_LABEL:
138 + final Criteria.MplsCriterion mplsCriterion =
139 + (Criteria.MplsCriterion) criterion;
140 + final int label = mplsCriterion.label();
141 + final int jsonLabel = jsonCriterion.get("label").intValue();
142 + if (label != jsonLabel) {
143 + description.appendText("label was " + Integer.toString(jsonLabel));
144 + return false;
145 + }
146 + break;
147 +
148 + case OCH_SIGID:
149 + final Criteria.LambdaCriterion lambdaCriterion =
150 + (Criteria.LambdaCriterion) criterion;
151 + final short lambda = lambdaCriterion.lambda();
152 + final short jsonLambda = jsonCriterion.get("lambda").shortValue();
153 + if (lambda != jsonLambda) {
154 + description.appendText("lambda was " + Short.toString(lambda));
155 + return false;
156 + }
157 + break;
158 +
159 + case OCH_SIGTYPE:
160 + final Criteria.OpticalSignalTypeCriterion opticalSignalTypeCriterion =
161 + (Criteria.OpticalSignalTypeCriterion) criterion;
162 + final short signalType = opticalSignalTypeCriterion.signalType();
163 + final short jsonSignalType = jsonCriterion.get("signalType").shortValue();
164 + if (signalType != jsonSignalType) {
165 + description.appendText("signal type was " + Short.toString(signalType));
166 + return false;
167 + }
168 + break;
169 +
170 + default:
171 + // Don't know how to format this type
172 + description.appendText("unknown criterion type " +
173 + criterion.type());
174 + return false;
175 + }
176 + return true;
177 + }
178 +
179 + @Override
180 + public void describeTo(Description description) {
181 + description.appendText(criterion.toString());
182 + }
183 +
184 + /**
185 + * Factory to allocate an criterion matcher.
186 + *
187 + * @param criterion criterion object we are looking for
188 + * @return matcher
189 + */
190 + public static CriterionJsonMatcher matchesCriterion(Criterion criterion) {
191 + return new CriterionJsonMatcher(criterion);
192 + }
193 +}
...@@ -24,12 +24,12 @@ import com.fasterxml.jackson.databind.JsonNode; ...@@ -24,12 +24,12 @@ import com.fasterxml.jackson.databind.JsonNode;
24 /** 24 /**
25 * Hamcrest matcher for ethernet objects. 25 * Hamcrest matcher for ethernet objects.
26 */ 26 */
27 -public class EthernetJsonMatcher extends TypeSafeMatcher<JsonNode> { 27 +public final class EthernetJsonMatcher extends TypeSafeMatcher<JsonNode> {
28 28
29 private final Ethernet ethernet; 29 private final Ethernet ethernet;
30 private String reason = ""; 30 private String reason = "";
31 31
32 - public EthernetJsonMatcher(Ethernet ethernetValue) { 32 + private EthernetJsonMatcher(Ethernet ethernetValue) {
33 ethernet = ethernetValue; 33 ethernet = ethernetValue;
34 } 34 }
35 35
......
...@@ -44,7 +44,7 @@ public class InstructionCodecTest { ...@@ -44,7 +44,7 @@ public class InstructionCodecTest {
44 JsonCodec<Instruction> instructionCodec; 44 JsonCodec<Instruction> instructionCodec;
45 45
46 /** 46 /**
47 - * Sets up for each tests. Creates a context and fetches the instruction 47 + * Sets up for each test. Creates a context and fetches the instruction
48 * codec. 48 * codec.
49 */ 49 */
50 @Before 50 @Before
......
...@@ -31,11 +31,11 @@ import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*; ...@@ -31,11 +31,11 @@ import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*;
31 /** 31 /**
32 * Hamcrest matcher for instructions. 32 * Hamcrest matcher for instructions.
33 */ 33 */
34 -public class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> { 34 +public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
35 35
36 private final Instruction instruction; 36 private final Instruction instruction;
37 37
38 - public InstructionJsonMatcher(Instruction instructionValue) { 38 + private InstructionJsonMatcher(Instruction instructionValue) {
39 instruction = instructionValue; 39 instruction = instructionValue;
40 } 40 }
41 41
...@@ -134,7 +134,7 @@ public class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> ...@@ -134,7 +134,7 @@ public class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode>
134 } 134 }
135 135
136 /** 136 /**
137 - * Matches the contents of a mod lambda instruction. 137 + * Matches the contents of a mod Ethernet instruction.
138 * 138 *
139 * @param instructionJson JSON instruction to match 139 * @param instructionJson JSON instruction to match
140 * @return true if contents match, false otherwise 140 * @return true if contents match, false otherwise
...@@ -262,7 +262,7 @@ public class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> ...@@ -262,7 +262,7 @@ public class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode>
262 } 262 }
263 263
264 /** 264 /**
265 - * Matches the contents of a mod ip instruction. 265 + * Matches the contents of a mod MPLS label instruction.
266 * 266 *
267 * @param instructionJson JSON instruction to match 267 * @param instructionJson JSON instruction to match
268 * @return true if contents match, false otherwise 268 * @return true if contents match, false otherwise
......
1 +/*
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 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import java.util.List;
19 +
20 +import org.junit.Test;
21 +import org.onlab.packet.IpPrefix;
22 +import org.onlab.packet.MacAddress;
23 +import org.onosproject.codec.CodecContext;
24 +import org.onosproject.codec.JsonCodec;
25 +import org.onosproject.core.ApplicationId;
26 +import org.onosproject.core.DefaultApplicationId;
27 +import org.onosproject.net.ConnectPoint;
28 +import org.onosproject.net.HostId;
29 +import org.onosproject.net.NetTestTools;
30 +import org.onosproject.net.PortNumber;
31 +import org.onosproject.net.flow.DefaultTrafficSelector;
32 +import org.onosproject.net.flow.DefaultTrafficTreatment;
33 +import org.onosproject.net.flow.TrafficSelector;
34 +import org.onosproject.net.flow.TrafficTreatment;
35 +import org.onosproject.net.intent.Constraint;
36 +import org.onosproject.net.intent.HostToHostIntent;
37 +import org.onosproject.net.intent.AbstractIntentTest;
38 +import org.onosproject.net.intent.PointToPointIntent;
39 +import org.onosproject.net.intent.constraint.BandwidthConstraint;
40 +import org.onosproject.net.intent.constraint.LambdaConstraint;
41 +import org.onosproject.net.resource.Bandwidth;
42 +import org.onosproject.net.resource.Lambda;
43 +
44 +import com.fasterxml.jackson.databind.node.ObjectNode;
45 +import com.google.common.collect.ImmutableList;
46 +
47 +import static org.onosproject.codec.impl.IntentJsonMatcher.matchesIntent;
48 +import static org.onosproject.net.NetTestTools.hid;
49 +
50 +
51 +import static org.hamcrest.MatcherAssert.assertThat;
52 +import static org.hamcrest.Matchers.notNullValue;
53 +
54 +/**
55 + * Unit tests for the host to host intent class codec.
56 + */
57 +public class IntentCodecTest extends AbstractIntentTest {
58 +
59 + private final HostId id1 = hid("12:34:56:78:91:ab/1");
60 + private final HostId id2 = hid("12:34:56:78:92:ab/1");
61 + private final ApplicationId appId =
62 + new DefaultApplicationId((short) 3, "test");
63 + final TrafficSelector emptySelector =
64 + DefaultTrafficSelector.builder().build();
65 + final TrafficTreatment emptyTreatment =
66 + DefaultTrafficTreatment.builder().build();
67 + private final CodecContext context = new MockCodecContext();
68 +
69 + /**
70 + * Tests the encoding of a host to host intent.
71 + */
72 + @Test
73 + public void hostToHostIntent() {
74 + final HostToHostIntent intent =
75 + new HostToHostIntent(appId, id1, id2);
76 +
77 + final JsonCodec<HostToHostIntent> intentCodec =
78 + context.codec(HostToHostIntent.class);
79 + assertThat(intentCodec, notNullValue());
80 +
81 + final ObjectNode intentJson = intentCodec.encode(intent, context);
82 + assertThat(intentJson, matchesIntent(intent));
83 + }
84 +
85 + /**
86 + * Tests the encoding of a point to point intent.
87 + */
88 + @Test
89 + public void pointToPointIntent() {
90 + ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
91 + ConnectPoint egress = NetTestTools.connectPoint("egress", 2);
92 +
93 + final PointToPointIntent intent =
94 + new PointToPointIntent(appId, emptySelector,
95 + emptyTreatment, ingress, egress);
96 +
97 + final CodecContext context = new MockCodecContext();
98 + final JsonCodec<PointToPointIntent> intentCodec =
99 + context.codec(PointToPointIntent.class);
100 + assertThat(intentCodec, notNullValue());
101 +
102 + final ObjectNode intentJson = intentCodec.encode(intent, context);
103 + assertThat(intentJson, matchesIntent(intent));
104 + }
105 +
106 + /**
107 + * Tests the encoding of an intent with treatment, selector and constraints
108 + * specified.
109 + */
110 + @Test
111 + public void intentWithTreatmentSelectorAndConstraints() {
112 + ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
113 + ConnectPoint egress = NetTestTools.connectPoint("egress", 2);
114 + final TrafficSelector selector = DefaultTrafficSelector.builder()
115 + .matchIPProtocol((byte) 3)
116 + .matchMplsLabel(4)
117 + .matchOpticalSignalType((short) 5)
118 + .matchLambda((short) 6)
119 + .matchEthDst(MacAddress.BROADCAST)
120 + .matchIPDst(IpPrefix.valueOf("1.2.3.4/24"))
121 + .build();
122 + final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
123 + .setLambda((short) 33)
124 + .setMpls(44)
125 + .setOutput(PortNumber.CONTROLLER)
126 + .setEthDst(MacAddress.BROADCAST)
127 + .build();
128 + final Constraint constraint1 = new BandwidthConstraint(Bandwidth.valueOf(1.0));
129 + final Constraint constraint2 = new LambdaConstraint(Lambda.valueOf(3));
130 + final List<Constraint> constraints = ImmutableList.of(constraint1, constraint2);
131 +
132 + final PointToPointIntent intent =
133 + new PointToPointIntent(appId, selector, treatment,
134 + ingress, egress, constraints);
135 +
136 + final CodecContext context = new MockCodecContext();
137 + final JsonCodec<PointToPointIntent> intentCodec =
138 + context.codec(PointToPointIntent.class);
139 + assertThat(intentCodec, notNullValue());
140 +
141 + final ObjectNode intentJson = intentCodec.encode(intent, context);
142 + assertThat(intentJson, matchesIntent(intent));
143 +
144 + }
145 +}
1 +/*
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 + */
16 +package org.onosproject.codec.impl;
17 +
18 +import java.util.List;
19 +import java.util.Set;
20 +
21 +import org.hamcrest.Description;
22 +import org.hamcrest.TypeSafeDiagnosingMatcher;
23 +import org.onosproject.net.ConnectPoint;
24 +import org.onosproject.net.NetworkResource;
25 +import org.onosproject.net.flow.TrafficSelector;
26 +import org.onosproject.net.flow.TrafficTreatment;
27 +import org.onosproject.net.flow.criteria.Criterion;
28 +import org.onosproject.net.flow.instructions.Instruction;
29 +import org.onosproject.net.intent.ConnectivityIntent;
30 +import org.onosproject.net.intent.Constraint;
31 +import org.onosproject.net.intent.HostToHostIntent;
32 +import org.onosproject.net.intent.Intent;
33 +import org.onosproject.net.intent.PointToPointIntent;
34 +
35 +import com.fasterxml.jackson.databind.JsonNode;
36 +
37 +/**
38 + * Hamcrest matcher to check that an intent representation in JSON matches
39 + * the actual intent.
40 + */
41 +public final class IntentJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
42 +
43 + private final Intent intent;
44 +
45 + /**
46 + * Constructor is private, use factory method.
47 + *
48 + * @param intentValue the intent object to compare against
49 + */
50 + private IntentJsonMatcher(Intent intentValue) {
51 + intent = intentValue;
52 + }
53 +
54 + /**
55 + * Matches the JSON representation of a host to host intent.
56 + *
57 + * @param jsonIntent JSON representation of the intent
58 + * @param description Description object used for recording errors
59 + * @return true if the JSON matches the intent, false otherwise
60 + */
61 + private boolean matchHostToHostIntent(JsonNode jsonIntent, Description description) {
62 + final HostToHostIntent hostToHostIntent = (HostToHostIntent) intent;
63 +
64 + // check host one
65 + final String host1 = hostToHostIntent.one().toString();
66 + final String jsonHost1 = jsonIntent.get("one").asText();
67 + if (!host1.equals(jsonHost1)) {
68 + description.appendText("host one was " + jsonHost1);
69 + return false;
70 + }
71 +
72 + // check host 2
73 + final String host2 = hostToHostIntent.two().toString();
74 + final String jsonHost2 = jsonIntent.get("two").asText();
75 + if (!host2.equals(jsonHost2)) {
76 + description.appendText("host two was " + jsonHost2);
77 + return false;
78 + }
79 + return true;
80 + }
81 +
82 + /**
83 + * Matches the JSON representation of a point to point intent.
84 + *
85 + * @param jsonIntent JSON representation of the intent
86 + * @param description Description object used for recording errors
87 + * @return true if the JSON matches the intent, false otherwise
88 + */
89 + private boolean matchPointToPointIntent(JsonNode jsonIntent, Description description) {
90 + final PointToPointIntent pointToPointIntent = (PointToPointIntent) intent;
91 +
92 + // check ingress connection
93 + final ConnectPoint ingress = pointToPointIntent.ingressPoint();
94 + final ConnectPointJsonMatcher ingressMatcher =
95 + ConnectPointJsonMatcher.matchesConnectPoint(ingress);
96 + final JsonNode jsonIngress = jsonIntent.get("ingressPoint");
97 + final boolean ingressMatches =
98 + ingressMatcher.matchesSafely(jsonIngress, description);
99 +
100 + if (!ingressMatches) {
101 + description.appendText("ingress was " + jsonIngress);
102 + return false;
103 + }
104 +
105 + // check egress connection
106 + final ConnectPoint egress = pointToPointIntent.egressPoint();
107 + final ConnectPointJsonMatcher egressMatcher =
108 + ConnectPointJsonMatcher.matchesConnectPoint(egress);
109 + final JsonNode jsonEgress = jsonIntent.get("egressPoint");
110 + final boolean egressMatches =
111 + egressMatcher.matchesSafely(jsonEgress, description);
112 +
113 + if (!egressMatches) {
114 + description.appendText("egress was " + jsonEgress);
115 + return false;
116 + }
117 +
118 + return true;
119 + }
120 +
121 + /**
122 + * Matches the JSON representation of a connectivity intent. Calls the
123 + * matcher for the connectivity intent subtype.
124 + *
125 + * @param jsonIntent JSON representation of the intent
126 + * @param description Description object used for recording errors
127 + * @return true if the JSON matches the intent, false otherwise
128 + */
129 + private boolean matchConnectivityIntent(JsonNode jsonIntent, Description description) {
130 + final ConnectivityIntent connectivityIntent = (ConnectivityIntent) intent;
131 +
132 + // check selector
133 + final JsonNode jsonSelector = jsonIntent.get("selector");
134 + final TrafficSelector selector = connectivityIntent.selector();
135 + final Set<Criterion> criteria = selector.criteria();
136 + final JsonNode jsonCriteria = jsonSelector.get("criteria");
137 + if (jsonCriteria.size() != criteria.size()) {
138 + description.appendText("size of criteria array is "
139 + + Integer.toString(jsonCriteria.size()));
140 + return false;
141 + }
142 +
143 + for (Criterion criterion : criteria) {
144 + boolean criterionFound = false;
145 + for (int criterionIndex = 0; criterionIndex < jsonCriteria.size(); criterionIndex++) {
146 + final CriterionJsonMatcher criterionMatcher =
147 + CriterionJsonMatcher.matchesCriterion(criterion);
148 + if (criterionMatcher.matches(jsonCriteria.get(criterionIndex))) {
149 + criterionFound = true;
150 + break;
151 + }
152 + }
153 + if (!criterionFound) {
154 + description.appendText("criterion not found " + criterion.toString());
155 + return false;
156 + }
157 + }
158 +
159 + // check treatment
160 + final JsonNode jsonTreatment = jsonIntent.get("treatment");
161 + final TrafficTreatment treatment = connectivityIntent.treatment();
162 + final List<Instruction> instructions = treatment.instructions();
163 + final JsonNode jsonInstructions = jsonTreatment.get("instructions");
164 + if (jsonInstructions.size() != instructions.size()) {
165 + description.appendText("size of instructions array is "
166 + + Integer.toString(jsonInstructions.size()));
167 + return false;
168 + }
169 +
170 + for (Instruction instruction : instructions) {
171 + boolean instructionFound = false;
172 + for (int instructionIndex = 0; instructionIndex < jsonCriteria.size(); instructionIndex++) {
173 + final InstructionJsonMatcher instructionMatcher =
174 + InstructionJsonMatcher.matchesInstruction(instruction);
175 + if (instructionMatcher.matches(jsonInstructions.get(instructionIndex))) {
176 + instructionFound = true;
177 + break;
178 + }
179 + }
180 + if (!instructionFound) {
181 + description.appendText("instruction not found " + instruction.toString());
182 + return false;
183 + }
184 + }
185 +
186 + // Check constraints
187 + final JsonNode jsonConstraints = jsonIntent.get("constraints");
188 + if (connectivityIntent.constraints() != null) {
189 + if (connectivityIntent.constraints().size() != jsonConstraints.size()) {
190 + description.appendText("constraints array size was "
191 + + Integer.toString(jsonConstraints.size()));
192 + return false;
193 + }
194 + for (final Constraint constraint : connectivityIntent.constraints()) {
195 + boolean constraintFound = false;
196 + final String constraintString = constraint.toString();
197 + for (int constraintIndex = 0; constraintIndex < jsonConstraints.size();
198 + constraintIndex++) {
199 + final JsonNode value = jsonConstraints.get(constraintIndex);
200 + if (value.asText().equals(constraintString)) {
201 + constraintFound = true;
202 + }
203 + }
204 + if (!constraintFound) {
205 + description.appendText("resource missing " + constraintString);
206 + return false;
207 + }
208 + }
209 + } else if (jsonConstraints.size() != 0) {
210 + description.appendText("constraint array not empty");
211 + return false;
212 + }
213 +
214 + if (connectivityIntent instanceof HostToHostIntent) {
215 + return matchHostToHostIntent(jsonIntent, description);
216 + } else if (connectivityIntent instanceof PointToPointIntent) {
217 + return matchPointToPointIntent(jsonIntent, description);
218 + } else {
219 + description.appendText("class of connectivity intent is unknown");
220 + return false;
221 + }
222 + }
223 +
224 + @Override
225 + public boolean matchesSafely(JsonNode jsonIntent, Description description) {
226 + // check id
227 + final String jsonId = jsonIntent.get("id").asText();
228 + final String id = intent.id().toString();
229 + if (!jsonId.equals(id)) {
230 + description.appendText("id was " + jsonId);
231 + return false;
232 + }
233 +
234 + // check application id
235 + final String jsonAppId = jsonIntent.get("appId").asText();
236 + final String appId = intent.appId().toString();
237 + if (!jsonAppId.equals(appId)) {
238 + description.appendText("appId was " + jsonAppId);
239 + return false;
240 + }
241 +
242 + // check intent type
243 + final String jsonType = jsonIntent.get("type").asText();
244 + final String type = intent.getClass().getSimpleName();
245 + if (!jsonType.equals(type)) {
246 + description.appendText("type was " + jsonType);
247 + return false;
248 + }
249 +
250 + // check details field
251 + final String jsonDetails = jsonIntent.get("details").asText();
252 + final String details = intent.toString();
253 + if (!jsonDetails.equals(details)) {
254 + description.appendText("details were " + jsonDetails);
255 + return false;
256 + }
257 +
258 + // check resources array
259 + final JsonNode jsonResources = jsonIntent.get("resources");
260 + if (intent.resources() != null) {
261 + if (intent.resources().size() != jsonResources.size()) {
262 + description.appendText("resources array size was "
263 + + Integer.toString(jsonResources.size()));
264 + return false;
265 + }
266 + for (final NetworkResource resource : intent.resources()) {
267 + boolean resourceFound = false;
268 + final String resourceString = resource.toString();
269 + for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
270 + final JsonNode value = jsonResources.get(resourceIndex);
271 + if (value.asText().equals(resourceString)) {
272 + resourceFound = true;
273 + }
274 + }
275 + if (!resourceFound) {
276 + description.appendText("resource missing " + resourceString);
277 + return false;
278 + }
279 + }
280 + } else if (jsonResources.size() != 0) {
281 + description.appendText("resources array empty");
282 + return false;
283 + }
284 +
285 + if (intent instanceof ConnectivityIntent) {
286 + return matchConnectivityIntent(jsonIntent, description);
287 + } else {
288 + description.appendText("class of intent is unknown");
289 + return false;
290 + }
291 + }
292 +
293 + @Override
294 + public void describeTo(Description description) {
295 + description.appendText(intent.toString());
296 + }
297 +
298 + /**
299 + * Factory to allocate an intent matcher.
300 + *
301 + * @param intent intent object we are looking for
302 + * @return matcher
303 + */
304 + public static IntentJsonMatcher matchesIntent(Intent intent) {
305 + return new IntentJsonMatcher(intent);
306 + }
307 +}
...@@ -28,6 +28,9 @@ public final class MockCodecContext implements CodecContext { ...@@ -28,6 +28,9 @@ public final class MockCodecContext implements CodecContext {
28 private ObjectMapper mapper = new ObjectMapper(); 28 private ObjectMapper mapper = new ObjectMapper();
29 private CodecManager manager = new CodecManager(); 29 private CodecManager manager = new CodecManager();
30 30
31 + /**
32 + * Constructs a new mock codec context.
33 + */
31 public MockCodecContext() { 34 public MockCodecContext() {
32 manager.activate(); 35 manager.activate();
33 } 36 }
......