HC2VPP-381: Validation support for V3PO module 62/19562/9
authorTibor Král <[email protected]>
Tue, 14 May 2019 10:19:44 +0000 (12:19 +0200)
committerMichal Cmarada <[email protected]>
Mon, 27 May 2019 06:25:05 +0000 (08:25 +0200)
Change-Id: If288d97dce15bcc6924d4dd65c640a20920f094d
Signed-off-by: Tibor Král <[email protected]>
57 files changed:
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/InterfacesWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/factory/SubinterfaceAugmentationWriterFactory.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/GreCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/GreValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfacesStatisticsCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfacesStatisticsValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/L2Validator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/LoopbackValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/RewriteCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/RewriteValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2Validator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Validator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VhostUserCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizer.java
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceValidator.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/EthernetCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesValidatorTest.java [new file with mode: 0644]
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/VxlanGpeCustomizerTest.java
v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfacesstate/span/MirroredInterfacesCustomizerTest.java

index 3fbdb9f..4e9f7b9 100644 (file)
@@ -22,20 +22,35 @@ import com.google.inject.name.Named;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
 import io.fd.hc2vpp.v3po.interfaces.AfPacketCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.AfPacketValidator;
 import io.fd.hc2vpp.v3po.interfaces.EthernetCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.EthernetValidator;
 import io.fd.hc2vpp.v3po.interfaces.GreCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.GreValidator;
 import io.fd.hc2vpp.v3po.interfaces.InterfaceCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.InterfaceRoutingCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.InterfaceRoutingValidator;
 import io.fd.hc2vpp.v3po.interfaces.InterfaceUnnumberedCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.InterfaceUnnumberedValidator;
+import io.fd.hc2vpp.v3po.interfaces.InterfaceValidator;
 import io.fd.hc2vpp.v3po.interfaces.InterfacesStatisticsCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.InterfacesStatisticsValidator;
 import io.fd.hc2vpp.v3po.interfaces.L2Customizer;
+import io.fd.hc2vpp.v3po.interfaces.L2Validator;
 import io.fd.hc2vpp.v3po.interfaces.LoopbackCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.LoopbackValidator;
 import io.fd.hc2vpp.v3po.interfaces.TapV2Customizer;
+import io.fd.hc2vpp.v3po.interfaces.TapV2Validator;
 import io.fd.hc2vpp.v3po.interfaces.VhostUserCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.VhostUserValidator;
 import io.fd.hc2vpp.v3po.interfaces.VxlanCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.VxlanGpeCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.VxlanGpeValidator;
+import io.fd.hc2vpp.v3po.interfaces.VxlanValidator;
 import io.fd.hc2vpp.v3po.interfaces.pbb.PbbRewriteCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.pbb.PbbRewriteValidator;
 import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfaceCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfaceValidator;
 import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceStatisticsManager;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
 import io.fd.honeycomb.translate.impl.write.GenericWriter;
@@ -98,9 +113,11 @@ public final class InterfacesWriterFactory implements WriterFactory {
     public void init(final ModifiableWriterRegistryBuilder registry) {
         // Interfaces
         registry.add(new GenericWriter<>(IFCS_ID.augmentation(VppInterfacesStatsAugmentation.class)
-                .child(Statistics.class), new InterfacesStatisticsCustomizer(statisticsManager)));
+                .child(Statistics.class), new InterfacesStatisticsCustomizer(statisticsManager),
+                new InterfacesStatisticsValidator(statisticsManager)));
         //  Interface =
-        registry.add(new GenericListWriter<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingContext)));
+        registry.add(new GenericListWriter<>(IFC_ID, new InterfaceCustomizer(jvpp, ifcNamingContext),
+                new InterfaceValidator(ifcNamingContext)));
         //   VppInterfaceAugmentation
         addVppInterfaceAgmentationWriters(IFC_ID, registry);
 
@@ -111,47 +128,51 @@ public final class InterfacesWriterFactory implements WriterFactory {
                                                    final ModifiableWriterRegistryBuilder registry) {
         // VhostUser(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<VhostUser> vhostId = VPP_IFC_AUG_ID.child(VhostUser.class);
-        registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addBefore(new GenericWriter<>(vhostId, new VhostUserCustomizer(jvpp, ifcNamingContext),
+                new VhostUserValidator(ifcNamingContext)), ifcId);
         // AfPacket(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<AfPacket> afpacketId = VPP_IFC_AUG_ID.child(AfPacket.class);
-        registry.addBefore(new GenericWriter<>(afpacketId, new AfPacketCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addBefore(new GenericWriter<>(afpacketId, new AfPacketCustomizer(jvpp, ifcNamingContext),
+                new AfPacketValidator(ifcNamingContext)), ifcId);
         // Vxlan(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Vxlan> vxlanId = VPP_IFC_AUG_ID.child(Vxlan.class);
-        registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext)),
+        registry.addBefore(new GenericWriter<>(vxlanId, new VxlanCustomizer(jvpp, ifcNamingContext, ifcDisableContext),
+                        new VxlanValidator(ifcNamingContext, ifcDisableContext)),
                 ifcId);
         // VxlanGpe(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<VxlanGpe> vxlanGpeId = VPP_IFC_AUG_ID.child(VxlanGpe.class);
         registry.addBefore(new GenericWriter<>(vxlanGpeId,
-                new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext)), ifcId);
+                new VxlanGpeCustomizer(jvpp, ifcNamingContext, ifcDisableContext),
+                new VxlanGpeValidator(ifcNamingContext, ifcDisableContext)), ifcId);
         // TapV2(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<TapV2> tapV2Id = VPP_IFC_AUG_ID.child(TapV2.class);
-        registry.addBefore(new GenericWriter<>(tapV2Id, new TapV2Customizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addBefore(new GenericWriter<>(tapV2Id, new TapV2Customizer(jvpp, ifcNamingContext),
+                new TapV2Validator(ifcNamingContext)), ifcId);
         // Loopback(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Loopback> loopbackId = VPP_IFC_AUG_ID.child(Loopback.class);
-        registry.addBefore(new GenericWriter<>(loopbackId, new LoopbackCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addBefore(new GenericWriter<>(loopbackId, new LoopbackCustomizer(jvpp, ifcNamingContext),
+                new LoopbackValidator(ifcNamingContext)), ifcId);
 
         // Gre(Needs to be executed before Interface customizer) =
         final InstanceIdentifier<Gre> greId = VPP_IFC_AUG_ID.child(Gre.class);
-        registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addBefore(new GenericWriter<>(greId, new GreCustomizer(jvpp, ifcNamingContext),
+                new GreValidator(ifcNamingContext)), ifcId);
 
         final Set<InstanceIdentifier<?>> specificIfcTypes =
                 Sets.newHashSet(vhostId, afpacketId, vxlanId, vxlanGpeId, tapV2Id, loopbackId);
 
         // Ethernet =
         registry.add(new GenericWriter<>(VPP_IFC_AUG_ID.child(Ethernet.class),
-                new EthernetCustomizer(jvpp, ifcNamingContext)));
+                new EthernetCustomizer(jvpp, ifcNamingContext), new EthernetValidator(ifcNamingContext)));
         // Routing(Execute only after specific interface customizers) =
         registry.addAfter(
                 new GenericWriter<>(VPP_IFC_AUG_ID.child(Routing.class),
-                        new InterfaceRoutingCustomizer(jvpp, ifcNamingContext)),
+                        new InterfaceRoutingCustomizer(jvpp, ifcNamingContext),
+                        new InterfaceRoutingValidator(ifcNamingContext)),
                 specificIfcTypes);
         // L2(Execute only after subinterface (and all other ifc types) =
-        registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcNamingContext, bdNamingContext)),
+        registry.addAfter(new GenericWriter<>(L2_ID, new L2Customizer(jvpp, ifcNamingContext, bdNamingContext),
+                        new L2Validator(ifcNamingContext, bdNamingContext)),
                 SubinterfaceAugmentationWriterFactory.SUB_IFC_ID);
 
         // Span writers
@@ -161,13 +182,15 @@ public final class InterfacesWriterFactory implements WriterFactory {
                 .child(MirroredInterfaces.class)
                 .child(MirroredInterface.class);
         registry.addAfter(new GenericWriter<>(mirroredIfcId, new MirroredInterfaceCustomizer(jvpp, ifcNamingContext,
-                id -> id.firstKeyOf(Interface.class).getName())), ifcId);
+                        id -> id.firstKeyOf(Interface.class).getName()),
+                        new MirroredInterfaceValidator(ifcNamingContext, id -> id.firstKeyOf(Interface.class).getName())),
+                ifcId);
 
         // Unnumbered =
         final InstanceIdentifier<Unnumbered> unnumberedId =
                 IFC_ID.augmentation(InterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
-        registry.addAfter(new GenericWriter<>(unnumberedId, new InterfaceUnnumberedCustomizer(jvpp, ifcNamingContext)),
-                ifcId);
+        registry.addAfter(new GenericWriter<>(unnumberedId, new InterfaceUnnumberedCustomizer(jvpp, ifcNamingContext),
+                new InterfaceUnnumberedValidator(ifcNamingContext)), ifcId);
     }
 
     private void addPbbAugmentationWriters(final InstanceIdentifier<Interface> ifcId,
@@ -175,6 +198,7 @@ public final class InterfacesWriterFactory implements WriterFactory {
         final InstanceIdentifier<PbbRewrite> pbbRewriteId =
                 ifcId.augmentation(PbbRewriteInterfaceAugmentation.class).child(PbbRewrite.class);
 
-        registry.add(new GenericWriter<>(pbbRewriteId, new PbbRewriteCustomizer(jvpp, ifcNamingContext)));
+        registry.add(new GenericWriter<>(pbbRewriteId, new PbbRewriteCustomizer(jvpp, ifcNamingContext),
+                new PbbRewriteValidator(ifcNamingContext)));
     }
 }
index cdcd070..237eab5 100644 (file)
@@ -21,10 +21,15 @@ import com.google.inject.Inject;
 import com.google.inject.name.Named;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.hc2vpp.v3po.interfaces.RewriteCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.RewriteValidator;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceCustomizer;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceL2Customizer;
+import io.fd.hc2vpp.v3po.interfaces.SubInterfaceL2Validator;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceRoutingCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.SubInterfaceRoutingValidator;
 import io.fd.hc2vpp.v3po.interfaces.SubInterfaceUnnumberedCustomizer;
+import io.fd.hc2vpp.v3po.interfaces.SubInterfaceUnnumberedValidator;
+import io.fd.hc2vpp.v3po.interfaces.SubInterfaceValidator;
 import io.fd.hc2vpp.v3po.interfaces.span.MirroredInterfaceCustomizer;
 import io.fd.hc2vpp.v3po.util.SubInterfaceUtils;
 import io.fd.honeycomb.translate.impl.write.GenericListWriter;
@@ -59,11 +64,11 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor
     private final NamingContext bdContext;
 
     public static final InstanceIdentifier<SubinterfaceAugmentation> SUB_IFC_AUG_ID =
-        InterfacesWriterFactory.IFC_ID.augmentation(SubinterfaceAugmentation.class);
+            InterfacesWriterFactory.IFC_ID.augmentation(SubinterfaceAugmentation.class);
     public static final InstanceIdentifier<SubInterface> SUB_IFC_ID =
-        SUB_IFC_AUG_ID.child(SubInterfaces.class).child(SubInterface.class);
+            SUB_IFC_AUG_ID.child(SubInterfaces.class).child(SubInterface.class);
     public static final InstanceIdentifier<L2> L2_ID = SUB_IFC_ID.child(
-        L2.class);
+            L2.class);
 
     @Inject
     public SubinterfaceAugmentationWriterFactory(final FutureJVppCore jvpp,
@@ -79,31 +84,35 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor
         // Subinterfaces
         //  Subinterface(Handle only after all interface related stuff gets processed) =
         registry.subtreeAddAfter(
-            // TODO HONEYCOMB-188 this customizer covers quite a lot of complex child nodes (maybe refactor ?)
-            Sets.newHashSet(
-                InstanceIdentifier.create(SubInterface.class).child(Tags.class),
-                InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class),
-                InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(
-                    Dot1qTag.class),
-                InstanceIdentifier.create(SubInterface.class).child(Match.class),
-                InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)),
-            new GenericListWriter<>(SUB_IFC_ID, new SubInterfaceCustomizer(jvpp, ifcContext)),
-            InterfacesWriterFactory.IFC_ID);
+                // TODO HONEYCOMB-188 this customizer covers quite a lot of complex child nodes (maybe refactor ?)
+                Sets.newHashSet(
+                        InstanceIdentifier.create(SubInterface.class).child(Tags.class),
+                        InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class),
+                        InstanceIdentifier.create(SubInterface.class).child(Tags.class).child(Tag.class).child(
+                                Dot1qTag.class),
+                        InstanceIdentifier.create(SubInterface.class).child(Match.class),
+                        InstanceIdentifier.create(SubInterface.class).child(Match.class).child(VlanTagged.class)),
+                new GenericListWriter<>(SUB_IFC_ID, new SubInterfaceCustomizer(jvpp, ifcContext),
+                        new SubInterfaceValidator(ifcContext)),
+                InterfacesWriterFactory.IFC_ID);
         //   L2 =
-        registry.addAfter(new GenericWriter<>(L2_ID, new SubInterfaceL2Customizer(jvpp, ifcContext, bdContext)),
-            SUB_IFC_ID);
+        registry.addAfter(new GenericWriter<>(L2_ID, new SubInterfaceL2Customizer(jvpp, ifcContext, bdContext),
+                        new SubInterfaceL2Validator(ifcContext, bdContext)),
+                SUB_IFC_ID);
         //    Rewrite(also handles pushTags + pushTags/dot1qtag) =
         final InstanceIdentifier<Rewrite> rewriteId = L2_ID.child(Rewrite.class);
         registry.subtreeAddAfter(
-            Sets.newHashSet(
-                InstanceIdentifier.create(Rewrite.class).child(PushTags.class),
-                InstanceIdentifier.create(Rewrite.class).child(PushTags.class)
-                    .child(
-                        org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)),
-            new GenericWriter<>(rewriteId, new RewriteCustomizer(jvpp, ifcContext)),
-            L2_ID);
+                Sets.newHashSet(
+                        InstanceIdentifier.create(Rewrite.class).child(PushTags.class),
+                        InstanceIdentifier.create(Rewrite.class).child(PushTags.class)
+                                .child(
+                                        org.opendaylight.yang.gen.v1.urn.ieee.params.xml.ns.yang.dot1q.types.rev150626.dot1q.tag.Dot1qTag.class)),
+                new GenericWriter<>(rewriteId, new RewriteCustomizer(jvpp, ifcContext),
+                        new RewriteValidator(ifcContext)),
+                L2_ID);
         final InstanceIdentifier<Routing> routingId = SUB_IFC_ID.child(Routing.class);
-        registry.add(new GenericWriter<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcContext)));
+        registry.add(new GenericWriter<>(routingId, new SubInterfaceRoutingCustomizer(jvpp, ifcContext),
+                new SubInterfaceRoutingValidator(ifcContext)));
 
         final InstanceIdentifier<MirroredInterface> mirroredId =
                 SUB_IFC_ID.augmentation(VppSubinterfaceSpanAugmentation.class)
@@ -116,8 +125,9 @@ public final class SubinterfaceAugmentationWriterFactory implements WriterFactor
 
         // Unnumbered =
         final InstanceIdentifier<Unnumbered> unnumberedId =
-            SUB_IFC_ID.augmentation(SubinterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
-        registry.addAfter(new GenericWriter<>(unnumberedId, new SubInterfaceUnnumberedCustomizer(jvpp, ifcContext)),
-            SUB_IFC_ID);
+                SUB_IFC_ID.augmentation(SubinterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
+        registry.addAfter(new GenericWriter<>(unnumberedId, new SubInterfaceUnnumberedCustomizer(jvpp, ifcContext),
+                        new SubInterfaceUnnumberedValidator(ifcContext)),
+                SUB_IFC_ID);
     }
 }
index ecb4f8c..ea4220a 100644 (file)
@@ -16,9 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.MacTranslator;
@@ -49,7 +46,7 @@ public class AfPacketCustomizer extends AbstractInterfaceTypeCustomizer<AfPacket
 
     public AfPacketCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext) {
         super(vppApi);
-        this.interfaceContext = checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.interfaceContext = interfaceContext;
     }
 
     @Override
@@ -92,12 +89,7 @@ public class AfPacketCustomizer extends AbstractInterfaceTypeCustomizer<AfPacket
 
     private AfPacketCreate getCreateRequest(@Nonnull final AfPacket afPacket) {
         final AfPacketCreate request = new AfPacketCreate();
-        checkArgument(afPacket.getHostInterfaceName() != null,
-            "host-interface-name is mandatory for af-packet interface");
         request.hostIfName = afPacket.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
-        checkArgument(request.hostIfName.length <= 64,
-            "Interface name for af_packet interface should not be longer than 64 bytes, but was %s",
-            request.hostIfName.length);
         final PhysAddress mac = afPacket.getMac();
         if (mac == null) {
             request.useRandomHwAddr = 1;
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidator.java
new file mode 100644 (file)
index 0000000..f76922c
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.v3po.interfaces;
+
+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.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.nio.charset.StandardCharsets;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketValidator implements Validator<AfPacket> {
+
+    public AfPacketValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            validateAfPacket(dataAfter);
+        } catch (Exception e) {
+            throw new CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataBefore,
+                               @Nonnull final AfPacket dataAfter, @Nonnull final WriteContext writeContext)
+            throws UpdateValidationFailedException {
+        try {
+            validateAfPacket(dataAfter);
+        } catch (Exception e) {
+            throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<AfPacket> id, @Nonnull final AfPacket dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            validateAfPacket(dataBefore);
+        } catch (Exception e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateAfPacket(final AfPacket data) {
+        checkNotNull(data.getHostInterfaceName(), "host-interface-name is mandatory for af-packet interface");
+        byte[] hostIfName = data.getHostInterfaceName().getBytes(StandardCharsets.UTF_8);
+        checkArgument(hostIfName.length <= 64,
+                "Interface name for af_packet interface should not be longer than 64 bytes, but was %s",
+                hostIfName.length);
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidator.java
new file mode 100644 (file)
index 0000000..e8fa32a
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EthernetValidator implements Validator<Ethernet> {
+
+    public EthernetValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Ethernet> id, @Nonnull final Ethernet dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        checkNotNull(dataAfter.getMtu(), "MTU cannot be null");
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Ethernet> id, @Nonnull final Ethernet dataBefore,
+                               @Nonnull final Ethernet dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        checkNotNull(dataAfter.getMtu(), "MTU cannot be null");
+    }
+}
index 3496fdd..b133881 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
 import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
 import io.fd.hc2vpp.common.translate.util.AddressTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -125,15 +123,7 @@ public class GreCustomizer extends AbstractInterfaceTypeCustomizer<Gre> implemen
     }
 
     private boolean isIpv6(final Gre gre) {
-        if (gre.getSrc().getIpv4AddressNoZone() == null) {
-            checkArgument(gre.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s", gre.getSrc(),
-                    gre.getDst());
-            return true;
-        } else {
-            checkArgument(gre.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s", gre.getSrc(),
-                    gre.getDst());
-            return false;
-        }
+        return gre.getSrc().getIpv4AddressNoZone() == null;
     }
 
     private void deleteGreTunnel(final InstanceIdentifier<Gre> id, final String swIfName, final Gre gre,
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/GreValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/GreValidator.java
new file mode 100644 (file)
index 0000000..9376ab8
--- /dev/null
@@ -0,0 +1,72 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GreValidator implements Validator<Gre> {
+
+    public GreValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validateGre(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Gre> id, @Nonnull final Gre dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validateGre(dataBefore);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateGre(final Gre data) {
+        checkNotNull(data.getOuterFibId(), "Outer Fib ID cannot be null");
+        checkNotNull(data.getSrc(), "Source cannot be null");
+        checkNotNull(data.getDst(), "Destination cannot be null");
+        if (data.getSrc().getIpv4AddressNoZone() == null) {
+            checkArgument(data.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getSrc(),
+                    data.getDst());
+        } else {
+            checkArgument(data.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getSrc(),
+                    data.getDst());
+        }
+    }
+}
index 30885fc..e498e0c 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkState;
-
-import java.util.Optional;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
-import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.jvpp.core.future.FutureJVppCore;
-import java.util.List;
 import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class InterfaceRoutingCustomizer extends RoutingCustomizer
@@ -46,10 +38,6 @@ public class InterfaceRoutingCustomizer extends RoutingCustomizer
     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id,
                                        @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-
-        checkState(isAddressNotPresentForInterface(id, writeContext, true),
-                "Cannot change routing configuration, if address is present for interface");
-
         final String ifName = id.firstKeyOf(Interface.class).getName();
         setRouting(id, ifName, dataAfter, writeContext);
     }
@@ -59,9 +47,6 @@ public class InterfaceRoutingCustomizer extends RoutingCustomizer
                                         @Nonnull final Routing dataBefore, @Nonnull final Routing dataAfter,
                                         @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-        checkState(isAddressNotPresentForInterface(id, writeContext, true),
-                "Cannot change routing configuration, if address is present for interface");
-
         final String ifName = id.firstKeyOf(Interface.class).getName();
         setRouting(id, ifName, dataAfter, writeContext);
     }
@@ -70,35 +55,7 @@ public class InterfaceRoutingCustomizer extends RoutingCustomizer
     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> id,
                                         @Nonnull final Routing dataBefore, @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-        checkState(isAddressNotPresentForInterface(id, writeContext, false),
-                "Cannot change routing configuration, if address is present for interface");
-
         final String ifName = id.firstKeyOf(Interface.class).getName();
         disableRouting(id, ifName, writeContext);
     }
-
-    /**
-     * Returns true if interface does not have v4/v6 addresses configured
-     */
-    private boolean isAddressNotPresentForInterface(@Nonnull final InstanceIdentifier<Routing> id,
-                                                    @Nonnull final WriteContext ctx,
-                                                    boolean checkBefore) {
-        final Optional<Interface> interfaceData = checkBefore
-                ? ctx.readBefore(RWUtils.cutId(id, Interface.class))
-                : ctx.readAfter(RWUtils.cutId(id, Interface.class));
-
-        if (interfaceData.isPresent()) {
-            final java.util.Optional<Interface1> augData = java.util.Optional.of(interfaceData.get())
-                    .map(iface -> iface.augmentation(Interface1.class));
-
-            final boolean v4NotPresent =
-                    augData.map(Interface1::getIpv4).map(Ipv4::getAddress).map(List::isEmpty).orElse(true);
-
-            final boolean v6NotPresent =
-                    augData.map(Interface1::getIpv6).map(Ipv6::getAddress).map(List::isEmpty).orElse(true);
-
-            return v4NotPresent && v6NotPresent;
-        }
-        return true;
-    }
 }
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidator.java
new file mode 100644 (file)
index 0000000..0117726
--- /dev/null
@@ -0,0 +1,118 @@
+/*
+ * 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.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.RoutingBaseAttributes;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingValidator implements Validator<Routing> {
+
+    public InterfaceRoutingValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            checkVrfIds(dataAfter);
+            checkInterfaceAddressConf(id, writeContext, true);
+        } catch (Exception e) {
+            throw new CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+                               @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
+            throws UpdateValidationFailedException {
+        try {
+            checkVrfIds(dataAfter);
+            checkInterfaceAddressConf(id, writeContext, true);
+        } catch (Exception e) {
+            throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            checkVrfIds(dataBefore);
+            checkInterfaceAddressConf(id, writeContext, false);
+        } catch (Exception e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void checkVrfIds(final RoutingBaseAttributes data) {
+        checkArgument(data.getIpv4VrfId() != null || data.getIpv6VrfId() != null, "No vrf-id given");
+    }
+
+    private void checkInterfaceAddressConf(@Nonnull final InstanceIdentifier<Routing> id,
+                                           @Nonnull final WriteContext ctx,
+                                           boolean checkBefore) {
+        checkState(isAddressNotPresentForInterface(id, ctx, checkBefore),
+                "Cannot change routing configuration, if address is present for interface");
+    }
+
+    /**
+     * Returns true if interface does not have v4/v6 addresses configured
+     */
+    private boolean isAddressNotPresentForInterface(@Nonnull final InstanceIdentifier<Routing> id,
+                                                    @Nonnull final WriteContext ctx,
+                                                    boolean checkBefore) {
+        final Optional<Interface> interfaceData = checkBefore
+                ? ctx.readBefore(RWUtils.cutId(id, Interface.class))
+                : ctx.readAfter(RWUtils.cutId(id, Interface.class));
+
+        if (interfaceData.isPresent()) {
+            final java.util.Optional<Interface1> augData = java.util.Optional.of(interfaceData.get())
+                    .map(iface -> iface.augmentation(Interface1.class));
+
+            final boolean v4NotPresent =
+                    augData.map(Interface1::getIpv4).map(Ipv4::getAddress).map(List::isEmpty).orElse(true);
+
+            final boolean v6NotPresent =
+                    augData.map(Interface1::getIpv6).map(Ipv6::getAddress).map(List::isEmpty).orElse(true);
+
+            return v4NotPresent && v6NotPresent;
+        }
+        return true;
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidator.java
new file mode 100644 (file)
index 0000000..0120582
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceUnnumberedValidator implements Validator<Unnumbered> {
+
+    public InterfaceUnnumberedValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        checkNotNull(dataAfter.getUse(), "Use cannot be null");
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+                               @Nonnull final Unnumbered dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        checkNotNull(dataAfter.getUse(), "Use cannot be null");
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        checkNotNull(dataBefore.getUse(), "Use cannot be null");
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidator.java
new file mode 100644 (file)
index 0000000..3e6ed63
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * 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.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+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.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceValidator implements Validator<Interface> {
+
+    public InterfaceValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            checkInterface(dataAfter);
+        } catch (Exception e) {
+            throw new CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataBefore,
+                               @Nonnull final Interface dataAfter, @Nonnull final WriteContext writeContext)
+            throws UpdateValidationFailedException {
+        try {
+            checkInterface(dataAfter);
+        } catch (Exception e) {
+            throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Interface> id, @Nonnull final Interface dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            checkInterface(dataBefore);
+        } catch (Exception e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void checkInterface(final Interface data) {
+        checkNotNull(data.isEnabled(), "Enabled tag cannot be null");
+        checkNotNull(data.getName(), "Name cannot be null");
+    }
+}
index b67eccd..e7ef14d 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceStatisticsManager;
 import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
 import io.fd.honeycomb.translate.write.WriteContext;
@@ -26,13 +24,12 @@ import javax.annotation.Nonnull;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces.Statistics;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
-public class InterfacesStatisticsCustomizer implements
-        WriterCustomizer<Statistics> {
+public class InterfacesStatisticsCustomizer implements WriterCustomizer<Statistics> {
 
     private final InterfaceStatisticsManager statisticsManager;
 
     public InterfacesStatisticsCustomizer(final InterfaceStatisticsManager statisticsManager) {
-        this.statisticsManager = checkNotNull(statisticsManager, "Statistics Collection Manager should not be null");
+        this.statisticsManager = statisticsManager;
     }
 
     @Override
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfacesStatisticsValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/InterfacesStatisticsValidator.java
new file mode 100644 (file)
index 0000000..00c58b5
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import io.fd.hc2vpp.v3po.interfacesstate.cache.InterfaceStatisticsManager;
+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.v3po.rev190502.interfaces.Statistics;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfacesStatisticsValidator implements Validator<Statistics> {
+
+    public InterfacesStatisticsValidator(final InterfaceStatisticsManager statisticsManager) {
+        checkNotNull(statisticsManager, "Statistics Collection Manager should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataBefore,
+                               @Nonnull final Statistics dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Statistics> id, @Nonnull final Statistics dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/L2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/L2Validator.java
new file mode 100644 (file)
index 0000000..3c59bd9
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.L2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class L2Validator implements Validator<L2> {
+
+    public L2Validator(final NamingContext interfaceContext,
+                       final NamingContext bridgeDomainContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+        checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+                               @Nonnull final L2 dataAfter,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/LoopbackValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/LoopbackValidator.java
new file mode 100644 (file)
index 0000000..57f1eb1
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.Loopback;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class LoopbackValidator implements Validator<Loopback> {
+
+    public LoopbackValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataBefore,
+                               @Nonnull final Loopback dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Loopback> id, @Nonnull final Loopback dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
index 2c350eb..169dd99 100644 (file)
@@ -16,7 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import com.google.common.base.Preconditions;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -55,7 +54,7 @@ public class RewriteCustomizer extends FutureJVppCustomizer
     public RewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
                              @Nonnull final NamingContext interfaceContext) {
         super(futureJVppCore);
-        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.interfaceContext = interfaceContext;
     }
 
     @Override
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/RewriteValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/RewriteValidator.java
new file mode 100644 (file)
index 0000000..e867a10
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.vpp.vlan.rev180319.rewrite.attributes.Rewrite;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class RewriteValidator implements Validator<Rewrite> {
+
+    public RewriteValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataBefore,
+                               @Nonnull final Rewrite dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Rewrite> id, @Nonnull final Rewrite dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
index d3688d8..8814475 100644 (file)
@@ -20,7 +20,6 @@ import static com.google.common.base.Preconditions.checkState;
 import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getNumberOfTags;
 import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.getSubInterfaceName;
 
-import com.google.common.base.Preconditions;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -65,7 +64,7 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer
     public SubInterfaceCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
                                   @Nonnull final NamingContext interfaceContext) {
         super(futureJVppCore);
-        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.interfaceContext = interfaceContext;
     }
 
     @Override
@@ -116,8 +115,8 @@ public class SubInterfaceCustomizer extends FutureJVppCustomizer
         // TODO HONEYCOMB-183 match should be mandatory
         final MatchType matchType = subInterface.getMatch().getMatchType();
         request.exactMatch = booleanToByte(
-            matchType instanceof VlanTagged
-                && ((VlanTagged) matchType).getVlanTagged().isMatchExactTags()
+                matchType instanceof VlanTagged
+                        && ((VlanTagged) matchType).getVlanTagged().isMatchExactTags()
         );
         request.defaultSub = booleanToByte(matchType instanceof Default);
         if (numberOfTags > 0) {
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceL2Validator.java
new file mode 100644 (file)
index 0000000..3a2ed5d
--- /dev/null
@@ -0,0 +1,58 @@
+/*
+ * 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.v3po.interfaces;
+
+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.vpp.vlan.rev180319.sub._interface.l2.config.attributes.L2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceL2Validator implements Validator<L2> {
+
+    public SubInterfaceL2Validator(final NamingContext interfaceContext,
+                                   final NamingContext bridgeDomainContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+        checkNotNull(bridgeDomainContext, "bridgeDomainContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+                               @Nonnull final L2 dataAfter,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<L2> id, @Nonnull final L2 dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
index fbaccfa..951944a 100644 (file)
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkState;
 import static io.fd.hc2vpp.v3po.util.SubInterfaceUtils.subInterfaceFullNameConfig;
 
-import java.util.Optional;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
 import io.fd.honeycomb.translate.spi.write.WriterCustomizer;
-import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.honeycomb.translate.write.WriteContext;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.jvpp.core.future.FutureJVppCore;
-import java.util.List;
 import javax.annotation.Nonnull;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
@@ -45,8 +38,6 @@ public class SubInterfaceRoutingCustomizer extends RoutingCustomizer implements
     public void writeCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
                                        @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-        checkState(isAddressNotPresentForSubInterface(instanceIdentifier, writeContext, true),
-                "Cannot change routing configuration, if address is present for sub-interface");
         setRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), routing, writeContext);
     }
 
@@ -54,8 +45,6 @@ public class SubInterfaceRoutingCustomizer extends RoutingCustomizer implements
     public void updateCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
                                         @Nonnull final Routing routing, @Nonnull final Routing d1,
                                         @Nonnull final WriteContext writeContext) throws WriteFailedException {
-        checkState(isAddressNotPresentForSubInterface(instanceIdentifier, writeContext, true),
-                "Cannot change routing configuration, if address is present for sub-interface");
         setRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), routing, writeContext);
     }
 
@@ -63,35 +52,6 @@ public class SubInterfaceRoutingCustomizer extends RoutingCustomizer implements
     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Routing> instanceIdentifier,
                                         @Nonnull final Routing routing, @Nonnull final WriteContext writeContext)
             throws WriteFailedException {
-        checkState(isAddressNotPresentForSubInterface(instanceIdentifier, writeContext, false),
-                "Cannot change routing configuration, if address is present for sub-interface");
         disableRouting(instanceIdentifier, subInterfaceFullNameConfig(instanceIdentifier), writeContext);
     }
-
-    /**
-     * Returns true if interface does not have v4/v6 addresses configured
-     */
-    private boolean isAddressNotPresentForSubInterface(@Nonnull final InstanceIdentifier<Routing> id,
-                                                       @Nonnull final WriteContext ctx,
-                                                       boolean checkBefore) {
-        final Optional<SubInterface> subInterfaceData = checkBefore
-                ?
-                ctx.readBefore(RWUtils.cutId(id, SubInterface.class))
-                :
-                        ctx.readAfter(RWUtils.cutId(id, SubInterface.class));
-
-        if (subInterfaceData.isPresent()) {
-            final SubInterface subInterface = subInterfaceData.get();
-
-            final boolean v4NotPresent =
-                    java.util.Optional.ofNullable(subInterface.getIpv4()).map(Ipv4::getAddress).map(List::isEmpty)
-                            .orElse(true);
-
-            final boolean v6NotPresent =
-                    java.util.Optional.ofNullable(subInterface.getIpv6()).map(Ipv6::getAddress).map(List::isEmpty)
-                            .orElse(true);
-            return v4NotPresent && v6NotPresent;
-        }
-        return true;
-    }
 }
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidator.java
new file mode 100644 (file)
index 0000000..85b864d
--- /dev/null
@@ -0,0 +1,110 @@
+/*
+ * 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.v3po.interfaces;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.Validator;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.List;
+import java.util.Optional;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingValidator implements Validator<Routing> {
+
+    public SubInterfaceRoutingValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            checkInterfaceAddressConf(id, writeContext, true);
+        } catch (Exception e) {
+            throw new CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+                               @Nonnull final Routing dataAfter, @Nonnull final WriteContext writeContext)
+            throws UpdateValidationFailedException {
+        try {
+            checkInterfaceAddressConf(id, writeContext, true);
+        } catch (Exception e) {
+            throw new UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Routing> id, @Nonnull final Routing dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            checkInterfaceAddressConf(id, writeContext, false);
+        } catch (Exception e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void checkInterfaceAddressConf(@Nonnull final InstanceIdentifier<Routing> id,
+                                           @Nonnull final WriteContext ctx,
+                                           boolean checkBefore) {
+        checkState(isAddressNotPresentForSubInterface(id, ctx, checkBefore),
+                "Cannot change routing configuration, if address is present for sub-interface");
+    }
+
+    /**
+     * Returns true if interface does not have v4/v6 addresses configured
+     */
+    private boolean isAddressNotPresentForSubInterface(@Nonnull final InstanceIdentifier<Routing> id,
+                                                       @Nonnull final WriteContext ctx,
+                                                       boolean checkBefore) {
+        final Optional<SubInterface> subInterfaceData = checkBefore
+                ?
+                ctx.readBefore(RWUtils.cutId(id, SubInterface.class))
+                :
+                        ctx.readAfter(RWUtils.cutId(id, SubInterface.class));
+
+        if (subInterfaceData.isPresent()) {
+            final SubInterface subInterface = subInterfaceData.get();
+
+            final boolean v4NotPresent =
+                    java.util.Optional.ofNullable(subInterface.getIpv4()).map(Ipv4::getAddress).map(List::isEmpty)
+                            .orElse(true);
+
+            final boolean v6NotPresent =
+                    java.util.Optional.ofNullable(subInterface.getIpv6()).map(Ipv6::getAddress).map(List::isEmpty)
+                            .orElse(true);
+            return v4NotPresent && v6NotPresent;
+        }
+        return true;
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidator.java
new file mode 100644 (file)
index 0000000..8cc565c
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceUnnumberedValidator implements Validator<Unnumbered> {
+
+    public SubInterfaceUnnumberedValidator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        checkNotNull(dataAfter.getUse());
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+                               @Nonnull final Unnumbered dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        checkNotNull(dataAfter.getUse());
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Unnumbered> id, @Nonnull final Unnumbered dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        checkNotNull(dataBefore.getUse());
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidator.java
new file mode 100644 (file)
index 0000000..0f8a862
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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.v3po.interfaces;
+
+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.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceValidator implements Validator<SubInterface> {
+
+    public SubInterfaceValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<SubInterface> id, @Nonnull final SubInterface dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            checkSubInterface(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<SubInterface> id,
+                               @Nonnull final SubInterface dataBefore,
+                               @Nonnull final SubInterface dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        try {
+            checkSubInterface(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    private void checkSubInterface(final SubInterface data) {
+        checkNotNull(data.getIdentifier(), "Identifier cannot be null");
+        checkNotNull(data.getMatch(), "Match cannot be null");
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Validator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/TapV2Validator.java
new file mode 100644 (file)
index 0000000..0d3c3ef
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.TapV2;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class TapV2Validator implements Validator<TapV2> {
+
+    public TapV2Validator(final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataBefore,
+                               @Nonnull final TapV2 dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        // there is nothing to validate yet
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<TapV2> id, @Nonnull final TapV2 dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
index c009e71..61ce546 100644 (file)
@@ -16,7 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import com.google.common.base.Preconditions;
 import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -52,7 +51,7 @@ public class VhostUserCustomizer extends AbstractInterfaceTypeCustomizer<VhostUs
 
     public VhostUserCustomizer(@Nonnull final FutureJVppCore vppApi, @Nonnull final NamingContext interfaceContext) {
         super(vppApi);
-        this.interfaceContext = Preconditions.checkNotNull(interfaceContext, "interfaceContext should not be null");
+        this.interfaceContext = interfaceContext;
     }
 
     @Override
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidator.java
new file mode 100644 (file)
index 0000000..5526bbb
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VhostUserValidator implements Validator<VhostUser> {
+
+    public VhostUserValidator(@Nonnull final NamingContext interfaceContext) {
+        checkNotNull(interfaceContext, "interfaceContext should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        checkNotNull(dataAfter.getSocket(), "Socket cannot be null");
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataBefore,
+                               @Nonnull final VhostUser dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        checkNotNull(dataAfter.getSocket(), "Socket cannot be null");
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<VhostUser> id, @Nonnull final VhostUser dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        // there is nothing to validate yet
+    }
+}
index fba4394..638d7ec 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
 import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
 import io.fd.hc2vpp.common.translate.util.AddressTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -49,8 +47,8 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> impl
     private final DisabledInterfacesManager interfaceDisableContext;
 
     public VxlanCustomizer(@Nonnull final FutureJVppCore vppApi,
-            @Nonnull final NamingContext interfaceNamingContext,
-            @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
+                           @Nonnull final NamingContext interfaceNamingContext,
+                           @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
         super(vppApi);
         this.interfaceNamingContext = interfaceNamingContext;
         this.interfaceDisableContext = interfaceDisableContext;
@@ -63,29 +61,27 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> impl
 
     @Override
     protected final void writeInterface(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataAfter,
-            @Nonnull final WriteContext writeContext)
-                    throws WriteFailedException {
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
         final String swIfName = id.firstKeyOf(Interface.class).getName();
         createVxlanTunnel(id, swIfName, dataAfter, writeContext);
     }
 
     @Override
     public void deleteCurrentAttributes(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataBefore,
-            @Nonnull final WriteContext writeContext)
-                    throws WriteFailedException {
+                                        @Nonnull final WriteContext writeContext)
+            throws WriteFailedException {
         final String swIfName = id.firstKeyOf(Interface.class).getName();
         deleteVxlanTunnel(id, swIfName, dataBefore, writeContext);
     }
 
     private void createVxlanTunnel(final InstanceIdentifier<Vxlan> id, final String swIfName, final Vxlan vxlan,
-            final WriteContext writeContext)
-                    throws WriteFailedException {
+                                   final WriteContext writeContext)
+            throws WriteFailedException {
         final byte isIpv6 = (byte) (isIpv6(vxlan)
-            ? 1
-            : 0);
+                ? 1
+                : 0);
 
-        checkArgument(vxlan.getEncapVrfId() != null && vxlan.getEncapVrfId().getValue() != null,
-            "encap-vrf-id is mandatory but was not given");
         int encapVrfId = vxlan.getEncapVrfId().getValue().intValue();
         int vni = vxlan.getVni().getValue().intValue();
 
@@ -98,8 +94,8 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> impl
 
         LOG.debug("Setting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
         final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
-            getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, vxlan.getSrc(),
-                vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
+                getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 1 /* is add */, vxlan.getSrc(),
+                        vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
 
         final VxlanAddDelTunnelReply reply =
                 getReplyForCreate(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, vxlan);
@@ -131,25 +127,16 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> impl
     }
 
     private boolean isIpv6(final Vxlan vxlan) {
-        if (vxlan.getSrc().getIpv4AddressNoZone() == null) {
-            checkArgument(vxlan.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s", vxlan.getSrc(),
-                    vxlan.getDst());
-            return true;
-        } else {
-            checkArgument(vxlan.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s", vxlan.getSrc(),
-                    vxlan.getDst());
-            return false;
-        }
+        return vxlan.getSrc().getIpv4AddressNoZone() == null;
+
     }
 
     private void deleteVxlanTunnel(final InstanceIdentifier<Vxlan> id, final String swIfName, final Vxlan vxlan,
-            final WriteContext writeContext) throws WriteFailedException {
+                                   final WriteContext writeContext) throws WriteFailedException {
         final byte isIpv6 = (byte) (isIpv6(vxlan)
-            ? 1
-            : 0);
+                ? 1
+                : 0);
 
-        checkArgument(vxlan.getEncapVrfId() != null && vxlan.getEncapVrfId().getValue() != null,
-            "encap-vrf-id is mandatory but was not given");
         int encapVrfId = vxlan.getEncapVrfId().getValue().intValue();
         int vni = vxlan.getVni().getValue().intValue();
 
@@ -162,8 +149,8 @@ public class VxlanCustomizer extends AbstractInterfaceTypeCustomizer<Vxlan> impl
 
         LOG.debug("Deleting vxlan tunnel for interface: {}. Vxlan: {}", swIfName, vxlan);
         final CompletionStage<VxlanAddDelTunnelReply> vxlanAddDelTunnelReplyCompletionStage =
-            getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 0 /* is add */, vxlan.getSrc(),
-                vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
+                getFutureJVpp().vxlanAddDelTunnel(getVxlanTunnelRequest((byte) 0 /* is add */, vxlan.getSrc(),
+                        vxlan.getDst(), encapVrfId, decapNext, vni, isIpv6));
 
         getReplyForDelete(vxlanAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
         LOG.debug("Vxlan tunnel deleted successfully for: {}, vxlan: {}", swIfName, vxlan);
index d61f50b..b362941 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces;
 
-import static com.google.common.base.Preconditions.checkArgument;
-
 import io.fd.hc2vpp.common.translate.util.AbstractInterfaceTypeCustomizer;
 import io.fd.hc2vpp.common.translate.util.AddressTranslator;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
@@ -90,8 +88,9 @@ public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe
 
         LOG.debug("Setting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
         final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
-            getFutureJVpp().vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, vxlanGpe.getLocal(),
-                vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
+                getFutureJVpp()
+                        .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 1 /* is add */, vxlanGpe.getLocal(),
+                                vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
 
         final VxlanGpeAddDelTunnelReply reply =
                 getReplyForCreate(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id, vxlanGpe);
@@ -115,17 +114,8 @@ public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe
     }
 
     private boolean isIpv6(final VxlanGpe vxlanGpe) {
-        if (vxlanGpe.getLocal().getIpv4AddressNoZone() == null) {
-            checkArgument(vxlanGpe.getRemote().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
-                    vxlanGpe.getLocal(),
-                    vxlanGpe.getRemote());
-            return true;
-        } else {
-            checkArgument(vxlanGpe.getRemote().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
-                    vxlanGpe.getLocal(),
-                    vxlanGpe.getRemote());
-            return false;
-        }
+        return vxlanGpe.getLocal().getIpv4AddressNoZone() == null;
+
     }
 
     private void deleteVxlanGpeTunnel(final InstanceIdentifier<VxlanGpe> id, final String swIfName,
@@ -143,8 +133,8 @@ public class VxlanGpeCustomizer extends AbstractInterfaceTypeCustomizer<VxlanGpe
         LOG.debug("Deleting VxlanGpe tunnel for interface: {}. VxlanGpe: {}", swIfName, vxlanGpe);
         final CompletionStage<VxlanGpeAddDelTunnelReply> VxlanGpeAddDelTunnelReplyCompletionStage =
                 getFutureJVpp()
-                    .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, vxlanGpe.getLocal(),
-                        vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
+                        .vxlanGpeAddDelTunnel(getVxlanGpeTunnelRequest((byte) 0 /* is delete */, vxlanGpe.getLocal(),
+                                vxlanGpe.getRemote(), vni, protocol, encapVrfId, decapVrfId, isIpv6));
         getReplyForDelete(VxlanGpeAddDelTunnelReplyCompletionStage.toCompletableFuture(), id);
         final int index = interfaceNamingContext.getIndex(swIfName, writeContext.getMappingContext());
         // Mark this interface as disabled to not include it in operational reads
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidator.java
new file mode 100644 (file)
index 0000000..22b5365
--- /dev/null
@@ -0,0 +1,78 @@
+/*
+ * 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.v3po.interfaces;
+
+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.hc2vpp.v3po.DisabledInterfacesManager;
+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.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanGpeValidator implements Validator<VxlanGpe> {
+
+    public VxlanGpeValidator(@Nonnull final NamingContext interfaceNamingContext,
+                             @Nonnull final DisabledInterfacesManager interfaceDisableContext) {
+        checkNotNull(interfaceNamingContext, "interfaceContext should not be null");
+        checkNotNull(interfaceDisableContext, "DisabledInterfacesManager should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validateVxlanGpe(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<VxlanGpe> id, @Nonnull final VxlanGpe dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validateVxlanGpe(dataBefore);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateVxlanGpe(final VxlanGpe data) {
+        checkNotNull(data.getLocal(), "Local address cannot be null");
+        checkNotNull(data.getRemote(), "Remote address cannot be null");
+        if (data.getLocal().getIpv4AddressNoZone() == null) {
+            checkArgument(data.getRemote().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getLocal(),
+                    data.getRemote());
+        } else {
+            checkArgument(data.getRemote().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getLocal(),
+                    data.getRemote());
+        }
+        checkNotNull(data.getEncapVrfId(), "encap-vrf-id is mandatory but was not given");
+        checkNotNull(data.getDecapVrfId(), "decap-vrf-id is mandatory but was not given");
+        checkNotNull(data.getVni(), "VNI cannot be null");
+        checkNotNull(data.getNextProtocol(), "Next protocol cannot be null");
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidator.java
new file mode 100644 (file)
index 0000000..1496a88
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.v3po.interfaces;
+
+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.hc2vpp.v3po.DisabledInterfacesManager;
+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.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanValidator implements Validator<Vxlan> {
+
+    public VxlanValidator(@Nonnull final NamingContext interfaceNamingContext,
+                          @Nonnull final DisabledInterfacesManager disabledInterfacesManager) {
+        checkNotNull(interfaceNamingContext, "interfaceContext should not be null");
+        checkNotNull(disabledInterfacesManager, "disabledInterfacesManager should not be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws CreateValidationFailedException {
+        try {
+            validateVxlan(dataAfter);
+        } catch (Exception e) {
+            throw new CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<Vxlan> id, @Nonnull final Vxlan dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DeleteValidationFailedException {
+        try {
+            validateVxlan(dataBefore);
+        } catch (Exception e) {
+            throw new DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validateVxlan(final Vxlan data) {
+
+        checkNotNull(data.getSrc(), "Source cannot be null");
+        checkNotNull(data.getDst(), "Destination cannot be null");
+        if (data.getSrc().getIpv4AddressNoZone() == null) {
+            checkArgument(data.getDst().getIpv4AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getSrc(),
+                    data.getDst());
+        } else {
+            checkArgument(data.getDst().getIpv6AddressNoZone() == null, "Inconsistent ip addresses: %s, %s",
+                    data.getSrc(),
+                    data.getDst());
+        }
+        checkArgument(data.getEncapVrfId() != null && data.getEncapVrfId().getValue() != null,
+                "encap-vrf-id is mandatory but was not given");
+        checkNotNull(data.getVni(), "VNI cannot be null");
+    }
+}
index 13fccf7..8662266 100644 (file)
@@ -16,8 +16,6 @@
 
 package io.fd.hc2vpp.v3po.interfaces.pbb;
 
-import static com.google.common.base.Preconditions.checkNotNull;
-
 import io.fd.hc2vpp.common.translate.util.FutureJVppCustomizer;
 import io.fd.hc2vpp.common.translate.util.JvppReplyConsumer;
 import io.fd.hc2vpp.common.translate.util.MacTranslator;
@@ -44,7 +42,7 @@ public class PbbRewriteCustomizer extends FutureJVppCustomizer
     public PbbRewriteCustomizer(@Nonnull final FutureJVppCore futureJVppCore,
                                 @Nonnull final NamingContext interfaceNamingContext) {
         super(futureJVppCore);
-        this.interfaceNamingContext = checkNotNull(interfaceNamingContext, "Interface naming context cannot be null");
+        this.interfaceNamingContext = interfaceNamingContext;
     }
 
     @Override
@@ -84,16 +82,16 @@ public class PbbRewriteCustomizer extends FutureJVppCustomizer
     private void setPbbRewrite(final InstanceIdentifier<PbbRewrite> id, final PbbRewrite data,
                                final WriteContext writeContext, final boolean disable)
             throws TimeoutException, VppBaseCallException {
-        final String interfaceName = checkNotNull(id.firstKeyOf(Interface.class), "Interface key not found").getName();
+        final String interfaceName = id.firstKeyOf(Interface.class).getName();
 
         final L2InterfacePbbTagRewrite request = new L2InterfacePbbTagRewrite();
 
         //checking all attributes in preconditions(pbb-rewrite is subcontainer, so there can't be mandatory statements)
         request.swIfIndex = interfaceNamingContext.getIndex(interfaceName, writeContext.getMappingContext());
-        request.bDmac = parseMac(verifiedDestinationAddress(data));
-        request.bSmac = parseMac(verifiedSourceAddress(data));
-        request.bVlanid = verifiedBVlanId(data);
-        request.iSid = verifiedISid(data);
+        request.bDmac = parseMac(data.getDestinationAddress().getValue());
+        request.bSmac = parseMac(data.getSourceAddress().getValue());
+        request.bVlanid = data.getBVlanTagVlanId().shortValue();
+        request.iSid = data.getITagIsid().intValue();
         request.vtrOp = verifiedOperation(data, disable);
 
         //not sure whats gonna happen to this attribute, so its left optional for now
@@ -104,27 +102,10 @@ public class PbbRewriteCustomizer extends FutureJVppCustomizer
         getReply(getFutureJVpp().l2InterfacePbbTagRewrite(request).toCompletableFuture());
     }
 
-    private String verifiedDestinationAddress(final PbbRewrite data) {
-        return checkNotNull(data.getDestinationAddress(), "Destination address cannot be null").getValue();
-    }
-
-    private String verifiedSourceAddress(final PbbRewrite data) {
-        return checkNotNull(data.getSourceAddress(), "Destination address cannot be null").getValue();
-    }
-
-    private short verifiedBVlanId(final PbbRewrite data) {
-        return checkNotNull(data.getBVlanTagVlanId(), "BVlan id cannot be null").shortValue();
-    }
-
-    private int verifiedISid(final PbbRewrite data) {
-        return checkNotNull(data.getITagIsid(), "ISid cannot be null").intValue();
-    }
-
     // if disabled ,then uses non-public allowed value 0, which is equal to operation disable
     private int verifiedOperation(final PbbRewrite data, final boolean disable) {
-
         return disable
                 ? OPERATION_DISABLE
-                : checkNotNull(data.getInterfaceOperation(), "Operation cannot be null").getIntValue();
+                : data.getInterfaceOperation().getIntValue();
     }
 }
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidator.java
new file mode 100644 (file)
index 0000000..e5ec7fc
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.v3po.interfaces.pbb;
+
+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.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteValidator implements Validator<PbbRewrite> {
+
+
+    public PbbRewriteValidator(@Nonnull final NamingContext interfaceNamingContext) {
+        checkNotNull(interfaceNamingContext, "Interface naming context cannot be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            validatePbbRewrite(id, dataAfter, false);
+        } catch(Exception e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataBefore,
+                               @Nonnull final PbbRewrite dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+
+        try {
+            validatePbbRewrite(id, dataAfter, false);
+        } catch(Exception e) {
+            throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            validatePbbRewrite(id, dataBefore, true);
+        } catch(Exception e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void validatePbbRewrite(final InstanceIdentifier<PbbRewrite> id, @Nonnull final PbbRewrite data,
+                                    final boolean disable) {
+        checkNotNull(id.firstKeyOf(Interface.class), "Interface key not found");
+        checkNotNull(data.getDestinationAddress(), "Destination address cannot be null");
+        checkNotNull(data.getSourceAddress(), "Source address cannot be null");
+        checkNotNull(data.getBVlanTagVlanId(), "BVlan id cannot be null");
+        checkNotNull(data.getITagIsid(), "ISid cannot be null");
+        if (disable) {
+            checkNotNull(data.getInterfaceOperation(), "Operation cannot be null");
+        }
+    }
+}
diff --git a/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceValidator.java b/v3po/v3po2vpp/src/main/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfaceValidator.java
new file mode 100644 (file)
index 0000000..f51ad6f
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.v3po.interfaces.span;
+
+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 java.util.function.Function;
+import javax.annotation.Nonnull;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MirroredInterfaceValidator implements Validator<MirroredInterface> {
+
+    public MirroredInterfaceValidator(@Nonnull final NamingContext ifcContext,
+                                      @Nonnull final Function<InstanceIdentifier<MirroredInterfaces>, String> destinationInterfaceNameExtractor) {
+        checkNotNull(ifcContext, "Interface naming context cannot be null");
+        checkNotNull(destinationInterfaceNameExtractor, "Destination Interface Name extractor cannot be null");
+    }
+
+    @Override
+    public void validateWrite(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+                              @Nonnull final MirroredInterface dataAfter,
+                              @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.CreateValidationFailedException {
+        try {
+            checkMirroredInterfaceData(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.CreateValidationFailedException(id, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateUpdate(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+                               @Nonnull final MirroredInterface dataBefore,
+                               @Nonnull final MirroredInterface dataAfter, @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        try {
+            checkMirroredInterfaceData(dataAfter);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.UpdateValidationFailedException(id, dataBefore, dataAfter, e);
+        }
+    }
+
+    @Override
+    public void validateDelete(@Nonnull final InstanceIdentifier<MirroredInterface> id,
+                               @Nonnull final MirroredInterface dataBefore,
+                               @Nonnull final WriteContext writeContext)
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        try {
+            checkMirroredInterfaceData(dataBefore);
+        } catch (Exception e) {
+            throw new DataValidationFailedException.DeleteValidationFailedException(id, e);
+        }
+    }
+
+    private void checkMirroredInterfaceData(final MirroredInterface data) {
+        checkNotNull(data.getIfaceRef(), "IfaceRef cannot be null");
+        checkNotNull(data.getState(), "State cannot be null");
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/AfPacketValidatorTest.java
new file mode 100644 (file)
index 0000000..ebdc770
--- /dev/null
@@ -0,0 +1,88 @@
+/*
+ * 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.v3po.interfaces;
+
+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.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacket;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.AfPacketBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class AfPacketValidatorTest {
+
+    private AfPacketValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private final String IFACE_NAME = "veth1";
+    private final InstanceIdentifier<AfPacket> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(AfPacket.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new AfPacketValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, afPacket(IFACE_NAME), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoHostName() throws CreateValidationFailedException {
+        validator.validateWrite(ID, afPacket(null), writeContext);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testWriteFailedLongHostName() throws CreateValidationFailedException {
+        validator.validateWrite(ID,
+                afPacket(IntStream.range(1, 64).boxed().map(i -> i.toString()).collect(Collectors.joining(","))),
+                writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        validator.validateUpdate(ID, afPacket(IFACE_NAME), afPacket(IFACE_NAME), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, afPacket(IFACE_NAME), writeContext);
+    }
+
+    private AfPacket afPacket(String name) {
+        return new AfPacketBuilder().setHostInterfaceName(name).build();
+    }
+}
index 18ec661..f7befc4 100644 (file)
@@ -29,7 +29,6 @@ import io.fd.jvpp.core.dto.HwInterfaceSetMtuReply;
 import org.junit.Test;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.EthernetBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.iana._if.type.rev180703.EthernetCsmacd;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
@@ -57,7 +56,7 @@ public class EthernetCustomizerTest extends WriterCustomizerTest {
     public void testWrite() throws WriteFailedException {
         when(api.hwInterfaceSetMtu(any())).thenReturn(future(new HwInterfaceSetMtuReply()));
         final int mtu = 1234;
-        customizer.writeCurrentAttributes(IF_IID, ethernet(mtu), writeContext);
+        customizer.writeCurrentAttributes(IF_IID, EthernetValidatorTest.ethernet(mtu), writeContext);
         verify(api).hwInterfaceSetMtu(mtuSetRequest(mtu));
     }
 
@@ -65,7 +64,7 @@ public class EthernetCustomizerTest extends WriterCustomizerTest {
     public void testUpdate() throws WriteFailedException {
         when(api.hwInterfaceSetMtu(any())).thenReturn(future(new HwInterfaceSetMtuReply()));
         final int mtu = 5678;
-        customizer.updateCurrentAttributes(IF_IID, mock(Ethernet.class), ethernet(mtu), writeContext);
+        customizer.updateCurrentAttributes(IF_IID, mock(Ethernet.class), EthernetValidatorTest.ethernet(mtu), writeContext);
         verify(api).hwInterfaceSetMtu(mtuSetRequest(mtu));
     }
 
@@ -80,11 +79,4 @@ public class EthernetCustomizerTest extends WriterCustomizerTest {
     public void testDelete() throws WriteFailedException {
         customizer.deleteCurrentAttributes(IF_IID, mock(Ethernet.class), writeContext);
     }
-
-    private static Ethernet ethernet(final int mtu) {
-        final EthernetBuilder ethernet = new EthernetBuilder();
-        ethernet.setMtu(mtu);
-        return ethernet.build();
-    }
-
 }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/EthernetValidatorTest.java
new file mode 100644 (file)
index 0000000..ce639d2
--- /dev/null
@@ -0,0 +1,76 @@
+/*
+ * 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.v3po.interfaces;
+
+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.UpdateValidationFailedException;
+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.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Ethernet;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.EthernetBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class EthernetValidatorTest {
+
+    private EthernetValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth0";
+    private static final int IF_MTU = 1234;
+    private static final InstanceIdentifier<Ethernet> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME)).augmentation(
+                    VppInterfaceAugmentation.class).child(Ethernet.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new EthernetValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, ethernet(IF_MTU), writeContext);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteFailedNoMTU() throws CreateValidationFailedException {
+        validator.validateWrite(ID, ethernet(null), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        validator.validateUpdate(ID, ethernet(IF_MTU), ethernet(IF_MTU + 1), writeContext);
+    }
+
+    static Ethernet ethernet(final Integer mtu) {
+        final EthernetBuilder ethernet = new EthernetBuilder();
+        ethernet.setMtu(mtu);
+        return ethernet.build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/GreValidatorTest.java
new file mode 100644 (file)
index 0000000..e7f786b
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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.v3po.interfaces;
+
+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.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Gre;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.GreBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class GreValidatorTest {
+
+    private GreValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IPV6 = "a::100";
+    private static final String IPV4_1 = "192.168.20.10";
+    private static final String IPV4_2 = "192.168.20.11";
+    private static final Long OUT_FIB_ID = Long.valueOf(123);
+    private static final String IFACE_NAME = "eth0";
+    private static final InstanceIdentifier<Gre> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(Gre.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new GreValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateCorrectGre(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedMixedIpv4Ipv6() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateGre(ip4(IPV4_1), ip6(IPV6), OUT_FIB_ID), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoSrcAddr() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateGre(null, ip6(IPV6), OUT_FIB_ID), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoDstAddr() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateGre(ip4(IPV4_1), null, OUT_FIB_ID), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoOutFibId() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateGre(ip4(IPV4_1), ip4(IPV4_2), null), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, generateCorrectGre(), writeContext);
+    }
+
+    private Gre generateCorrectGre() {
+        return generateGre(ip4(IPV4_1), ip4(IPV4_2), OUT_FIB_ID);
+    }
+
+    private Gre generateGre(final IpAddressNoZone srcAddr, final IpAddressNoZone dstAddr, final Long outerFibId) {
+        final GreBuilder builder = new GreBuilder();
+        builder.setSrc(srcAddr);
+        builder.setDst(dstAddr);
+        builder.setOuterFibId(outerFibId);
+        return builder.build();
+    }
+
+    private IpAddressNoZone ip4(String addr) {
+        return new IpAddressNoZone(new Ipv4AddressNoZone(addr));
+    }
+
+    private IpAddressNoZone ip6(String addr) {
+        return new IpAddressNoZone(new Ipv6AddressNoZone(addr));
+    }
+}
index a3028ac..533c627 100644 (file)
@@ -20,14 +20,12 @@ import static org.mockito.Matchers.any;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Optional;
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.NamingContext;
-import io.fd.honeycomb.translate.util.RWUtils;
 import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.jvpp.core.dto.SwInterfaceSetTable;
 import io.fd.jvpp.core.dto.SwInterfaceSetTableReply;
-import java.util.Collections;
+import java.util.Optional;
 import org.junit.Test;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
@@ -37,11 +35,6 @@ import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1Builder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4Builder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6Builder;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressBuilder;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class InterfaceRoutingCustomizerTest extends WriterCustomizerTest {
@@ -76,52 +69,16 @@ public class InterfaceRoutingCustomizerTest extends WriterCustomizerTest {
         customizer.writeCurrentAttributes(IID, routing(213), writeContext);
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testWriteFailedIpv4Present() throws WriteFailedException {
-        when(writeContext.readBefore(RWUtils.cutId(IID, Interface.class)))
-                .thenReturn(Optional.of(ifaceWithV4Address()));
-        customizer.writeCurrentAttributes(IID, routing(213), writeContext);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testWriteFailedIpv6Present() throws WriteFailedException {
-        when(writeContext.readBefore(RWUtils.cutId(IID, Interface.class)))
-                .thenReturn(Optional.of(ifaceWithV6Address()));
-        customizer.writeCurrentAttributes(IID, routing(213), writeContext);
-    }
-
     @Test
     public void testWriteEmptyIfaceData() throws WriteFailedException {
-        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(new InterfaceBuilder().build()));
+        when(writeContext.readBefore(any(InstanceIdentifier.class)))
+                .thenReturn(Optional.of(new InterfaceBuilder().build()));
         final int vrfId = 123;
         when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
         customizer.writeCurrentAttributes(IID, routing(vrfId), writeContext);
         verify(api).swInterfaceSetTable(expectedRequest(vrfId));
     }
 
-    private static Interface ifaceWithV4Address() {
-        return new InterfaceBuilder()
-                .addAugmentation(Interface1.class, new Interface1Builder()
-                        .setIpv4(new Ipv4Builder()
-                                .setAddress(Collections.singletonList(new AddressBuilder().build()))
-                                .build())
-                        .build())
-                .build();
-    }
-
-
-    private static Interface ifaceWithV6Address() {
-        return new InterfaceBuilder()
-                .addAugmentation(Interface1.class, new Interface1Builder()
-                        .setIpv6(new Ipv6Builder()
-                                .setAddress(Collections.singletonList(
-                                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.AddressBuilder()
-                                                .build()))
-                                .build())
-                        .build())
-                .build();
-    }
-
     @Test(expected = WriteFailedException.class)
     public void testUpdateFailed() throws WriteFailedException {
         when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceRoutingValidatorTest.java
new file mode 100644 (file)
index 0000000..e10aba4
--- /dev/null
@@ -0,0 +1,146 @@
+/*
+ * 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.v3po.interfaces;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.util.RWUtils;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.CreateValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.DeleteValidationFailedException;
+import io.fd.honeycomb.translate.write.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.Interface1Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv4.AddressBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceRoutingValidatorTest {
+
+    private InterfaceRoutingValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth1";
+    private static final Long VRF_ID = Long.valueOf(123);
+
+    private static final InstanceIdentifier<Routing> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(Routing.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new InterfaceRoutingValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoFrfIds() throws CreateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateWrite(ID, routing(null, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedWithV4Address() throws CreateValidationFailedException {
+        when(writeContext.readBefore(RWUtils.cutId(ID, Interface.class)))
+                .thenReturn(Optional.of(ifaceWithV4Address()));
+        validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedWithV6Address() throws CreateValidationFailedException {
+        when(writeContext.readBefore(RWUtils.cutId(ID, Interface.class)))
+                .thenReturn(Optional.of(ifaceWithV6Address()));
+        validator.validateWrite(ID, routing(VRF_ID, true, false), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateUpdate(ID, routing(VRF_ID, true, false),
+                routing(VRF_ID, true, true), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateDelete(ID, routing(VRF_ID, true, false), writeContext);
+    }
+
+    private Routing routing(final Long vrfId, final boolean hasIpv4, final boolean hasIpv6) {
+        VniReference vni = null;
+        if (vrfId != null) {
+            vni = new VniReference(vrfId);
+        }
+
+        RoutingBuilder builder = new RoutingBuilder();
+        if (hasIpv4) {
+            builder.setIpv4VrfId(vni);
+        }
+        if (hasIpv6) {
+            builder.setIpv6VrfId(vni);
+        }
+        return builder.build();
+    }
+
+    private Interface ifaceWithV4Address() {
+        return new InterfaceBuilder()
+                .addAugmentation(Interface1.class, new Interface1Builder()
+                        .setIpv4(new Ipv4Builder()
+                                .setAddress(Collections.singletonList(new AddressBuilder().build()))
+                                .build())
+                        .build())
+                .build();
+    }
+
+    private Interface ifaceWithV6Address() {
+        return new InterfaceBuilder()
+                .addAugmentation(Interface1.class, new Interface1Builder()
+                        .setIpv6(new Ipv6Builder()
+                                .setAddress(Collections.singletonList(
+                                        new org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.ip.rev140616.interfaces._interface.ipv6.AddressBuilder()
+                                                .build()))
+                                .build())
+                        .build())
+                .build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceUnnumberedValidatorTest.java
new file mode 100644 (file)
index 0000000..79b3f91
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.v3po.interfaces;
+
+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.DataValidationFailedException.UpdateValidationFailedException;
+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.unnumbered.interfaces.rev180103.InterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.UnnumberedBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceUnnumberedValidatorTest {
+
+    private InterfaceUnnumberedValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth2";
+    private static final String TARGET_IFC0_NAME = "eth0";
+    private static final InstanceIdentifier<Unnumbered> ID = InstanceIdentifier.create(Interfaces.class)
+            .child(Interface.class, new InterfaceKey(IF_NAME))
+            .augmentation(InterfaceUnnumberedAugmentation.class)
+            .child(Unnumbered.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new InterfaceUnnumberedValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteFailedNoUse() throws CreateValidationFailedException {
+        validator.validateWrite(ID, getUnnumberedIfc(null), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        validator.validateUpdate(ID, getUnnumberedIfc(TARGET_IFC0_NAME), getUnnumberedIfc(TARGET_IFC0_NAME),
+                writeContext);
+    }
+
+    @Test
+    public void testDeleteeSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+    }
+
+    private Unnumbered getUnnumberedIfc(String use) {
+        return new UnnumberedBuilder().setUse(use).build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/InterfaceValidatorTest.java
new file mode 100644 (file)
index 0000000..21de26f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.v3po.interfaces;
+
+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.DataValidationFailedException.UpdateValidationFailedException;
+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.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class InterfaceValidatorTest {
+
+    private InterfaceValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth0";
+    private static final InstanceIdentifier<Interface> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME));
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new InterfaceValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, getInterface(true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoName() throws CreateValidationFailedException {
+        validator.validateWrite(ID, getInterface(null, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoEnableFlag() throws CreateValidationFailedException {
+        validator.validateWrite(ID, getInterface(null), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        validator.validateUpdate(ID, getInterface(true), getInterface(true), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, getInterface(true), writeContext);
+    }
+
+    private Interface getInterface(final String name, final Boolean enabled) {
+        return new InterfaceBuilder().setName(name).setEnabled(enabled).build();
+    }
+
+    private Interface getInterface(final Boolean enabled) {
+        return new InterfaceBuilder().setName(IF_NAME).setEnabled(enabled).build();
+    }
+}
index 6c6a2be..37a185d 100644 (file)
@@ -95,13 +95,13 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
         return tag.build();
     }
 
-    private static Match generateMatch() {
+    static Match generateMatch() {
         final MatchBuilder match = new MatchBuilder();
         final VlanTaggedBuilder tagged = new VlanTaggedBuilder();
         tagged.setMatchExactTags(true);
         match.setMatchType(
-            new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.VlanTaggedBuilder()
-                .setVlanTagged(tagged.build()).build());
+                new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.match.attributes.match.type.VlanTaggedBuilder()
+                        .setVlanTagged(tagged.build()).build());
         return match.build();
     }
 
@@ -136,8 +136,8 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
         request.twoTags = 1;
         request.innerVlanId = innerVlanId;
         request.innerVlanIdAny = (byte) (isInnerAny
-            ? 1
-            : 0);
+                ? 1
+                : 0);
         request.dot1Ad = 1;
         request.outerVlanId = STAG_ID;
         request.exactMatch = 1;
@@ -153,8 +153,8 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
 
     private InstanceIdentifier<SubInterface> getSubInterfaceId(final String name, final long index) {
         return InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(name)).augmentation(
-            SubinterfaceAugmentation.class).child(SubInterfaces.class)
-            .child(SubInterface.class, new SubInterfaceKey(index));
+                SubinterfaceAugmentation.class).child(SubInterfaces.class)
+                .child(SubInterface.class, new SubInterfaceKey(index));
     }
 
     private void whenCreateSubifThenSuccess() {
@@ -173,7 +173,7 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
     }
 
     private SwInterfaceSetFlags verifySwInterfaceSetFlagsWasInvoked(final SwInterfaceSetFlags expected)
-        throws VppBaseCallException {
+            throws VppBaseCallException {
         ArgumentCaptor<SwInterfaceSetFlags> argumentCaptor = ArgumentCaptor.forClass(SwInterfaceSetFlags.class);
         verify(api).swInterfaceSetFlags(argumentCaptor.capture());
         final SwInterfaceSetFlags actual = argumentCaptor.getValue();
@@ -195,8 +195,8 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
 
         verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
         verify(mappingContext)
-            .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
-                mapping(SUB_IFACE_NAME, 0).get()));
+                .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
+                        mapping(SUB_IFACE_NAME, 0).get()));
     }
 
     @Test
@@ -211,8 +211,8 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
 
         verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ANY_ID, true));
         verify(mappingContext)
-            .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
-                mapping(SUB_IFACE_NAME, 0).get()));
+                .put(eq(mappingIid(SUB_IFACE_NAME, IFC_TEST_INSTANCE)), eq(
+                        mapping(SUB_IFACE_NAME, 0).get()));
     }
 
     @Test
@@ -228,8 +228,8 @@ public class SubInterfaceCustomizerTest extends WriterCustomizerTest {
             assertTrue(e.getCause() instanceof VppBaseCallException);
             verify(api).createSubif(generateSubInterfaceRequest(SUPER_IF_ID, CTAG_ID, false));
             verify(mappingContext, times(0)).put(
-                eq(mappingIid(SUPER_IF_NAME, IFC_TEST_INSTANCE)),
-                eq(mapping(SUPER_IF_NAME, 0).get()));
+                    eq(mappingIid(SUPER_IF_NAME, IFC_TEST_INSTANCE)),
+                    eq(mapping(SUPER_IF_NAME, 0).get()));
             return;
         }
         fail("WriteFailedException.CreateFailedException was expected");
index 5732d58..90c9d66 100644 (file)
@@ -21,7 +21,6 @@ import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import java.util.Optional;
 import com.google.common.collect.ImmutableSet;
 import io.fd.hc2vpp.common.test.write.WriterCustomizerTest;
 import io.fd.hc2vpp.common.translate.util.ByteDataTranslator;
@@ -30,6 +29,7 @@ import io.fd.honeycomb.translate.write.WriteFailedException;
 import io.fd.jvpp.core.dto.SwInterfaceSetTable;
 import io.fd.jvpp.core.dto.SwInterfaceSetTableReply;
 import java.util.Collections;
+import java.util.Optional;
 import java.util.Set;
 import org.junit.Test;
 import org.mockito.ArgumentCaptor;
@@ -38,11 +38,7 @@ import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.managem
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4Builder;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.ipv4.AddressBuilder;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6Builder;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.RoutingBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
@@ -80,20 +76,6 @@ public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest impl
         when(api.swInterfaceSetTable(any())).thenReturn(future(new SwInterfaceSetTableReply()));
     }
 
-    @Test(expected = IllegalStateException.class)
-    public void testWriteFailedV4AddressPresent() throws WriteFailedException {
-        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v4AddressPresent()));
-        final Routing v4Routing = new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
-        customizer.writeCurrentAttributes(VALID_ID, v4Routing, writeContext);
-    }
-
-    @Test(expected = IllegalStateException.class)
-    public void testWriteFailedV6AddressPresent() throws WriteFailedException {
-        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v6AddressPresent()));
-        final Routing v4Routing = new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
-        customizer.writeCurrentAttributes(VALID_ID, v4Routing, writeContext);
-    }
-
     @Test
     public void testWriteIpv4Vrf() throws WriteFailedException {
         when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
@@ -102,7 +84,6 @@ public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest impl
         verifySetTableRequest(1, Collections.singleton(request(false, SUBIF_INDEX, 4)));
     }
 
-
     @Test
     public void testWriteIpv6Vrf() throws WriteFailedException {
         when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
@@ -115,9 +96,9 @@ public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest impl
     public void testUpdateIpv4Vrf() throws WriteFailedException {
         when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
         final Routing routingBefore = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
-            .setIpv4VrfId(new VniReference(4L)).build();
+                .setIpv4VrfId(new VniReference(4L)).build();
         final Routing routingAfter = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
-            .setIpv4VrfId(new VniReference(5L)).build();
+                .setIpv4VrfId(new VniReference(5L)).build();
         customizer.updateCurrentAttributes(VALID_ID, routingBefore, routingAfter, writeContext);
         verifySetTableRequest(2, ImmutableSet.of(request(false, SUBIF_INDEX, 5),
                 request(true, SUBIF_INDEX, 3)));
@@ -127,9 +108,9 @@ public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest impl
     public void testUpdateIpv6Vrf() throws WriteFailedException {
         when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
         final Routing routingBefore = new RoutingBuilder().setIpv6VrfId(new VniReference(3L))
-            .setIpv4VrfId(new VniReference(4L)).build();
+                .setIpv4VrfId(new VniReference(4L)).build();
         final Routing routingAfter = new RoutingBuilder().setIpv6VrfId(new VniReference(8L))
-            .setIpv4VrfId(new VniReference(4L)).build();
+                .setIpv4VrfId(new VniReference(4L)).build();
         customizer.updateCurrentAttributes(VALID_ID, routingBefore, routingAfter, writeContext);
         verifySetTableRequest(2, ImmutableSet.of(request(false, SUBIF_INDEX, 4),
                 request(true, SUBIF_INDEX, 8)));
@@ -164,20 +145,4 @@ public class SubInterfaceRoutingCustomizerTest extends WriterCustomizerTest impl
         verify(api, times(times)).swInterfaceSetTable(requestCaptor.capture());
         requestCaptor.getAllValues().containsAll(requests);
     }
-
-    private static SubInterface v4AddressPresent() {
-        return new SubInterfaceBuilder()
-                .setIpv4(new Ipv4Builder()
-                        .setAddress(Collections.singletonList(new AddressBuilder().build()))
-                        .build())
-                .build();
-    }
-
-    private static SubInterface v6AddressPresent(){
-        return new SubInterfaceBuilder()
-                .setIpv6(new Ipv6Builder()
-                        .setAddress(Collections.singletonList(new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.ipv6.AddressBuilder().build()))
-                        .build())
-                .build();
-    }
 }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceRoutingValidatorTest.java
new file mode 100644 (file)
index 0000000..510887e
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * 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.v3po.interfaces;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.when;
+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.DataValidationFailedException.UpdateValidationFailedException;
+import io.fd.honeycomb.translate.write.WriteContext;
+import java.util.Collections;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.Ipv4Builder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip4.attributes.ipv4.AddressBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.Ipv6Builder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.Routing;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.routing.attributes.RoutingBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceRoutingValidatorTest {
+
+    private SubInterfaceRoutingValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth1";
+    private static final int SUBIF_INDEX = 0;
+    private static final InstanceIdentifier<Routing> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IF_NAME))
+                    .augmentation(SubinterfaceAugmentation.class)
+                    .child(SubInterfaces.class)
+                    .child(SubInterface.class, new SubInterfaceKey((long) SUBIF_INDEX))
+                    .child(Routing.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new SubInterfaceRoutingValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateWrite(ID, getRouting(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedV4AddressPresent() throws CreateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v4AddressPresent()));
+        validator.validateWrite(ID, getRouting(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedV6AddressPresent() throws CreateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.of(v6AddressPresent()));
+        validator.validateWrite(ID, getRouting(), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws UpdateValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateUpdate(ID, getRouting(), getRouting(), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        when(writeContext.readBefore(any(InstanceIdentifier.class))).thenReturn(Optional.empty());
+        validator.validateDelete(ID, getRouting(), writeContext);
+    }
+
+    private Routing getRouting() {
+        return new RoutingBuilder().setIpv4VrfId(new VniReference(4L)).build();
+    }
+
+    private SubInterface v4AddressPresent() {
+        return new SubInterfaceBuilder()
+                .setIpv4(new Ipv4Builder()
+                        .setAddress(Collections.singletonList(new AddressBuilder().build()))
+                        .build())
+                .build();
+    }
+
+    private SubInterface v6AddressPresent() {
+        return new SubInterfaceBuilder()
+                .setIpv6(new Ipv6Builder()
+                        .setAddress(Collections.singletonList(
+                                new org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.ip6.attributes.ipv6.AddressBuilder()
+                                        .build()))
+                        .build())
+                .build();
+    }
+}
index 5c640d2..fdaf6f9 100644 (file)
@@ -34,10 +34,10 @@ public class SubInterfaceUnnumberedCustomizerTest extends AbstractUnnumberedCust
     private static final int UNNUMBERED_IFC_ID = 2;
     private static final long UNNUMBERED_IFC_NUMBER = 123;
     private static final InstanceIdentifier<Unnumbered> UNNUMBERED_IFC_IID = InstanceIdentifier.create(Interfaces.class)
-        .child(Interface.class, new InterfaceKey(PARENT_IFC_NAME))
-        .augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class)
-        .child(SubInterface.class, new SubInterfaceKey(UNNUMBERED_IFC_NUMBER)).augmentation(
-            SubinterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
+            .child(Interface.class, new InterfaceKey(PARENT_IFC_NAME))
+            .augmentation(SubinterfaceAugmentation.class).child(SubInterfaces.class)
+            .child(SubInterface.class, new SubInterfaceKey(UNNUMBERED_IFC_NUMBER))
+            .augmentation(SubinterfaceUnnumberedAugmentation.class).child(Unnumbered.class);
 
     @Override
     protected int getUnnumberedIfcId() {
@@ -58,5 +58,4 @@ public class SubInterfaceUnnumberedCustomizerTest extends AbstractUnnumberedCust
     protected AbstractUnnumberedCustomizer getCustomizer() {
         return new SubInterfaceUnnumberedCustomizer(api, new NamingContext("ifc-prefix", IFC_CTX_NAME));
     }
-
 }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceUnnumberedValidatorTest.java
new file mode 100644 (file)
index 0000000..73043be
--- /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.v3po.interfaces;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+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.unnumbered.interfaces.rev180103.InterfaceUnnumberedAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.Unnumbered;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.unnumbered.interfaces.rev180103.unnumbered.config.attributes.UnnumberedBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceUnnumberedValidatorTest {
+
+    private SubInterfaceUnnumberedValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String IF_NAME = "eth2";
+    private static final String TARGET_IFC0_NAME = "eth0";
+    private static final InstanceIdentifier<Unnumbered> ID = InstanceIdentifier.create(Interfaces.class)
+            .child(Interface.class, new InterfaceKey(IF_NAME))
+            .augmentation(InterfaceUnnumberedAugmentation.class)
+            .child(Unnumbered.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new SubInterfaceUnnumberedValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws DataValidationFailedException.CreateValidationFailedException {
+        validator.validateWrite(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteFailedNoUse() throws DataValidationFailedException.CreateValidationFailedException {
+        validator.validateWrite(ID, getUnnumberedIfc(null), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws DataValidationFailedException.UpdateValidationFailedException {
+        validator.validateUpdate(ID, getUnnumberedIfc(TARGET_IFC0_NAME), getUnnumberedIfc(TARGET_IFC0_NAME),
+                writeContext);
+    }
+
+    @Test
+    public void testDeleteeSuccessful() throws DataValidationFailedException.DeleteValidationFailedException {
+        validator.validateDelete(ID, getUnnumberedIfc(TARGET_IFC0_NAME), writeContext);
+    }
+
+    private Unnumbered getUnnumberedIfc(String use) {
+        return new UnnumberedBuilder().setUse(use).build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/SubInterfaceValidatorTest.java
new file mode 100644 (file)
index 0000000..e7b9e66
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * 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.v3po.interfaces;
+
+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.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.vlan.rev180319.SubinterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.SubInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.interfaces._interface.sub.interfaces.SubInterfaceKey;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.vlan.rev180319.sub._interface.base.attributes.Match;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class SubInterfaceValidatorTest {
+
+    private SubInterfaceValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String SUPER_IF_NAME = "local0";
+    private static final String SUB_IFACE_NAME = "local0.11";
+    private static final long SUBIF_INDEX = 11;
+    private static final InstanceIdentifier<SubInterface> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(SUPER_IF_NAME))
+                    .augmentation(
+                            SubinterfaceAugmentation.class).child(SubInterfaces.class)
+                    .child(SubInterface.class, new SubInterfaceKey(SUBIF_INDEX));
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new SubInterfaceValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator
+                .validateWrite(ID, generateSubInterface(11L, SubInterfaceCustomizerTest.generateMatch()), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoIdentifier() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateSubInterface(null, SubInterfaceCustomizerTest.generateMatch()),
+                writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoMatch() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateSubInterface(11L, null), writeContext);
+    }
+
+    private SubInterface generateSubInterface(final Long identifier, final Match match) {
+        return new SubInterfaceBuilder()
+                .setIdentifier(identifier)
+                .setMatch(match)
+                .setEnabled(true)
+                .build();
+    }
+}
index ea3b699..db190ee 100644 (file)
@@ -61,7 +61,7 @@ public class VhostUserCustomizerTest extends WriterCustomizerTest implements Ipv
                     .augmentation(VppInterfaceAugmentation.class).child(VhostUser.class);
     private VhostUserCustomizer customizer;
 
-    private static VhostUser generateVhostUser(final VhostUserRole role, final String socketName) {
+    static VhostUser generateVhostUser(final VhostUserRole role, final String socketName) {
         VhostUserBuilder builder = new VhostUserBuilder();
         builder.setRole(role);
         builder.setSocket(socketName);
@@ -121,7 +121,7 @@ public class VhostUserCustomizerTest extends WriterCustomizerTest implements Ipv
         customizer.writeCurrentAttributes(ID, vhostUser, writeContext);
         verifyCreateVhostUserIfWasInvoked(vhostUser);
         verify(mappingContext).put(eq(mappingIid(IFACE_NAME, "test-instance")), eq(
-            mapping(IFACE_NAME, 0).get()));
+                mapping(IFACE_NAME, 0).get()));
     }
 
     @Test
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VhostUserValidatorTest.java
new file mode 100644 (file)
index 0000000..eb85412
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * 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.v3po.interfaces;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+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.v3po.rev190502.VhostUserRole;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VhostUser;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VhostUserValidatorTest {
+
+    private VhostUserValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+
+    private static final String SOCKET = "testSocket";
+    private static final String IFACE_NAME = "eth0";
+    private static final InstanceIdentifier<VhostUser> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(VhostUser.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new VhostUserValidator(ifcContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws DataValidationFailedException.CreateValidationFailedException {
+        validator.validateWrite(ID, getVhostUser(SOCKET), writeContext);
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testWriteFailedNoSocket() throws DataValidationFailedException.CreateValidationFailedException {
+        validator.validateWrite(ID, getVhostUser(null), writeContext);
+    }
+
+    @Test
+    public void testUpdateSuccessful() throws DataValidationFailedException.UpdateValidationFailedException {
+        validator.validateUpdate(ID, getVhostUser(SOCKET),
+                getVhostUser(SOCKET), writeContext);
+    }
+
+    @Test
+    public void testDeleteeSuccessful() throws DataValidationFailedException.DeleteValidationFailedException {
+        validator.validateDelete(ID, getVhostUser(SOCKET), writeContext);
+    }
+
+    private VhostUser getVhostUser(final String socketName) {
+        return VhostUserCustomizerTest.generateVhostUser(VhostUserRole.Client, socketName);
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanGpeValidatorTest.java
new file mode 100644 (file)
index 0000000..c4955d8
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+ * 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.v3po.interfaces;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+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.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeNextProtocol;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanGpeVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpe;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanGpeBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanGpeValidatorTest {
+
+    private VxlanGpeValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+    @Mock
+    private DisabledInterfacesManager interfaceDisableContext;
+
+    private static final String IPV6 = "a::100";
+    private static final String IPV4_1 = "192.168.20.10";
+    private static final String IPV4_2 = "192.168.20.11";
+    private static final Long VNI = Long.valueOf(11);
+    private static final Long ENCAP = Long.valueOf(123);
+    private static final Long DECAP = Long.valueOf(321);
+    private static final String IFACE_NAME = "eth0";
+    private static final InstanceIdentifier<VxlanGpe> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(VxlanGpe.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new VxlanGpeValidator(ifcContext, interfaceDisableContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanCorrect(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedMixedIpFamilies() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanMixedIpFamilies(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoLocal() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(false, true, true, true, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoRemote() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, false, true, true, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoEncapVrfId() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, false, true, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoDecapVrfId() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, true, false, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoVNI() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, true, true, false, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoNextProtocol() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, true, true, true, false), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, generateVxlanCorrect(), writeContext);
+    }
+
+    private VxlanGpe generateVxlanSetFields(final boolean src, final boolean dst, final boolean encapVrfId,
+                                            final boolean decapVrfId, final boolean vni, final boolean protocol) {
+        final VxlanGpeBuilder builder = new VxlanGpeBuilder();
+        builder.setLocal(src
+                ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1))
+                : null);
+        builder.setRemote(dst
+                ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2))
+                : null);
+        builder.setEncapVrfId(encapVrfId
+                ? ENCAP
+                : null);
+        builder.setDecapVrfId(decapVrfId
+                ? DECAP
+                : null);
+        builder.setVni(vni
+                ? new VxlanGpeVni(VNI)
+                : null);
+        builder.setNextProtocol(protocol
+                ? VxlanGpeNextProtocol.forValue(1)
+                : null);
+        return builder.build();
+    }
+
+    private VxlanGpe generateVxlanCorrect() {
+        return generateVxlanSetFields(true, true, true, true, true, true);
+    }
+
+    private VxlanGpe generateVxlanMixedIpFamilies() {
+        return new VxlanGpeBuilder()
+                .setLocal(new IpAddressNoZone(new Ipv6AddressNoZone(IPV6)))
+                .setRemote(new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1)))
+                .setEncapVrfId(ENCAP).setDecapVrfId(DECAP)
+                .setVni(new VxlanGpeVni(VNI))
+                .setNextProtocol(VxlanGpeNextProtocol.forValue(1))
+                .build();
+    }
+}
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/VxlanValidatorTest.java
new file mode 100644 (file)
index 0000000..587b9f3
--- /dev/null
@@ -0,0 +1,142 @@
+/*
+ * 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.v3po.interfaces;
+
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.hc2vpp.v3po.DisabledInterfacesManager;
+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.v3po.rev190502.L2Input;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VxlanVni;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Vxlan;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.VxlanBuilder;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.fib.table.management.rev180521.VniReference;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class VxlanValidatorTest {
+
+    private VxlanValidator validator;
+
+    @Mock
+    private WriteContext writeContext;
+    @Mock
+    private DisabledInterfacesManager interfaceDisableContext;
+
+    private static final String IPV6 = "a::100";
+    private static final String IPV4_1 = "192.168.20.10";
+    private static final String IPV4_2 = "192.168.20.11";
+    private static final Long VNI = Long.valueOf(11);
+    private static final Long ENCAP = Long.valueOf(123);
+    private static final String IFACE_NAME = "eth0";
+    private static final InstanceIdentifier<Vxlan> ID =
+            InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                    .augmentation(VppInterfaceAugmentation.class).child(Vxlan.class);
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new VxlanValidator(ifcContext, interfaceDisableContext);
+    }
+
+    @Test
+    public void testWriteSuccessful() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanCorrect(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedMixedIpFamilies() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanMixedIpFamilies(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoSrc() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(false, true, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoDst() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, false, true, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoEncap() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, false, true), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedNoVNI() throws CreateValidationFailedException {
+        validator.validateWrite(ID, generateVxlanSetFields(true, true, true, false), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful() throws DeleteValidationFailedException {
+        validator.validateDelete(ID, generateVxlanCorrect(), writeContext);
+    }
+
+    private Vxlan generateVxlan(final IpAddressNoZone src, final IpAddressNoZone dst, final VniReference encapVrfId,
+                                final long vni) {
+        final VxlanBuilder builder = new VxlanBuilder();
+        builder.setSrc(src);
+        builder.setDst(dst);
+        builder.setEncapVrfId(encapVrfId);
+        builder.setVni(new VxlanVni(vni));
+        builder.setDecapNext(L2Input.class);
+        return builder.build();
+    }
+
+    private Vxlan generateVxlanSetFields(final boolean src, final boolean dst, final boolean encapVrfId,
+                                         final boolean vni) {
+        final VxlanBuilder builder = new VxlanBuilder();
+        builder.setSrc(src
+                ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_1))
+                : null);
+        builder.setDst(dst
+                ? new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2))
+                : null);
+        builder.setEncapVrfId(encapVrfId
+                ? new VniReference(ENCAP)
+                : null);
+        builder.setVni(vni
+                ? new VxlanVni(VNI)
+                : null);
+        builder.setDecapNext(L2Input.class);
+        return builder.build();
+    }
+
+    private Vxlan generateVxlanCorrect() {
+        return generateVxlanSetFields(true, true, true, true);
+    }
+
+    private Vxlan generateVxlanMixedIpFamilies() {
+        return generateVxlan(new IpAddressNoZone(new Ipv6AddressNoZone(IPV6)),
+                new IpAddressNoZone(new Ipv4AddressNoZone(IPV4_2)), new VniReference(ENCAP), VNI);
+    }
+}
index d2c9ed3..206a5a0 100644 (file)
@@ -38,11 +38,9 @@ import org.mockito.Captor;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.pbb.types.rev161214.Operation;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentation;
 import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
-import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewriteBuilder;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
 import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
-import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
 import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
 
 public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
@@ -72,14 +70,14 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
     @Test
     public void testWrite() throws WriteFailedException {
         whenRewriteThenSuccess();
-        customizer.writeCurrentAttributes(validId, validData(), writeContext);
+        customizer.writeCurrentAttributes(validId, PbbRewriteValidatorTest.validData(), writeContext);
         verifyRewriteRequest(desiredSetResult());
     }
 
     @Test
     public void testWriteFailedCallFailed() {
         whenRewriteThenFail();
-        final PbbRewrite validData = validData();
+        final PbbRewrite validData = PbbRewriteValidatorTest.validData();
         try {
             customizer.writeCurrentAttributes(validId, validData, writeContext);
         } catch (Exception e) {
@@ -95,19 +93,10 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
         fail("Test should have failed");
     }
 
-    @Test
-    public void testWriteFailedInvalidData() {
-        verifyInvalidWriteDataCombination(invalidDataNoDestination());
-        verifyInvalidWriteDataCombination(invalidDataNoSource());
-        verifyInvalidWriteDataCombination(invalidDataNoItag());
-        verifyInvalidWriteDataCombination(invalidDataNoOperation());
-        verifyInvalidWriteDataCombination(invalidDataNoVlan());
-    }
-
     @Test
     public void testUpdate() throws WriteFailedException {
         whenRewriteThenSuccess();
-        final PbbRewrite rewrite = validData();
+        final PbbRewrite rewrite = PbbRewriteValidatorTest.validData();
         customizer.updateCurrentAttributes(validId, rewrite, rewrite, writeContext);
         verifyRewriteRequest(desiredSetResult());
     }
@@ -115,8 +104,8 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
     @Test
     public void testUpdateFailedCallFailed() {
         whenRewriteThenFail();
-        final PbbRewrite invalidData = invalidDataNoVlan();
-        final PbbRewrite validData = validData();
+        final PbbRewrite invalidData = PbbRewriteValidatorTest.invalidDataNoVlan();
+        final PbbRewrite validData = PbbRewriteValidatorTest.validData();
         try {
             customizer.updateCurrentAttributes(validId, invalidData, validData, writeContext);
         } catch (Exception e) {
@@ -133,26 +122,17 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
         fail("Test should have failed");
     }
 
-    @Test
-    public void testUpdateFailedInvalidData() {
-        verifyInvalidUpdateDataCombination(invalidDataNoDestination());
-        verifyInvalidUpdateDataCombination(invalidDataNoSource());
-        verifyInvalidUpdateDataCombination(invalidDataNoItag());
-        verifyInvalidUpdateDataCombination(invalidDataNoOperation());
-        verifyInvalidUpdateDataCombination(invalidDataNoVlan());
-    }
-
     @Test
     public void testDelete() throws WriteFailedException {
         whenRewriteThenSuccess();
-        customizer.deleteCurrentAttributes(validId, validData(), writeContext);
+        customizer.deleteCurrentAttributes(validId, PbbRewriteValidatorTest.validData(), writeContext);
         verifyRewriteRequest(desiredDisableResult());
     }
 
     @Test
     public void testDeleteFailedCallFailed() {
         whenRewriteThenFail();
-        final PbbRewrite validData = validData();
+        final PbbRewrite validData = PbbRewriteValidatorTest.validData();
         try {
             customizer.deleteCurrentAttributes(validId, validData, writeContext);
         } catch (Exception e) {
@@ -165,15 +145,6 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
         fail("Test should have failed");
     }
 
-    @Test
-    public void testDeleteFailedInvalidData() {
-        verifyInvalidDeleteDataCombination(invalidDataNoDestination());
-        verifyInvalidDeleteDataCombination(invalidDataNoSource());
-        verifyInvalidDeleteDataCombination(invalidDataNoItag());
-        verifyInvalidDeleteDataCombination(invalidDataNoOperation());
-        verifyInvalidDeleteDataCombination(invalidDataNoVlan());
-    }
-
     private void whenRewriteThenSuccess() {
         when(api.l2InterfacePbbTagRewrite(any())).thenReturn(future(new L2InterfacePbbTagRewriteReply()));
     }
@@ -182,41 +153,6 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
         when(api.l2InterfacePbbTagRewrite(any())).thenReturn(failedFuture());
     }
 
-    private void verifyInvalidWriteDataCombination(final PbbRewrite invalidData) {
-        try {
-            customizer.writeCurrentAttributes(validId, invalidData, writeContext);
-        } catch (Exception e) {
-            assertTrue(e instanceof NullPointerException);
-            return;
-        }
-
-        fail("Verifying of invalid combination failed");
-    }
-
-    private void verifyInvalidUpdateDataCombination(final PbbRewrite invalidData) {
-        try {
-            customizer.updateCurrentAttributes(validId, validData(), invalidData, writeContext);
-        } catch (Exception e) {
-            assertTrue(e instanceof NullPointerException);
-            return;
-        }
-
-        fail("Verifying of invalid combination failed");
-    }
-
-
-    private void verifyInvalidDeleteDataCombination(final PbbRewrite invalidData) {
-        try {
-            customizer.deleteCurrentAttributes(validId, invalidData, writeContext);
-        } catch (Exception e) {
-            assertTrue(e instanceof NullPointerException);
-            return;
-        }
-
-        fail("Verifying of invalid combination failed");
-    }
-
-
     private L2InterfacePbbTagRewrite desiredSetResult() {
         final L2InterfacePbbTagRewrite desiredResult = new L2InterfacePbbTagRewrite();
         desiredResult.swIfIndex = 1;
@@ -254,59 +190,4 @@ public class PbbRewriteCustomizerTest extends WriterCustomizerTest {
         assertArrayEquals(actualRequest.bDmac, desiredResult.bDmac);
         assertArrayEquals(actualRequest.bSmac, desiredResult.bSmac);
     }
-
-    private PbbRewrite invalidDataNoDestination() {
-        return new PbbRewriteBuilder()
-                .setBVlanTagVlanId(1234)
-                .setITagIsid(2L)
-                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
-
-    private PbbRewrite invalidDataNoSource() {
-        return new PbbRewriteBuilder()
-                .setBVlanTagVlanId(1234)
-                .setITagIsid(2L)
-                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
-
-    private PbbRewrite invalidDataNoItag() {
-        return new PbbRewriteBuilder()
-                .setBVlanTagVlanId(1234)
-                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
-                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
-
-    private PbbRewrite invalidDataNoVlan() {
-        return new PbbRewriteBuilder()
-                .setITagIsid(2L)
-                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
-                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
-
-    private PbbRewrite invalidDataNoOperation() {
-        return new PbbRewriteBuilder()
-                .setITagIsid(2L)
-                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
-                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
-
-    private PbbRewrite validData() {
-        return new PbbRewriteBuilder()
-                .setBVlanTagVlanId(1234)
-                .setITagIsid(2L)
-                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
-                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
-                .setInterfaceOperation(Operation.Pop2)
-                .build();
-    }
 }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/pbb/PbbRewriteValidatorTest.java
new file mode 100644 (file)
index 0000000..114a1bc
--- /dev/null
@@ -0,0 +1,189 @@
+/*
+ * 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.v3po.interfaces.pbb;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+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.DataValidationFailedException.UpdateValidationFailedException;
+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.pbb.types.rev161214.Operation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.PbbRewriteInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewrite;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.vpp.pbb.rev161214.interfaces._interface.PbbRewriteBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.yang.types.rev130715.MacAddress;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class PbbRewriteValidatorTest {
+
+    private PbbRewriteValidator validator;
+    private InstanceIdentifier<PbbRewrite> validId;
+    private InstanceIdentifier<PbbRewrite> invalidId;
+
+    @Mock
+    private WriteContext writeContext;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new PbbRewriteValidator(ifcContext);
+        validId = InstanceIdentifier.create(Interfaces.class)
+                .child(Interface.class, new InterfaceKey("pbb-interface"))
+                .augmentation(PbbRewriteInterfaceAugmentation.class)
+                .child(PbbRewrite.class);
+
+        invalidId = InstanceIdentifier.create(PbbRewrite.class);
+    }
+
+    @Test
+    public void testWriteSuccessful()
+            throws CreateValidationFailedException {
+        validator.validateWrite(validId, validData(), writeContext);
+    }
+
+    @Test(expected = CreateValidationFailedException.class)
+    public void testWriteFailedInvalidIID()
+            throws CreateValidationFailedException {
+        validator.validateWrite(invalidId, validData(), writeContext);
+    }
+
+    @Test
+    public void testWriteFailedInvalidData() {
+        verifyInvalidWriteDataCombination(invalidDataNoDestination());
+        verifyInvalidWriteDataCombination(invalidDataNoSource());
+        verifyInvalidWriteDataCombination(invalidDataNoItag());
+        verifyInvalidWriteDataCombination(invalidDataNoOperation());
+        verifyInvalidWriteDataCombination(invalidDataNoVlan());
+    }
+
+    @Test
+    public void testUpdateFailedInvalidData() {
+        verifyInvalidUpdateDataCombination(invalidDataNoDestination());
+        verifyInvalidUpdateDataCombination(invalidDataNoSource());
+        verifyInvalidUpdateDataCombination(invalidDataNoItag());
+        verifyInvalidUpdateDataCombination(invalidDataNoOperation());
+        verifyInvalidUpdateDataCombination(invalidDataNoVlan());
+    }
+
+    @Test
+    public void testDeleteFailedInvalidData() {
+        verifyInvalidDeleteDataCombination(invalidDataNoDestination());
+        verifyInvalidDeleteDataCombination(invalidDataNoSource());
+        verifyInvalidDeleteDataCombination(invalidDataNoItag());
+        verifyInvalidDeleteDataCombination(invalidDataNoOperation());
+        verifyInvalidDeleteDataCombination(invalidDataNoVlan());
+    }
+
+    private void verifyInvalidWriteDataCombination(final PbbRewrite invalidData) {
+        try {
+            validator.validateWrite(validId, invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof CreateValidationFailedException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+    private void verifyInvalidUpdateDataCombination(final PbbRewrite invalidData) {
+        try {
+            validator.validateUpdate(validId, validData(), invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof UpdateValidationFailedException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+    private void verifyInvalidDeleteDataCombination(final PbbRewrite invalidData) {
+        try {
+            validator.validateDelete(validId, invalidData, writeContext);
+        } catch (Exception e) {
+            assertTrue(e instanceof DeleteValidationFailedException);
+            return;
+        }
+
+        fail("Verifying of invalid combination failed");
+    }
+
+    static PbbRewrite invalidDataNoDestination() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1234)
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    static PbbRewrite invalidDataNoSource() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1234)
+                .setITagIsid(2L)
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    static PbbRewrite invalidDataNoItag() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1234)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    static PbbRewrite invalidDataNoVlan() {
+        return new PbbRewriteBuilder()
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    static PbbRewrite invalidDataNoOperation() {
+        return new PbbRewriteBuilder()
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+
+    static PbbRewrite validData() {
+        return new PbbRewriteBuilder()
+                .setBVlanTagVlanId(1234)
+                .setITagIsid(2L)
+                .setSourceAddress(new MacAddress("aa:aa:aa:aa:aa:aa"))
+                .setDestinationAddress(new MacAddress("bb:bb:bb:bb:bb:bb"))
+                .setInterfaceOperation(Operation.Pop2)
+                .build();
+    }
+}
index 9a8ef72..e73106a 100644 (file)
@@ -110,5 +110,4 @@ public class MirroredInterfacesCustomizerTest extends WriterCustomizerTest {
         assertEquals(IFACE_INDEX, deleteRequest.swIfIndexTo);
         assertEquals(SRC_IFACE_INDEX, deleteRequest.swIfIndexFrom);
     }
-
 }
diff --git a/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesValidatorTest.java b/v3po/v3po2vpp/src/test/java/io/fd/hc2vpp/v3po/interfaces/span/MirroredInterfacesValidatorTest.java
new file mode 100644 (file)
index 0000000..e596c13
--- /dev/null
@@ -0,0 +1,115 @@
+/*
+ * 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.v3po.interfaces.span;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.MockitoAnnotations.initMocks;
+
+import io.fd.hc2vpp.common.translate.util.NamingContext;
+import io.fd.honeycomb.translate.write.DataValidationFailedException;
+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.v3po.rev190502.SpanState;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.VppInterfaceAugmentation;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.interfaces._interface.Span;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.MirroredInterfaces;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterface;
+import org.opendaylight.yang.gen.v1.http.fd.io.hc2vpp.yang.v3po.rev190502.span.attributes.mirrored.interfaces.MirroredInterfaceBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.Interfaces;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.Interface;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.interfaces.rev180220.interfaces.InterfaceKey;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+
+public class MirroredInterfacesValidatorTest {
+
+    private InstanceIdentifier<MirroredInterface> validId;
+    private MirroredInterfaceValidator validator;
+    private static final String IFACE_NAME = "iface";
+    private static final String SRC_IFACE_NAME = "src-iface";
+
+    @Mock
+    private WriteContext writeContext;
+
+    @Before
+    public void setUp() {
+        initMocks(this);
+        NamingContext ifcContext = new NamingContext("testInterfaceContext", "testInterfaceContext");
+        validator = new MirroredInterfaceValidator(ifcContext, id -> id.firstKeyOf(Interface.class).getName());
+        validId = InstanceIdentifier.create(Interfaces.class).child(Interface.class, new InterfaceKey(IFACE_NAME))
+                .augmentation(VppInterfaceAugmentation.class).child(Span.class)
+                .child(MirroredInterfaces.class)
+                .child(MirroredInterface.class);
+    }
+
+    @Test
+    public void testWriteSuccessful()
+            throws DataValidationFailedException.CreateValidationFailedException {
+        validator.validateWrite(validId, validData(), writeContext);
+    }
+
+    @Test
+    public void testWriteFailed() {
+        validateWritingIncorrectData(incorrectDataNoIfaceRef());
+        validateWritingIncorrectData(incorrectDataNoSpanState());
+    }
+
+    @Test
+    public void testUpdateSuccessful()
+            throws DataValidationFailedException.UpdateValidationFailedException {
+        validator.validateUpdate(validId, validData(), validData(), writeContext);
+    }
+
+    @Test
+    public void testDeleteSuccessful()
+            throws DataValidationFailedException.DeleteValidationFailedException {
+        validator.validateDelete(validId, validData(), writeContext);
+    }
+
+    private void validateWritingIncorrectData(final MirroredInterface data) {
+        try {
+            validator.validateWrite(validId, data, writeContext);
+        } catch (DataValidationFailedException.CreateValidationFailedException e) {
+            assertTrue(e instanceof DataValidationFailedException.CreateValidationFailedException);
+            return;
+        }
+        fail("Verifying of invalid combination failed");
+    }
+
+    private MirroredInterface incorrectDataNoIfaceRef() {
+        return new MirroredInterfaceBuilder()
+                .setIfaceRef(null)
+                .setState(SpanState.Receive)
+                .build();
+    }
+
+    private MirroredInterface incorrectDataNoSpanState() {
+        return new MirroredInterfaceBuilder()
+                .setIfaceRef(SRC_IFACE_NAME)
+                .setState(null)
+                .build();
+    }
+
+    private MirroredInterface validData() {
+        return new MirroredInterfaceBuilder()
+                .setIfaceRef(SRC_IFACE_NAME)
+                .setState(SpanState.Receive)
+                .build();
+    }
+}
index 2b89df0..e5bd6dc 100644 (file)
@@ -139,145 +139,3 @@ public class VxlanGpeCustomizerTest extends ReaderCustomizerTest<VxlanGpe, Vxlan
         return new VxlanGpeCustomizer(api, interfacesContext, dumpCacheManager);
     }
 }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
index da7c879..c13775c 100644 (file)
@@ -104,7 +104,6 @@ public class MirroredInterfacesCustomizerTest
         MirroredInterfacesBuilder builder = new MirroredInterfacesBuilder();
         getCustomizer().readCurrentAttributes(validId, builder, ctx);
 
-
         final MirroredInterfaces data = builder.build();
         // 1,2 should be returned,0 should be filtered out because of disabled state