P4Runtime unit tests for api, ctl, model modules
Change-Id: Iac1b1ef6e274c355ce3a26cffbd8adcb39694f69
diff --git a/protocols/p4runtime/api/BUCK b/protocols/p4runtime/api/BUCK
index 8b740b84..fd05763 100644
--- a/protocols/p4runtime/api/BUCK
+++ b/protocols/p4runtime/api/BUCK
@@ -5,6 +5,13 @@
'//incubator/grpc-dependencies:grpc-core-repkg-' + GRPC_VER,
]
-osgi_jar(
+TEST_DEPS = [
+ '//core/api:onos-api-tests',
+ '//lib:TEST',
+ '//protocols/p4runtime/api:onos-protocols-p4runtime-api',
+]
+
+osgi_jar_with_tests(
deps = COMPILE_DEPS,
-)
\ No newline at end of file
+ test_deps = TEST_DEPS,
+)
diff --git a/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/DefaultPacketInTest.java b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/DefaultPacketInTest.java
new file mode 100644
index 0000000..38fcf6d
--- /dev/null
+++ b/protocols/p4runtime/ctl/src/test/java/org/onosproject/p4runtime/ctl/DefaultPacketInTest.java
@@ -0,0 +1,154 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.ctl;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onlab.util.ImmutableByteSequence;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.pi.runtime.PiControlMetadata;
+import org.onosproject.net.pi.model.PiControlMetadataId;
+import org.onosproject.net.pi.runtime.PiPacketOperation;
+
+import static org.onlab.util.ImmutableByteSequence.copyFrom;
+import static org.onlab.util.ImmutableByteSequence.fit;
+import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_OUT;
+import static org.onosproject.net.pi.model.PiPacketOperationType.PACKET_IN;
+
+/**
+ * Test for DefaultPacketIn class.
+ */
+public class DefaultPacketInTest {
+
+ private static final int DEFAULT_ORIGINAL_VALUE = 255;
+ private static final int DEFAULT_BIT_WIDTH = 9;
+
+ private final DeviceId deviceId = DeviceId.deviceId("dummy:1");
+ private final DeviceId sameDeviceId = DeviceId.deviceId("dummy:1");
+ private final DeviceId deviceId2 = DeviceId.deviceId("dummy:2");
+ private final DeviceId nullDeviceId = null;
+
+ private PiPacketOperation packetOperation;
+ private PiPacketOperation packetOperation2;
+ private PiPacketOperation nullPacketOperation = null;
+
+ private DefaultPacketIn packetIn;
+ private DefaultPacketIn sameAsPacketIn;
+ private DefaultPacketIn packetIn2;
+ private DefaultPacketIn packetIn3;
+
+ /**
+ * Setup method for packetOperation and packetOperation2.
+ * @throws ImmutableByteSequence.ByteSequenceTrimException if byte sequence cannot be trimmed
+ */
+ @Before
+ public void setup() throws ImmutableByteSequence.ByteSequenceTrimException {
+
+ packetOperation = PiPacketOperation.builder()
+ .forDevice(deviceId)
+ .withData(ImmutableByteSequence.ofOnes(512))
+ .withType(PACKET_OUT)
+ .withMetadata(PiControlMetadata.builder()
+ .withId(PiControlMetadataId.of("egress_port"))
+ .withValue(fit(copyFrom(DEFAULT_ORIGINAL_VALUE), DEFAULT_BIT_WIDTH))
+ .build())
+ .build();
+
+ packetOperation2 = PiPacketOperation.builder()
+ .forDevice(deviceId2)
+ .withData(ImmutableByteSequence.ofOnes(512))
+ .withType(PACKET_IN)
+ .withMetadata(PiControlMetadata.builder()
+ .withId(PiControlMetadataId.of("ingress_port"))
+ .withValue(fit(copyFrom(DEFAULT_ORIGINAL_VALUE), DEFAULT_BIT_WIDTH))
+ .build())
+ .build();
+
+ packetIn = new DefaultPacketIn(deviceId, packetOperation);
+ sameAsPacketIn = new DefaultPacketIn(sameDeviceId, packetOperation);
+ packetIn2 = new DefaultPacketIn(deviceId2, packetOperation);
+ packetIn3 = new DefaultPacketIn(deviceId, packetOperation2);
+ }
+
+ /**
+ * tearDown method for packetOperation and packetOperation2.
+ */
+ @After
+ public void tearDown() {
+ packetOperation = null;
+ packetOperation2 = null;
+
+ packetIn = null;
+ sameAsPacketIn = null;
+ packetIn2 = null;
+ packetIn3 = null;
+ }
+
+
+ /**
+ * Tests constructor with null object as a DeviceId parameter.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testConstructorWithNullDeviceId() {
+
+ new DefaultPacketIn(nullDeviceId, packetOperation);
+ }
+
+ /**
+ * Tests constructor with null object as PacketOperation parameter.
+ */
+ @Test(expected = NullPointerException.class)
+ public void testConstructorWithNullPacketOperation() {
+
+ new DefaultPacketIn(deviceId, nullPacketOperation);
+ }
+
+ /**
+ * Test for deviceId method.
+ */
+ @Test
+ public void deviceId() {
+ new EqualsTester()
+ .addEqualityGroup(deviceId, packetIn.deviceId(), sameAsPacketIn.deviceId())
+ .addEqualityGroup(packetIn2)
+ .testEquals();
+ }
+
+ /**
+ * Test for packetOperation method.
+ */
+ @Test
+ public void packetOperation() {
+ new EqualsTester()
+ .addEqualityGroup(packetOperation, packetIn.packetOperation())
+ .addEqualityGroup(packetIn3.packetOperation())
+ .testEquals();
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(packetIn, sameAsPacketIn)
+ .addEqualityGroup(packetIn2)
+ .addEqualityGroup(packetIn3)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/BUCK b/protocols/p4runtime/model/BUCK
index 86c44c4..61e5d49 100644
--- a/protocols/p4runtime/model/BUCK
+++ b/protocols/p4runtime/model/BUCK
@@ -6,6 +6,9 @@
'//lib:protobuf-java-' + PROTOBUF_VER,
]
-osgi_jar(
- deps = COMPILE_DEPS,
+TEST_DEPS = [
+]
+
+osgi_jar_with_tests(
+ deps = COMPILE_DEPS + TEST_DEPS,
)
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionModelTest.java
new file mode 100644
index 0000000..387fad4
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionModelTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiActionId;
+import org.onosproject.net.pi.model.PiActionParamId;
+import org.onosproject.net.pi.model.PiActionParamModel;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test for P4ActionModel class.
+ */
+public class P4ActionModelTest {
+
+ final PiActionId actionId = PiActionId.of("dec_ttl");
+ final PiActionId sameAsActionId = PiActionId.of("dec_ttl");
+ final PiActionId actionId2 = PiActionId.of("mod_vlan_vid");
+
+ private final PiActionParamId piActionParamId = PiActionParamId.of("port");
+ private final PiActionParamId sameAsPiActionParamId = PiActionParamId.of("port");
+ private final PiActionParamId piActionParamId2 = PiActionParamId.of("dstAddr");
+
+ private static final int BIT_WIDTH = 32;
+
+ private final P4ActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, BIT_WIDTH);
+
+ private final P4ActionParamModel actionParamModel2 = new P4ActionParamModel(piActionParamId2, BIT_WIDTH);
+
+
+ private final ImmutableMap<PiActionParamId, PiActionParamModel> params = new
+ ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(piActionParamId, actionParamModel)
+ .build();
+ private final ImmutableMap<PiActionParamId, PiActionParamModel> sameAsParams = new
+ ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(sameAsPiActionParamId, actionParamModel)
+ .build();
+ private final ImmutableMap<PiActionParamId, PiActionParamModel> params2 = new
+ ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(piActionParamId2, actionParamModel)
+ .build();
+ private final ImmutableMap<PiActionParamId, PiActionParamModel> params3 = new
+ ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(piActionParamId, actionParamModel2)
+ .build();
+
+ private final P4ActionModel actionModel = new P4ActionModel(actionId, params);
+
+ private final P4ActionModel sameAsActionModel = new P4ActionModel(sameAsActionId, params);
+
+ private final P4ActionModel sameAsActionModel2 = new P4ActionModel(actionId, sameAsParams);
+
+ private final P4ActionModel actionModel2 = new P4ActionModel(actionId2, params);
+
+ private final P4ActionModel actionModel3 = new P4ActionModel(actionId, params2);
+
+ private final P4ActionModel actionModel4 = new P4ActionModel(actionId, params3);
+
+ /**
+ * Checks that the P4ActionModel class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(P4ActionModel.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(actionModel, sameAsActionModel, sameAsActionModel2)
+ .addEqualityGroup(actionModel2)
+ .addEqualityGroup(actionModel3)
+ .addEqualityGroup(actionModel4)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionParamModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionParamModelTest.java
new file mode 100644
index 0000000..035465c
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionParamModelTest.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiActionParamId;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test for P4ActionParamModel class.
+ */
+public class P4ActionParamModelTest {
+ private final PiActionParamId piActionParamId = PiActionParamId.of("port");
+ private final PiActionParamId sameAsPiActionParamId = PiActionParamId.of("port");
+ private final PiActionParamId piActionParamId2 = PiActionParamId.of("dstAddr");
+
+ private static final int BIT_WIDTH_32 = 32;
+ private static final int BIT_WIDTH_64 = 64;
+
+ private final P4ActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, BIT_WIDTH_32);
+
+ private final P4ActionParamModel sameAsActionParamModel = new P4ActionParamModel(sameAsPiActionParamId,
+ BIT_WIDTH_32);
+
+ private final P4ActionParamModel actionParamModel2 = new P4ActionParamModel(piActionParamId2, BIT_WIDTH_32);
+
+ private final P4ActionParamModel actionParamModel3 = new P4ActionParamModel(piActionParamId, BIT_WIDTH_64);
+
+
+
+ /**
+ * Checks that the P4CounterModel class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(P4ActionParamModel.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(actionParamModel, sameAsActionParamModel)
+ .addEqualityGroup(actionParamModel2)
+ .addEqualityGroup(actionParamModel3)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java
new file mode 100644
index 0000000..3042414
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ActionProfileModelTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiActionProfileId;
+import org.onosproject.net.pi.model.PiTableId;
+
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test for P4ActionProfile class.
+ */
+public class P4ActionProfileModelTest {
+
+ private static final String TABLE_0 = "table0";
+ private static final String WCMP_TABLE = "wcmp_table";
+
+ private final PiTableId tableId = PiTableId.of(TABLE_0);
+ private final PiTableId sameAsTableId = PiTableId.of(TABLE_0);
+ private final PiTableId tableId2 = PiTableId.of(WCMP_TABLE);
+
+ private final ImmutableSet<PiTableId> tables = new ImmutableSet.Builder<PiTableId>()
+ .add(tableId, tableId2)
+ .build();
+
+ private final ImmutableSet<PiTableId> sameAsTables = new ImmutableSet.Builder<PiTableId>()
+ .add(sameAsTableId, tableId2)
+ .build();
+
+ private final ImmutableSet<PiTableId> tables2 = new ImmutableSet.Builder<PiTableId>()
+ .add(tableId, sameAsTableId)
+ .build();
+
+ private final PiActionProfileId id = PiActionProfileId.of("name");
+ private final PiActionProfileId id2 = PiActionProfileId.of("name2");
+
+ private final P4ActionProfileModel metadataModel = new P4ActionProfileModel(id, tables,
+ true, 64);
+ private final P4ActionProfileModel sameAsMetadataModel = new P4ActionProfileModel(id, sameAsTables,
+ true, 64);
+ private final P4ActionProfileModel metadataModel2 = new P4ActionProfileModel(id, tables2,
+ true, 64);
+ private final P4ActionProfileModel metadataModel3 = new P4ActionProfileModel(id2, tables,
+ true, 64);
+ private final P4ActionProfileModel metadataModel4 = new P4ActionProfileModel(id, tables,
+ false, 64);
+ private final P4ActionProfileModel metadataModel5 = new P4ActionProfileModel(id, tables,
+ true, 32);
+
+ /**
+ * Checks that the P4ActionProfileModel class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(P4ActionProfileModel.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(metadataModel, sameAsMetadataModel)
+ .addEqualityGroup(metadataModel2)
+ .addEqualityGroup(metadataModel3)
+ .addEqualityGroup(metadataModel4)
+ .addEqualityGroup(metadataModel5)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ControlMetadataModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ControlMetadataModelTest.java
new file mode 100644
index 0000000..998875a
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4ControlMetadataModelTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiControlMetadataId;
+
+import static org.junit.Assert.*;
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test for P4ControlMetadataModel class.
+ */
+public class P4ControlMetadataModelTest {
+
+ private final PiControlMetadataId piControlMetadataId = PiControlMetadataId.of("EGRESS_PORT");
+ private final PiControlMetadataId sameAsPiControlMetadataId = PiControlMetadataId.of("EGRESS_PORT");
+ private final PiControlMetadataId piControlMetadataId2 = PiControlMetadataId.of("INGRESS_PORT");
+
+ private static final int BIT_WIDTH_32 = 32;
+ private static final int BIT_WIDTH_64 = 64;
+
+ private final P4ControlMetadataModel metadataModel = new P4ControlMetadataModel(piControlMetadataId, BIT_WIDTH_32);
+
+ private final P4ControlMetadataModel sameAsMetadataModel = new P4ControlMetadataModel(sameAsPiControlMetadataId,
+ BIT_WIDTH_32);
+
+ private final P4ControlMetadataModel metadataModel2 = new P4ControlMetadataModel(piControlMetadataId2,
+ BIT_WIDTH_32);
+
+ private final P4ControlMetadataModel metadataModel3 = new P4ControlMetadataModel(piControlMetadataId, BIT_WIDTH_64);
+
+
+
+ /**
+ * Checks that the P4CounterModel class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(P4ControlMetadataModel.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(metadataModel, sameAsMetadataModel)
+ .addEqualityGroup(metadataModel2)
+ .addEqualityGroup(metadataModel3)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4CounterModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4CounterModelTest.java
new file mode 100644
index 0000000..a3be5b4
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4CounterModelTest.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.testing.EqualsTester;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiCounterId;
+import org.onosproject.net.pi.model.PiCounterModel;
+import org.onosproject.net.pi.model.PiCounterType;
+import org.onosproject.net.pi.model.PiTableId;
+
+import static org.onlab.junit.ImmutableClassChecker.assertThatClassIsImmutable;
+
+/**
+ * Test for P4CounterModel class.
+ */
+public class P4CounterModelTest {
+ private static final String TABLE_0 = "table0";
+ private static final String WCMP_TABLE = "wcmp_table";
+
+ private final PiTableId tableId = PiTableId.of(TABLE_0);
+ private final PiTableId sameAsTableId = PiTableId.of(TABLE_0);
+ private final PiTableId tableId2 = PiTableId.of(WCMP_TABLE);
+
+ private final PiCounterId counterId = PiCounterId.of("name");
+
+ private final P4CounterModel counterModel = new P4CounterModel(counterId, PiCounterType.DIRECT,
+ PiCounterModel.Unit.BYTES, tableId, 16);
+
+ private final P4CounterModel sameAsCounterModel = new P4CounterModel(counterId, PiCounterType.DIRECT,
+ PiCounterModel.Unit.BYTES, sameAsTableId, 16);
+
+ private final P4CounterModel counterModel2 = new P4CounterModel(counterId, PiCounterType.INDIRECT,
+ PiCounterModel.Unit.BYTES, tableId, 16);
+
+ private final P4CounterModel counterModel3 = new P4CounterModel(counterId, PiCounterType.DIRECT,
+ PiCounterModel.Unit.PACKETS, tableId, 16);
+
+ private final P4CounterModel counterModel4 = new P4CounterModel(counterId, PiCounterType.DIRECT,
+ PiCounterModel.Unit.BYTES, tableId2, 16);
+
+ private final P4CounterModel counterModel5 = new P4CounterModel(counterId, PiCounterType.DIRECT,
+ PiCounterModel.Unit.BYTES, tableId, 32);
+ /**
+ * Checks that the P4CounterModel class is immutable.
+ */
+ @Test
+ public void testImmutability() {
+ assertThatClassIsImmutable(P4CounterModel.class);
+ }
+
+ /**
+ * Checks the operation of equals(), hashCode() and toString() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester()
+ .addEqualityGroup(counterModel, sameAsCounterModel)
+ .addEqualityGroup(counterModel2)
+ .addEqualityGroup(counterModel3)
+ .addEqualityGroup(counterModel4)
+ .addEqualityGroup(counterModel5)
+ .testEquals();
+ }
+}
\ No newline at end of file
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java
new file mode 100644
index 0000000..452a7a7
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4InfoParserTest.java
@@ -0,0 +1,294 @@
+/*
+ * Copyright 2017-present Open Networking Foundation
+ *
+ * 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.p4runtime.model;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.testing.EqualsTester;
+import com.google.protobuf.ExtensionRegistry;
+import com.google.protobuf.TextFormat;
+import org.hamcrest.collection.IsIterableContainingInAnyOrder;
+import org.hamcrest.collection.IsIterableContainingInOrder;
+import org.junit.Test;
+import org.onosproject.net.pi.model.PiActionId;
+import org.onosproject.net.pi.model.PiActionModel;
+import org.onosproject.net.pi.model.PiActionParamId;
+import org.onosproject.net.pi.model.PiActionParamModel;
+import org.onosproject.net.pi.model.PiActionProfileId;
+import org.onosproject.net.pi.model.PiActionProfileModel;
+import org.onosproject.net.pi.model.PiCounterId;
+import org.onosproject.net.pi.model.PiCounterModel;
+import org.onosproject.net.pi.model.PiMatchFieldId;
+import org.onosproject.net.pi.model.PiMatchFieldModel;
+import org.onosproject.net.pi.model.PiMatchType;
+import org.onosproject.net.pi.model.PiMeterModel;
+import org.onosproject.net.pi.model.PiPacketOperationModel;
+import org.onosproject.net.pi.model.PiPacketOperationType;
+import org.onosproject.net.pi.model.PiPipelineModel;
+import org.onosproject.net.pi.model.PiTableId;
+import org.onosproject.net.pi.model.PiTableModel;
+import p4.config.P4InfoOuterClass.Table;
+import p4.config.P4InfoOuterClass.P4Info;
+import p4.config.P4InfoOuterClass.MatchField;
+import p4.config.P4InfoOuterClass.ActionRef;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.*;
+import static org.hamcrest.core.IsNull.notNullValue;
+
+/**
+ * Test for P4Info Parser.
+ */
+public class P4InfoParserTest {
+ private static final String PATH = "basic.p4info";
+
+ private final URL p4InfoUrl = P4InfoParserTest.class.getResource(PATH);
+
+ private static final Long DEFAULT_MAX_TABLE_SIZE = 1024L;
+ private static final Long DEFAULT_MAX_ACTION_PROFILE_SIZE = 64L;
+
+ public P4InfoParserTest() throws MalformedURLException { }
+
+ /**
+ * Tests parse method.
+ * @throws Exception if equality group objects dose not match as expected
+ */
+ @Test
+ public void testParse() throws Exception {
+ // Generate two PiPipelineModels from p4Info file
+ PiPipelineModel model = P4InfoParser.parse(p4InfoUrl);
+ PiPipelineModel model2 = P4InfoParser.parse(p4InfoUrl);
+
+ // Check equality
+ new EqualsTester().addEqualityGroup(model, model2).testEquals();
+
+ // Generate a P4Info object from the file
+ final P4Info p4info;
+ try {
+ p4info = getP4InfoMessage(p4InfoUrl);
+ } catch (IOException e) {
+ throw new P4InfoParserException("Unable to parse protobuf " + p4InfoUrl.toString(), e);
+ }
+
+ List<Table> tableMsgs = p4info.getTablesList();
+ PiTableId table0Id = PiTableId.of(tableMsgs.get(0).getPreamble().getName());
+ PiTableId wcmpTableId = PiTableId.of(tableMsgs.get(1).getPreamble().getName());
+
+ //parse tables
+ PiTableModel table0Model = model.table(table0Id).orElse(null);
+ PiTableModel wcmpTableModel = model.table(wcmpTableId).orElse(null);
+ PiTableModel table0Model2 = model2.table(table0Id).orElse(null);
+ PiTableModel wcmpTableModel2 = model2.table(wcmpTableId).orElse(null);
+
+ new EqualsTester().addEqualityGroup(table0Model, table0Model2)
+ .addEqualityGroup(wcmpTableModel, wcmpTableModel2).testEquals();
+
+ // Check existence
+ assertThat("model parsed value is null", table0Model, notNullValue());
+ assertThat("model parsed value is null", wcmpTableModel, notNullValue());
+ assertThat("Incorrect size for table0 size", table0Model.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
+ assertThat("Incorrect size for wcmp_table size", wcmpTableModel.maxSize(), is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
+
+ // Check matchFields
+ List<MatchField> matchFieldList = tableMsgs.get(0).getMatchFieldsList();
+ List<PiMatchFieldModel> piMatchFieldList = new ArrayList<>();
+
+ for (MatchField matchFieldIter : matchFieldList) {
+ int matchTypeNumber = matchFieldIter.getMatchType().getNumber();
+ PiMatchType piMatchType = PiMatchType.VALID;
+ switch (matchTypeNumber) {
+ case 1: piMatchType = PiMatchType.VALID; break;
+ case 2: piMatchType = PiMatchType.EXACT; break;
+ case 3: piMatchType = PiMatchType.LPM; break;
+ case 4: piMatchType = piMatchType.TERNARY; break;
+ case 5: piMatchType = piMatchType.RANGE; break;
+ default: piMatchType = PiMatchType.VALID; break;
+ }
+ piMatchFieldList.add(new P4MatchFieldModel(PiMatchFieldId.of(matchFieldIter.getName()),
+ matchFieldIter.getBitwidth(), piMatchType));
+ }
+ // Check MatchFields size
+ assertThat("Incorrect size for matchFields", table0Model.matchFields().size(), is(equalTo(9)));
+ // Check if matchFields are in order
+ assertThat("Incorrect order for matchFields", table0Model.matchFields(), IsIterableContainingInOrder.contains(
+ piMatchFieldList.get(0), piMatchFieldList.get(1),
+ piMatchFieldList.get(2), piMatchFieldList.get(3),
+ piMatchFieldList.get(4), piMatchFieldList.get(5),
+ piMatchFieldList.get(6), piMatchFieldList.get(7),
+ piMatchFieldList.get(8)));
+
+ assertThat("Incorrect size for matchFields", wcmpTableModel.matchFields().size(), is(equalTo(1)));
+
+ // check if matchFields are in order
+ matchFieldList = tableMsgs.get(1).getMatchFieldsList();
+ assertThat("Incorrect order for matchFields",
+ wcmpTableModel.matchFields(), IsIterableContainingInOrder.contains(
+ new P4MatchFieldModel(PiMatchFieldId.of(matchFieldList.get(0).getName()),
+ matchFieldList.get(0).getBitwidth(), PiMatchType.EXACT)));
+
+ //check table0 actionsRefs
+ List<ActionRef> actionRefList = tableMsgs.get(0).getActionRefsList();
+ assertThat("Incorrect size for actionRefs", actionRefList.size(), is(equalTo(4)));
+
+ //create action instances
+ PiActionId actionId = PiActionId.of("set_egress_port");
+ PiActionParamId piActionParamId = PiActionParamId.of("port");
+ int bitWitdth = 9;
+ PiActionParamModel actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
+ ImmutableMap<PiActionParamId, PiActionParamModel> params = new
+ ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(piActionParamId, actionParamModel).build();
+
+ PiActionModel setEgressPortAction = new P4ActionModel(actionId, params);
+
+ actionId = PiActionId.of("send_to_cpu");
+ PiActionModel sendToCpuAction =
+ new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
+
+ actionId = PiActionId.of("_drop");
+ PiActionModel dropAction =
+ new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
+
+ actionId = PiActionId.of("NoAction");
+ PiActionModel noAction =
+ new P4ActionModel(actionId, new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>().build());
+
+ actionId = PiActionId.of("table0_control.set_next_hop_id");
+ piActionParamId = PiActionParamId.of("next_hop_id");
+ bitWitdth = 16;
+ actionParamModel = new P4ActionParamModel(piActionParamId, bitWitdth);
+ params = new ImmutableMap.Builder<PiActionParamId, PiActionParamModel>()
+ .put(piActionParamId, actionParamModel).build();
+
+ PiActionModel setNextHopIdAction = new P4ActionModel(actionId, params);
+
+ //check table0 actions
+ assertThat("action dose not match",
+ table0Model.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(
+ setEgressPortAction, sendToCpuAction, setNextHopIdAction, dropAction));
+
+ //check wcmp_table actions
+ assertThat("actions dose not match",
+ wcmpTableModel.actions(), IsIterableContainingInAnyOrder.containsInAnyOrder(
+ setEgressPortAction, noAction));
+
+ PiActionModel table0DefaultAction = table0Model.defaultAction().orElse(null);
+
+ new EqualsTester().addEqualityGroup(table0DefaultAction, dropAction).testEquals();
+
+ // Check existence
+ assertThat("model parsed value is null", table0DefaultAction, notNullValue());
+
+ //parse action profiles
+ PiTableId tableId = PiTableId.of("wcmp_control.wcmp_table");
+ ImmutableSet<PiTableId> tableIds = new ImmutableSet.Builder<PiTableId>().add(tableId).build();
+ PiActionProfileId actionProfileId = PiActionProfileId.of("wcmp_control.wcmp_selector");
+ PiActionProfileModel wcmpSelector3 = new P4ActionProfileModel(actionProfileId, tableIds,
+ true, DEFAULT_MAX_ACTION_PROFILE_SIZE);
+ PiActionProfileModel wcmpSelector = model.actionProfiles(actionProfileId).orElse(null);
+ PiActionProfileModel wcmpSelector2 = model2.actionProfiles(actionProfileId).orElse(null);
+
+ new EqualsTester().addEqualityGroup(wcmpSelector, wcmpSelector2, wcmpSelector3).testEquals();
+
+ // Check existence
+ assertThat("model parsed value is null", wcmpSelector, notNullValue());
+ assertThat("Incorrect value for actions profiles", model.actionProfiles(), containsInAnyOrder(wcmpSelector));
+ // ActionProfiles size
+ assertThat("Incorrect size for action profiles", model.actionProfiles().size(), is(equalTo(1)));
+
+ //parse counters
+ PiCounterModel ingressPortCounterModel =
+ model.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
+ PiCounterModel egressPortCounterModel =
+ model.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
+ PiCounterModel table0CounterModel =
+ model.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
+ PiCounterModel wcmpTableCounterModel =
+ model.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
+
+ PiCounterModel ingressPortCounterModel2 =
+ model2.counter(PiCounterId.of("port_counters_ingress.ingress_port_counter")).orElse(null);
+ PiCounterModel egressPortCounterModel2 =
+ model2.counter(PiCounterId.of("port_counters_egress.egress_port_counter")).orElse(null);
+ PiCounterModel table0CounterModel2 =
+ model2.counter(PiCounterId.of("table0_control.table0_counter")).orElse(null);
+ PiCounterModel wcmpTableCounterModel2 =
+ model2.counter(PiCounterId.of("wcmp_control.wcmp_table_counter")).orElse(null);
+
+ new EqualsTester()
+ .addEqualityGroup(ingressPortCounterModel, ingressPortCounterModel2)
+ .addEqualityGroup(egressPortCounterModel, egressPortCounterModel2)
+ .addEqualityGroup(table0CounterModel, table0CounterModel2)
+ .addEqualityGroup(wcmpTableCounterModel, wcmpTableCounterModel2)
+ .testEquals();
+
+ assertThat("model parsed value is null", ingressPortCounterModel, notNullValue());
+ assertThat("model parsed value is null", egressPortCounterModel, notNullValue());
+ assertThat("model parsed value is null", table0CounterModel, notNullValue());
+ assertThat("model parsed value is null", wcmpTableCounterModel, notNullValue());
+
+ //Parse meters
+ Collection<PiMeterModel> meterModel = model.meters();
+ Collection<PiMeterModel> meterModel2 = model2.meters();
+
+ assertThat("model pased meter collaction should be empty", meterModel.isEmpty(), is(true));
+ assertThat("model pased meter collaction should be empty", meterModel2.isEmpty(), is(true));
+
+ //parse packet operations
+ PiPacketOperationModel packetInOperationalModel =
+ model.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
+ PiPacketOperationModel packetOutOperationalModel =
+ model.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
+
+ PiPacketOperationModel packetInOperationalModel2 =
+ model2.packetOperationModel(PiPacketOperationType.PACKET_IN).orElse(null);
+ PiPacketOperationModel packetOutOperationalModel2 =
+ model2.packetOperationModel(PiPacketOperationType.PACKET_OUT).orElse(null);
+
+ new EqualsTester()
+ .addEqualityGroup(packetInOperationalModel, packetInOperationalModel2)
+ .addEqualityGroup(packetOutOperationalModel, packetOutOperationalModel2)
+ .testEquals();
+
+ // Check existence
+ assertThat("model parsed value is null", packetInOperationalModel, notNullValue());
+ assertThat("model parsed value is null", packetOutOperationalModel, notNullValue());
+ }
+
+ /**
+ * Gets P4Info message from the URL.
+ * @param p4InfoUrl link to the p4Info file
+ * @return a P4Info object
+ * @throws IOException if any problem occurs while reading from the URL connection.
+ */
+ private P4Info getP4InfoMessage(URL p4InfoUrl) throws IOException {
+ InputStream p4InfoStream = p4InfoUrl.openStream();
+ P4Info.Builder p4InfoBuilder = P4Info.newBuilder();
+ TextFormat.getParser().merge(new InputStreamReader(p4InfoStream),
+ ExtensionRegistry.getEmptyRegistry(),
+ p4InfoBuilder);
+ return p4InfoBuilder.build();
+ }
+}
diff --git a/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info b/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info
new file mode 100644
index 0000000..8010892
--- /dev/null
+++ b/protocols/p4runtime/model/src/test/resources/org/onosproject/p4runtime/model/basic.p4info
@@ -0,0 +1,222 @@
+tables {
+ preamble {
+ id: 33571508
+ name: "table0_control.table0"
+ alias: "table0"
+ }
+ match_fields {
+ id: 1
+ name: "standard_metadata.ingress_port"
+ bitwidth: 9
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 2
+ name: "hdr.ethernet.src_addr"
+ bitwidth: 48
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 3
+ name: "hdr.ethernet.dst_addr"
+ bitwidth: 48
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 4
+ name: "hdr.ethernet.ether_type"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 5
+ name: "hdr.ipv4.src_addr"
+ bitwidth: 32
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 6
+ name: "hdr.ipv4.dst_addr"
+ bitwidth: 32
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 7
+ name: "hdr.ipv4.protocol"
+ bitwidth: 8
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 8
+ name: "local_metadata.l4_src_port"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ match_fields {
+ id: 9
+ name: "local_metadata.l4_dst_port"
+ bitwidth: 16
+ match_type: TERNARY
+ }
+ action_refs {
+ id: 16794308
+ }
+ action_refs {
+ id: 16829080
+ }
+ action_refs {
+ id: 16802895
+ }
+ action_refs {
+ id: 16784184
+ }
+ const_default_action_id: 16784184
+ direct_resource_ids: 302046050
+ size: 1024
+}
+tables {
+ preamble {
+ id: 33592597
+ name: "wcmp_control.wcmp_table"
+ alias: "wcmp_table"
+ }
+ match_fields {
+ id: 1
+ name: "local_metadata.next_hop_id"
+ bitwidth: 16
+ match_type: EXACT
+ }
+ action_refs {
+ id: 16794308
+ }
+ action_refs {
+ id: 16800567
+ annotations: "@defaultonly()"
+ }
+ implementation_id: 285259294
+ direct_resource_ids: 302001091
+ size: 1024
+}
+actions {
+ preamble {
+ id: 16794308
+ name: "set_egress_port"
+ alias: "set_egress_port"
+ }
+ params {
+ id: 1
+ name: "port"
+ bitwidth: 9
+ }
+}
+actions {
+ preamble {
+ id: 16829080
+ name: "send_to_cpu"
+ alias: "send_to_cpu"
+ }
+}
+actions {
+ preamble {
+ id: 16784184
+ name: "_drop"
+ alias: "_drop"
+ }
+}
+actions {
+ preamble {
+ id: 16800567
+ name: "NoAction"
+ alias: "NoAction"
+ }
+}
+actions {
+ preamble {
+ id: 16802895
+ name: "table0_control.set_next_hop_id"
+ alias: "set_next_hop_id"
+ }
+ params {
+ id: 1
+ name: "next_hop_id"
+ bitwidth: 16
+ }
+}
+action_profiles {
+ preamble {
+ id: 285259294
+ name: "wcmp_control.wcmp_selector"
+ alias: "wcmp_selector"
+ }
+ table_ids: 33592597
+ with_selector: true
+ size: 64
+}
+counters {
+ preamble {
+ id: 302012579
+ name: "port_counters_ingress.ingress_port_counter"
+ alias: "ingress_port_counter"
+ }
+ spec {
+ unit: PACKETS
+ }
+ size: 511
+}
+counters {
+ preamble {
+ id: 302012501
+ name: "port_counters_egress.egress_port_counter"
+ alias: "egress_port_counter"
+ }
+ spec {
+ unit: PACKETS
+ }
+ size: 511
+}
+direct_counters {
+ preamble {
+ id: 302046050
+ name: "table0_control.table0_counter"
+ alias: "table0_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33571508
+}
+direct_counters {
+ preamble {
+ id: 302001091
+ name: "wcmp_control.wcmp_table_counter"
+ alias: "wcmp_table_counter"
+ }
+ spec {
+ unit: BOTH
+ }
+ direct_table_id: 33592597
+}
+controller_packet_metadata {
+ preamble {
+ id: 2868941301
+ name: "packet_in"
+ annotations: "@controller_header(\"packet_in\")"
+ }
+ metadata {
+ id: 1
+ name: "ingress_port"
+ bitwidth: 9
+ }
+}
+controller_packet_metadata {
+ preamble {
+ id: 2868916615
+ name: "packet_out"
+ annotations: "@controller_header(\"packet_out\")"
+ }
+ metadata {
+ id: 1
+ name: "egress_port"
+ bitwidth: 9
+ }
+}