HC2VPP-387: Validation support for Vpp-Classifier module 11/17211/11
authorTibor Král <[email protected]>
Thu, 31 Jan 2019 16:50:29 +0000 (17:50 +0100)
committerTibor Král <[email protected]>
Tue, 26 Mar 2019 11:54:21 +0000 (12:54 +0100)
Change-Id: Ia97fa466bc3e39c04bd8f7625c4b6306523e3fce
Signed-off-by: Tibor Král <[email protected]>
22 files changed:
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerCustomizer.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerValidator.java [new file with mode: 0644]
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerWriterFactory.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerCustomizer.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerValidator.java [new file with mode: 0644]
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerWriterFactory.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/InterfaceAclWriterFactory.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/SubInterfaceAclWriterFactory.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/factory/write/VppClassifierHoneycombWriterFactory.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidator.java [new file with mode: 0644]
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriter.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidator.java [new file with mode: 0644]
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriter.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/acl/ingress/AclCustomizer.java
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/acl/ingress/AclValidator.java [new file with mode: 0644]
vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/acl/ingress/AclWriter.java
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/policer/write/PolicerValidatorTest.java [new file with mode: 0644]
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidatorTest.java [new file with mode: 0644]
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionWriterTest.java
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidatorTest.java [new file with mode: 0644]
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableWriterTest.java
vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/acl/AclValidatorTest.java [new file with mode: 0644]

index a3df551..a042e23 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.policer.write;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -46,8 +44,8 @@ final class InterfacePolicerCustomizer extends FutureJVppCustomizer implements W
     InterfacePolicerCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext,
                                @Nonnull final VppClassifierContextManager classifyTableContext) {
         super(vppApi);
-        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
-        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");;
+        this.interfaceContext = interfaceContext;
+        this.classifyTableContext = classifyTableContext;
     }
 
     @Override
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerValidator.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/InterfacePolicerValidator.java
new file mode 100644 (file)
index 0000000..513ccde
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.policer.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang._interface.policer.rev170315._interface.policer.attributes.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacePolicerValidator implements Validator<Policer> {
+
+    public InterfacePolicerValidator(final NamingContext interfaceContext,
+                                     final VppClassifierContextManager classifyTableContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+        checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Policer> id,
+                              @Nonnull final Policer policer,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        //noop for now
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Policer> id, @Nonnull final Policer dataBefore,
+                               @Nonnull final Policer dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // noop for now
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Policer> id, @Nonnull final Policer dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        //noop for now
+    }
+}
index 641b00d..9422cc1 100644 (file)
@@ -37,9 +37,9 @@ import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class InterfacePolicerWriterFactory implements WriterFactory {
     private static final InstanceIdentifier<Interface> IFC_ID =
-        InstanceIdentifier.create(Interfaces.class).child(Interface.class);
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class);
     private static final InstanceIdentifier<PolicerInterfaceAugmentation> POLICER_IFC_ID =
-        IFC_ID.augmentation(PolicerInterfaceAugmentation.class);
+            IFC_ID.augmentation(PolicerInterfaceAugmentation.class);
     static final InstanceIdentifier<Policer> POLICER_ID = POLICER_IFC_ID.child(Policer.class);
 
     @Inject
@@ -54,7 +54,9 @@ public class InterfacePolicerWriterFactory implements WriterFactory {
     @Override
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
         registry.addAfter(
-            new GenericWriter<>(POLICER_ID, new InterfacePolicerCustomizer(vppApi, ifcContext, classifyTableContext)),
-            Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
+                new GenericWriter<>(POLICER_ID,
+                        new InterfacePolicerCustomizer(vppApi, ifcContext, classifyTableContext),
+                        new InterfacePolicerValidator(ifcContext, classifyTableContext)),
+                Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
     }
 }
index 8cad88f..b844d52 100644 (file)
@@ -16,9 +16,6 @@
 
 package io.fd.hc2vpp.policer.write;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -33,7 +30,6 @@ import java.nio.charset.StandardCharsets;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.DscpType;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionDrop;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionMarkDscp;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionParams;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionTransmit;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionType;
@@ -47,13 +43,14 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 public class PolicerCustomizer extends FutureJVppCustomizer implements ListWriterCustomizer<Policer, PolicerKey>,
-    JvppReplyConsumer, ByteDataTranslator {
+        JvppReplyConsumer, ByteDataTranslator {
     private static final Logger LOG = LoggerFactory.getLogger(PolicerCustomizer.class);
     private final NamingContext policerContext;
 
-    public PolicerCustomizer(@Nonnull final FutureJVppCore futureJVppCore, @Nonnull final NamingContext policerContext) {
+    public PolicerCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
+                             @Nonnull final NamingContext policerContext) {
         super(futureJVppCore);
-        this.policerContext = checkNotNull(policerContext, "policerContext should not be null");
+        this.policerContext = policerContext;
     }
 
     @Override
@@ -68,7 +65,7 @@ public class PolicerCustomizer extends FutureJVppCustomizer implements ListWrite
     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
                                         @Nonnull final Policer dataBefore,
                                         @Nonnull final Policer dataAfter, @Nonnull final WriteContext ctx)
-        throws WriteFailedException {
+            throws WriteFailedException {
         LOG.debug("Updating Policer {} dataBefore={} dataAfter={}", id, dataBefore, dataAfter);
         policerAddDel(id, dataAfter, true);
     }
@@ -77,14 +74,14 @@ public class PolicerCustomizer extends FutureJVppCustomizer implements ListWrite
     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Policer> id,
                                         @Nonnull final Policer dataBefore,
                                         @Nonnull final WriteContext ctx)
-        throws WriteFailedException {
+            throws WriteFailedException {
         LOG.debug("Removing Policer {} dataBefore={}", id, dataBefore);
         policerAddDel(id, dataBefore, false);
         policerContext.removeName(dataBefore.getName(), ctx.getMappingContext());
     }
 
     private int policerAddDel(final InstanceIdentifier<Policer> id, final Policer policer, final boolean isAdd)
-        throws WriteFailedException {
+            throws WriteFailedException {
         final PolicerAddDel request = new PolicerAddDel();
         request.isAdd = booleanToByte(isAdd);
         request.name = policer.getName().getBytes(StandardCharsets.US_ASCII);
@@ -128,7 +125,7 @@ public class PolicerCustomizer extends FutureJVppCustomizer implements ListWrite
         }
         LOG.debug("Policer config change id={} request={}", id, request);
         final PolicerAddDelReply reply =
-            getReplyForWrite(getFutureJVpp().policerAddDel(request).toCompletableFuture(), id);
+                getReplyForWrite(getFutureJVpp().policerAddDel(request).toCompletableFuture(), id);
         return reply.policerIndex;
     }
 
@@ -137,9 +134,6 @@ public class PolicerCustomizer extends FutureJVppCustomizer implements ListWrite
         if (dscp == null) {
             return 0;
         }
-        final Class<? extends MeterActionType> meterActionType = actionParams.getMeterActionType();
-        checkArgument(MeterActionMarkDscp.class == meterActionType,
-            "dcsp is supported only for meter-action-mark-dscp, but %s defined", meterActionType);
         if (dscp.getVppDscpType() != null) {
             return (byte) dscp.getVppDscpType().getIntValue();
         }
@@ -154,10 +148,8 @@ public class PolicerCustomizer extends FutureJVppCustomizer implements ListWrite
             return 0;
         } else if (MeterActionTransmit.class == meterActionType) {
             return 1;
-        } else if (MeterActionMarkDscp.class == meterActionType) {
-            return 2;
         } else {
-            throw new IllegalArgumentException("Unsupported meter action type " + meterActionType);
+            return 2;
         }
     }
 }
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerValidator.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/policer/write/PolicerValidator.java
new file mode 100644 (file)
index 0000000..47d5c87
--- /dev/null
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.policer.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionDrop;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionMarkDscp;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionParams;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionTransmit;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionType;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policers.Policer;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicerValidator implements Validator<Policer> {
+
+    public PolicerValidator(final NamingContext policerContext) {
+        checkNotNull(policerContext, "policerContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Policer> id,
+                              @Nonnull final Policer policer,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validatePolicer(policer);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, policer, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Policer> id,
+                               @Nonnull final Policer policer,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validatePolicer(policer);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validatePolicer(final Policer policer) {
+        checkAction(policer.getConformAction());
+        checkAction(policer.getExceedAction());
+        checkAction(policer.getViolateAction());
+    }
+
+    private void checkAction(MeterActionParams action) {
+        if (action != null) {
+            Class<? extends MeterActionType> actionType = action.getMeterActionType();
+            checkActionType(actionType);
+            if (action.getDscp() != null) {
+                checkDscp(actionType);
+            }
+        }
+    }
+
+    private void checkDscp(final Class<? extends MeterActionType> actionType) {
+        checkArgument(MeterActionMarkDscp.class == actionType,
+                "dcsp is supported only for meter-action-mark-dscp, but %s defined", actionType);
+    }
+
+    private void checkActionType(Class<? extends MeterActionType> type) {
+        checkArgument(
+                type == MeterActionDrop.class || type == MeterActionTransmit.class || type == MeterActionMarkDscp.class,
+                "Unsupported meter action type %s", type);
+    }
+}
index 0b6532f..db3d500 100644 (file)
@@ -33,7 +33,8 @@ import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.pol
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class PolicerWriterFactory implements WriterFactory {
-    private static final InstanceIdentifier<Policer> POLICER_IID = InstanceIdentifier.create(Policers.class).child(Policer.class);
+    private static final InstanceIdentifier<Policer> POLICER_IID =
+            InstanceIdentifier.create(Policers.class).child(Policer.class);
 
     @Inject
     private FutureJVppCore vppApi;
@@ -45,8 +46,9 @@ public class PolicerWriterFactory implements WriterFactory {
     public void init(@Nonnull final ModifiableWriterRegistryBuilder registry) {
         InstanceIdentifier<Policer> IID = InstanceIdentifier.create(Policer.class);
         registry.subtreeAdd(
-            Sets.newHashSet(IID.child(ConformAction.class), IID.child(ExceedAction.class),
-                IID.child(ViolateAction.class)),
-            new GenericListWriter<>(POLICER_IID, new PolicerCustomizer(vppApi, policerContext)));
+                Sets.newHashSet(IID.child(ConformAction.class), IID.child(ExceedAction.class),
+                        IID.child(ViolateAction.class)),
+                new GenericListWriter<>(POLICER_IID, new PolicerCustomizer(vppApi, policerContext),
+                        new PolicerValidator(policerContext)));
     }
 }
index 1648152..2538904 100644 (file)
@@ -25,6 +25,7 @@ import com.google.inject.name.Named;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
 import io.fd.hc2vpp.vpp.classifier.write.acl.ingress.AclCustomizer;
+import io.fd.hc2vpp.vpp.classifier.write.acl.ingress.AclValidator;
 import io.fd.honeycomb.translate.impl.write.GenericWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
 import io.fd.honeycomb.translate.write.registry.ModifiableWriterRegistryBuilder;
@@ -71,7 +72,8 @@ public class InterfaceAclWriterFactory implements WriterFactory {
                         Sets.newHashSet(ingressId.child(L2Acl.class), ingressId.child(Ip4Acl.class),
                                 ingressId.child(Ip6Acl.class)),
                         new GenericWriter<>(INGRESS_ACL_ID,
-                                new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext)),
+                                new AclCustomizer(jvpp, ifcNamingContext, classifyTableContext),
+                                new AclValidator(ifcNamingContext, classifyTableContext)),
                         Sets.newHashSet(CLASSIFY_TABLE_ID, CLASSIFY_SESSION_ID));
     }
 }
index e283618..7b0dfff 100644 (file)
@@ -22,6 +22,7 @@ import com.google.inject.name.Named;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.v3po.factory.InterfacesWriterFactory;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.hc2vpp.vpp.classifier.write.acl.ingress.AclValidator;
 import io.fd.hc2vpp.vpp.classifier.write.acl.ingress.SubInterfaceAclCustomizer;
 import io.fd.honeycomb.translate.impl.write.GenericWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
@@ -71,7 +72,8 @@ public class SubInterfaceAclWriterFactory implements WriterFactory {
                 .subtreeAddAfter(
                         Sets.newHashSet(aclId.child(L2Acl.class), aclId.child(Ip4Acl.class), aclId.child(Ip6Acl.class)),
                         new GenericWriter<>(SUBIF_INGRESS_ACL_ID,
-                                new SubInterfaceAclCustomizer(jvpp, ifcNamingContext, classifyTableContext)),
+                                new SubInterfaceAclCustomizer(jvpp, ifcNamingContext, classifyTableContext),
+                                new AclValidator(ifcNamingContext, classifyTableContext)),
                         Sets.newHashSet(VppClassifierHoneycombWriterFactory.CLASSIFY_TABLE_ID,
                                 VppClassifierHoneycombWriterFactory.CLASSIFY_SESSION_ID));
     }
index 7248498..0569930 100644 (file)
@@ -20,7 +20,9 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.hc2vpp.vpp.classifier.write.ClassifySessionValidator;
 import io.fd.hc2vpp.vpp.classifier.write.ClassifySessionWriter;
+import io.fd.hc2vpp.vpp.classifier.write.ClassifyTableValidator;
 import io.fd.hc2vpp.vpp.classifier.write.ClassifyTableWriter;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.translate.write.WriterFactory;
@@ -58,11 +60,14 @@ public final class VppClassifierHoneycombWriterFactory implements WriterFactory
         // Ordering here is: First create table, then create sessions and then assign as ACL
         // ClassifyTable
         registry.addBefore(
-                new GenericListWriter<>(CLASSIFY_TABLE_ID, new ClassifyTableWriter(jvpp, classifyTableContext)),
+                new GenericListWriter<>(CLASSIFY_TABLE_ID, new ClassifyTableWriter(jvpp, classifyTableContext),
+                        new ClassifyTableValidator()),
                 CLASSIFY_SESSION_ID);
         //  ClassifyTableSession
         registry.addBefore(
-                new GenericListWriter<>(CLASSIFY_SESSION_ID, new ClassifySessionWriter(jvpp, classifyTableContext, policerContext)),
+                new GenericListWriter<>(CLASSIFY_SESSION_ID,
+                        new ClassifySessionWriter(jvpp, classifyTableContext, policerContext),
+                        new ClassifySessionValidator(classifyTableContext, policerContext)),
                 InterfaceAclWriterFactory.ACL_ID);
     }
 }
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidator.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidator.java
new file mode 100644 (file)
index 0000000..ec46414
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import com.google.common.base.Preconditions;
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.classify.table.base.attributes.ClassifySession;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTable;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTableKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClassifySessionValidator implements Validator<ClassifySession>, ClassifyWriter{
+
+    private final VppClassifierContextManager classifyTableContext;
+
+    public ClassifySessionValidator(@Nonnull final VppClassifierContextManager classifyTableContext,
+                                    @Nonnull final NamingContext policerContext) {
+        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+        checkNotNull(policerContext, "policerContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<ClassifySession> id,
+                              @Nonnull final ClassifySession session,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validateSession(id, writeContext);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, session, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<ClassifySession> id,
+                               @Nonnull final ClassifySession dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validateSession(id, writeContext);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateSession(final InstanceIdentifier<ClassifySession> id,
+                                 @Nonnull final WriteContext writeContext) {
+        final ClassifyTableKey tableKey = id.firstKeyOf(ClassifyTable.class);
+        Preconditions.checkArgument(tableKey != null, "could not find classify table key in {}", id);
+        final String tableName = tableKey.getName();
+        Preconditions.checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()),
+                "Could not find classify table index for {} in the classify table context", tableName);
+    }
+}
index bc5951c..d50dbda 100644 (file)
 
 package io.fd.hc2vpp.vpp.classifier.write;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import com.google.common.base.Optional;
-import com.google.common.base.Preconditions;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
@@ -63,8 +60,8 @@ public class ClassifySessionWriter extends VppNodeWriter
                                  @Nonnull final VppClassifierContextManager classifyTableContext,
                                  @Nonnull final NamingContext policerContext) {
         super(futureJVppCore);
-        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
-        this.policerContext = checkNotNull(policerContext, "policerContext should not be null");
+        this.classifyTableContext = classifyTableContext;
+        this.policerContext = policerContext;
     }
 
     @Override
@@ -106,11 +103,7 @@ public class ClassifySessionWriter extends VppNodeWriter
                                        @Nonnull final WriteContext writeContext)
             throws VppBaseCallException, WriteFailedException {
         final ClassifyTableKey tableKey = id.firstKeyOf(ClassifyTable.class);
-        Preconditions.checkArgument(tableKey != null, "could not find classify table key in {}", id);
-
         final String tableName = tableKey.getName();
-        Preconditions.checkState(classifyTableContext.containsTable(tableName, writeContext.getMappingContext()),
-                "Could not find classify table index for {} in the classify table context", tableName);
         final int tableIndex = classifyTableContext.getTableIndex(tableName, writeContext.getMappingContext());
 
         final ClassifyTable classifyTable = getClassifyTable(writeContext, id, isAdd);
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidator.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidator.java
new file mode 100644 (file)
index 0000000..1ec6131
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTable;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClassifyTableValidator implements Validator<ClassifyTable>, ClassifyWriter {
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<ClassifyTable> id,
+                              @Nonnull final ClassifyTable table,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            validateTable(id, table);
+        } catch (RuntimeException e) {
+            throw new CreateValidationFailedException(id, table, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<ClassifyTable> id,
+                               @Nonnull final ClassifyTable dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            validateTable(id, dataBefore);
+        } catch (RuntimeException e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateTable(final InstanceIdentifier<ClassifyTable> id, final ClassifyTable table) {
+        checkArgument(table.getNbuckets() != null, "nbuckets is a mandatory field and is missing");
+        checkArgument(table.getMemorySize() != null, "memorySize is a mandatory field and is missing");
+        checkArgument(table.getSkipNVectors() != null, "skipNVectors is a mandatory field and is missing");
+        checkArgument(table.getSkipNVectors() != null, "skipNVectors is a mandatory field and is missing");
+        if (table.getMask() != null) {
+            checkArgument(getBinaryVector(table.getMask()).length % 16 == 0,
+                    "Number of mask bytes must be multiple of 16.");
+        }
+    }
+}
index 1b072bf..e1d2241 100644 (file)
@@ -16,7 +16,6 @@
 
 package io.fd.hc2vpp.vpp.classifier.write;
 
-import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.base.Preconditions;
@@ -146,7 +145,6 @@ public class ClassifyTableWriter extends VppNodeWriter
         }
         request.mask = getBinaryVector(table.getMask());
         request.maskLen = request.mask.length;
-        checkArgument(request.mask.length % 16 == 0, "Number of mask bytes must be multiple of 16.");
         request.matchNVectors = request.mask.length / 16;
 
         return request;
index fe66c99..d7ddda4 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.vpp.classifier.write.acl.ingress;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
@@ -44,8 +42,8 @@ public class AclCustomizer extends FutureJVppCustomizer implements WriterCustomi
     public AclCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext,
                          @Nonnull final VppClassifierContextManager classifyTableContext) {
         super(vppApi);
-        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
-        this.classifyTableContext = checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+        this.interfaceContext = interfaceContext;
+        this.classifyTableContext = classifyTableContext;
     }
 
     @Override
diff --git a/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/acl/ingress/AclValidator.java b/vpp-classifier/impl/src/main/java/io/fd/hc2vpp/vpp/classifier/write/acl/ingress/AclValidator.java
new file mode 100644 (file)
index 0000000..7ac576f
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write.acl.ingress;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.AclBaseAttributes;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.vpp.acl.attributes.acl.Ingress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclValidator implements Validator<Ingress> {
+
+    public AclValidator(@Nonnull final NamingContext interfaceContext,
+                        @Nonnull final VppClassifierContextManager classifyTableContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+        checkNotNull(classifyTableContext, "classifyTableContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Ingress> id,
+                              @Nonnull final Ingress acl,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validateAcl(acl);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, acl, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Ingress> id,
+                               @Nonnull final Ingress dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validateAcl(dataBefore);
+        } catch (RuntimeException e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateAcl(@Nonnull final AclBaseAttributes acl) {
+        final L2Acl l2Acl = acl.getL2Acl();
+        if (l2Acl != null) {
+            checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null");
+        }
+        final Ip4Acl ip4Acl = acl.getIp4Acl();
+        if (ip4Acl != null) {
+            checkNotNull(ip4Acl.getClassifyTable(), "IPv4 classify table is null");
+        }
+        final Ip6Acl ip6Acl = acl.getIp6Acl();
+        if (ip6Acl != null) {
+            checkNotNull(ip6Acl.getClassifyTable(), "IPv6 classify table is null");
+        }
+    }
+}
index 2bc4233..18d194a 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.vpp.classifier.write.acl.ingress;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
@@ -51,17 +49,17 @@ interface AclWriter extends ByteDataTranslator, JvppReplyConsumer {
 
         final L2Acl l2Acl = acl.getL2Acl();
         if (l2Acl != null) {
-            final String tableName = checkNotNull(l2Acl.getClassifyTable(), "L2 classify table is null");
+            final String tableName = l2Acl.getClassifyTable();
             request.l2TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext);
         }
         final Ip4Acl ip4Acl = acl.getIp4Acl();
         if (ip4Acl != null) {
-            final String tableName = checkNotNull(ip4Acl.getClassifyTable(), "IPv4 classify table is null");
+            final String tableName = ip4Acl.getClassifyTable();
             request.ip4TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext);
         }
         final Ip6Acl ip6Acl = acl.getIp6Acl();
         if (ip6Acl != null) {
-            final String tableName = checkNotNull(ip6Acl.getClassifyTable(), "IPv6 classify table is null");
+            final String tableName = ip6Acl.getClassifyTable();
             request.ip6TableIndex = classifyTableContext.getTableIndex(tableName, mappingContext);
         }
 
diff --git a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/policer/write/PolicerValidatorTest.java b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/policer/write/PolicerValidatorTest.java
new file mode 100644 (file)
index 0000000..15122bb
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.policer.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.DscpType;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionDrop;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionMarkDscp;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionTransmit;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.MeterActionType;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ConformAction;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ConformActionBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ExceedAction;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ExceedActionBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ViolateAction;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policer.base.attributes.ViolateActionBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policers.Policer;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.policer.rev170315.policers.PolicerBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PolicerValidatorTest {
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final InstanceIdentifier<Policer> POLICER_IID = InstanceIdentifier.create(Policer.class);
+    private static short DSCP = 10;
+    private PolicerValidator validator;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        validator = new PolicerValidator(new NamingContext("testPolicerValidator", "testPolicerValidator"));
+    }
+
+    @Test
+    public void testWriteSuccessfull()
+            throws CreateValidationFailedException {
+        PolicerBuilder builder = generatePrePopulatedPolicerBuilder();
+        validator.validateWrite(POLICER_IID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedDscp()
+            throws CreateValidationFailedException {
+        PolicerBuilder builder = generatePrePopulatedPolicerBuilder();
+        builder.setConformAction(generateConformAction(true, MeterActionDrop.class));
+        validator.validateWrite(POLICER_IID, builder.build(), writeContext);
+    }
+
+    @Test(expected = DeleteValidationFailedException.class)
+    public void testDeleteFailedDscp()
+            throws DeleteValidationFailedException {
+        PolicerBuilder builder = generatePrePopulatedPolicerBuilder();
+        builder.setExceedAction(generateExceedAction(true, MeterActionTransmit.class));
+        validator.validateDelete(POLICER_IID, builder.build(), writeContext);
+    }
+
+    private PolicerBuilder generatePrePopulatedPolicerBuilder() {
+        PolicerBuilder builder = new PolicerBuilder();
+        builder.setConformAction(generateConformAction(true, MeterActionMarkDscp.class))
+                .setExceedAction(generateExceedAction(false, MeterActionTransmit.class))
+                .setViolateAction(generateViolateAction(false, MeterActionDrop.class));
+        return builder;
+    }
+
+    private ExceedAction generateExceedAction(final boolean hasDscp,
+                                              final Class<? extends MeterActionType> actionType) {
+        ExceedActionBuilder builder = new ExceedActionBuilder();
+        if (hasDscp) {
+            builder.setDscp(new DscpType(new Dscp(DSCP)));
+        }
+        builder.setMeterActionType(actionType);
+        return builder.build();
+    }
+
+    private ConformAction generateConformAction(final boolean hasDscp,
+                                                final Class<? extends MeterActionType> actionType) {
+        ConformActionBuilder builder = new ConformActionBuilder();
+        if (hasDscp) {
+            builder.setDscp(new DscpType(new Dscp(DSCP)));
+        }
+        builder.setMeterActionType(actionType);
+        return builder.build();
+    }
+
+    private ViolateAction generateViolateAction(final boolean hasDscp,
+                                                final Class<? extends MeterActionType> actionType) {
+        ViolateActionBuilder builder = new ViolateActionBuilder();
+        if (hasDscp) {
+            builder.setDscp(new DscpType(new Dscp(DSCP)));
+        }
+        builder.setMeterActionType(actionType);
+        return builder.build();
+    }
+}
diff --git a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidatorTest.java b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifySessionValidatorTest.java
new file mode 100644 (file)
index 0000000..c6f50d1
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.classify.table.base.attributes.ClassifySession;
+
+public class ClassifySessionValidatorTest {
+
+    @Mock
+    private WriteContext writeContext;
+    @Mock
+    private VppClassifierContextManager classifyTableContext;
+    @Mock
+    private ClassifySession session;
+
+    private NamingContext policerContext;
+    private ClassifySessionValidator validator;
+
+    private static final String MATCH = "00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00";
+    private static final String TABLE_NAME = "table123";
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        policerContext = new NamingContext("testPolicerContext", "testPolicerContext");
+        validator = new ClassifySessionValidator(classifyTableContext, policerContext);
+    }
+
+    @Test
+    public void testWriteSuccessfull()
+            throws CreateValidationFailedException {
+        when(classifyTableContext.containsTable(eq(TABLE_NAME), any())).thenReturn(true);
+        validator.validateWrite(ClassifySessionWriterTest.getClassifySessionId(TABLE_NAME, MATCH), session,
+                writeContext);
+    }
+
+    @Test(expected = DeleteValidationFailedException.class)
+    public void testDeleteFailedContextMissingTable()
+            throws DeleteValidationFailedException {
+        when(classifyTableContext.containsTable(eq(TABLE_NAME), any())).thenReturn(Boolean.FALSE);
+        validator.validateDelete(ClassifySessionWriterTest.getClassifySessionId(TABLE_NAME, MATCH), session,
+                writeContext);
+    }
+}
index 631ce2e..84bc4d6 100644 (file)
@@ -69,7 +69,7 @@ public class ClassifySessionWriterTest extends WriterCustomizerTest {
         return builder.build();
     }
 
-    private static InstanceIdentifier<ClassifySession> getClassifySessionId(final String tableName,
+    static InstanceIdentifier<ClassifySession> getClassifySessionId(final String tableName,
                                                                             final String match) {
         return InstanceIdentifier.create(VppClassifier.class)
                 .child(ClassifyTable.class, new ClassifyTableKey(tableName))
diff --git a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidatorTest.java b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/ClassifyTableValidatorTest.java
new file mode 100644 (file)
index 0000000..bec9df2
--- /dev/null
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.PacketHandlingAction;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.VppNode;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.VppNodeName;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTable;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTableBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.rev170327.vpp.classifier.ClassifyTableKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.HexString;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class ClassifyTableValidatorTest implements ByteDataTranslator {
+
+    private static final String TABLE_NAME = "table123";
+    private InstanceIdentifier<ClassifyTable> tableIID;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private ClassifyTableValidator validator;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        validator = new ClassifyTableValidator();
+        tableIID = ClassifyTableWriterTest.getClassifyTableId(TABLE_NAME);
+    }
+
+    @Test
+    public void testWriteSuccessfull()
+            throws CreateValidationFailedException {
+        ClassifyTableBuilder builder = generatePrePopulatedClassifyTableBuilder(TABLE_NAME);
+        validator.validateWrite(tableIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedOnEmptyNBuckets()
+            throws CreateValidationFailedException {
+        ClassifyTableBuilder builder = generatePrePopulatedClassifyTableBuilder(TABLE_NAME);
+        builder.setNbuckets(null);
+        validator.validateWrite(tableIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedOnEmptyMemorySize()
+            throws CreateValidationFailedException {
+        ClassifyTableBuilder builder = generatePrePopulatedClassifyTableBuilder(TABLE_NAME);
+        builder.setMemorySize(null);
+        validator.validateWrite(tableIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = DeleteValidationFailedException.class)
+    public void testDeleteFailedOnEmptySkipNVectors()
+            throws DeleteValidationFailedException {
+        ClassifyTableBuilder builder = generatePrePopulatedClassifyTableBuilder(TABLE_NAME);
+        builder.setSkipNVectors(null);
+        validator.validateDelete(tableIID, builder.build(), writeContext);
+    }
+
+    private ClassifyTableBuilder generatePrePopulatedClassifyTableBuilder(final String name) {
+        final ClassifyTableBuilder builder = new ClassifyTableBuilder();
+        builder.setName(name);
+        builder.setClassifierNode(new VppNodeName("ip4-classifier"));
+        builder.withKey(new ClassifyTableKey(name));
+        builder.setSkipNVectors(0L);
+        builder.setNbuckets(2L);
+        builder.setMemorySize(2L << 20);
+        builder.setMissNext(new VppNode(PacketHandlingAction.Permit));
+        builder.setMask(new HexString("00:00:00:00:00:00:01:02:03:04:05:06:00:00:00:00"));
+        return builder;
+    }
+}
index 536a4ae..89082c6 100644 (file)
@@ -66,7 +66,7 @@ public class ClassifyTableWriterTest extends WriterCustomizerTest {
         return builder.build();
     }
 
-    private static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) {
+    static InstanceIdentifier<ClassifyTable> getClassifyTableId(final String name) {
         return InstanceIdentifier.create(VppClassifier.class)
                 .child(ClassifyTable.class, new ClassifyTableKey(name));
     }
diff --git a/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/acl/AclValidatorTest.java b/vpp-classifier/impl/src/test/java/io/fd/hc2vpp/vpp/classifier/write/acl/AclValidatorTest.java
new file mode 100644 (file)
index 0000000..ee4a202
--- /dev/null
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2019 PANTHEON.tech.
+ *
+ * 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 io.fd.hc2vpp.vpp.classifier.write.acl;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.vpp.classifier.context.VppClassifierContextManager;
+import io.fd.hc2vpp.vpp.classifier.write.acl.ingress.AclValidator;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip4Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip4AclBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip6Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.Ip6AclBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.L2Acl;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.acl.base.attributes.L2AclBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.vpp.acl.attributes.acl.Ingress;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.classifier.acl.rev170503.vpp.acl.attributes.acl.IngressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AclValidatorTest {
+
+    @Mock
+    private VppClassifierContextManager classifyTableContext;
+    @Mock
+    private WriteContext writeContext;
+
+    private AclValidator validator;
+    private NamingContext interfaceContext;
+
+    private InstanceIdentifier<Ingress> ingressIID;
+    private static final String ACL_TABLE_NAME = "table0";
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        ingressIID = InstanceIdentifier.create(Ingress.class);
+        interfaceContext = new NamingContext("testAclValidator", "testAclValidator");
+        validator = new AclValidator(interfaceContext, classifyTableContext);
+    }
+
+    @Test
+    public void testWriteSuccessfullL24Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        L2Acl l2Acl = new L2AclBuilder().setClassifyTable(ACL_TABLE_NAME).build();
+        builder.setL2Acl(l2Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedL2Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        L2Acl l2Acl = new L2AclBuilder().setClassifyTable(null).build();
+        builder.setL2Acl(l2Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+
+    @Test
+    public void testWriteSuccessfullIp4Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        Ip4Acl ip42Acl = new Ip4AclBuilder().setClassifyTable(ACL_TABLE_NAME).build();
+        builder.setIp4Acl(ip42Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedIp4Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        Ip4Acl ip42Acl = new Ip4AclBuilder().setClassifyTable(null).build();
+        builder.setIp4Acl(ip42Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+
+    @Test
+    public void testWriteSuccessfullIp6Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        Ip6Acl ip6Acl = new Ip6AclBuilder().setClassifyTable(ACL_TABLE_NAME).build();
+        builder.setIp6Acl(ip6Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedIp6Acl()
+            throws CreateValidationFailedException {
+        final IngressBuilder builder = new IngressBuilder();
+        Ip6Acl ip6Acl = new Ip6AclBuilder().setClassifyTable(null).build();
+        builder.setIp6Acl(ip6Acl);
+        validator.validateWrite(ingressIID, builder.build(), writeContext);
+    }
+}