aboutsummaryrefslogtreecommitdiffstats
path: root/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl
diff options
context:
space:
mode:
authorAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
committerAshlee Young <ashlee@onosfw.com>2015-09-09 22:15:21 -0700
commit13d05bc8458758ee39cb829098241e89616717ee (patch)
tree22a4d1ce65f15952f07a3df5af4b462b4697cb3a /framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl
parent6139282e1e93c2322076de4b91b1c85d0bc4a8b3 (diff)
ONOS checkin based on commit tag e796610b1f721d02f9b0e213cf6f7790c10ecd60
Change-Id: Ife8810491034fe7becdba75dda20de4267bd15cd
Diffstat (limited to 'framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl')
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConnectPointJsonMatcher.java71
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java202
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java445
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java609
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DeviceCodecTest.java59
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverCodecTest.java65
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverJsonMatcher.java118
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetCodecTest.java55
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetJsonMatcher.java122
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java546
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupBucketJsonMatcher.java87
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java61
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupJsonMatcher.java120
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ImmutableCodecsTest.java65
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java247
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java438
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java288
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentJsonMatcher.java512
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/JsonCodecUtils.java83
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LinkCodecTest.java54
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LoadCodecTest.java47
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java64
-rw-r--r--framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/PortCodecTest.java66
23 files changed, 4424 insertions, 0 deletions
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConnectPointJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConnectPointJsonMatcher.java
new file mode 100644
index 00000000..8d85751e
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConnectPointJsonMatcher.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.ConnectPoint;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher for connect points.
+ */
+
+public final class ConnectPointJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final ConnectPoint connectPoint;
+
+ private ConnectPointJsonMatcher(ConnectPoint connectPointValue) {
+ connectPoint = connectPointValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonConnectPoint, Description description) {
+ // check device
+ final String jsonDevice = jsonConnectPoint.get("device").asText();
+ final String device = connectPoint.deviceId().toString();
+ if (!jsonDevice.equals(device)) {
+ description.appendText("device was " + jsonDevice);
+ return false;
+ }
+
+ // check port
+ final String jsonPort = jsonConnectPoint.get("port").asText();
+ final String port = connectPoint.port().toString();
+ if (!jsonPort.equals(port)) {
+ description.appendText("port was " + jsonPort);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(connectPoint.toString());
+ }
+
+ /**
+ * Factory to allocate an connect point matcher.
+ *
+ * @param connectPoint connect point object we are looking for
+ * @return matcher
+ */
+ public static ConnectPointJsonMatcher matchesConnectPoint(ConnectPoint connectPoint) {
+ return new ConnectPointJsonMatcher(connectPoint);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java
new file mode 100644
index 00000000..2a47d115
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ConstraintCodecTest.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.Link;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.constraint.AnnotationConstraint;
+import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.intent.constraint.LatencyConstraint;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
+import org.onosproject.net.intent.constraint.ObstacleConstraint;
+import org.onosproject.net.intent.constraint.WaypointConstraint;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+import static org.onosproject.net.NetTestTools.did;
+
+/**
+ * Unit tests for Constraint codec.
+ */
+public class ConstraintCodecTest {
+
+ MockCodecContext context;
+ JsonCodec<Constraint> constraintCodec;
+ final CoreService mockCoreService = createMock(CoreService.class);
+
+ /**
+ * Sets up for each test. Creates a context and fetches the flow rule
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ constraintCodec = context.codec(Constraint.class);
+ assertThat(constraintCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Reads in a constraint from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the constraint
+ * @return decoded constraint
+ */
+ private Constraint getConstraint(String resourceName) {
+ InputStream jsonStream = ConstraintCodecTest.class
+ .getResourceAsStream(resourceName);
+ try {
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ Constraint constraint = constraintCodec.decode((ObjectNode) json, context);
+ assertThat(constraint, notNullValue());
+ return checkNotNull(constraint);
+ } catch (IOException ioe) {
+ Assert.fail(ioe.getMessage());
+ throw new IllegalStateException("cannot happen");
+ }
+ }
+
+
+ /**
+ * Tests link type constraint.
+ */
+ @Test
+ public void linkTypeConstraint() {
+ Constraint constraint = getConstraint("LinkTypeConstraint.json");
+ assertThat(constraint, instanceOf(LinkTypeConstraint.class));
+
+ LinkTypeConstraint linkTypeConstraint = (LinkTypeConstraint) constraint;
+ assertThat(linkTypeConstraint.isInclusive(), is(false));
+ assertThat(linkTypeConstraint.types(), hasSize(2));
+ assertThat(linkTypeConstraint.types(), hasItem(Link.Type.OPTICAL));
+ assertThat(linkTypeConstraint.types(), hasItem(Link.Type.DIRECT));
+ }
+
+ /**
+ * Tests annotation constraint.
+ */
+ @Test
+ public void annotationConstraint() {
+ Constraint constraint = getConstraint("AnnotationConstraint.json");
+ assertThat(constraint, instanceOf(AnnotationConstraint.class));
+
+ AnnotationConstraint annotationConstraint = (AnnotationConstraint) constraint;
+ assertThat(annotationConstraint.key(), is("key"));
+ assertThat(annotationConstraint.threshold(), is(123.0D));
+ }
+
+ /**
+ * Tests bandwidth constraint.
+ */
+ @Test
+ public void bandwidthConstraint() {
+ Constraint constraint = getConstraint("BandwidthConstraint.json");
+ assertThat(constraint, instanceOf(BandwidthConstraint.class));
+
+ BandwidthConstraint bandwidthConstraint = (BandwidthConstraint) constraint;
+ assertThat(bandwidthConstraint.bandwidth().toDouble(), is(345.678D));
+ }
+
+ /**
+ * Tests lambda constraint.
+ */
+ @Test
+ public void lambdaConstraint() {
+ Constraint constraint = getConstraint("LambdaConstraint.json");
+ assertThat(constraint, instanceOf(LambdaConstraint.class));
+
+ LambdaConstraint lambdaConstraint = (LambdaConstraint) constraint;
+ assertThat(lambdaConstraint.lambda().toInt(), is(444));
+ }
+
+ /**
+ * Tests latency constraint.
+ */
+ @Test
+ public void latencyConstraint() {
+ Constraint constraint = getConstraint("LatencyConstraint.json");
+ assertThat(constraint, instanceOf(LatencyConstraint.class));
+
+ LatencyConstraint latencyConstraint = (LatencyConstraint) constraint;
+ assertThat(latencyConstraint.latency().toMillis(), is(111L));
+ }
+
+ /**
+ * Tests obstacle constraint.
+ */
+ @Test
+ public void obstacleConstraint() {
+ Constraint constraint = getConstraint("ObstacleConstraint.json");
+ assertThat(constraint, instanceOf(ObstacleConstraint.class));
+
+ ObstacleConstraint obstacleConstraint = (ObstacleConstraint) constraint;
+
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev1")));
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev2")));
+ assertThat(obstacleConstraint.obstacles(), hasItem(did("dev3")));
+ }
+
+ /**
+ * Tests waypoint constaint.
+ */
+ @Test
+ public void waypointConstraint() {
+ Constraint constraint = getConstraint("WaypointConstraint.json");
+ assertThat(constraint, instanceOf(WaypointConstraint.class));
+
+ WaypointConstraint waypointConstraint = (WaypointConstraint) constraint;
+
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devA")));
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devB")));
+ assertThat(waypointConstraint.waypoints(), hasItem(did("devC")));
+ }
+
+ /**
+ * Tests asymmetric path constraint.
+ */
+ @Test
+ public void asymmetricPathConstraint() {
+ Constraint constraint = getConstraint("AsymmetricPathConstraint.json");
+ assertThat(constraint, instanceOf(AsymmetricPathConstraint.class));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
new file mode 100644
index 00000000..6bf46803
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionCodecTest.java
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.util.EnumMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.TpPort;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onlab.junit.TestUtils.getField;
+import static org.onlab.junit.TestUtils.setField;
+import static org.onosproject.codec.impl.CriterionJsonMatcher.matchesCriterion;
+
+/**
+ * Unit tests for criterion codec.
+ */
+public class CriterionCodecTest {
+
+ CodecContext context;
+ JsonCodec<Criterion> criterionCodec;
+ final PortNumber port = PortNumber.portNumber(1);
+ final IpPrefix ipPrefix4 = IpPrefix.valueOf("10.1.1.0/24");
+ final IpPrefix ipPrefix6 = IpPrefix.valueOf("fe80::/64");
+ final MacAddress mac1 = MacAddress.valueOf("00:00:11:00:00:01");
+ final TpPort tpPort = TpPort.tpPort(40000);
+
+ /**
+ * Sets up for each test. Creates a context and fetches the criterion
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ criterionCodec = context.codec(Criterion.class);
+ assertThat(criterionCodec, notNullValue());
+ }
+
+
+ /**
+ * Checks that all criterion types are covered by the codec.
+ */
+ @Test
+ public void checkCriterionTypes() throws Exception {
+ EncodeCriterionCodecHelper encoder = new EncodeCriterionCodecHelper(
+ Criteria.dummy(), context);
+ EnumMap<Criterion.Type, Object> formatMap =
+ getField(encoder, "formatMap");
+ assertThat(formatMap, notNullValue());
+
+ for (Criterion.Type type : Criterion.Type.values()) {
+ assertThat("Entry not found for " + type.toString(),
+ formatMap.get(type), notNullValue());
+ }
+ }
+
+ /**
+ * Tests in port criterion.
+ */
+ @Test
+ public void matchInPortTest() {
+ Criterion criterion = Criteria.matchInPort(port);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests in physical port criterion.
+ */
+ @Test
+ public void matchInPhyPortTest() {
+ Criterion criterion = Criteria.matchInPhyPort(port);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests metadata criterion.
+ */
+ @Test
+ public void matchMetadataTest() {
+ Criterion criterion = Criteria.matchMetadata(0xabcdL);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ethernet destination criterion.
+ */
+ @Test
+ public void matchEthDstTest() {
+ Criterion criterion = Criteria.matchEthDst(mac1);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ethernet source criterion.
+ */
+ @Test
+ public void matchEthSrcTest() {
+ Criterion criterion = Criteria.matchEthSrc(mac1);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ethernet type criterion.
+ */
+ @Test
+ public void matchEthTypeTest() {
+ Criterion criterion = Criteria.matchEthType((short) 0x8844);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests VLAN Id criterion.
+ */
+ @Test
+ public void matchVlanIdTest() {
+ Criterion criterion = Criteria.matchVlanId(VlanId.ANY);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests VLAN PCP criterion.
+ */
+ @Test
+ public void matchVlanPcpTest() {
+ Criterion criterion = Criteria.matchVlanPcp((byte) 7);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IP DSCP criterion.
+ */
+ @Test
+ public void matchIPDscpTest() {
+ Criterion criterion = Criteria.matchIPDscp((byte) 63);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IP ECN criterion.
+ */
+ @Test
+ public void matchIPEcnTest() {
+ Criterion criterion = Criteria.matchIPEcn((byte) 3);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IP protocol criterion.
+ */
+ @Test
+ public void matchIPProtocolTest() {
+ Criterion criterion = Criteria.matchIPProtocol((byte) 250);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IP source criterion.
+ */
+ @Test
+ public void matchIPSrcTest() {
+ Criterion criterion = Criteria.matchIPSrc(ipPrefix4);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IP destination criterion.
+ */
+ @Test
+ public void matchIPDstTest() {
+ Criterion criterion = Criteria.matchIPDst(ipPrefix4);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests source TCP port criterion.
+ */
+ @Test
+ public void matchTcpSrcTest() {
+ Criterion criterion = Criteria.matchTcpSrc(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests destination TCP port criterion.
+ */
+ @Test
+ public void matchTcpDstTest() {
+ Criterion criterion = Criteria.matchTcpDst(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests source UDP port criterion.
+ */
+ @Test
+ public void matchUdpSrcTest() {
+ Criterion criterion = Criteria.matchUdpSrc(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests destination UDP criterion.
+ */
+ @Test
+ public void matchUdpDstTest() {
+ Criterion criterion = Criteria.matchUdpDst(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests source SCTP criterion.
+ */
+ @Test
+ public void matchSctpSrcTest() {
+ Criterion criterion = Criteria.matchSctpSrc(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests destination SCTP criterion.
+ */
+ @Test
+ public void matchSctpDstTest() {
+ Criterion criterion = Criteria.matchSctpDst(tpPort);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ICMP type criterion.
+ */
+ @Test
+ public void matchIcmpTypeTest() {
+ Criterion criterion = Criteria.matchIcmpType((byte) 250);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ICMP code criterion.
+ */
+ @Test
+ public void matchIcmpCodeTest() {
+ Criterion criterion = Criteria.matchIcmpCode((byte) 250);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPv6 source criterion.
+ */
+ @Test
+ public void matchIPv6SrcTest() {
+ Criterion criterion = Criteria.matchIPv6Src(ipPrefix6);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPv6 destination criterion.
+ */
+ @Test
+ public void matchIPv6DstTest() {
+ Criterion criterion = Criteria.matchIPv6Dst(ipPrefix6);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPv6 flow label criterion.
+ */
+ @Test
+ public void matchIPv6FlowLabelTest() {
+ Criterion criterion = Criteria.matchIPv6FlowLabel(0xffffe);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ICMP v6 type criterion.
+ */
+ @Test
+ public void matchIcmpv6TypeTest() {
+ Criterion criterion = Criteria.matchIcmpv6Type((byte) 250);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests ICMP v6 code criterion.
+ */
+ @Test
+ public void matchIcmpv6CodeTest() {
+ Criterion criterion = Criteria.matchIcmpv6Code((byte) 250);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPV6 target address criterion.
+ */
+ @Test
+ public void matchIPv6NDTargetAddressTest() {
+ Criterion criterion =
+ Criteria.matchIPv6NDTargetAddress(
+ Ip6Address.valueOf("1111:2222::"));
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPV6 SLL criterion.
+ */
+ @Test
+ public void matchIPv6NDSourceLinkLayerAddressTest() {
+ Criterion criterion = Criteria.matchIPv6NDSourceLinkLayerAddress(mac1);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPV6 TLL criterion.
+ */
+ @Test
+ public void matchIPv6NDTargetLinkLayerAddressTest() {
+ Criterion criterion = Criteria.matchIPv6NDTargetLinkLayerAddress(mac1);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests MPLS label criterion.
+ */
+ @Test
+ public void matchMplsLabelTest() {
+ Criterion criterion = Criteria.matchMplsLabel(MplsLabel.mplsLabel(0xffffe));
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests IPv6 Extension Header pseudo-field flags criterion.
+ */
+ @Test
+ public void matchIPv6ExthdrFlagsTest() {
+ int exthdrFlags =
+ Criterion.IPv6ExthdrFlags.NONEXT.getValue() |
+ Criterion.IPv6ExthdrFlags.ESP.getValue() |
+ Criterion.IPv6ExthdrFlags.AUTH.getValue() |
+ Criterion.IPv6ExthdrFlags.DEST.getValue() |
+ Criterion.IPv6ExthdrFlags.FRAG.getValue() |
+ Criterion.IPv6ExthdrFlags.ROUTER.getValue() |
+ Criterion.IPv6ExthdrFlags.HOP.getValue() |
+ Criterion.IPv6ExthdrFlags.UNREP.getValue() |
+ Criterion.IPv6ExthdrFlags.UNSEQ.getValue();
+ Criterion criterion = Criteria.matchIPv6ExthdrFlags(exthdrFlags);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests lambda criterion.
+ */
+ @Test
+ public void matchOchSignal() {
+ Lambda ochSignal = Lambda.ochSignal(GridType.DWDM, ChannelSpacing.CHL_100GHZ, 4, 8);
+ Criterion criterion = Criteria.matchLambda(ochSignal);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests Och signal type criterion.
+ */
+ @Test
+ public void matchOchSignalTypeTest() {
+ Criterion criterion = Criteria.matchOchSignalType(OchSignalType.FIXED_GRID);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result, matchesCriterion(criterion));
+ }
+
+ /**
+ * Tests that an unimplemented criterion type only returns the type and
+ * no other data.
+ */
+ @Test
+ public void matchUnknownTypeTest() throws Exception {
+ Criterion criterion = Criteria.matchOpticalSignalType((byte) 250);
+ setField(criterion, "type", Criterion.Type.UNASSIGNED_40);
+ ObjectNode result = criterionCodec.encode(criterion, context);
+ assertThat(result.get("type").textValue(), is(criterion.type().toString()));
+ assertThat(result.size(), is(1));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
new file mode 100644
index 00000000..bb3acad5
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/CriterionJsonMatcher.java
@@ -0,0 +1,609 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import com.google.common.base.Joiner;
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.flow.criteria.Criterion;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.IPDscpCriterion;
+import org.onosproject.net.flow.criteria.IPEcnCriterion;
+import org.onosproject.net.flow.criteria.IPProtocolCriterion;
+import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
+import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
+import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
+import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
+import org.onosproject.net.flow.criteria.MetadataCriterion;
+import org.onosproject.net.flow.criteria.MplsCriterion;
+import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.OchSignalTypeCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.SctpPortCriterion;
+import org.onosproject.net.flow.criteria.TcpPortCriterion;
+import org.onosproject.net.flow.criteria.UdpPortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+
+import java.util.Objects;
+
+/**
+ * Hamcrest matcher for criterion objects.
+ */
+public final class CriterionJsonMatcher extends
+ TypeSafeDiagnosingMatcher<JsonNode> {
+
+ final Criterion criterion;
+ Description description;
+ JsonNode jsonCriterion;
+
+ /**
+ * Constructs a matcher object.
+ *
+ * @param criterionValue criterion to match
+ */
+ private CriterionJsonMatcher(Criterion criterionValue) {
+ criterion = criterionValue;
+ }
+
+ /**
+ * Factory to allocate an criterion matcher.
+ *
+ * @param criterion criterion object we are looking for
+ * @return matcher
+ */
+ public static CriterionJsonMatcher matchesCriterion(Criterion criterion) {
+ return new CriterionJsonMatcher(criterion);
+ }
+
+ /**
+ * Matches a port criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(PortCriterion criterion) {
+ final long port = criterion.port().toLong();
+ final long jsonPort = jsonCriterion.get("port").asLong();
+ if (port != jsonPort) {
+ description.appendText("port was " + Long.toString(jsonPort));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches a metadata criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(MetadataCriterion criterion) {
+ final long metadata = criterion.metadata();
+ final long jsonMetadata = jsonCriterion.get("metadata").asLong();
+ if (metadata != jsonMetadata) {
+ description.appendText("metadata was "
+ + Long.toString(jsonMetadata));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an eth criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(EthCriterion criterion) {
+ final String mac = criterion.mac().toString();
+ final String jsonMac = jsonCriterion.get("mac").textValue();
+ if (!mac.equals(jsonMac)) {
+ description.appendText("mac was " + jsonMac);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an eth type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(EthTypeCriterion criterion) {
+ final int ethType = criterion.ethType().toShort();
+ final int jsonEthType = jsonCriterion.get("ethType").intValue();
+ if (ethType != jsonEthType) {
+ description.appendText("ethType was "
+ + Integer.toString(jsonEthType));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches a VLAN ID criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(VlanIdCriterion criterion) {
+ final short vlanId = criterion.vlanId().toShort();
+ final short jsonVlanId = jsonCriterion.get("vlanId").shortValue();
+ if (vlanId != jsonVlanId) {
+ description.appendText("vlanId was " + Short.toString(jsonVlanId));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches a VLAN PCP criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(VlanPcpCriterion criterion) {
+ final byte priority = criterion.priority();
+ final byte jsonPriority =
+ (byte) jsonCriterion.get("priority").shortValue();
+ if (priority != jsonPriority) {
+ description.appendText("priority was " + Byte.toString(jsonPriority));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IP DSCP criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPDscpCriterion criterion) {
+ final byte ipDscp = criterion.ipDscp();
+ final byte jsonIpDscp = (byte) jsonCriterion.get("ipDscp").shortValue();
+ if (ipDscp != jsonIpDscp) {
+ description.appendText("IP DSCP was " + Byte.toString(jsonIpDscp));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IP ECN criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPEcnCriterion criterion) {
+ final byte ipEcn = criterion.ipEcn();
+ final byte jsonIpEcn = (byte) jsonCriterion.get("ipEcn").shortValue();
+ if (ipEcn != jsonIpEcn) {
+ description.appendText("IP ECN was " + Byte.toString(jsonIpEcn));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IP protocol criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPProtocolCriterion criterion) {
+ final short protocol = criterion.protocol();
+ final short jsonProtocol = jsonCriterion.get("protocol").shortValue();
+ if (protocol != jsonProtocol) {
+ description.appendText("protocol was "
+ + Short.toString(jsonProtocol));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IP address criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPCriterion criterion) {
+ final String ip = criterion.ip().toString();
+ final String jsonIp = jsonCriterion.get("ip").textValue();
+ if (!ip.equals(jsonIp)) {
+ description.appendText("ip was " + jsonIp);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches a TCP port criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(TcpPortCriterion criterion) {
+ final int tcpPort = criterion.tcpPort().toInt();
+ final int jsonTcpPort = jsonCriterion.get("tcpPort").intValue();
+ if (tcpPort != jsonTcpPort) {
+ description.appendText("tcp port was "
+ + Integer.toString(jsonTcpPort));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches a UDP port criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(UdpPortCriterion criterion) {
+ final int udpPort = criterion.udpPort().toInt();
+ final int jsonUdpPort = jsonCriterion.get("udpPort").intValue();
+ if (udpPort != jsonUdpPort) {
+ description.appendText("udp port was "
+ + Integer.toString(jsonUdpPort));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an SCTP port criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(SctpPortCriterion criterion) {
+ final int sctpPort = criterion.sctpPort().toInt();
+ final int jsonSctpPort = jsonCriterion.get("sctpPort").intValue();
+ if (sctpPort != jsonSctpPort) {
+ description.appendText("sctp port was "
+ + Integer.toString(jsonSctpPort));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an ICMP type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IcmpTypeCriterion criterion) {
+ final short icmpType = criterion.icmpType();
+ final short jsonIcmpType = jsonCriterion.get("icmpType").shortValue();
+ if (icmpType != jsonIcmpType) {
+ description.appendText("icmp type was "
+ + Short.toString(jsonIcmpType));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an ICMP code criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IcmpCodeCriterion criterion) {
+ final short icmpCode = criterion.icmpCode();
+ final short jsonIcmpCode = jsonCriterion.get("icmpCode").shortValue();
+ if (icmpCode != jsonIcmpCode) {
+ description.appendText("icmp code was "
+ + Short.toString(jsonIcmpCode));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IPV6 flow label criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPv6FlowLabelCriterion criterion) {
+ final int flowLabel = criterion.flowLabel();
+ final int jsonFlowLabel = jsonCriterion.get("flowLabel").intValue();
+ if (flowLabel != jsonFlowLabel) {
+ description.appendText("IPv6 flow label was "
+ + Integer.toString(jsonFlowLabel));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an ICMP V6 type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(Icmpv6TypeCriterion criterion) {
+ final short icmpv6Type = criterion.icmpv6Type();
+ final short jsonIcmpv6Type =
+ jsonCriterion.get("icmpv6Type").shortValue();
+ if (icmpv6Type != jsonIcmpv6Type) {
+ description.appendText("icmpv6 type was "
+ + Short.toString(jsonIcmpv6Type));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IPV6 code criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(Icmpv6CodeCriterion criterion) {
+ final short icmpv6Code = criterion.icmpv6Code();
+ final short jsonIcmpv6Code =
+ jsonCriterion.get("icmpv6Code").shortValue();
+ if (icmpv6Code != jsonIcmpv6Code) {
+ description.appendText("icmpv6 code was "
+ + Short.toString(jsonIcmpv6Code));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IPV6 ND target criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPv6NDTargetAddressCriterion criterion) {
+ final String targetAddress =
+ criterion.targetAddress().toString();
+ final String jsonTargetAddress =
+ jsonCriterion.get("targetAddress").textValue();
+ if (!targetAddress.equals(jsonTargetAddress)) {
+ description.appendText("target address was " +
+ jsonTargetAddress);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IPV6 ND link layer criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPv6NDLinkLayerAddressCriterion criterion) {
+ final String llAddress =
+ criterion.mac().toString();
+ final String jsonLlAddress =
+ jsonCriterion.get("mac").textValue();
+ if (!llAddress.equals(jsonLlAddress)) {
+ description.appendText("mac was " + jsonLlAddress);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an MPLS label criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(MplsCriterion criterion) {
+ final int label = criterion.label().toInt();
+ final int jsonLabel = jsonCriterion.get("label").intValue();
+ if (label != jsonLabel) {
+ description.appendText("label was " + Integer.toString(jsonLabel));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an IPV6 exthdr criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(IPv6ExthdrFlagsCriterion criterion) {
+ final int exthdrFlags = criterion.exthdrFlags();
+ final int jsonExthdrFlags =
+ jsonCriterion.get("exthdrFlags").intValue();
+ if (exthdrFlags != jsonExthdrFlags) {
+ description.appendText("exthdrFlags was "
+ + Long.toHexString(jsonExthdrFlags));
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an Och signal criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OchSignalCriterion criterion) {
+ final OchSignal ochSignal = criterion.lambda();
+ final JsonNode jsonOchSignal = jsonCriterion.get("ochSignalId");
+ String jsonGridType = jsonOchSignal.get("gridType").textValue();
+ String jsonChannelSpacing = jsonOchSignal.get("channelSpacing").textValue();
+ int jsonSpacingMultiplier = jsonOchSignal.get("spacingMultiplier").intValue();
+ int jsonSlotGranularity = jsonOchSignal.get("slotGranularity").intValue();
+
+ boolean equality = Objects.equals(ochSignal.gridType().name(), jsonGridType)
+ && Objects.equals(ochSignal.channelSpacing().name(), jsonChannelSpacing)
+ && Objects.equals(ochSignal.spacingMultiplier(), jsonSpacingMultiplier)
+ && Objects.equals(ochSignal.slotGranularity(), jsonSlotGranularity);
+
+ if (!equality) {
+ String joined = Joiner.on(", ")
+ .join(jsonGridType, jsonChannelSpacing, jsonSpacingMultiplier, jsonSlotGranularity);
+
+ description.appendText("och signal id was " + joined);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches an Och signal type criterion object.
+ *
+ * @param criterion criterion to match
+ * @return true if the JSON matches the criterion, false otherwise.
+ */
+ private boolean matchCriterion(OchSignalTypeCriterion criterion) {
+ final String signalType = criterion.signalType().name();
+ final String jsonSignalType = jsonCriterion.get("ochSignalType").textValue();
+ if (!signalType.equals(jsonSignalType)) {
+ description.appendText("signal type was " + jsonSignalType);
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonCriterion,
+ Description description) {
+ this.description = description;
+ this.jsonCriterion = jsonCriterion;
+ final String type = criterion.type().name();
+ final String jsonType = jsonCriterion.get("type").asText();
+ if (!type.equals(jsonType)) {
+ description.appendText("type was " + type);
+ return false;
+ }
+
+ switch (criterion.type()) {
+
+ case IN_PORT:
+ case IN_PHY_PORT:
+ return matchCriterion((PortCriterion) criterion);
+
+ case METADATA:
+ return matchCriterion((MetadataCriterion) criterion);
+
+ case ETH_DST:
+ case ETH_SRC:
+ return matchCriterion((EthCriterion) criterion);
+
+ case ETH_TYPE:
+ return matchCriterion((EthTypeCriterion) criterion);
+
+ case VLAN_VID:
+ return matchCriterion((VlanIdCriterion) criterion);
+
+ case VLAN_PCP:
+ return matchCriterion((VlanPcpCriterion) criterion);
+
+ case IP_DSCP:
+ return matchCriterion((IPDscpCriterion) criterion);
+
+ case IP_ECN:
+ return matchCriterion((IPEcnCriterion) criterion);
+
+ case IP_PROTO:
+ return matchCriterion((IPProtocolCriterion) criterion);
+
+ case IPV4_SRC:
+ case IPV4_DST:
+ case IPV6_SRC:
+ case IPV6_DST:
+ return matchCriterion((IPCriterion) criterion);
+
+ case TCP_SRC:
+ case TCP_DST:
+ return matchCriterion((TcpPortCriterion) criterion);
+
+ case UDP_SRC:
+ case UDP_DST:
+ return matchCriterion((UdpPortCriterion) criterion);
+
+ case SCTP_SRC:
+ case SCTP_DST:
+ return matchCriterion((SctpPortCriterion) criterion);
+
+ case ICMPV4_TYPE:
+ return matchCriterion((IcmpTypeCriterion) criterion);
+
+ case ICMPV4_CODE:
+ return matchCriterion((IcmpCodeCriterion) criterion);
+
+ case IPV6_FLABEL:
+ return matchCriterion((IPv6FlowLabelCriterion) criterion);
+
+ case ICMPV6_TYPE:
+ return matchCriterion((Icmpv6TypeCriterion) criterion);
+
+ case ICMPV6_CODE:
+ return matchCriterion((Icmpv6CodeCriterion) criterion);
+
+ case IPV6_ND_TARGET:
+ return matchCriterion(
+ (IPv6NDTargetAddressCriterion) criterion);
+
+ case IPV6_ND_SLL:
+ case IPV6_ND_TLL:
+ return matchCriterion(
+ (IPv6NDLinkLayerAddressCriterion) criterion);
+
+ case MPLS_LABEL:
+ return matchCriterion((MplsCriterion) criterion);
+
+ case IPV6_EXTHDR:
+ return matchCriterion(
+ (IPv6ExthdrFlagsCriterion) criterion);
+
+ case OCH_SIGID:
+ return matchCriterion((OchSignalCriterion) criterion);
+
+ case OCH_SIGTYPE:
+ return matchCriterion((OchSignalTypeCriterion) criterion);
+
+ default:
+ // Don't know how to format this type
+ description.appendText("unknown criterion type " +
+ criterion.type());
+ return false;
+ }
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(criterion.toString());
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DeviceCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DeviceCodecTest.java
new file mode 100644
index 00000000..c7196e8b
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DeviceCodecTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.codec.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.hamcrest.Matchers.is;
+import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable;
+
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.Device;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+
+/**
+ * Unit test for DeviceCodec.
+ */
+public class DeviceCodecTest {
+
+ private Device device = new DefaultDevice(JsonCodecUtils.PID,
+ JsonCodecUtils.DID1,
+ Device.Type.SWITCH,
+ JsonCodecUtils.MFR,
+ JsonCodecUtils.HW,
+ JsonCodecUtils.SW1,
+ JsonCodecUtils.SN,
+ JsonCodecUtils.CID,
+ JsonCodecUtils.A1);
+
+
+
+ @Test
+ public void deviceCodecTest() {
+ final MockCodecContext context = new MockCodecContext();
+ context.registerService(DeviceService.class, new DeviceServiceAdapter());
+ final JsonCodec<Device> codec = context.codec(Device.class);
+ assertThat(codec, is(notNullValue()));
+ final Device pojoIn = device;
+
+ assertJsonEncodable(context, codec, pojoIn);
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverCodecTest.java
new file mode 100644
index 00000000..a1c95176
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverCodecTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+
+import java.util.Map;
+
+import org.junit.Test;
+import org.onosproject.net.driver.Behaviour;
+import org.onosproject.net.driver.DefaultDriver;
+import org.onosproject.net.driver.Driver;
+import org.onosproject.net.driver.TestBehaviour;
+import org.onosproject.net.driver.TestBehaviourImpl;
+import org.onosproject.net.driver.TestBehaviourTwo;
+import org.onosproject.net.driver.TestBehaviourTwoImpl;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableMap;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.onosproject.codec.impl.DriverJsonMatcher.matchesDriver;
+
+/**
+ * Unit tests for the driver codec.
+ */
+public class DriverCodecTest {
+
+ @Test
+ public void codecTest() {
+ Map<Class<? extends Behaviour>, Class<? extends Behaviour>> behaviours =
+ ImmutableMap.of(TestBehaviour.class,
+ TestBehaviourImpl.class,
+ TestBehaviourTwo.class,
+ TestBehaviourTwoImpl.class);
+ Map<String, String> properties =
+ ImmutableMap.of("key1", "value1", "key2", "value2");
+
+ DefaultDriver parent = new DefaultDriver("parent", null, "Acme",
+ "HW1.2.3", "SW1.2.3",
+ behaviours,
+ properties);
+ DefaultDriver child = new DefaultDriver("child", parent, "Acme",
+ "HW1.2.3.1", "SW1.2.3.1",
+ behaviours,
+ properties);
+
+ MockCodecContext context = new MockCodecContext();
+ ObjectNode driverJson = context.codec(Driver.class).encode(child, context);
+
+ assertThat(driverJson, matchesDriver(child));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverJsonMatcher.java
new file mode 100644
index 00000000..6f0070e5
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/DriverJsonMatcher.java
@@ -0,0 +1,118 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.util.Map;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.driver.Driver;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher for drivers.
+ */
+public final class DriverJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+ private final Driver driver;
+
+ private DriverJsonMatcher(Driver driver) {
+ this.driver = driver;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonDriver, Description description) {
+ // check id
+ String jsonDriverName = jsonDriver.get("name").asText();
+ String driverName = driver.name();
+ if (!jsonDriverName.equals(driverName)) {
+ description.appendText("name was " + jsonDriverName);
+ return false;
+ }
+
+
+ // check parent
+ String jsonParent = jsonDriver.get("parent").asText();
+ String parent = driver.parent().name();
+ if (!jsonParent.equals(parent)) {
+ description.appendText("parent was " + jsonParent);
+ return false;
+ }
+
+ // check manufacturer
+ String jsonManufacturer = jsonDriver.get("manufacturer").asText();
+ String manufacturer = driver.manufacturer();
+ if (!jsonManufacturer.equals(manufacturer)) {
+ description.appendText("manufacturer was " + jsonManufacturer);
+ return false;
+ }
+
+ // check HW version
+ String jsonHWVersion = jsonDriver.get("hwVersion").asText();
+ String hwVersion = driver.hwVersion();
+ if (!jsonHWVersion.equals(hwVersion)) {
+ description.appendText("HW version was " + jsonHWVersion);
+ return false;
+ }
+
+ // check SW version
+ String jsonSWVersion = jsonDriver.get("swVersion").asText();
+ String swVersion = driver.swVersion();
+ if (!jsonSWVersion.equals(swVersion)) {
+ description.appendText("SW version was " + jsonSWVersion);
+ return false;
+ }
+
+ // Check properties
+ JsonNode jsonProperties = jsonDriver.get("properties");
+ if (driver.properties().size() != jsonProperties.size()) {
+ description.appendText("properties map size was was " + jsonProperties.size());
+ return false;
+ }
+ for (Map.Entry<String, String> entry : driver.properties().entrySet()) {
+ boolean propertyFound = false;
+ for (int propertyIndex = 0; propertyIndex < jsonProperties.size(); propertyIndex++) {
+ String jsonName = jsonProperties.get(propertyIndex).get("name").asText();
+ String jsonValue = jsonProperties.get(propertyIndex).get("value").asText();
+ if (!jsonName.equals(entry.getKey()) ||
+ !jsonValue.equals(entry.getValue())) {
+ propertyFound = true;
+ break;
+ }
+ }
+ if (!propertyFound) {
+ description.appendText("property not found " + entry.getKey());
+ return false;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(driver.toString());
+ }
+
+ /**
+ * Factory to allocate a driver matcher.
+ *
+ * @param driver driver object we are looking for
+ * @return matcher
+ */
+ public static DriverJsonMatcher matchesDriver(Driver driver) {
+ return new DriverJsonMatcher(driver);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetCodecTest.java
new file mode 100644
index 00000000..847b0d09
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetCodecTest.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.junit.Test;
+import org.onlab.packet.Ethernet;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.EthernetJsonMatcher.matchesEthernet;
+
+/**
+ * Unit test for Ethernet class codec.
+ */
+public class EthernetCodecTest {
+
+ /**
+ * Unit test for the ethernet object codec.
+ */
+ @Test
+ public void ethernetCodecTest() {
+ final CodecContext context = new MockCodecContext();
+ final JsonCodec<Ethernet> ethernetCodec = context.codec(Ethernet.class);
+ assertThat(ethernetCodec, notNullValue());
+
+ final Ethernet eth1 = new Ethernet();
+ eth1.setSourceMACAddress("11:22:33:44:55:01");
+ eth1.setDestinationMACAddress("11:22:33:44:55:02");
+ eth1.setPad(true);
+ eth1.setEtherType(Ethernet.TYPE_ARP);
+ eth1.setPriorityCode((byte) 7);
+ eth1.setVlanID((short) 33);
+
+ final ObjectNode eth1Json = ethernetCodec.encode(eth1, context);
+ assertThat(eth1Json, notNullValue());
+ assertThat(eth1Json, matchesEthernet(eth1));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetJsonMatcher.java
new file mode 100644
index 00000000..c5827b91
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/EthernetJsonMatcher.java
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeMatcher;
+import org.onlab.packet.Ethernet;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher for ethernet objects.
+ */
+public final class EthernetJsonMatcher extends TypeSafeMatcher<JsonNode> {
+
+ private final Ethernet ethernet;
+ private String reason = "";
+
+ private EthernetJsonMatcher(Ethernet ethernetValue) {
+ ethernet = ethernetValue;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonEthernet) {
+
+ // check source MAC
+ final JsonNode jsonSourceMacNode = jsonEthernet.get("srcMac");
+ if (ethernet.getSourceMAC() != null) {
+ final String jsonSourceMac = jsonSourceMacNode.textValue();
+ final String sourceMac = ethernet.getSourceMAC().toString();
+ if (!jsonSourceMac.equals(sourceMac)) {
+ reason = "source MAC " + ethernet.getSourceMAC().toString();
+ return false;
+ }
+ } else {
+ // source MAC not specified, JSON representation must be empty
+ if (jsonSourceMacNode != null) {
+ reason = "source mac should be null ";
+ return false;
+ }
+ }
+
+ // check destination MAC
+ final JsonNode jsonDestinationMacNode = jsonEthernet.get("destMac");
+ if (ethernet.getDestinationMAC() != null) {
+ final String jsonDestinationMac = jsonDestinationMacNode.textValue();
+ final String destinationMac = ethernet.getDestinationMAC().toString();
+ if (!jsonDestinationMac.equals(destinationMac)) {
+ reason = "destination MAC " + ethernet.getDestinationMAC().toString();
+ return false;
+ }
+ } else {
+ // destination MAC not specified, JSON representation must be empty
+ if (jsonDestinationMacNode != null) {
+ reason = "destination mac should be null ";
+ return false;
+ }
+ }
+
+ // check priority code
+ final short jsonPriorityCode = jsonEthernet.get("priorityCode").shortValue();
+ final short priorityCode = ethernet.getPriorityCode();
+ if (jsonPriorityCode != priorityCode) {
+ reason = "priority code " + Short.toString(ethernet.getPriorityCode());
+ return false;
+ }
+
+ // check vlanId
+ final short jsonVlanId = jsonEthernet.get("vlanId").shortValue();
+ final short vlanId = ethernet.getVlanID();
+ if (jsonVlanId != vlanId) {
+ reason = "vlan id " + Short.toString(ethernet.getVlanID());
+ return false;
+ }
+
+ // check etherType
+ final short jsonEtherType = jsonEthernet.get("etherType").shortValue();
+ final short etherType = ethernet.getEtherType();
+ if (jsonEtherType != etherType) {
+ reason = "etherType " + Short.toString(ethernet.getEtherType());
+ return false;
+ }
+
+ // check pad
+ final boolean jsonPad = jsonEthernet.get("pad").asBoolean();
+ final boolean pad = ethernet.isPad();
+ if (jsonPad != pad) {
+ reason = "pad " + Boolean.toString(ethernet.isPad());
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(reason);
+ }
+
+ /**
+ * Factory to allocate a ethernet matcher.
+ *
+ * @param ethernet ethernet object we are looking for
+ * @return matcher
+ */
+ public static EthernetJsonMatcher matchesEthernet(Ethernet ethernet) {
+ return new EthernetJsonMatcher(ethernet);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
new file mode 100644
index 00000000..6c88ac1e
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/FlowRuleCodecTest.java
@@ -0,0 +1,546 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.EthType;
+import org.onlab.packet.Ethernet;
+import org.onlab.packet.IpAddress;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.IPCriterion;
+import org.onosproject.net.flow.criteria.IPDscpCriterion;
+import org.onosproject.net.flow.criteria.IPEcnCriterion;
+import org.onosproject.net.flow.criteria.IPProtocolCriterion;
+import org.onosproject.net.flow.criteria.IPv6ExthdrFlagsCriterion;
+import org.onosproject.net.flow.criteria.IPv6FlowLabelCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDLinkLayerAddressCriterion;
+import org.onosproject.net.flow.criteria.IPv6NDTargetAddressCriterion;
+import org.onosproject.net.flow.criteria.IcmpCodeCriterion;
+import org.onosproject.net.flow.criteria.IcmpTypeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6CodeCriterion;
+import org.onosproject.net.flow.criteria.Icmpv6TypeCriterion;
+import org.onosproject.net.flow.criteria.IndexedLambdaCriterion;
+import org.onosproject.net.flow.criteria.MplsCriterion;
+import org.onosproject.net.flow.criteria.OchSignalCriterion;
+import org.onosproject.net.flow.criteria.PortCriterion;
+import org.onosproject.net.flow.criteria.SctpPortCriterion;
+import org.onosproject.net.flow.criteria.TcpPortCriterion;
+import org.onosproject.net.flow.criteria.TunnelIdCriterion;
+import org.onosproject.net.flow.criteria.UdpPortCriterion;
+import org.onosproject.net.flow.criteria.VlanIdCriterion;
+import org.onosproject.net.flow.criteria.VlanPcpCriterion;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.net.NetTestTools.APP_ID;
+
+/**
+ * Flow rule codec unit tests.
+ */
+public class FlowRuleCodecTest {
+
+ MockCodecContext context;
+ JsonCodec<FlowRule> flowRuleCodec;
+ final CoreService mockCoreService = createMock(CoreService.class);
+
+ /**
+ * Sets up for each test. Creates a context and fetches the flow rule
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ flowRuleCodec = context.codec(FlowRule.class);
+ assertThat(flowRuleCodec, notNullValue());
+
+ expect(mockCoreService.registerApplication(FlowRuleCodec.REST_APP_ID))
+ .andReturn(APP_ID).anyTimes();
+ replay(mockCoreService);
+ context.registerService(CoreService.class, mockCoreService);
+ }
+
+ /**
+ * Reads in a rule from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded flow rule
+ * @throws IOException if processing the resource fails
+ */
+ private FlowRule getRule(String resourceName) throws IOException {
+ InputStream jsonStream = FlowRuleCodecTest.class
+ .getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ FlowRule rule = flowRuleCodec.decode((ObjectNode) json, context);
+ assertThat(rule, notNullValue());
+ return rule;
+ }
+
+ /**
+ * Checks that the data shared by all the resources is correct for a
+ * given rule.
+ *
+ * @param rule rule to check
+ */
+ private void checkCommonData(FlowRule rule) {
+ assertThat(rule.appId(), is(APP_ID.id()));
+ assertThat(rule.isPermanent(), is(false));
+ assertThat(rule.timeout(), is(1));
+ assertThat(rule.priority(), is(1));
+ assertThat(rule.deviceId().toString(), is("of:0000000000000001"));
+ }
+
+ /**
+ * Checks that a simple rule decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecSimpleFlowTest() throws IOException {
+ FlowRule rule = getRule("simple-flow.json");
+
+ checkCommonData(rule);
+
+ assertThat(rule.selector().criteria().size(), is(1));
+ Criterion criterion1 = rule.selector().criteria().iterator().next();
+ assertThat(criterion1.type(), is(Criterion.Type.ETH_TYPE));
+ assertThat(((EthTypeCriterion) criterion1).ethType(), is(new EthType(2054)));
+
+ assertThat(rule.treatment().allInstructions().size(), is(1));
+ Instruction instruction1 = rule.treatment().allInstructions().get(0);
+ assertThat(instruction1.type(), is(Instruction.Type.OUTPUT));
+ assertThat(((Instructions.OutputInstruction) instruction1).port(), is(PortNumber.CONTROLLER));
+ }
+
+ SortedMap<String, Instruction> instructions = new TreeMap<>();
+
+ /**
+ * Looks up an instruction in the instruction map based on type and subtype.
+ *
+ * @param type type string
+ * @param subType subtype string
+ * @return instruction that matches
+ */
+ private Instruction getInstruction(Instruction.Type type, String subType) {
+ Instruction instruction = instructions.get(type.name() + "/" + subType);
+ assertThat(instruction, notNullValue());
+ assertThat(instruction.type(), is(type));
+ return instruction;
+ }
+
+ /**
+ * Checks that a rule with one of each instruction type decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void decodeInstructionsFlowTest() throws Exception {
+ FlowRule rule = getRule("instructions-flow.json");
+
+ checkCommonData(rule);
+
+ rule.treatment().allInstructions()
+ .stream()
+ .forEach(instruction ->
+ {
+ String subType;
+ if (instruction.type() == Instruction.Type.L0MODIFICATION) {
+ subType = ((L0ModificationInstruction) instruction)
+ .subtype().name();
+ } else if (instruction.type() == Instruction.Type.L2MODIFICATION) {
+ subType = ((L2ModificationInstruction) instruction)
+ .subtype().name();
+ } else if (instruction.type() == Instruction.Type.L3MODIFICATION) {
+ subType = ((L3ModificationInstruction) instruction)
+ .subtype().name();
+ } else if (instruction.type() == Instruction.Type.L4MODIFICATION) {
+ subType = ((L4ModificationInstruction) instruction)
+ .subtype().name();
+ } else {
+ subType = "";
+ }
+ instructions.put(
+ instruction.type().name() + "/" + subType, instruction);
+ });
+
+ assertThat(rule.treatment().allInstructions().size(), is(24));
+
+ Instruction instruction;
+
+ instruction = getInstruction(Instruction.Type.OUTPUT, "");
+ assertThat(instruction.type(), is(Instruction.Type.OUTPUT));
+ assertThat(((Instructions.OutputInstruction) instruction).port(), is(PortNumber.CONTROLLER));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.ETH_SRC.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
+ is(MacAddress.valueOf("12:34:56:78:90:12")));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.ETH_DST.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModEtherInstruction) instruction).mac(),
+ is(MacAddress.valueOf("98:76:54:32:01:00")));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.VLAN_ID.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModVlanIdInstruction) instruction).vlanId().toShort(),
+ is((short) 22));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.VLAN_PCP.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModVlanPcpInstruction) instruction).vlanPcp(),
+ is((byte) 1));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.MPLS_LABEL.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModMplsLabelInstruction) instruction)
+ .mplsLabel().toInt(),
+ is(MplsLabel.MAX_MPLS));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.MPLS_PUSH.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.PushHeaderInstructions) instruction)
+ .ethernetType().toShort(),
+ is(Ethernet.MPLS_UNICAST));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.MPLS_POP.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.PushHeaderInstructions) instruction)
+ .ethernetType().toShort(),
+ is(Ethernet.MPLS_UNICAST));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.DEC_MPLS_TTL.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(instruction, instanceOf(L2ModificationInstruction.ModMplsTtlInstruction.class));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.VLAN_POP.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(instruction, instanceOf(L2ModificationInstruction.PopVlanInstruction.class));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.VLAN_PUSH.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(instruction, instanceOf(L2ModificationInstruction.PushHeaderInstructions.class));
+
+ instruction = getInstruction(Instruction.Type.L2MODIFICATION,
+ L2ModificationInstruction.L2SubType.TUNNEL_ID.name());
+ assertThat(instruction.type(), is(Instruction.Type.L2MODIFICATION));
+ assertThat(((L2ModificationInstruction.ModTunnelIdInstruction) instruction)
+ .tunnelId(), is(100L));
+
+ instruction = getInstruction(Instruction.Type.L3MODIFICATION,
+ L3ModificationInstruction.L3SubType.IPV4_SRC.name());
+ assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
+ assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
+ is(IpAddress.valueOf("1.2.3.4")));
+
+ instruction = getInstruction(Instruction.Type.L3MODIFICATION,
+ L3ModificationInstruction.L3SubType.IPV4_DST.name());
+ assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
+ assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
+ is(IpAddress.valueOf("1.2.3.3")));
+
+ instruction = getInstruction(Instruction.Type.L3MODIFICATION,
+ L3ModificationInstruction.L3SubType.IPV6_SRC.name());
+ assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
+ assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
+ is(IpAddress.valueOf("1.2.3.2")));
+
+ instruction = getInstruction(Instruction.Type.L3MODIFICATION,
+ L3ModificationInstruction.L3SubType.IPV6_DST.name());
+ assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
+ assertThat(((L3ModificationInstruction.ModIPInstruction) instruction).ip(),
+ is(IpAddress.valueOf("1.2.3.1")));
+
+ instruction = getInstruction(Instruction.Type.L3MODIFICATION,
+ L3ModificationInstruction.L3SubType.IPV6_FLABEL.name());
+ assertThat(instruction.type(), is(Instruction.Type.L3MODIFICATION));
+ assertThat(((L3ModificationInstruction.ModIPv6FlowLabelInstruction) instruction)
+ .flowLabel(),
+ is(8));
+
+ instruction = getInstruction(Instruction.Type.L0MODIFICATION,
+ L0ModificationInstruction.L0SubType.LAMBDA.name());
+ assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
+ assertThat(((L0ModificationInstruction.ModLambdaInstruction) instruction)
+ .lambda(),
+ is((short) 7));
+
+ instruction = getInstruction(Instruction.Type.L0MODIFICATION,
+ L0ModificationInstruction.L0SubType.OCH.name());
+ assertThat(instruction.type(), is(Instruction.Type.L0MODIFICATION));
+ L0ModificationInstruction.ModOchSignalInstruction och =
+ (L0ModificationInstruction.ModOchSignalInstruction) instruction;
+ assertThat(och.lambda().spacingMultiplier(), is(4));
+ assertThat(och.lambda().slotGranularity(), is(8));
+ assertThat(och.lambda().gridType(), is(GridType.DWDM));
+ assertThat(och.lambda().channelSpacing(), is(ChannelSpacing.CHL_100GHZ));
+
+ instruction = getInstruction(Instruction.Type.L4MODIFICATION,
+ L4ModificationInstruction.L4SubType.TCP_DST.name());
+ assertThat(instruction.type(), is(Instruction.Type.L4MODIFICATION));
+ assertThat(((L4ModificationInstruction.ModTransportPortInstruction) instruction)
+ .port().toInt(), is(40001));
+
+ instruction = getInstruction(Instruction.Type.L4MODIFICATION,
+ L4ModificationInstruction.L4SubType.TCP_SRC.name());
+ assertThat(instruction.type(), is(Instruction.Type.L4MODIFICATION));
+ assertThat(((L4ModificationInstruction.ModTransportPortInstruction) instruction)
+ .port().toInt(), is(40002));
+
+ instruction = getInstruction(Instruction.Type.L4MODIFICATION,
+ L4ModificationInstruction.L4SubType.UDP_DST.name());
+ assertThat(instruction.type(), is(Instruction.Type.L4MODIFICATION));
+ assertThat(((L4ModificationInstruction.ModTransportPortInstruction) instruction)
+ .port().toInt(), is(40003));
+
+ instruction = getInstruction(Instruction.Type.L4MODIFICATION,
+ L4ModificationInstruction.L4SubType.UDP_SRC.name());
+ assertThat(instruction.type(), is(Instruction.Type.L4MODIFICATION));
+ assertThat(((L4ModificationInstruction.ModTransportPortInstruction) instruction)
+ .port().toInt(), is(40004));
+ }
+
+ SortedMap<String, Criterion> criteria = new TreeMap<>();
+
+ /**
+ * Looks up a criterion in the instruction map based on type and subtype.
+ *
+ * @param type type string
+ * @return criterion that matches
+ */
+ private Criterion getCriterion(Criterion.Type type) {
+ Criterion criterion = criteria.get(type.name());
+ assertThat(criterion.type(), is(type));
+ return criterion;
+ }
+
+ /**
+ * Checks that a rule with one of each kind of criterion decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecCriteriaFlowTest() throws Exception {
+ FlowRule rule = getRule("criteria-flow.json");
+
+ checkCommonData(rule);
+
+ assertThat(rule.selector().criteria().size(), is(33));
+
+ rule.selector().criteria()
+ .stream()
+ .forEach(criterion ->
+ criteria.put(criterion.type().name(), criterion));
+
+ Criterion criterion;
+
+ criterion = getCriterion(Criterion.Type.ETH_TYPE);
+ assertThat(((EthTypeCriterion) criterion).ethType(), is(new EthType(2054)));
+
+ criterion = getCriterion(Criterion.Type.ETH_DST);
+ assertThat(((EthCriterion) criterion).mac(),
+ is(MacAddress.valueOf("00:11:22:33:44:55")));
+
+ criterion = getCriterion(Criterion.Type.ETH_SRC);
+ assertThat(((EthCriterion) criterion).mac(),
+ is(MacAddress.valueOf("00:11:22:33:44:55")));
+
+ criterion = getCriterion(Criterion.Type.IN_PORT);
+ assertThat(((PortCriterion) criterion).port(),
+ is(PortNumber.portNumber(23)));
+
+ criterion = getCriterion(Criterion.Type.IN_PHY_PORT);
+ assertThat(((PortCriterion) criterion).port(),
+ is(PortNumber.portNumber(44)));
+
+ criterion = getCriterion(Criterion.Type.VLAN_VID);
+ assertThat(((VlanIdCriterion) criterion).vlanId(),
+ is(VlanId.vlanId((short) 777)));
+
+ criterion = getCriterion(Criterion.Type.VLAN_PCP);
+ assertThat(((VlanPcpCriterion) criterion).priority(),
+ is(((byte) 3)));
+
+ criterion = getCriterion(Criterion.Type.IP_DSCP);
+ assertThat(((IPDscpCriterion) criterion).ipDscp(),
+ is(((byte) 2)));
+
+ criterion = getCriterion(Criterion.Type.IP_ECN);
+ assertThat(((IPEcnCriterion) criterion).ipEcn(),
+ is(((byte) 1)));
+
+ criterion = getCriterion(Criterion.Type.IP_PROTO);
+ assertThat(((IPProtocolCriterion) criterion).protocol(),
+ is(((short) 4)));
+
+ criterion = getCriterion(Criterion.Type.IPV4_SRC);
+ assertThat(((IPCriterion) criterion).ip(),
+ is((IpPrefix.valueOf("1.2.0.0/32"))));
+
+ criterion = getCriterion(Criterion.Type.IPV4_DST);
+ assertThat(((IPCriterion) criterion).ip(),
+ is((IpPrefix.valueOf("2.2.0.0/32"))));
+
+ criterion = getCriterion(Criterion.Type.IPV6_SRC);
+ assertThat(((IPCriterion) criterion).ip(),
+ is((IpPrefix.valueOf("3.2.0.0/32"))));
+
+ criterion = getCriterion(Criterion.Type.IPV6_DST);
+ assertThat(((IPCriterion) criterion).ip(),
+ is((IpPrefix.valueOf("4.2.0.0/32"))));
+
+ criterion = getCriterion(Criterion.Type.TCP_SRC);
+ assertThat(((TcpPortCriterion) criterion).tcpPort().toInt(),
+ is(80));
+
+ criterion = getCriterion(Criterion.Type.TCP_DST);
+ assertThat(((TcpPortCriterion) criterion).tcpPort().toInt(),
+ is(443));
+
+ criterion = getCriterion(Criterion.Type.UDP_SRC);
+ assertThat(((UdpPortCriterion) criterion).udpPort().toInt(),
+ is(180));
+
+ criterion = getCriterion(Criterion.Type.UDP_DST);
+ assertThat(((UdpPortCriterion) criterion).udpPort().toInt(),
+ is(1443));
+
+ criterion = getCriterion(Criterion.Type.SCTP_SRC);
+ assertThat(((SctpPortCriterion) criterion).sctpPort().toInt(),
+ is(280));
+
+ criterion = getCriterion(Criterion.Type.SCTP_DST);
+ assertThat(((SctpPortCriterion) criterion).sctpPort().toInt(),
+ is(2443));
+
+ criterion = getCriterion(Criterion.Type.ICMPV4_TYPE);
+ assertThat(((IcmpTypeCriterion) criterion).icmpType(),
+ is((short) 24));
+
+ criterion = getCriterion(Criterion.Type.ICMPV4_CODE);
+ assertThat(((IcmpCodeCriterion) criterion).icmpCode(),
+ is((short) 16));
+
+ criterion = getCriterion(Criterion.Type.ICMPV6_TYPE);
+ assertThat(((Icmpv6TypeCriterion) criterion).icmpv6Type(),
+ is((short) 14));
+
+ criterion = getCriterion(Criterion.Type.ICMPV6_CODE);
+ assertThat(((Icmpv6CodeCriterion) criterion).icmpv6Code(),
+ is((short) 6));
+
+ criterion = getCriterion(Criterion.Type.IPV6_FLABEL);
+ assertThat(((IPv6FlowLabelCriterion) criterion).flowLabel(),
+ is(8));
+
+ criterion = getCriterion(Criterion.Type.IPV6_ND_TARGET);
+ assertThat(((IPv6NDTargetAddressCriterion) criterion)
+ .targetAddress().toString(),
+ is("1111:2222:3333:4444:5555:6666:7777:8888"));
+
+ criterion = getCriterion(Criterion.Type.IPV6_ND_SLL);
+ assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
+ is(MacAddress.valueOf("00:11:22:33:44:56")));
+
+ criterion = getCriterion(Criterion.Type.IPV6_ND_TLL);
+ assertThat(((IPv6NDLinkLayerAddressCriterion) criterion).mac(),
+ is(MacAddress.valueOf("00:11:22:33:44:57")));
+
+ criterion = getCriterion(Criterion.Type.MPLS_LABEL);
+ assertThat(((MplsCriterion) criterion).label(),
+ is(MplsLabel.mplsLabel(123)));
+
+ criterion = getCriterion(Criterion.Type.IPV6_EXTHDR);
+ assertThat(((IPv6ExthdrFlagsCriterion) criterion).exthdrFlags(),
+ is(99));
+
+ criterion = getCriterion(Criterion.Type.OCH_SIGID);
+ assertThat(((IndexedLambdaCriterion) criterion).lambda(),
+ is(Lambda.indexedLambda(122)));
+
+ criterion = getCriterion(Criterion.Type.TUNNEL_ID);
+ assertThat(((TunnelIdCriterion) criterion).tunnelId(),
+ is(100L));
+ }
+
+ /**
+ * Checks that a rule with a SigId criterion decodes properly.
+ *
+ * @throws IOException if the resource cannot be processed
+ */
+ @Test
+ public void codecSigIdCriteriaFlowTest() throws Exception {
+ FlowRule rule = getRule("sigid-flow.json");
+
+ checkCommonData(rule);
+
+ assertThat(rule.selector().criteria().size(), is(1));
+ Criterion criterion = rule.selector().criteria().iterator().next();
+ assertThat(criterion.type(), is(Criterion.Type.OCH_SIGID));
+ Lambda lambda = ((OchSignalCriterion) criterion).lambda();
+ assertThat(lambda, instanceOf(OchSignal.class));
+ OchSignal ochSignal = (OchSignal) lambda;
+ assertThat(ochSignal.spacingMultiplier(), is(3));
+ assertThat(ochSignal.slotGranularity(), is(4));
+ assertThat(ochSignal.gridType(), is(GridType.CWDM));
+ assertThat(ochSignal.channelSpacing(), is(ChannelSpacing.CHL_25GHZ));
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupBucketJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupBucketJsonMatcher.java
new file mode 100644
index 00000000..b3056216
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupBucketJsonMatcher.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.group.GroupBucket;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher for instructions.
+ */
+public final class GroupBucketJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final GroupBucket bucket;
+
+ private GroupBucketJsonMatcher(GroupBucket bucket) {
+ this.bucket = bucket;
+ }
+
+ /**
+ * Matches the contents of a group bucket.
+ *
+ * @param bucketJson JSON representation of bucket to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ @Override
+ public boolean matchesSafely(JsonNode bucketJson, Description description) {
+
+ // check type
+ final String jsonType = bucketJson.get("type").textValue();
+ if (!bucket.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final long jsonWeight = bucketJson.get("weight").longValue();
+ if (bucket.weight() != jsonWeight) {
+ description.appendText("weight was " + jsonWeight);
+ return false;
+ }
+
+ final long packetsJson = bucketJson.get("packets").asLong();
+ if (bucket.packets() != packetsJson) {
+ description.appendText("packets was " + packetsJson);
+ return false;
+ }
+
+ final long bytesJson = bucketJson.get("bytes").asLong();
+ if (bucket.bytes() != bytesJson) {
+ description.appendText("bytes was " + packetsJson);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(bucket.toString());
+ }
+
+ /**
+ * Factory to allocate an bucket matcher.
+ *
+ * @param bucket bucket object we are looking for
+ * @return matcher
+ */
+ public static GroupBucketJsonMatcher matchesGroupBucket(GroupBucket bucket) {
+ return new GroupBucketJsonMatcher(bucket);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
new file mode 100644
index 00000000..409f8eb3
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupCodecTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.junit.Test;
+import org.onosproject.core.DefaultGroupId;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.group.DefaultGroup;
+import org.onosproject.net.group.DefaultGroupBucket;
+import org.onosproject.net.group.GroupBucket;
+import org.onosproject.net.group.GroupBuckets;
+import org.onosproject.net.group.GroupDescription;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.onosproject.codec.impl.GroupJsonMatcher.matchesGroup;
+
+/**
+ * Group codec unit tests.
+ */
+
+public class GroupCodecTest {
+
+ @Test
+ public void codecTest() {
+ GroupBucket bucket1 = DefaultGroupBucket
+ .createSelectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+ GroupBucket bucket2 = DefaultGroupBucket
+ .createIndirectGroupBucket(DefaultTrafficTreatment.emptyTreatment());
+ GroupBuckets buckets = new GroupBuckets(ImmutableList.of(bucket1, bucket2));
+
+
+ DefaultGroup group = new DefaultGroup(
+ new DefaultGroupId(1),
+ NetTestTools.did("d1"),
+ GroupDescription.Type.INDIRECT,
+ buckets);
+
+ MockCodecContext context = new MockCodecContext();
+ GroupCodec codec = new GroupCodec();
+ ObjectNode groupJson = codec.encode(group, context);
+
+ assertThat(groupJson, matchesGroup(group));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupJsonMatcher.java
new file mode 100644
index 00000000..0e62c305
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/GroupJsonMatcher.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.group.Group;
+import org.onosproject.net.group.GroupBucket;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher for groups.
+ */
+
+public final class GroupJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final Group group;
+
+ private GroupJsonMatcher(Group group) {
+ this.group = group;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonGroup, Description description) {
+ // check id
+ String jsonGroupId = jsonGroup.get("id").asText();
+ String groupId = group.id().toString();
+ if (!jsonGroupId.equals(groupId)) {
+ description.appendText("group id was " + jsonGroupId);
+ return false;
+ }
+
+ // check state
+ String jsonState = jsonGroup.get("state").asText();
+ String state = group.state().toString();
+ if (!jsonState.equals(state)) {
+ description.appendText("state was " + jsonState);
+ return false;
+ }
+
+ // check life
+ long jsonLife = jsonGroup.get("life").asLong();
+ long life = group.life();
+ if (life != jsonLife) {
+ description.appendText("life was " + jsonLife);
+ return false;
+ }
+
+ // check bytes
+ long jsonBytes = jsonGroup.get("bytes").asLong();
+ long bytes = group.bytes();
+ if (bytes != jsonBytes) {
+ description.appendText("bytes was " + jsonBytes);
+ return false;
+ }
+
+ // check packets
+ long jsonPackets = jsonGroup.get("packets").asLong();
+ long packets = group.packets();
+ if (packets != jsonPackets) {
+ description.appendText("packets was " + jsonPackets);
+ return false;
+ }
+
+ // check size of bucket array
+ JsonNode jsonBuckets = jsonGroup.get("buckets");
+ if (jsonBuckets.size() != group.buckets().buckets().size()) {
+ description.appendText("buckets size was " + jsonBuckets.size());
+ return false;
+ }
+
+ // Check buckets
+ for (GroupBucket bucket : group.buckets().buckets()) {
+ boolean bucketFound = false;
+ for (int bucketIndex = 0; bucketIndex < jsonBuckets.size(); bucketIndex++) {
+ GroupBucketJsonMatcher bucketMatcher =
+ GroupBucketJsonMatcher.matchesGroupBucket(bucket);
+ if (bucketMatcher.matches(jsonBuckets.get(bucketIndex))) {
+ bucketFound = true;
+ break;
+ }
+ }
+ if (!bucketFound) {
+ description.appendText("bucket not found " + bucket.toString());
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(group.toString());
+ }
+
+ /**
+ * Factory to allocate a group matcher.
+ *
+ * @param group group object we are looking for
+ * @return matcher
+ */
+ public static GroupJsonMatcher matchesGroup(Group group) {
+ return new GroupJsonMatcher(group);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ImmutableCodecsTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ImmutableCodecsTest.java
new file mode 100644
index 00000000..2081fa58
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/ImmutableCodecsTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.junit.Test;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutableBaseClass;
+
+/**
+ * Tests to assure that the codec classes follow the contract of having
+ * no local context.
+ */
+public class ImmutableCodecsTest {
+
+ /**
+ * Checks that the codec classes adhere to the contract that there cannot
+ * be any local context in a codec.
+ */
+ @Test
+ public void checkImmutability() {
+ assertThatClassIsImmutableBaseClass(AnnotatedCodec.class);
+ assertThatClassIsImmutable(AnnotationsCodec.class);
+ assertThatClassIsImmutable(ApplicationCodec.class);
+ assertThatClassIsImmutable(ConnectivityIntentCodec.class);
+ assertThatClassIsImmutable(ConnectPointCodec.class);
+ assertThatClassIsImmutable(ConstraintCodec.class);
+ assertThatClassIsImmutable(EncodeConstraintCodecHelper.class);
+ assertThatClassIsImmutable(DecodeConstraintCodecHelper.class);
+ assertThatClassIsImmutable(CriterionCodec.class);
+ assertThatClassIsImmutable(EncodeCriterionCodecHelper.class);
+ assertThatClassIsImmutable(DecodeCriterionCodecHelper.class);
+ assertThatClassIsImmutable(DeviceCodec.class);
+ assertThatClassIsImmutable(EthernetCodec.class);
+ assertThatClassIsImmutable(FlowEntryCodec.class);
+ assertThatClassIsImmutable(HostCodec.class);
+ assertThatClassIsImmutable(HostLocationCodec.class);
+ assertThatClassIsImmutable(HostToHostIntentCodec.class);
+ assertThatClassIsImmutable(InstructionCodec.class);
+ assertThatClassIsImmutable(EncodeInstructionCodecHelper.class);
+ assertThatClassIsImmutable(DecodeInstructionCodecHelper.class);
+ assertThatClassIsImmutable(IntentCodec.class);
+ assertThatClassIsImmutable(LinkCodec.class);
+ assertThatClassIsImmutable(PathCodec.class);
+ assertThatClassIsImmutable(PointToPointIntentCodec.class);
+ assertThatClassIsImmutable(PortCodec.class);
+ assertThatClassIsImmutable(TopologyClusterCodec.class);
+ assertThatClassIsImmutable(TopologyCodec.class);
+ assertThatClassIsImmutable(TrafficSelectorCodec.class);
+ assertThatClassIsImmutable(TrafficTreatmentCodec.class);
+ assertThatClassIsImmutable(FlowRuleCodec.class);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
new file mode 100644
index 00000000..bafbc0f1
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionCodecTest.java
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.Ip4Address;
+import org.onlab.packet.Ip6Address;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.packet.VlanId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.GridType;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.instructions.L0ModificationInstruction;
+import org.onosproject.net.flow.instructions.L2ModificationInstruction;
+import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.InstructionJsonMatcher.matchesInstruction;
+
+/**
+ * Unit tests for Instruction codec.
+ */
+public class InstructionCodecTest {
+ CodecContext context;
+ JsonCodec<Instruction> instructionCodec;
+
+ /**
+ * Sets up for each test. Creates a context and fetches the instruction
+ * codec.
+ */
+ @Before
+ public void setUp() {
+ context = new MockCodecContext();
+ instructionCodec = context.codec(Instruction.class);
+ assertThat(instructionCodec, notNullValue());
+ }
+
+ /**
+ * Tests the encoding of push header instructions.
+ */
+ @Test
+ public void pushHeaderInstructionsTest() {
+ final L2ModificationInstruction.PushHeaderInstructions instruction =
+ (L2ModificationInstruction.PushHeaderInstructions) Instructions.pushMpls();
+ final ObjectNode instructionJson = instructionCodec.encode(instruction, context);
+
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of drop instructions.
+ */
+ @Test
+ public void dropInstructionTest() {
+ final Instructions.DropInstruction instruction =
+ Instructions.createDrop();
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of output instructions.
+ */
+ @Test
+ public void outputInstructionTest() {
+ final Instructions.OutputInstruction instruction =
+ Instructions.createOutput(PortNumber.portNumber(22));
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod lambda instructions.
+ */
+ @Test
+ public void modLambdaInstructionTest() {
+ final L0ModificationInstruction.ModLambdaInstruction instruction =
+ (L0ModificationInstruction.ModLambdaInstruction)
+ Instructions.modL0Lambda(new IndexedLambda(55));
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod OCh signal instructions.
+ */
+ @Test
+ public void modOchSignalInstructionTest() {
+ L0ModificationInstruction.ModOchSignalInstruction instruction =
+ (L0ModificationInstruction.ModOchSignalInstruction)
+ Instructions.modL0Lambda(Lambda.ochSignal(GridType.DWDM, ChannelSpacing.CHL_100GHZ, 4, 8));
+ ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod ether instructions.
+ */
+ @Test
+ public void modEtherInstructionTest() {
+ final L2ModificationInstruction.ModEtherInstruction instruction =
+ (L2ModificationInstruction.ModEtherInstruction)
+ Instructions.modL2Src(MacAddress.valueOf("11:22:33:44:55:66"));
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod vlan id instructions.
+ */
+ @Test
+ public void modVlanIdInstructionTest() {
+ final L2ModificationInstruction.ModVlanIdInstruction instruction =
+ (L2ModificationInstruction.ModVlanIdInstruction)
+ Instructions.modVlanId(VlanId.vlanId((short) 12));
+
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod vlan pcp instructions.
+ */
+ @Test
+ public void modVlanPcpInstructionTest() {
+ final L2ModificationInstruction.ModVlanPcpInstruction instruction =
+ (L2ModificationInstruction.ModVlanPcpInstruction)
+ Instructions.modVlanPcp((byte) 9);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod IPv4 src instructions.
+ */
+ @Test
+ public void modIPSrcInstructionTest() {
+ final Ip4Address ip = Ip4Address.valueOf("1.2.3.4");
+ final L3ModificationInstruction.ModIPInstruction instruction =
+ (L3ModificationInstruction.ModIPInstruction)
+ Instructions.modL3Src(ip);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod IPv4 dst instructions.
+ */
+ @Test
+ public void modIPDstInstructionTest() {
+ final Ip4Address ip = Ip4Address.valueOf("1.2.3.4");
+ final L3ModificationInstruction.ModIPInstruction instruction =
+ (L3ModificationInstruction.ModIPInstruction)
+ Instructions.modL3Dst(ip);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod IPv6 src instructions.
+ */
+ @Test
+ public void modIPv6SrcInstructionTest() {
+ final Ip6Address ip = Ip6Address.valueOf("1111::2222");
+ final L3ModificationInstruction.ModIPInstruction instruction =
+ (L3ModificationInstruction.ModIPInstruction)
+ Instructions.modL3IPv6Src(ip);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod IPv6 dst instructions.
+ */
+ @Test
+ public void modIPv6DstInstructionTest() {
+ final Ip6Address ip = Ip6Address.valueOf("1111::2222");
+ final L3ModificationInstruction.ModIPInstruction instruction =
+ (L3ModificationInstruction.ModIPInstruction)
+ Instructions.modL3IPv6Dst(ip);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod IPv6 flow label instructions.
+ */
+ @Test
+ public void modIPv6FlowLabelInstructionTest() {
+ final int flowLabel = 0xfffff;
+ final L3ModificationInstruction.ModIPv6FlowLabelInstruction instruction =
+ (L3ModificationInstruction.ModIPv6FlowLabelInstruction)
+ Instructions.modL3IPv6FlowLabel(flowLabel);
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+ /**
+ * Tests the encoding of mod MPLS label instructions.
+ */
+ @Test
+ public void modMplsLabelInstructionTest() {
+ final L2ModificationInstruction.ModMplsLabelInstruction instruction =
+ (L2ModificationInstruction.ModMplsLabelInstruction)
+ Instructions.modMplsLabel(MplsLabel.mplsLabel(99));
+ final ObjectNode instructionJson =
+ instructionCodec.encode(instruction, context);
+ assertThat(instructionJson, matchesInstruction(instruction));
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
new file mode 100644
index 00000000..72081e6c
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/InstructionJsonMatcher.java
@@ -0,0 +1,438 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.flow.instructions.Instruction;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import static org.onosproject.net.flow.instructions.Instructions.*;
+import static org.onosproject.net.flow.instructions.L0ModificationInstruction.*;
+import static org.onosproject.net.flow.instructions.L2ModificationInstruction.*;
+import static org.onosproject.net.flow.instructions.L3ModificationInstruction.*;
+
+/**
+ * Hamcrest matcher for instructions.
+ */
+public final class InstructionJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final Instruction instruction;
+
+ private InstructionJsonMatcher(Instruction instructionValue) {
+ instruction = instructionValue;
+ }
+
+ /**
+ * Matches the contents of a push header instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchPushHeaderInstruction(JsonNode instructionJson,
+ Description description) {
+ PushHeaderInstructions instructionToMatch =
+ (PushHeaderInstructions) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final JsonNode ethJson = instructionJson.get("ethernetType");
+ if (ethJson == null) {
+ description.appendText("ethernetType was not null");
+ return false;
+ }
+
+ if (instructionToMatch.ethernetType().toShort() != ethJson.asInt()) {
+ description.appendText("ethernetType was " + ethJson);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of an output instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchOutputInstruction(JsonNode instructionJson,
+ Description description) {
+ OutputInstruction instructionToMatch = (OutputInstruction) instruction;
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final long jsonPort = instructionJson.get("port").asLong();
+ if (instructionToMatch.port().toLong() != jsonPort) {
+ description.appendText("port was " + jsonPort);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod lambda instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModLambdaInstruction(JsonNode instructionJson,
+ Description description) {
+ ModLambdaInstruction instructionToMatch =
+ (ModLambdaInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final long jsonLambda = instructionJson.get("lambda").shortValue();
+ if (instructionToMatch.lambda() != jsonLambda) {
+ description.appendText("lambda was " + jsonLambda);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches teh contents of a mod OCh singal instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents matches, false otherwise
+ */
+ private boolean matchModOchSingalInstruction(JsonNode instructionJson,
+ Description description) {
+ ModOchSignalInstruction instructionToMatch =
+ (ModOchSignalInstruction) instruction;
+
+ String jsonSubType = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubType)) {
+ description.appendText("subtype was " + jsonSubType);
+ return false;
+ }
+
+ String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ String jsonGridType = instructionJson.get("gridType").textValue();
+ if (!instructionToMatch.lambda().gridType().name().equals(jsonGridType)) {
+ description.appendText("gridType was " + jsonGridType);
+ return false;
+ }
+
+ String jsonChannelSpacing = instructionJson.get("channelSpacing").textValue();
+ if (!instructionToMatch.lambda().channelSpacing().name().equals(jsonChannelSpacing)) {
+ description.appendText("channelSpacing was " + jsonChannelSpacing);
+ return false;
+ }
+
+ int jsonSpacingMultiplier = instructionJson.get("spacingMultiplier").intValue();
+ if (instructionToMatch.lambda().spacingMultiplier() != jsonSpacingMultiplier) {
+ description.appendText("spacingMultiplier was " + jsonSpacingMultiplier);
+ return false;
+ }
+
+ int jsonSlotGranularity = instructionJson.get("slotGranularity").intValue();
+ if (instructionToMatch.lambda().slotGranularity() != jsonSlotGranularity) {
+ description.appendText("slotGranularity was " + jsonSlotGranularity);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod Ethernet instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModEtherInstruction(JsonNode instructionJson,
+ Description description) {
+ ModEtherInstruction instructionToMatch =
+ (ModEtherInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final String jsonMac = instructionJson.get("mac").textValue();
+ final String mac = instructionToMatch.mac().toString();
+ if (!mac.equals(jsonMac)) {
+ description.appendText("mac was " + jsonMac);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod vlan id instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModVlanIdInstruction(JsonNode instructionJson,
+ Description description) {
+ ModVlanIdInstruction instructionToMatch =
+ (ModVlanIdInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final short jsonVlanId = instructionJson.get("vlanId").shortValue();
+ final short vlanId = instructionToMatch.vlanId().toShort();
+ if (jsonVlanId != vlanId) {
+ description.appendText("vlan id was " + jsonVlanId);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod vlan pcp instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModVlanPcpInstruction(JsonNode instructionJson,
+ Description description) {
+ ModVlanPcpInstruction instructionToMatch =
+ (ModVlanPcpInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final short jsonVlanPcp = instructionJson.get("vlanPcp").shortValue();
+ final short vlanId = instructionToMatch.vlanPcp();
+ if (jsonVlanPcp != vlanId) {
+ description.appendText("vlan pcp was " + jsonVlanPcp);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod ip instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModIpInstruction(JsonNode instructionJson,
+ Description description) {
+ ModIPInstruction instructionToMatch =
+ (ModIPInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final String jsonIp = instructionJson.get("ip").textValue();
+ final String ip = instructionToMatch.ip().toString();
+ if (!ip.equals(jsonIp)) {
+ description.appendText("ip was " + jsonIp);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod IPv6 Flow Label instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModIPv6FlowLabelInstruction(JsonNode instructionJson,
+ Description description) {
+ ModIPv6FlowLabelInstruction instructionToMatch =
+ (ModIPv6FlowLabelInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final int jsonFlowLabel = instructionJson.get("flowLabel").intValue();
+ final int flowLabel = instructionToMatch.flowLabel();
+ if (flowLabel != jsonFlowLabel) {
+ description.appendText("IPv6 flow label was " + jsonFlowLabel);
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Matches the contents of a mod MPLS label instruction.
+ *
+ * @param instructionJson JSON instruction to match
+ * @param description Description object used for recording errors
+ * @return true if contents match, false otherwise
+ */
+ private boolean matchModMplsLabelInstruction(JsonNode instructionJson,
+ Description description) {
+ ModMplsLabelInstruction instructionToMatch =
+ (ModMplsLabelInstruction) instruction;
+ final String jsonSubtype = instructionJson.get("subtype").textValue();
+ if (!instructionToMatch.subtype().name().equals(jsonSubtype)) {
+ description.appendText("subtype was " + jsonSubtype);
+ return false;
+ }
+
+ final String jsonType = instructionJson.get("type").textValue();
+ if (!instructionToMatch.type().name().equals(jsonType)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ final int jsonLabel = instructionJson.get("label").intValue();
+ final int label = instructionToMatch.mplsLabel().toInt();
+ if (label != jsonLabel) {
+ description.appendText("MPLS label was " + jsonLabel);
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonInstruction, Description description) {
+
+ // check type
+ final JsonNode jsonTypeNode = jsonInstruction.get("type");
+ final String jsonType = jsonTypeNode.textValue();
+ final String type = instruction.type().name();
+ if (!jsonType.equals(type)) {
+ description.appendText("type was " + type);
+ return false;
+ }
+
+ if (instruction instanceof PushHeaderInstructions) {
+ return matchPushHeaderInstruction(jsonInstruction, description);
+ } else if (instruction instanceof DropInstruction) {
+ return true;
+ } else if (instruction instanceof OutputInstruction) {
+ return matchOutputInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModLambdaInstruction) {
+ return matchModLambdaInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModOchSignalInstruction) {
+ return matchModOchSingalInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModEtherInstruction) {
+ return matchModEtherInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModVlanIdInstruction) {
+ return matchModVlanIdInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModVlanPcpInstruction) {
+ return matchModVlanPcpInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModIPInstruction) {
+ return matchModIpInstruction(jsonInstruction, description);
+ } else if (instruction instanceof ModIPv6FlowLabelInstruction) {
+ return matchModIPv6FlowLabelInstruction(jsonInstruction,
+ description);
+ } else if (instruction instanceof ModMplsLabelInstruction) {
+ return matchModMplsLabelInstruction(jsonInstruction, description);
+ }
+
+ return false;
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(instruction.toString());
+ }
+
+ /**
+ * Factory to allocate an instruction matcher.
+ *
+ * @param instruction instruction object we are looking for
+ * @return matcher
+ */
+ public static InstructionJsonMatcher matchesInstruction(Instruction instruction) {
+ return new InstructionJsonMatcher(instruction);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
new file mode 100644
index 00000000..7cbce4d1
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentCodecTest.java
@@ -0,0 +1,288 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.time.Duration;
+import java.util.List;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.packet.IpPrefix;
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.MplsLabel;
+import org.onlab.util.Bandwidth;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.core.DefaultApplicationId;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.GridType;
+import org.onosproject.net.HostId;
+import org.onosproject.net.IndexedLambda;
+import org.onosproject.net.Lambda;
+import org.onosproject.net.NetTestTools;
+import org.onosproject.net.OchSignalType;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
+import org.onosproject.net.flow.instructions.Instructions;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.intent.AbstractIntentTest;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentServiceAdapter;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.constraint.AnnotationConstraint;
+import org.onosproject.net.intent.constraint.AsymmetricPathConstraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.intent.constraint.LatencyConstraint;
+import org.onosproject.net.intent.constraint.ObstacleConstraint;
+import org.onosproject.net.intent.constraint.WaypointConstraint;
+import org.onosproject.net.resource.link.BandwidthResource;
+import org.onosproject.net.resource.link.LambdaResource;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.google.common.collect.ImmutableList;
+
+import static org.easymock.EasyMock.createMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.hasSize;
+import static org.hamcrest.Matchers.instanceOf;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.IntentJsonMatcher.matchesIntent;
+import static org.onosproject.net.NetTestTools.did;
+import static org.onosproject.net.NetTestTools.hid;
+import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModEtherInstruction;
+
+/**
+ * Unit tests for the host to host intent class codec.
+ */
+public class IntentCodecTest extends AbstractIntentTest {
+
+ private final HostId id1 = hid("12:34:56:78:91:ab/1");
+ private final HostId id2 = hid("12:34:56:78:92:ab/1");
+ private final ApplicationId appId = new DefaultApplicationId(3, "test");
+ final TrafficSelector emptySelector =
+ DefaultTrafficSelector.emptySelector();
+ final TrafficTreatment emptyTreatment =
+ DefaultTrafficTreatment.emptyTreatment();
+ private final MockCodecContext context = new MockCodecContext();
+ final CoreService mockCoreService = createMock(CoreService.class);
+
+ @Before
+ public void setUpIntentService() {
+ final IntentService mockIntentService = new IntentServiceAdapter();
+ context.registerService(IntentService.class, mockIntentService);
+ context.registerService(CoreService.class, mockCoreService);
+ expect(mockCoreService.getAppId(appId.name()))
+ .andReturn(appId);
+ replay(mockCoreService);
+ }
+
+ /**
+ * Tests the encoding of a host to host intent.
+ */
+ @Test
+ public void hostToHostIntent() {
+ final HostToHostIntent intent =
+ HostToHostIntent.builder()
+ .appId(appId)
+ .one(id1)
+ .two(id2)
+ .build();
+
+ final JsonCodec<HostToHostIntent> intentCodec =
+ context.codec(HostToHostIntent.class);
+ assertThat(intentCodec, notNullValue());
+
+ final ObjectNode intentJson = intentCodec.encode(intent, context);
+ assertThat(intentJson, matchesIntent(intent));
+ }
+
+ /**
+ * Tests the encoding of a point to point intent.
+ */
+ @Test
+ public void pointToPointIntent() {
+ ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
+ ConnectPoint egress = NetTestTools.connectPoint("egress", 2);
+
+ final PointToPointIntent intent =
+ PointToPointIntent.builder()
+ .appId(appId)
+ .selector(emptySelector)
+ .treatment(emptyTreatment)
+ .ingressPoint(ingress)
+ .egressPoint(egress).build();
+
+ final JsonCodec<PointToPointIntent> intentCodec =
+ context.codec(PointToPointIntent.class);
+ assertThat(intentCodec, notNullValue());
+
+ final ObjectNode intentJson = intentCodec.encode(intent, context);
+ assertThat(intentJson, matchesIntent(intent));
+ }
+
+ /**
+ * Tests the encoding of an intent with treatment, selector and constraints
+ * specified.
+ */
+ @Test
+ public void intentWithTreatmentSelectorAndConstraints() {
+ ConnectPoint ingress = NetTestTools.connectPoint("ingress", 1);
+ ConnectPoint egress = NetTestTools.connectPoint("egress", 2);
+ DeviceId did1 = did("device1");
+ DeviceId did2 = did("device2");
+ DeviceId did3 = did("device3");
+ Lambda ochSignal = Lambda.ochSignal(GridType.DWDM, ChannelSpacing.CHL_100GHZ, 4, 8);
+ final TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchIPProtocol((byte) 3)
+ .matchMplsLabel(MplsLabel.mplsLabel(4))
+ .add(Criteria.matchOchSignalType(OchSignalType.FIXED_GRID))
+ .add(Criteria.matchLambda(ochSignal))
+ .matchEthDst(MacAddress.BROADCAST)
+ .matchIPDst(IpPrefix.valueOf("1.2.3.4/24"))
+ .build();
+ final TrafficTreatment treatment = DefaultTrafficTreatment.builder()
+ .add(Instructions.modL0Lambda(new IndexedLambda(33)))
+ .setMpls(MplsLabel.mplsLabel(44))
+ .setOutput(PortNumber.CONTROLLER)
+ .setEthDst(MacAddress.BROADCAST)
+ .build();
+
+ final List<Constraint> constraints =
+ ImmutableList.of(
+ new BandwidthConstraint(new BandwidthResource(Bandwidth.bps(1.0))),
+ new LambdaConstraint(LambdaResource.valueOf(3)),
+ new AnnotationConstraint("key", 33.0),
+ new AsymmetricPathConstraint(),
+ new LatencyConstraint(Duration.ofSeconds(2)),
+ new ObstacleConstraint(did1, did2),
+ new WaypointConstraint(did3));
+
+ final PointToPointIntent intent =
+ PointToPointIntent.builder()
+ .appId(appId)
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress)
+ .egressPoint(egress)
+ .constraints(constraints)
+ .build();
+
+
+ final JsonCodec<PointToPointIntent> intentCodec =
+ context.codec(PointToPointIntent.class);
+ assertThat(intentCodec, notNullValue());
+
+ final ObjectNode intentJson = intentCodec.encode(intent, context);
+ assertThat(intentJson, matchesIntent(intent));
+
+ }
+
+ /**
+ * Reads in a rule from the given resource and decodes it.
+ *
+ * @param resourceName resource to use to read the JSON for the rule
+ * @return decoded flow rule
+ * @throws IOException if processing the resource fails
+ */
+ private Intent getIntent(String resourceName, JsonCodec intentCodec) throws IOException {
+ InputStream jsonStream = FlowRuleCodecTest.class
+ .getResourceAsStream(resourceName);
+ JsonNode json = context.mapper().readTree(jsonStream);
+ assertThat(json, notNullValue());
+ Intent intent = (Intent) intentCodec.decode((ObjectNode) json, context);
+ assertThat(intent, notNullValue());
+ return intent;
+ }
+
+ /**
+ * Tests the point to point intent JSON codec.
+ *
+ * @throws IOException if JSON processing fails
+ */
+ @Test
+ public void decodePointToPointIntent() throws IOException {
+ JsonCodec<Intent> intentCodec = context.codec(Intent.class);
+ assertThat(intentCodec, notNullValue());
+
+ Intent intent = getIntent("PointToPointIntent.json", intentCodec);
+ assertThat(intent, notNullValue());
+ assertThat(intent, instanceOf(PointToPointIntent.class));
+
+ PointToPointIntent pointIntent = (PointToPointIntent) intent;
+ assertThat(pointIntent.priority(), is(55));
+ assertThat(pointIntent.ingressPoint().deviceId(), is(did("0000000000000001")));
+ assertThat(pointIntent.ingressPoint().port(), is(PortNumber.portNumber(1)));
+ assertThat(pointIntent.egressPoint().deviceId(), is(did("0000000000000007")));
+ assertThat(pointIntent.egressPoint().port(), is(PortNumber.portNumber(2)));
+
+ assertThat(pointIntent.constraints(), hasSize(1));
+
+ assertThat(pointIntent.selector(), notNullValue());
+ assertThat(pointIntent.selector().criteria(), hasSize(1));
+ Criterion criterion1 = pointIntent.selector().criteria().iterator().next();
+ assertThat(criterion1, instanceOf(EthCriterion.class));
+ EthCriterion ethCriterion = (EthCriterion) criterion1;
+ assertThat(ethCriterion.mac().toString(), is("11:22:33:44:55:66"));
+ assertThat(ethCriterion.type().name(), is("ETH_DST"));
+
+ assertThat(pointIntent.treatment(), notNullValue());
+ assertThat(pointIntent.treatment().allInstructions(), hasSize(1));
+ Instruction instruction1 = pointIntent.treatment().allInstructions().iterator().next();
+ assertThat(instruction1, instanceOf(ModEtherInstruction.class));
+ ModEtherInstruction ethInstruction = (ModEtherInstruction) instruction1;
+ assertThat(ethInstruction.mac().toString(), is("22:33:44:55:66:77"));
+ assertThat(ethInstruction.type().toString(), is("L2MODIFICATION"));
+ assertThat(ethInstruction.subtype().toString(), is("ETH_SRC"));
+ }
+
+ /**
+ * Tests the host to host intent JSON codec.
+ *
+ * @throws IOException
+ */
+ @Test
+ public void decodeHostToHostIntent() throws IOException {
+ JsonCodec<Intent> intentCodec = context.codec(Intent.class);
+ assertThat(intentCodec, notNullValue());
+
+ Intent intent = getIntent("HostToHostIntent.json", intentCodec);
+ assertThat(intent, notNullValue());
+ assertThat(intent, instanceOf(HostToHostIntent.class));
+
+ HostToHostIntent hostIntent = (HostToHostIntent) intent;
+ assertThat(hostIntent.priority(), is(7));
+ assertThat(hostIntent.constraints(), hasSize(1));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentJsonMatcher.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentJsonMatcher.java
new file mode 100644
index 00000000..e485a5fa
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/IntentJsonMatcher.java
@@ -0,0 +1,512 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.util.List;
+import java.util.Set;
+
+import org.hamcrest.Description;
+import org.hamcrest.TypeSafeDiagnosingMatcher;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.Link;
+import org.onosproject.net.NetworkResource;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.instructions.Instruction;
+import org.onosproject.net.intent.ConnectivityIntent;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.HostToHostIntent;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.constraint.AnnotationConstraint;
+import org.onosproject.net.intent.constraint.BandwidthConstraint;
+import org.onosproject.net.intent.constraint.LambdaConstraint;
+import org.onosproject.net.intent.constraint.LatencyConstraint;
+import org.onosproject.net.intent.constraint.LinkTypeConstraint;
+import org.onosproject.net.intent.constraint.ObstacleConstraint;
+import org.onosproject.net.intent.constraint.WaypointConstraint;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+/**
+ * Hamcrest matcher to check that an intent representation in JSON matches
+ * the actual intent.
+ */
+public final class IntentJsonMatcher extends TypeSafeDiagnosingMatcher<JsonNode> {
+
+ private final Intent intent;
+
+ /**
+ * Constructor is private, use factory method.
+ *
+ * @param intentValue the intent object to compare against
+ */
+ private IntentJsonMatcher(Intent intentValue) {
+ intent = intentValue;
+ }
+
+ /**
+ * Matches the JSON representation of a host to host intent.
+ *
+ * @param jsonIntent JSON representation of the intent
+ * @param description Description object used for recording errors
+ * @return true if the JSON matches the intent, false otherwise
+ */
+ private boolean matchHostToHostIntent(JsonNode jsonIntent, Description description) {
+ final HostToHostIntent hostToHostIntent = (HostToHostIntent) intent;
+
+ // check host one
+ final String host1 = hostToHostIntent.one().toString();
+ final String jsonHost1 = jsonIntent.get("one").asText();
+ if (!host1.equals(jsonHost1)) {
+ description.appendText("host one was " + jsonHost1);
+ return false;
+ }
+
+ // check host 2
+ final String host2 = hostToHostIntent.two().toString();
+ final String jsonHost2 = jsonIntent.get("two").asText();
+ if (!host2.equals(jsonHost2)) {
+ description.appendText("host two was " + jsonHost2);
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Matches the JSON representation of a point to point intent.
+ *
+ * @param jsonIntent JSON representation of the intent
+ * @param description Description object used for recording errors
+ * @return true if the JSON matches the intent, false otherwise
+ */
+ private boolean matchPointToPointIntent(JsonNode jsonIntent, Description description) {
+ final PointToPointIntent pointToPointIntent = (PointToPointIntent) intent;
+
+ // check ingress connection
+ final ConnectPoint ingress = pointToPointIntent.ingressPoint();
+ final ConnectPointJsonMatcher ingressMatcher =
+ ConnectPointJsonMatcher.matchesConnectPoint(ingress);
+ final JsonNode jsonIngress = jsonIntent.get("ingressPoint");
+ final boolean ingressMatches =
+ ingressMatcher.matchesSafely(jsonIngress, description);
+
+ if (!ingressMatches) {
+ description.appendText("ingress was " + jsonIngress);
+ return false;
+ }
+
+ // check egress connection
+ final ConnectPoint egress = pointToPointIntent.egressPoint();
+ final ConnectPointJsonMatcher egressMatcher =
+ ConnectPointJsonMatcher.matchesConnectPoint(egress);
+ final JsonNode jsonEgress = jsonIntent.get("egressPoint");
+ final boolean egressMatches =
+ egressMatcher.matchesSafely(jsonEgress, description);
+
+ if (!egressMatches) {
+ description.appendText("egress was " + jsonEgress);
+ return false;
+ }
+
+ return true;
+ }
+
+
+ /**
+ * Matches a bandwidth constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param bandwidthConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchBandwidthConstraint(BandwidthConstraint bandwidthConstraint,
+ JsonNode constraintJson) {
+ final JsonNode bandwidthJson = constraintJson.get("bandwidth");
+ return bandwidthJson != null
+ && constraintJson.get("bandwidth").asDouble()
+ == bandwidthConstraint.bandwidth().toDouble();
+ }
+
+ /**
+ * Matches a lamdba constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param lambdaConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchLambdaConstraint(LambdaConstraint lambdaConstraint,
+ JsonNode constraintJson) {
+ final JsonNode lambdaJson = constraintJson.get("lambda");
+ return lambdaJson != null
+ && constraintJson.get("lambda").asInt()
+ == lambdaConstraint.lambda().toInt();
+ }
+
+ /**
+ * Matches a link type constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param linkTypeConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchLinkTypeConstraint(LinkTypeConstraint linkTypeConstraint,
+ JsonNode constraintJson) {
+ final JsonNode inclusiveJson = constraintJson.get("inclusive");
+ final JsonNode typesJson = constraintJson.get("types");
+
+ if (typesJson.size() != linkTypeConstraint.types().size()) {
+ return false;
+ }
+
+ int foundType = 0;
+ for (Link.Type type : linkTypeConstraint.types()) {
+ for (int jsonIndex = 0; jsonIndex < typesJson.size(); jsonIndex++) {
+ if (type.name().equals(typesJson.get(jsonIndex).asText())) {
+ foundType++;
+ break;
+ }
+ }
+ }
+ return (inclusiveJson != null &&
+ inclusiveJson.asBoolean() == linkTypeConstraint.isInclusive()) &&
+ foundType == typesJson.size();
+ }
+
+ /**
+ * Matches an annotation constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param annotationConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchAnnotationConstraint(AnnotationConstraint annotationConstraint,
+ JsonNode constraintJson) {
+ final JsonNode keyJson = constraintJson.get("key");
+ final JsonNode thresholdJson = constraintJson.get("threshold");
+ return (keyJson != null
+ && keyJson.asText().equals(annotationConstraint.key())) &&
+ (thresholdJson != null
+ && thresholdJson.asDouble() == annotationConstraint.threshold());
+ }
+
+ /**
+ * Matches a latency constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param latencyConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchLatencyConstraint(LatencyConstraint latencyConstraint,
+ JsonNode constraintJson) {
+ final JsonNode latencyJson = constraintJson.get("latencyMillis");
+ return (latencyJson != null
+ && latencyJson.asInt() == latencyConstraint.latency().toMillis());
+ }
+
+ /**
+ * Matches an obstacle constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param obstacleConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchObstacleConstraint(ObstacleConstraint obstacleConstraint,
+ JsonNode constraintJson) {
+ final JsonNode obstaclesJson = constraintJson.get("obstacles");
+
+ if (obstaclesJson.size() != obstacleConstraint.obstacles().size()) {
+ return false;
+ }
+
+ for (int obstaclesIndex = 0; obstaclesIndex < obstaclesJson.size();
+ obstaclesIndex++) {
+ boolean obstacleFound = false;
+ final String obstacleJson = obstaclesJson.get(obstaclesIndex)
+ .asText();
+ for (DeviceId obstacle : obstacleConstraint.obstacles()) {
+ if (obstacle.toString().equals(obstacleJson)) {
+ obstacleFound = true;
+ }
+ }
+ if (!obstacleFound) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Matches a waypoint constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param waypointConstraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchWaypointConstraint(WaypointConstraint waypointConstraint,
+ JsonNode constraintJson) {
+ final JsonNode waypointsJson = constraintJson.get("waypoints");
+
+ if (waypointsJson.size() != waypointConstraint.waypoints().size()) {
+ return false;
+ }
+
+ for (int waypointsIndex = 0; waypointsIndex < waypointsJson.size();
+ waypointsIndex++) {
+ boolean waypointFound = false;
+ final String waypointJson = waypointsJson.get(waypointsIndex)
+ .asText();
+ for (DeviceId waypoint : waypointConstraint.waypoints()) {
+ if (waypoint.toString().equals(waypointJson)) {
+ waypointFound = true;
+ }
+ }
+ if (!waypointFound) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+
+ /**
+ * Matches a constraint against a JSON representation of the
+ * constraint.
+ *
+ * @param constraint constraint object to match
+ * @param constraintJson JSON representation of the constraint
+ * @return true if the constraint and JSON match, false otherwise.
+ */
+ private boolean matchConstraint(Constraint constraint, JsonNode constraintJson) {
+ final JsonNode typeJson = constraintJson.get("type");
+ if (!typeJson.asText().equals(constraint.getClass().getSimpleName())) {
+ return false;
+ }
+ if (constraint instanceof BandwidthConstraint) {
+ return matchBandwidthConstraint((BandwidthConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof LambdaConstraint) {
+ return matchLambdaConstraint((LambdaConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof LinkTypeConstraint) {
+ return matchLinkTypeConstraint((LinkTypeConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof AnnotationConstraint) {
+ return matchAnnotationConstraint((AnnotationConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof LatencyConstraint) {
+ return matchLatencyConstraint((LatencyConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof ObstacleConstraint) {
+ return matchObstacleConstraint((ObstacleConstraint) constraint,
+ constraintJson);
+ } else if (constraint instanceof WaypointConstraint) {
+ return matchWaypointConstraint((WaypointConstraint) constraint,
+ constraintJson);
+ }
+ return true;
+ }
+
+ /**
+ * Matches the JSON representation of a connectivity intent. Calls the
+ * matcher for the connectivity intent subtype.
+ *
+ * @param jsonIntent JSON representation of the intent
+ * @param description Description object used for recording errors
+ * @return true if the JSON matches the intent, false otherwise
+ */
+ private boolean matchConnectivityIntent(JsonNode jsonIntent, Description description) {
+ final ConnectivityIntent connectivityIntent = (ConnectivityIntent) intent;
+
+ // check selector
+ final JsonNode jsonSelector = jsonIntent.get("selector");
+ final TrafficSelector selector = connectivityIntent.selector();
+ final Set<Criterion> criteria = selector.criteria();
+ final JsonNode jsonCriteria = jsonSelector.get("criteria");
+ if (jsonCriteria.size() != criteria.size()) {
+ description.appendText("size of criteria array is "
+ + Integer.toString(jsonCriteria.size()));
+ return false;
+ }
+
+ for (Criterion criterion : criteria) {
+ boolean criterionFound = false;
+ for (int criterionIndex = 0; criterionIndex < jsonCriteria.size(); criterionIndex++) {
+ final CriterionJsonMatcher criterionMatcher =
+ CriterionJsonMatcher.matchesCriterion(criterion);
+ if (criterionMatcher.matches(jsonCriteria.get(criterionIndex))) {
+ criterionFound = true;
+ break;
+ }
+ }
+ if (!criterionFound) {
+ description.appendText("criterion not found " + criterion.toString());
+ return false;
+ }
+ }
+
+ // check treatment
+ final JsonNode jsonTreatment = jsonIntent.get("treatment");
+ final TrafficTreatment treatment = connectivityIntent.treatment();
+ final List<Instruction> instructions = treatment.immediate();
+ final JsonNode jsonInstructions = jsonTreatment.get("instructions");
+ if (jsonInstructions.size() != instructions.size()) {
+ description.appendText("size of instructions array is "
+ + Integer.toString(jsonInstructions.size()));
+ return false;
+ }
+
+ for (Instruction instruction : instructions) {
+ boolean instructionFound = false;
+ for (int instructionIndex = 0; instructionIndex < jsonInstructions.size(); instructionIndex++) {
+ final InstructionJsonMatcher instructionMatcher =
+ InstructionJsonMatcher.matchesInstruction(instruction);
+ if (instructionMatcher.matches(jsonInstructions.get(instructionIndex))) {
+ instructionFound = true;
+ break;
+ }
+ }
+ if (!instructionFound) {
+ description.appendText("instruction not found " + instruction.toString());
+ return false;
+ }
+ }
+
+ // Check constraints
+ final JsonNode jsonConstraints = jsonIntent.get("constraints");
+ if (connectivityIntent.constraints() != null) {
+ if (connectivityIntent.constraints().size() != jsonConstraints.size()) {
+ description.appendText("constraints array size was "
+ + Integer.toString(jsonConstraints.size()));
+ return false;
+ }
+ for (final Constraint constraint : connectivityIntent.constraints()) {
+ boolean constraintFound = false;
+ for (int constraintIndex = 0; constraintIndex < jsonConstraints.size();
+ constraintIndex++) {
+ final JsonNode value = jsonConstraints.get(constraintIndex);
+ if (matchConstraint(constraint, value)) {
+ constraintFound = true;
+ }
+ }
+ if (!constraintFound) {
+ final String constraintString = constraint.toString();
+ description.appendText("constraint missing " + constraintString);
+ return false;
+ }
+ }
+ } else if (jsonConstraints.size() != 0) {
+ description.appendText("constraint array not empty");
+ return false;
+ }
+
+ if (connectivityIntent instanceof HostToHostIntent) {
+ return matchHostToHostIntent(jsonIntent, description);
+ } else if (connectivityIntent instanceof PointToPointIntent) {
+ return matchPointToPointIntent(jsonIntent, description);
+ } else {
+ description.appendText("class of connectivity intent is unknown");
+ return false;
+ }
+ }
+
+ @Override
+ public boolean matchesSafely(JsonNode jsonIntent, Description description) {
+ // check id
+ final String jsonId = jsonIntent.get("id").asText();
+ final String id = intent.id().toString();
+ if (!jsonId.equals(id)) {
+ description.appendText("id was " + jsonId);
+ return false;
+ }
+
+ // check application id
+ final JsonNode jsonAppIdNode = jsonIntent.get("appId");
+
+ final String jsonAppId = jsonAppIdNode.asText();
+ final String appId = intent.appId().name();
+ if (!jsonAppId.equals(appId)) {
+ description.appendText("appId was " + jsonAppId);
+ return false;
+ }
+
+ // check intent type
+ final String jsonType = jsonIntent.get("type").asText();
+ final String type = intent.getClass().getSimpleName();
+ if (!jsonType.equals(type)) {
+ description.appendText("type was " + jsonType);
+ return false;
+ }
+
+ // check resources array
+ final JsonNode jsonResources = jsonIntent.get("resources");
+ if (intent.resources() != null) {
+ if (intent.resources().size() != jsonResources.size()) {
+ description.appendText("resources array size was "
+ + Integer.toString(jsonResources.size()));
+ return false;
+ }
+ for (final NetworkResource resource : intent.resources()) {
+ boolean resourceFound = false;
+ final String resourceString = resource.toString();
+ for (int resourceIndex = 0; resourceIndex < jsonResources.size(); resourceIndex++) {
+ final JsonNode value = jsonResources.get(resourceIndex);
+ if (value.asText().equals(resourceString)) {
+ resourceFound = true;
+ }
+ }
+ if (!resourceFound) {
+ description.appendText("resource missing " + resourceString);
+ return false;
+ }
+ }
+ } else if (jsonResources.size() != 0) {
+ description.appendText("resources array empty");
+ return false;
+ }
+
+ if (intent instanceof ConnectivityIntent) {
+ return matchConnectivityIntent(jsonIntent, description);
+ } else {
+ description.appendText("class of intent is unknown");
+ return false;
+ }
+ }
+
+ @Override
+ public void describeTo(Description description) {
+ description.appendText(intent.toString());
+ }
+
+ /**
+ * Factory to allocate an intent matcher.
+ *
+ * @param intent intent object we are looking for
+ * @return matcher
+ */
+ public static IntentJsonMatcher matchesIntent(Intent intent) {
+ return new IntentJsonMatcher(intent);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/JsonCodecUtils.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/JsonCodecUtils.java
new file mode 100644
index 00000000..67c2f47f
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/JsonCodecUtils.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.codec.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.junit.Assert.assertEquals;
+import static org.onosproject.net.DeviceId.deviceId;
+
+import org.onlab.packet.ChassisId;
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.DefaultAnnotations;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.SparseAnnotations;
+import org.onosproject.net.provider.ProviderId;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * JsonCodec test utilities.
+ */
+public abstract class JsonCodecUtils {
+
+ /**
+ * Checks if given Object can be encoded to JSON and back.
+ *
+ * @param context CodecContext
+ * @param codec JsonCodec
+ * @param pojoIn Java Object to encode.
+ * Object is expected to have #equals implemented.
+ */
+ public static <T> void assertJsonEncodable(final CodecContext context,
+ final JsonCodec<T> codec,
+ final T pojoIn) {
+ final ObjectNode json = codec.encode(pojoIn, context);
+
+ assertThat(json, is(notNullValue()));
+
+ final T pojoOut = codec.decode(json, context);
+ assertThat(pojoOut, is(notNullValue()));
+
+ assertEquals(pojoIn, pojoOut);
+ }
+
+ static final ProviderId PID = new ProviderId("of", "foo");
+ static final ProviderId PIDA = new ProviderId("of", "bar", true);
+ static final DeviceId DID1 = deviceId("of:foo");
+ static final DeviceId DID2 = deviceId("of:bar");
+ static final String MFR = "whitebox";
+ static final String HW = "1.1.x";
+ static final String SW1 = "3.8.1";
+ static final String SW2 = "3.9.5";
+ static final String SN = "43311-12345";
+ static final ChassisId CID = new ChassisId();
+ static final PortNumber P1 = PortNumber.portNumber(1);
+ static final PortNumber P2 = PortNumber.portNumber(2);
+ static final PortNumber P3 = PortNumber.portNumber(3);
+ static final SparseAnnotations A1 = DefaultAnnotations.builder()
+ .set("A1", "a1")
+ .set("B1", "b1")
+ .build();
+ static final ConnectPoint CP1 = new ConnectPoint(DID1, P1);
+ static final ConnectPoint CP2 = new ConnectPoint(DID2, P2);
+
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LinkCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LinkCodecTest.java
new file mode 100644
index 00000000..c44b0eb1
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LinkCodecTest.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.codec.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable;
+
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.DefaultLink;
+import org.onosproject.net.Link;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+
+/**
+ * Unit test for LinkCodec.
+ */
+public class LinkCodecTest {
+
+ private final Link link = new DefaultLink(JsonCodecUtils.PID,
+ JsonCodecUtils.CP1,
+ JsonCodecUtils.CP2,
+ Link.Type.DIRECT,
+ Link.State.ACTIVE,
+ false,
+ JsonCodecUtils.A1);
+
+ @Test
+ public void linkCodecTest() {
+ final MockCodecContext context = new MockCodecContext();
+ context.registerService(DeviceService.class, new DeviceServiceAdapter());
+ final JsonCodec<Link> codec = context.codec(Link.class);
+ assertThat(codec, is(notNullValue()));
+ final Link pojoIn = link;
+
+ assertJsonEncodable(context, codec, pojoIn);
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LoadCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LoadCodecTest.java
new file mode 100644
index 00000000..4cb2916e
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/LoadCodecTest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import org.junit.Test;
+import org.onosproject.net.statistic.DefaultLoad;
+import org.onosproject.net.statistic.Load;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThanOrEqualTo;
+import static org.hamcrest.Matchers.is;
+
+/**
+ * Unit tests for Load codec.
+ */
+public class LoadCodecTest {
+
+ /**
+ * Tests encoding of a Load object.
+ */
+ @Test
+ public void testLoadEncode() {
+ final long startTime = System.currentTimeMillis();
+ final Load load = new DefaultLoad(20, 10, 1);
+ final JsonNode node = new LoadCodec()
+ .encode(load, new MockCodecContext());
+ assertThat(node.get("valid").asBoolean(), is(true));
+ assertThat(node.get("latest").asLong(), is(20L));
+ assertThat(node.get("rate").asLong(), is(10L));
+ assertThat(node.get("time").asLong(), greaterThanOrEqualTo(startTime));
+ }
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java
new file mode 100644
index 00000000..6a9b6708
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/MockCodecContext.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onosproject.codec.impl;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onosproject.codec.CodecContext;
+import org.onosproject.codec.JsonCodec;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+/**
+ * Mock codec context for use in codec unit tests.
+ */
+public class MockCodecContext implements CodecContext {
+
+ private final ObjectMapper mapper = new ObjectMapper();
+ private final CodecManager manager = new CodecManager();
+ private final Map<Class<? extends Object>, Object> services = new HashMap<>();
+
+ /**
+ * Constructs a new mock codec context.
+ */
+ public MockCodecContext() {
+ manager.activate();
+ }
+
+ @Override
+ public ObjectMapper mapper() {
+ return mapper;
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> JsonCodec<T> codec(Class<T> entityClass) {
+ return manager.getCodec(entityClass);
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getService(Class<T> serviceClass) {
+ return (T) services.get(serviceClass);
+ }
+
+ // for registering mock services
+ public <T> void registerService(Class<T> serviceClass, T impl) {
+ services.put(serviceClass, impl);
+ }
+
+}
diff --git a/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/PortCodecTest.java b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/PortCodecTest.java
new file mode 100644
index 00000000..f3f7d920
--- /dev/null
+++ b/framework/src/onos/core/common/src/test/java/org/onosproject/codec/impl/PortCodecTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2015 Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.codec.impl;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+import static org.onosproject.codec.impl.JsonCodecUtils.assertJsonEncodable;
+
+import org.junit.Test;
+import org.onosproject.codec.JsonCodec;
+import org.onosproject.net.DefaultDevice;
+import org.onosproject.net.DefaultPort;
+import org.onosproject.net.Device;
+import org.onosproject.net.Port;
+import org.onosproject.net.device.DeviceService;
+import org.onosproject.net.device.DeviceServiceAdapter;
+
+/**
+ * Unit test for PortCodec.
+ */
+public class PortCodecTest {
+
+
+
+ private final Device device = new DefaultDevice(JsonCodecUtils.PID,
+ JsonCodecUtils.DID1,
+ Device.Type.SWITCH,
+ JsonCodecUtils.MFR,
+ JsonCodecUtils.HW,
+ JsonCodecUtils.SW1,
+ JsonCodecUtils.SN,
+ JsonCodecUtils.CID,
+ JsonCodecUtils.A1);
+
+ private final Port port = new DefaultPort(device,
+ JsonCodecUtils.P1,
+ true,
+ JsonCodecUtils.A1);
+
+ @Test
+ public void portCodecTest() {
+ final MockCodecContext context = new MockCodecContext();
+ context.registerService(DeviceService.class, new DeviceServiceAdapter());
+ final JsonCodec<Port> codec = context.codec(Port.class);
+ assertThat(codec, is(notNullValue()));
+ final Port pojoIn = port;
+
+ assertJsonEncodable(context, codec, pojoIn);
+ }
+
+}