Fix wait for schema in BindingToNormalizedNodeCodec 81/35881/7
authorTom Pantelis <tpanteli@brocade.com>
Mon, 7 Mar 2016 11:20:13 +0000 (06:20 -0500)
committerGerrit Code Review <gerrit@opendaylight.org>
Tue, 22 Mar 2016 14:06:37 +0000 (14:06 +0000)
The wait for schema mechanism does not work. A few issues were fixed:

 - FutureSchema did not add the FutureSchemaPredicate instances to the
   postponedOperations list so they always timed out.

 - The waitForSchema method in BindingToNormalizedNodeCodec checked for
   !futureSchema.waitForSchema so it only successfully returned on
   failure.

 - There was a timing issue in FutureSchema where a context update could
   occur just prior to adding a postponed operation to the list, in
   which case the operation may timeout if the new update contained the
   postponed criteria and another update didn't occur in time. To
   alleviate this, the sychronization was tighted up and runtime context
   is now stored in FutureSchema instead of BindingToNormalizedNodeCodec.

 - The runtimeContext field needs to be volatile.

I also added a wait if the runtimeContext was null b/c
onGlobalContextUpdated hadn't been initially notified yet.

Added unit tests to cover the wait for schema mechanism.

Change-Id: I7155dae021453d085f89d13dfd4b069178dd2fc8
Signed-off-by: Tom Pantelis <tpanteli@brocade.com>
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/BindingToNormalizedNodeCodec.java
opendaylight/md-sal/sal-binding-broker/src/main/java/org/opendaylight/controller/md/sal/binding/impl/FutureSchema.java
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/BindingNormalizedCodecTest.java [new file with mode: 0644]
opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingNormalizedCodecTest.java [deleted file]

index 845f422911428f06f07de9a94c08f1df5523c407..ee60afbfd3d0ed12587752ed6b0d85c779f6c116 100644 (file)
@@ -78,7 +78,6 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
 
             });
 
-    private BindingRuntimeContext runtimeContext;
     private DataNormalizer legacyToNormalized;
 
     public BindingToNormalizedNodeCodec(final GeneratedClassLoadingStrategy classLoadingStrategy,
@@ -91,7 +90,7 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
             final BindingNormalizedNodeCodecRegistry codecRegistry,final boolean waitForSchema) {
         this.classLoadingStrategy = Preconditions.checkNotNull(classLoadingStrategy,"classLoadingStrategy");
         this.codecRegistry = Preconditions.checkNotNull(codecRegistry,"codecRegistry");
-        this.futureSchema = waitForSchema ? new FutureSchema(WAIT_DURATION_SEC, TimeUnit.SECONDS) : null;
+        this.futureSchema = new FutureSchema(WAIT_DURATION_SEC, TimeUnit.SECONDS, waitForSchema);
     }
 
     YangInstanceIdentifier toYangInstanceIdentifierBlocking(final InstanceIdentifier<? extends DataObject> binding) {
@@ -227,13 +226,11 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
     }
 
     @Override
-    public void onGlobalContextUpdated(final SchemaContext arg0) {
-        legacyToNormalized = new DataNormalizer(arg0);
-        runtimeContext = BindingRuntimeContext.create(classLoadingStrategy, arg0);
+    public void onGlobalContextUpdated(final SchemaContext schemaContext) {
+        legacyToNormalized = new DataNormalizer(schemaContext);
+        BindingRuntimeContext runtimeContext = BindingRuntimeContext.create(classLoadingStrategy, schemaContext);
         codecRegistry.onBindingRuntimeContextUpdated(runtimeContext);
-        if(futureSchema != null) {
-            futureSchema.onRuntimeContextUpdated(runtimeContext);
-        }
+        futureSchema.onRuntimeContextUpdated(runtimeContext);
     }
 
     public <T extends DataObject> Function<Optional<NormalizedNode<?, ?>>, Optional<T>>  deserializeFunction(final InstanceIdentifier<T> path) {
@@ -306,33 +303,37 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
         final QNameModule moduleName = BindingReflections.getQNameModule(modeledClass);
         final URI namespace = moduleName.getNamespace();
         final Date revision = moduleName.getRevision();
-        Module module = runtimeContext.getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision);
-        if(module == null && futureSchema != null && futureSchema.waitForSchema(namespace,revision)) {
-            module = runtimeContext.getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision);
+        Module module = runtimeContext().getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision);
+        if(module == null && futureSchema.waitForSchema(namespace,revision)) {
+            module = runtimeContext().getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision);
         }
         Preconditions.checkState(module != null, "Schema for %s is not available.", modeledClass);
         return module;
     }
 
     private void waitForSchema(final Collection<Class<?>> binding, final MissingSchemaException e) {
-        if(futureSchema != null) {
-            LOG.warn("Blocking thread to wait for schema convergence updates for {} {}",futureSchema.getDuration(), futureSchema.getUnit());
-            if(!futureSchema.waitForSchema(binding)) {
-                return;
-            }
+        LOG.warn("Blocking thread to wait for schema convergence updates for {} {}", futureSchema.getDuration(),
+                futureSchema.getUnit());
+        if(futureSchema.waitForSchema(binding)) {
+            return;
         }
+
         throw e;
     }
 
     private Method findRpcMethod(final Class<? extends RpcService> key, final RpcDefinition rpcDef) throws NoSuchMethodException {
         final String methodName = BindingMapping.getMethodName(rpcDef.getQName());
         if(rpcDef.getInput() != null) {
-            final Class<?> inputClz = runtimeContext.getClassForSchema(rpcDef.getInput());
+            final Class<?> inputClz = runtimeContext().getClassForSchema(rpcDef.getInput());
             return key.getMethod(methodName, inputClz);
         }
         return key.getMethod(methodName);
     }
 
+    private BindingRuntimeContext runtimeContext() {
+        return futureSchema.runtimeContext();
+    }
+
     @Override
     public BindingCodecTree create(final BindingRuntimeContext context) {
         return codecRegistry.create(context);
@@ -361,11 +362,11 @@ public final class BindingToNormalizedNodeCodec implements BindingCodecTreeFacto
     @SuppressWarnings("unchecked")
     public Set<Class<? extends Notification>> getNotificationClasses(final Set<SchemaPath> interested) {
         final Set<Class<? extends Notification>> result = new HashSet<>();
-        final Set<NotificationDefinition> knownNotifications = runtimeContext.getSchemaContext().getNotifications();
+        final Set<NotificationDefinition> knownNotifications = runtimeContext().getSchemaContext().getNotifications();
         for (final NotificationDefinition notification : knownNotifications) {
             if (interested.contains(notification.getPath())) {
                 try {
-                    result.add((Class<? extends Notification>) runtimeContext.getClassForSchema(notification));
+                    result.add((Class<? extends Notification>) runtimeContext().getClassForSchema(notification));
                 } catch (final IllegalStateException e) {
                     // Ignore
                     LOG.warn("Class for {} is currently not known.",notification.getPath(),e);
index 2898ba7e37ca9729e0f0c113f8e6d34da3f9a188..fb70811840e4cbaa935e1523db64e54ea71036ff 100644 (file)
@@ -13,29 +13,51 @@ import com.google.common.base.Throwables;
 import com.google.common.util.concurrent.SettableFuture;
 import java.net.URI;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.LinkedHashSet;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import javax.annotation.concurrent.GuardedBy;
 import org.opendaylight.yangtools.sal.binding.generator.util.BindingRuntimeContext;
 import org.opendaylight.yangtools.yang.binding.Augmentation;
 
 class FutureSchema implements AutoCloseable {
 
-    private final List<FutureSchemaPredicate> postponedOperations = new CopyOnWriteArrayList<>();
+    @GuardedBy(value="postponedOperations")
+    private final Set<FutureSchemaPredicate> postponedOperations = new LinkedHashSet<>();
     private final long duration;
     private final TimeUnit unit;
+    private final boolean waitEnabled;
+    private volatile BindingRuntimeContext runtimeContext;
 
-    protected FutureSchema(final long time, final TimeUnit unit) {
+    protected FutureSchema(final long time, final TimeUnit unit, final boolean waitEnabled) {
         this.duration = time;
         this.unit = unit;
+        this.waitEnabled = waitEnabled;
+    }
+
+    BindingRuntimeContext runtimeContext() {
+        BindingRuntimeContext localRuntimeContext = runtimeContext;
+        if(localRuntimeContext != null) {
+            return localRuntimeContext;
+        }
+
+        if(waitForSchema(Collections.emptyList())) {
+            return runtimeContext;
+        }
+
+        throw new IllegalStateException("No SchemaContext is available");
     }
 
     void onRuntimeContextUpdated(final BindingRuntimeContext context) {
-        for (final FutureSchemaPredicate op : postponedOperations) {
-            op.unlockIfPossible(context);
+        synchronized(postponedOperations) {
+            runtimeContext = context;
+            for (final FutureSchemaPredicate op : postponedOperations) {
+                op.unlockIfPossible(context);
+            }
         }
     }
 
@@ -49,8 +71,10 @@ class FutureSchema implements AutoCloseable {
 
     @Override
     public void close() {
-        for (final FutureSchemaPredicate op : postponedOperations) {
-            op.cancel();
+        synchronized(postponedOperations) {
+            for (final FutureSchemaPredicate op : postponedOperations) {
+                op.cancel();
+            }
         }
     }
 
@@ -65,19 +89,16 @@ class FutureSchema implements AutoCloseable {
     }
 
     boolean waitForSchema(final URI namespace, final Date revision) {
-        final FutureSchemaPredicate postponedOp = new FutureSchemaPredicate() {
-
+        return addPostponedOpAndWait(new FutureSchemaPredicate() {
             @Override
             public boolean apply(final BindingRuntimeContext input) {
                 return input.getSchemaContext().findModuleByNamespaceAndRevision(namespace, revision) != null;
             }
-        };
-        return postponedOp.waitForSchema();
+        });
     }
 
     boolean waitForSchema(final Collection<Class<?>> bindingClasses) {
-        final FutureSchemaPredicate postponedOp = new FutureSchemaPredicate() {
-
+        return addPostponedOpAndWait(new FutureSchemaPredicate() {
             @Override
             public boolean apply(final BindingRuntimeContext context) {
                 for (final Class<?> clz : bindingClasses) {
@@ -87,7 +108,24 @@ class FutureSchema implements AutoCloseable {
                 }
                 return true;
             }
-        };
+        });
+    }
+
+    private boolean addPostponedOpAndWait(FutureSchemaPredicate postponedOp) {
+        if(!waitEnabled) {
+            return false;
+        }
+
+        BindingRuntimeContext localRuntimeContext = runtimeContext;
+        synchronized(postponedOperations) {
+            postponedOperations.add(postponedOp);
+
+            // If the runtimeContext changed, this op may now be satisfied so check it.
+            if(localRuntimeContext != runtimeContext) {
+                postponedOp.unlockIfPossible(runtimeContext);
+            }
+        }
+
         return postponedOp.waitForSchema();
     }
 
@@ -102,7 +140,9 @@ class FutureSchema implements AutoCloseable {
             } catch (final TimeoutException e) {
                 return false;
             } finally {
-                postponedOperations.remove(this);
+                synchronized(postponedOperations) {
+                    postponedOperations.remove(this);
+                }
             }
         }
 
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/BindingNormalizedCodecTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/BindingNormalizedCodecTest.java
new file mode 100644 (file)
index 0000000..2716fb7
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others.  All rights reserved.
+ *
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License v1.0 which accompanies this distribution,
+ * and is available at http://www.eclipse.org/legal/epl-v10.html
+ */
+
+package org.opendaylight.controller.md.sal.binding.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.SetMultimap;
+import com.google.common.util.concurrent.Uninterruptibles;
+import java.lang.reflect.Method;
+import java.net.URI;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicReference;
+import org.junit.Test;
+import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyAugment;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.bi.ba.rpcservice.rev140701.OpendaylightTestRpcServiceService;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
+import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
+import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
+import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
+import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.ModuleIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaPath;
+import org.opendaylight.yangtools.yang.model.util.AbstractSchemaContext;
+import javassist.ClassPool;
+
+public class BindingNormalizedCodecTest extends AbstractSchemaAwareTest {
+
+    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
+    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
+            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).build();
+    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
+    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
+    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
+    private static final QName NAME_QNAME = QName.create(Top.QNAME, "name");
+    private static final YangInstanceIdentifier BI_TOP_LEVEL_LIST = YangInstanceIdentifier.builder().
+            node(Top.QNAME).node(TopLevelList.QNAME).nodeWithKey(
+                    TopLevelList.QNAME, NAME_QNAME, TOP_FOO_KEY.getName()).build();
+
+
+    private BindingToNormalizedNodeCodec codec;
+    private SchemaContext context;
+
+    @Override
+    protected void setupWithSchema(final SchemaContext context) {
+        this.context = context;
+        final DataObjectSerializerGenerator streamWriter = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
+        final BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(streamWriter);
+        codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), registry, true);
+    };
+
+    @Test
+    public void testComplexAugmentationSerialization() {
+        codec.onGlobalContextUpdated(context);
+        final PathArgument lastArg = codec.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES).getLastPathArgument();
+        assertTrue(lastArg instanceof AugmentationIdentifier);
+    }
+
+
+    @Test
+    public void testLeafOnlyAugmentationSerialization() {
+        codec.onGlobalContextUpdated(context);
+        final PathArgument leafOnlyLastArg = codec.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
+        assertTrue(leafOnlyLastArg instanceof AugmentationIdentifier);
+        assertTrue(((AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
+    }
+
+    @Test
+    public void testToYangInstanceIdentifierBlocking() {
+        codec.onGlobalContextUpdated(new EmptySchemaContext());
+
+        final CountDownLatch done = new CountDownLatch(1);
+        final AtomicReference<YangInstanceIdentifier> yangId = new AtomicReference<>();
+        final AtomicReference<RuntimeException> error = new AtomicReference<>();
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    yangId.set(codec.toYangInstanceIdentifierBlocking(BA_TOP_LEVEL_LIST));
+                } catch(RuntimeException e) {
+                    error.set(e);
+                } finally {
+                    done.countDown();
+                }
+            }
+        }.start();
+
+        Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+        codec.onGlobalContextUpdated(context);
+
+        assertEquals("toYangInstanceIdentifierBlocking completed", true,
+                Uninterruptibles.awaitUninterruptibly(done, 3, TimeUnit.SECONDS));
+        if(error.get() != null) {
+            throw error.get();
+        }
+
+        assertEquals("toYangInstanceIdentifierBlocking", BI_TOP_LEVEL_LIST, yangId.get());
+    }
+
+    @Test
+    public void testGetRpcMethodToSchemaPathWithNoInitialSchemaContext() {
+        testGetRpcMethodToSchemaPath();
+    }
+
+    @Test
+    public void testGetRpcMethodToSchemaPathBlocking() {
+        codec.onGlobalContextUpdated(new EmptySchemaContext());
+        testGetRpcMethodToSchemaPath();
+    }
+
+    private void testGetRpcMethodToSchemaPath() {
+        final CountDownLatch done = new CountDownLatch(1);
+        final AtomicReference<ImmutableBiMap<Method, SchemaPath>> retMap = new AtomicReference<>();
+        final AtomicReference<RuntimeException> error = new AtomicReference<>();
+        new Thread() {
+            @Override
+            public void run() {
+                try {
+                    retMap.set(codec.getRpcMethodToSchemaPath(OpendaylightTestRpcServiceService.class));
+                } catch(RuntimeException e) {
+                    error.set(e);
+                } finally {
+                    done.countDown();
+                }
+            }
+        }.start();
+
+        Uninterruptibles.sleepUninterruptibly(500, TimeUnit.MILLISECONDS);
+        codec.onGlobalContextUpdated(context);
+
+        assertEquals("getRpcMethodToSchemaPath completed", true,
+                Uninterruptibles.awaitUninterruptibly(done, 3, TimeUnit.SECONDS));
+        if(error.get() != null) {
+            throw error.get();
+        }
+
+        for(Method method: retMap.get().keySet()) {
+            if(method.getName().equals("rockTheHouse")) {
+                return;
+            }
+        }
+
+        fail("rockTheHouse RPC method not found");
+    }
+
+    static class EmptySchemaContext extends AbstractSchemaContext {
+        @Override
+        public Set<Module> getModules() {
+            return Collections.emptySet();
+        }
+
+        @Override
+        protected Map<ModuleIdentifier, String> getIdentifiersToSources() {
+            return Collections.emptyMap();
+        }
+
+        @Override
+        protected SetMultimap<URI, Module> getNamespaceToModules() {
+            return Multimaps.forMap(Collections.emptyMap());
+        }
+
+        @Override
+        protected SetMultimap<String, Module> getNameToModules() {
+            return Multimaps.forMap(Collections.emptyMap());
+        }
+    }
+}
diff --git a/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingNormalizedCodecTest.java b/opendaylight/md-sal/sal-binding-broker/src/test/java/org/opendaylight/controller/md/sal/binding/impl/test/BindingNormalizedCodecTest.java
deleted file mode 100644 (file)
index a427392..0000000
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- * Copyright (c) 2014, 2015 Cisco Systems, Inc. and others.  All rights reserved.
- *
- * This program and the accompanying materials are made available under the
- * terms of the Eclipse Public License v1.0 which accompanies this distribution,
- * and is available at http://www.eclipse.org/legal/epl-v10.html
- */
-
-package org.opendaylight.controller.md.sal.binding.impl.test;
-
-import static org.junit.Assert.assertTrue;
-
-import javassist.ClassPool;
-import org.junit.Test;
-import org.opendaylight.controller.md.sal.binding.impl.BindingToNormalizedNodeCodec;
-import org.opendaylight.controller.md.sal.binding.test.AbstractSchemaAwareTest;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeComplexUsesAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.augment.rev140709.TreeLeafOnlyAugment;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.Top;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelList;
-import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.controller.md.sal.test.list.rev140701.two.level.list.TopLevelListKey;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.DataObjectSerializerGenerator;
-import org.opendaylight.yangtools.binding.data.codec.gen.impl.StreamWriterGenerator;
-import org.opendaylight.yangtools.binding.data.codec.impl.BindingNormalizedNodeCodecRegistry;
-import org.opendaylight.yangtools.sal.binding.generator.impl.GeneratedClassLoadingStrategy;
-import org.opendaylight.yangtools.sal.binding.generator.util.JavassistUtils;
-import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
-import org.opendaylight.yangtools.yang.common.QName;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.AugmentationIdentifier;
-import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.PathArgument;
-import org.opendaylight.yangtools.yang.model.api.SchemaContext;
-
-public class BindingNormalizedCodecTest extends AbstractSchemaAwareTest {
-
-    private static final TopLevelListKey TOP_FOO_KEY = new TopLevelListKey("foo");
-    private static final InstanceIdentifier<TopLevelList> BA_TOP_LEVEL_LIST = InstanceIdentifier
-            .builder(Top.class).child(TopLevelList.class, TOP_FOO_KEY).toInstance();
-    private static final InstanceIdentifier<TreeLeafOnlyAugment> BA_TREE_LEAF_ONLY = BA_TOP_LEVEL_LIST.augmentation(TreeLeafOnlyAugment.class);
-    private static final InstanceIdentifier<TreeComplexUsesAugment> BA_TREE_COMPLEX_USES = BA_TOP_LEVEL_LIST.augmentation(TreeComplexUsesAugment.class);
-    private static final QName SIMPLE_VALUE_QNAME = QName.create(TreeComplexUsesAugment.QNAME, "simple-value");
-
-
-   private BindingToNormalizedNodeCodec codec;
-
-    @Override
-    protected void setupWithSchema(final SchemaContext context) {
-        final DataObjectSerializerGenerator streamWriter = StreamWriterGenerator.create(JavassistUtils.forClassPool(ClassPool.getDefault()));
-        final BindingNormalizedNodeCodecRegistry registry = new BindingNormalizedNodeCodecRegistry(streamWriter);
-        codec = new BindingToNormalizedNodeCodec(GeneratedClassLoadingStrategy.getTCCLClassLoadingStrategy(), registry);
-        codec.onGlobalContextUpdated(context);
-    };
-
-    @Test
-    public void testComplexAugmentationSerialization() {
-
-        final PathArgument lastArg = codec.toYangInstanceIdentifier(BA_TREE_COMPLEX_USES).getLastPathArgument();
-        assertTrue(lastArg instanceof AugmentationIdentifier);
-    }
-
-
-    @Test
-    public void testLeafOnlyAugmentationSerialization() {
-
-        final PathArgument leafOnlyLastArg = codec.toYangInstanceIdentifier(BA_TREE_LEAF_ONLY).getLastPathArgument();
-        assertTrue(leafOnlyLastArg instanceof AugmentationIdentifier);
-        assertTrue(((AugmentationIdentifier) leafOnlyLastArg).getPossibleChildNames().contains(SIMPLE_VALUE_QNAME));
-    }
-
-}