Add support for one shot action profile programming in PI

A P4 table annotated with @oneshot annotation can be programmed
only with the action profile action set. For these kind of tables
we don't issue read request for action profile groups and members.

Change-Id: I7b6a743f4f4df4190f17d958ebb4807aca5feda5
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
index 558acb1..3785c96 100644
--- 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
@@ -83,10 +83,8 @@
         // 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 {
@@ -94,30 +92,33 @@
         } 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());
-
+        PiTableId wcmpTableOneShotId = PiTableId.of(tableMsgs.get(2).getPreamble().getName());
         //parse tables
         PiTableModel table0Model = model.table(table0Id).orElse(null);
         PiTableModel wcmpTableModel = model.table(wcmpTableId).orElse(null);
+        PiTableModel wcmpTableOneShotModel = model.table(wcmpTableOneShotId).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("model parsed value is null", wcmpTableOneShotModel, 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)));
+        assertThat("Incorrect size for wcmp_table_one_shot size", wcmpTableOneShotModel.maxSize(),
+                   is(equalTo(DEFAULT_MAX_TABLE_SIZE)));
+        // Check one-shot annotation
+        assertThat("error parsing one-shot annotation", wcmpTableModel.oneShotOnly(), is(false));
+        assertThat("error parsing one-shot annotation", wcmpTableOneShotModel.oneShotOnly(), is(true));
 
         // Check matchFields
         List<MatchField> matchFieldList = tableMsgs.get(0).getMatchFieldsList();
         List<PiMatchFieldModel> piMatchFieldList = new ArrayList<>();
-
         for (MatchField matchFieldIter : matchFieldList) {
             MatchField.MatchType matchType = matchFieldIter.getMatchType();
             PiMatchType piMatchType;
@@ -140,7 +141,6 @@
                 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
@@ -256,8 +256,8 @@
         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));
+        assertThat("model parsed meter collection should be empty", meterModel.isEmpty(), is(true));
+        assertThat("model parsed meter collection should be empty", meterModel2.isEmpty(), is(true));
 
         //parse packet operations
         PiPacketOperationModel packetInOperationalModel =
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4PipelineModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4PipelineModelTest.java
index fdc3d2e..3da1ffb 100644
--- a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4PipelineModelTest.java
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4PipelineModelTest.java
@@ -27,8 +27,6 @@
 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.PiPacketMetadataId;
-import org.onosproject.net.pi.model.PiPacketMetadataModel;
 import org.onosproject.net.pi.model.PiCounterId;
 import org.onosproject.net.pi.model.PiCounterModel;
 import org.onosproject.net.pi.model.PiCounterType;
@@ -38,6 +36,8 @@
 import org.onosproject.net.pi.model.PiMeterId;
 import org.onosproject.net.pi.model.PiMeterModel;
 import org.onosproject.net.pi.model.PiMeterType;
+import org.onosproject.net.pi.model.PiPacketMetadataId;
+import org.onosproject.net.pi.model.PiPacketMetadataModel;
 import org.onosproject.net.pi.model.PiPacketOperationModel;
 import org.onosproject.net.pi.model.PiPacketOperationType;
 import org.onosproject.net.pi.model.PiPipelineModel;
@@ -261,6 +261,7 @@
     /* Table Models */
     private static final PiTableId PI_TABLE_ID_1 = PiTableId.of("Table1");
     private static final PiTableId PI_TABLE_ID_2 = PiTableId.of("Table2");
+    private static final PiTableId PI_TABLE_ID_3 = PiTableId.of("Table3");
 
     private static final PiTableType PI_TABLE_TYPE_1 = PiTableType.DIRECT;
     private static final PiTableType PI_TABLE_TYPE_2 = PiTableType.INDIRECT;
@@ -277,11 +278,15 @@
     private static final PiTableModel P4_TABLE_MODEL_1 =
             new P4TableModel(PI_TABLE_ID_1, PI_TABLE_TYPE_1, P4_ACTION_PROFILE_MODEL_1, MAX_SIZE_1, COUNTERS_1,
                              METERS_1, SUPPORT_AGING_1, MATCH_FIELDS_1, ACTIONS_1, P4_ACTION_MODEL_DEFAULT_1,
-                             IS_CONST_TABLE_1);
+                             IS_CONST_TABLE_1, false);
     private static final PiTableModel P4_TABLE_MODEL_2 =
             new P4TableModel(PI_TABLE_ID_2, PI_TABLE_TYPE_2, P4_ACTION_PROFILE_MODEL_2, MAX_SIZE_2, COUNTERS_2,
                              METERS_2, SUPPORT_AGING_2, MATCH_FIELDS_2, ACTIONS_2, P4_ACTION_MODEL_DEFAULT_2,
-                             IS_CONST_TABLE_2);
+                             IS_CONST_TABLE_2, false);
+    private static final PiTableModel P4_TABLE_MODEL_3 =
+            new P4TableModel(PI_TABLE_ID_2, PI_TABLE_TYPE_2, P4_ACTION_PROFILE_MODEL_2, MAX_SIZE_2, COUNTERS_2,
+                             METERS_2, SUPPORT_AGING_2, MATCH_FIELDS_2, ACTIONS_2, P4_ACTION_MODEL_DEFAULT_2,
+                             IS_CONST_TABLE_2, true);
 
     /* Packet operations */
     private static final PiPacketOperationType PI_PACKET_OPERATION_TYPE_1 = PiPacketOperationType.PACKET_IN;
@@ -309,6 +314,10 @@
             new ImmutableMap.Builder<PiTableId, PiTableModel>()
                     .put(PI_TABLE_ID_2, P4_TABLE_MODEL_2)
                     .build();
+    private static final ImmutableMap<PiTableId, PiTableModel> TABLES_3 =
+            new ImmutableMap.Builder<PiTableId, PiTableModel>()
+                    .put(PI_TABLE_ID_3, P4_TABLE_MODEL_3)
+                    .build();
 
     private static final ImmutableMap<PiActionProfileId, PiActionProfileModel> ACTION_PROFILES_1 =
             new ImmutableMap.Builder<PiActionProfileId, PiActionProfileModel>()
@@ -357,16 +366,19 @@
 
     private static final PiPipelineModel P4_PIPELINE_MODEL_1 =
             new P4PipelineModel(TABLES_1, COUNTERS_1, METERS_1, REGISTERS_1, ACTION_PROFILES_1, PACKET_OPERATIONS_1,
-                    FINGER_PRINT_1);
+                                FINGER_PRINT_1);
     private static final PiPipelineModel SAME_AS_P4_PIPELINE_MODEL_1 =
             new P4PipelineModel(TABLES_1, COUNTERS_1, METERS_1, REGISTERS_1, ACTION_PROFILES_1, PACKET_OPERATIONS_1,
-                    FINGER_PRINT_1);
+                                FINGER_PRINT_1);
     private static final PiPipelineModel P4_PIPELINE_MODEL_2 =
             new P4PipelineModel(TABLES_2, COUNTERS_2, METERS_2, REGISTERS_1, ACTION_PROFILES_2, PACKET_OPERATIONS_2,
-                    FINGER_PRINT_2);
+                                FINGER_PRINT_2);
     private static final PiPipelineModel P4_PIPELINE_MODEL_3 =
             new P4PipelineModel(TABLES_2, COUNTERS_2, METERS_2, REGISTERS_1, ACTION_PROFILES_2, PACKET_OPERATIONS_3,
                                 FINGER_PRINT_2);
+    private static final PiPipelineModel P4_PIPELINE_MODEL_4 =
+            new P4PipelineModel(TABLES_3, COUNTERS_2, METERS_2, REGISTERS_1, ACTION_PROFILES_2, PACKET_OPERATIONS_3,
+                                FINGER_PRINT_2);
 
     /**
      * Checks that the P4PipelineModel class is immutable.
@@ -385,6 +397,7 @@
                 .addEqualityGroup(P4_PIPELINE_MODEL_1, SAME_AS_P4_PIPELINE_MODEL_1)
                 .addEqualityGroup(P4_PIPELINE_MODEL_2)
                 .addEqualityGroup(P4_PIPELINE_MODEL_3)
+                .addEqualityGroup(P4_PIPELINE_MODEL_4)
                 .testEquals();
     }
 }
diff --git a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4TableModelTest.java b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4TableModelTest.java
index 13677c0..d28d984 100644
--- a/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4TableModelTest.java
+++ b/protocols/p4runtime/model/src/test/java/org/onosproject/p4runtime/model/P4TableModelTest.java
@@ -250,15 +250,19 @@
     private static final PiTableModel P4_TABLE_MODEL_1 =
             new P4TableModel(PI_TABLE_ID_1, PI_TABLE_TYPE_1, P4_ACTION_PROFILE_MODEL_1, MAX_SIZE_1, COUNTERS_1,
                              METERS_1, SUPPORT_AGING_1, MATCH_FIELDS_1, ACTIONS_1, P4_ACTION_MODEL_DEFAULT_1,
-                             IS_CONST_TABLE_1);
+                             IS_CONST_TABLE_1, false);
     private static final PiTableModel SAME_AS_P4_TABLE_MODEL_1 =
             new P4TableModel(PI_TABLE_ID_1, PI_TABLE_TYPE_1, P4_ACTION_PROFILE_MODEL_1, MAX_SIZE_1, COUNTERS_1,
                              METERS_1, SUPPORT_AGING_1, MATCH_FIELDS_1, ACTIONS_1, P4_ACTION_MODEL_DEFAULT_1,
-                             IS_CONST_TABLE_1);
+                             IS_CONST_TABLE_1, false);
     private static final PiTableModel P4_TABLE_MODEL_2 =
             new P4TableModel(PI_TABLE_ID_2, PI_TABLE_TYPE_2, P4_ACTION_PROFILE_MODEL_2, MAX_SIZE_2, COUNTERS_2,
                              METERS_2, SUPPORT_AGING_2, MATCH_FIELDS_2, ACTIONS_2, P4_ACTION_MODEL_DEFAULT_2,
-                             IS_CONST_TABLE_2);
+                             IS_CONST_TABLE_2, false);
+    private static final PiTableModel P4_TABLE_MODEL_3 =
+            new P4TableModel(PI_TABLE_ID_2, PI_TABLE_TYPE_2, P4_ACTION_PROFILE_MODEL_2, MAX_SIZE_2, COUNTERS_2,
+                             METERS_2, SUPPORT_AGING_2, MATCH_FIELDS_2, ACTIONS_2, P4_ACTION_MODEL_DEFAULT_2,
+                             IS_CONST_TABLE_2, true);
 
     /**
      * Checks that the P4TableModel class is immutable.
@@ -276,6 +280,7 @@
         new EqualsTester()
                 .addEqualityGroup(P4_TABLE_MODEL_1, SAME_AS_P4_TABLE_MODEL_1)
                 .addEqualityGroup(P4_TABLE_MODEL_2)
+                .addEqualityGroup(P4_TABLE_MODEL_3)
                 .testEquals();
     }
 }