Merge "write /nodes/node/table/0 with ensure parents when node first appears"
authorEd Warnicke <eaw@cisco.com>
Fri, 15 Aug 2014 12:48:58 +0000 (12:48 +0000)
committerGerrit Code Review <gerrit@opendaylight.org>
Fri, 15 Aug 2014 12:48:58 +0000 (12:48 +0000)
24 files changed:
opendaylight/config/config-api/src/main/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtil.java
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java [new file with mode: 0644]
opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTracker.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelper.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/ModuleQNameUtil.java
opendaylight/config/config-manager/src/main/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtil.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/InterfacesHelperTest.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java [deleted file]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java [new file with mode: 0644]
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/AbstractTestingFixedThreadPoolModuleFactory.java
opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/testingservices/threadpool/test/SimpleConfigurationTest.java
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail [new file with mode: 0644]
opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok [new file with mode: 0644]
opendaylight/config/netconf-config-dispatcher/pom.xml
opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java [new file with mode: 0644]
opendaylight/config/netty-timer-config/src/test/java/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java [moved from opendaylight/config/netty-timer-config/src/test/org/opendaylight/controller/config/yang/netty/timer/HashedWheelTimerModuleTest.java with 99% similarity]

index d60e608..abb9f1a 100644 (file)
@@ -35,7 +35,6 @@ public class ObjectNameUtil {
     public static final String SERVICE_QNAME_KEY = "serviceQName";
     public static final String INSTANCE_NAME_KEY = "instanceName";
     public static final String TYPE_KEY = ConfigRegistryConstants.TYPE_KEY;
-    public static final String TYPE_CONFIG_REGISTRY = ConfigRegistryConstants.TYPE_CONFIG_REGISTRY;
     public static final String TYPE_CONFIG_TRANSACTION = "ConfigTransaction";
     public static final String TYPE_MODULE = "Module";
     public static final String TYPE_SERVICE_REFERENCE = "ServiceReference";
@@ -43,6 +42,7 @@ public class ObjectNameUtil {
     public static final String TRANSACTION_NAME_KEY = "TransactionName";
     public static final String REF_NAME_KEY = "RefName";
     private static final String REPLACED_QUOTATION_MARK = "\\?";
+    public static final String ON_WILDCARD = "*";
 
     public static ObjectName createON(String on) {
         try {
@@ -304,12 +304,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String moduleName,
                                                  String instanceName) {
-        if (moduleName == null) {
-            moduleName = "*";
-        }
-        if (instanceName == null) {
-            instanceName = "*";
-        }
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         // do not return object names containing transaction name
         ObjectName namePattern = ObjectNameUtil
                 .createON(ObjectNameUtil.ON_DOMAIN + ":"
@@ -323,6 +320,10 @@ public class ObjectNameUtil {
 
     public static ObjectName createModulePattern(String ifcName,
                                                  String instanceName, String transactionName) {
+        ifcName = ifcName == null ? ON_WILDCARD : ifcName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+        transactionName = transactionName == null ? ON_WILDCARD : transactionName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN
                 + ":type=Module," + ObjectNameUtil.MODULE_FACTORY_NAME_KEY
                 + "=" + ifcName + "," + ObjectNameUtil.INSTANCE_NAME_KEY + "="
@@ -332,6 +333,9 @@ public class ObjectNameUtil {
 
     public static ObjectName createRuntimeBeanPattern(String moduleName,
                                                       String instanceName) {
+        moduleName = moduleName == null ? ON_WILDCARD : moduleName;
+        instanceName = instanceName == null ? ON_WILDCARD : instanceName;
+
         return ObjectNameUtil.createON(ObjectNameUtil.ON_DOMAIN + ":"
                 + ObjectNameUtil.TYPE_KEY + "="
                 + ObjectNameUtil.TYPE_RUNTIME_BEAN + ","
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/JmxAttributeValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..7a057bb
--- /dev/null
@@ -0,0 +1,51 @@
+package org.opendaylight.controller.config.api;
+
+import static org.junit.Assert.assertEquals;
+
+import com.google.common.collect.Lists;
+import org.junit.Before;
+import org.junit.Test;
+
+public class JmxAttributeValidationExceptionTest {
+
+    private JmxAttribute jmxAttribute = new JmxAttribute("attr1");
+    private JmxAttribute jmxAttribute2 = new JmxAttribute("attr2");
+
+    @Before
+    public void setUp() throws Exception {
+
+    }
+
+    @Test
+    public void testGetAttributeNames() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckNotNull() throws Exception {
+        try {
+            JmxAttributeValidationException.checkNotNull(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+
+    }
+
+    @Test
+    public void testCheckCondition() throws Exception {
+        try {
+            JmxAttributeValidationException.checkCondition(false, "message", jmxAttribute);
+        } catch (JmxAttributeValidationException e) {
+            assertJmxEx(e, jmxAttribute.getAttributeName() + " " + "message", jmxAttribute);
+        }
+    }
+
+    private void assertJmxEx(JmxAttributeValidationException e, String message, JmxAttribute... attrNames) {
+        assertEquals(message, e.getMessage());
+        assertEquals(Lists.newArrayList(attrNames), e.getAttributeNames());
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/ValidationExceptionTest.java
new file mode 100644 (file)
index 0000000..1809e45
--- /dev/null
@@ -0,0 +1,54 @@
+package org.opendaylight.controller.config.api;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertThat;
+import static org.junit.matchers.JUnitMatchers.containsString;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Test;
+
+public class ValidationExceptionTest {
+
+    private String instance = "instance";
+    private final ModuleIdentifier mi = new ModuleIdentifier("module", instance);
+    private String instance2 = "instance2";
+    private final ModuleIdentifier mi2 = new ModuleIdentifier("module", instance2);
+    private final String message = "ex message";
+    private final Exception e = new IllegalStateException(message);
+
+    @Test
+    public void testCreateFromCollectedValidationExceptions() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi2, e);
+
+        ValidationException collected = ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+
+        Map<String, Map<String, ValidationException.ExceptionMessageWithStackTrace>> failedMap = collected.getFailedValidations();
+        assertEquals(1, failedMap.size());
+        assertTrue(failedMap.containsKey("module"));
+
+        Map<String, ValidationException.ExceptionMessageWithStackTrace> failedModule = failedMap.get("module");
+        assertEquals(2, failedModule.size());
+        assertTrue(failedModule.containsKey(instance));
+        assertEquals(message, failedModule.get(instance).getMessage());
+        assertEquals(message, failedModule.get(instance2).getMessage());
+        assertEquals(failedModule.get(instance), failedModule.get(instance2));
+    }
+
+    @Test
+    public void testCreateFromCollectedValidationExceptionsWithDuplicate() throws Exception {
+        ValidationException single = ValidationException.createForSingleException(mi, e);
+        ValidationException single2 = ValidationException.createForSingleException(mi, e);
+        try {
+            ValidationException.createFromCollectedValidationExceptions(Lists.newArrayList(single, single2));
+        } catch (IllegalArgumentException ex) {
+            // Duplicate exception
+            assertThat(ex.getMessage(), containsString("Cannot merge"));
+            return;
+        }
+        fail("Duplicate exception should have failed");
+    }
+}
\ No newline at end of file
diff --git a/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java b/opendaylight/config/config-api/src/test/java/org/opendaylight/controller/config/api/jmx/ObjectNameUtilTest.java
new file mode 100644 (file)
index 0000000..d3d8469
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2013 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.config.api.jmx;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.base.Throwables;
+import com.google.common.collect.Maps;
+import java.util.Map;
+import javax.management.ObjectName;
+import junit.framework.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+
+public class ObjectNameUtilTest {
+
+    private String moduleName;
+    private String instanceName;
+
+    @Before
+    public void setUp() throws Exception {
+        moduleName = "module";
+        instanceName = "instance";
+    }
+
+    @Test
+    public void testServiceReferenceName() throws Exception {
+        String serviceQName = "(namespace?revision=r)qname";
+        String refName = "refName";
+        String transaction = "transaction";
+
+        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
+        ObjectNameUtil.checkType(serviceReferenceON, ObjectNameUtil.TYPE_SERVICE_REFERENCE);
+
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
+        assertEquals(ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName), ObjectNameUtil.withoutTransactionName(serviceReferenceON));
+
+        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
+        assertFalse(serviceReferenceON.isPattern());
+        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
+        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
+        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
+    }
+
+    @Test
+    public void testModuleName() throws Exception {
+        String txName = "transaction";
+
+        ObjectName on = ObjectNameUtil.createTransactionModuleON(txName, moduleName, instanceName);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_MODULE);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(txName, ObjectNameUtil.getTransactionName(on));
+        assertEquals(4, ObjectNameUtil.getAdditionalProperties(on).size());
+
+        ObjectName withoutTx = ObjectNameUtil.withoutTransactionName(on);
+        assertEquals(ObjectNameUtil.createReadOnlyModuleON(moduleName, instanceName), withoutTx);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(withoutTx));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(withoutTx));
+        assertEquals(null, ObjectNameUtil.getTransactionName(withoutTx));
+        assertEquals(on, ObjectNameUtil.withTransactionName(withoutTx, txName));
+
+        ObjectName pattern = ObjectNameUtil.createModulePattern(moduleName, null);
+        assertPattern(withoutTx, pattern);
+        pattern = ObjectNameUtil.createModulePattern(moduleName, null, txName);
+        assertPattern(on, pattern);
+    }
+
+    private void assertPattern(ObjectName test, ObjectName pattern) {
+        assertTrue(pattern.isPattern());
+        assertTrue(pattern.apply(test));
+    }
+
+    @Test
+    public void testRuntimeBeanName() throws Exception {
+
+        Map<String, String> properties = Maps.newHashMap();
+        properties.put("p1", "value");
+        properties.put("p2", "value2");
+
+        ObjectName on = ObjectNameUtil.createRuntimeBeanName(moduleName, instanceName, properties);
+
+        ObjectNameUtil.checkDomain(on);
+        ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+
+        assertFalse(on.isPattern());
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+        assertEquals(2, ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).size());
+        assertTrue(ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).containsKey("p1"));
+        assertEquals("value", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p1"));
+        assertTrue(ObjectNameUtil.getAdditionalProperties(on).containsKey("p2"));
+        assertEquals("value2", ObjectNameUtil.getAdditionalPropertiesOfRuntimeBeanName(on).get("p2"));
+
+        ObjectName pattern = ObjectNameUtil.createRuntimeBeanPattern(null, instanceName);
+        assertPattern(on, pattern);
+    }
+
+    @Test
+    public void testModuleIdentifier() throws Exception {
+        ModuleIdentifier mi = new ModuleIdentifier(moduleName, instanceName);
+        ObjectName on = ObjectNameUtil.createReadOnlyModuleON(mi);
+        assertEquals(moduleName, ObjectNameUtil.getFactoryName(on));
+        assertEquals(instanceName, ObjectNameUtil.getInstanceName(on));
+
+        assertEquals(mi, ObjectNameUtil.fromON(on, ObjectNameUtil.TYPE_MODULE));
+    }
+
+    @Test
+    public void testChecks() throws Exception {
+        final ObjectName on = ObjectNameUtil.createON("customDomain", ObjectNameUtil.TYPE_KEY, ObjectNameUtil.TYPE_MODULE);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkTypeOneOf(on, ObjectNameUtil.TYPE_RUNTIME_BEAN, ObjectNameUtil.TYPE_CONFIG_TRANSACTION);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkType(on, ObjectNameUtil.TYPE_RUNTIME_BEAN);
+            }
+        }, IllegalArgumentException.class);
+
+        assertFailure(new Runnable() {
+            @Override
+            public void run() {
+                ObjectNameUtil.checkDomain(on);
+            }
+        }, IllegalArgumentException.class);
+    }
+
+    private void assertFailure(Runnable test, Class<? extends Exception> ex) {
+        try {
+            test.run();
+        } catch(Exception e) {
+            Assert.assertTrue("Failed with wrong exception: " + Throwables.getStackTraceAsString(e),
+                    e.getClass().isAssignableFrom(ex));
+            return;
+        }
+
+        fail(test + " should have failed on " + ex);
+    }
+}
index 720b719..375ef59 100644 (file)
@@ -7,6 +7,8 @@
  */
 package org.opendaylight.controller.config.manager.impl.osgi;
 
+import com.google.common.annotations.VisibleForTesting;
+import javax.management.ObjectName;
 import org.opendaylight.controller.config.api.ConflictingVersionException;
 import org.opendaylight.controller.config.api.ValidationException;
 import org.opendaylight.controller.config.api.jmx.CommitStatus;
@@ -17,8 +19,6 @@ import org.osgi.util.tracker.ServiceTrackerCustomizer;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.management.ObjectName;
-
 /**
  * Every time factory is added or removed, blank transaction is triggered to handle
  * {@link org.opendaylight.controller.config.spi.ModuleFactory#getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory, org.osgi.framework.BundleContext)}
@@ -27,10 +27,29 @@ import javax.management.ObjectName;
 public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<ModuleFactory, Object> {
     private static final Logger logger = LoggerFactory.getLogger(BlankTransactionServiceTracker.class);
 
-    private final ConfigRegistryImpl configRegistry;
+    public static final int DEFAULT_MAX_ATTEMPTS = 10;
 
-    public BlankTransactionServiceTracker(ConfigRegistryImpl configRegistry) {
-        this.configRegistry = configRegistry;
+    private final BlankTransaction blankTransaction;
+    private int maxAttempts;
+
+    public BlankTransactionServiceTracker(final ConfigRegistryImpl configRegistry) {
+        this(new BlankTransaction() {
+            @Override
+            public CommitStatus hit() throws ValidationException, ConflictingVersionException {
+                ObjectName tx = configRegistry.beginConfig(true);
+                return configRegistry.commitConfig(tx);
+            }
+        });
+    }
+
+    public BlankTransactionServiceTracker(final BlankTransaction blankTransaction) {
+        this(blankTransaction, DEFAULT_MAX_ATTEMPTS);
+    }
+
+    @VisibleForTesting
+    BlankTransactionServiceTracker(final BlankTransaction blankTx, final int maxAttempts) {
+        this.blankTransaction = blankTx;
+        this.maxAttempts = maxAttempts;
     }
 
     @Override
@@ -42,13 +61,10 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     synchronized void blankTransaction() {
         // race condition check: config-persister might push new configuration while server is starting up.
         ConflictingVersionException lastException = null;
-        int maxAttempts = 10;
         for (int i = 0; i < maxAttempts; i++) {
             try {
                 // create transaction
-                boolean blankTransaction = true;
-                ObjectName tx = configRegistry.beginConfig(blankTransaction);
-                CommitStatus commitStatus = configRegistry.commitConfig(tx);
+                CommitStatus commitStatus = blankTransaction.hit();
                 logger.debug("Committed blank transaction with status {}", commitStatus);
                 return;
             } catch (ConflictingVersionException e) {
@@ -77,4 +93,9 @@ public class BlankTransactionServiceTracker implements ServiceTrackerCustomizer<
     public void removedService(ServiceReference<ModuleFactory> moduleFactoryServiceReference, Object o) {
         blankTransaction();
     }
+
+    @VisibleForTesting
+    static interface BlankTransaction {
+        CommitStatus hit() throws ValidationException, ConflictingVersionException;
+    }
 }
index 05ca43c..3015ed2 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.osgi;
 
 import static java.lang.String.format;
 
+import com.google.common.annotations.VisibleForTesting;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.List;
@@ -70,9 +71,10 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
         blankTransactionServiceTracker.blankTransaction();
     }
 
-    // TODO:test
-    private static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
+    @VisibleForTesting
+    protected static ServiceRegistration<?> registerFactory(String factoryClassName, Bundle bundle) {
         String errorMessage;
+        Exception ex = null;
         try {
             Class<?> clazz = bundle.loadClass(factoryClassName);
             if (ModuleFactory.class.isAssignableFrom(clazz)) {
@@ -86,10 +88,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
                     errorMessage = logMessage(
                             "Could not instantiate {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 } catch (IllegalAccessException e) {
                     errorMessage = logMessage(
-                            "Illegal access during instatiation of class {} in bundle {}, reason {}",
+                            "Illegal access during instantiation of class {} in bundle {}, reason {}",
                             factoryClassName, bundle, e);
+                    ex = e;
                 }
             } else {
                 errorMessage = logMessage(
@@ -98,10 +102,12 @@ public class ModuleFactoryBundleTracker implements BundleTrackerCustomizer<Objec
             }
         } catch (ClassNotFoundException e) {
             errorMessage = logMessage(
-                    "Could not find class {} in bunde {}, reason {}",
+                    "Could not find class {} in bundle {}, reason {}",
                     factoryClassName, bundle, e);
+            ex = e;
         }
-        throw new IllegalStateException(errorMessage);
+
+        throw ex == null ? new IllegalStateException(errorMessage) : new IllegalStateException(errorMessage, ex);
     }
 
     public static String logMessage(String slfMessage, Object... params) {
index a6e9b1b..510fdf9 100644 (file)
@@ -109,7 +109,6 @@ public class InterfacesHelper {
      */
     public static Set<Class<?>> getOsgiRegistrationTypes(
             Class<? extends Module> configBeanClass) {
-        // TODO test with service interface hierarchy
         Set<Class<?>> serviceInterfaces = getServiceInterfaces(configBeanClass);
         Set<Class<?>> result = new HashSet<>();
         for (Class<?> clazz : serviceInterfaces) {
index e843377..f1072a7 100644 (file)
@@ -9,6 +9,7 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import org.opendaylight.controller.config.spi.ModuleFactory;
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
+import org.opendaylight.yangtools.yang.common.QName;
 import org.osgi.framework.BundleContext;
 
 import java.util.HashSet;
@@ -31,9 +32,7 @@ public class ModuleQNameUtil {
                 inspected = inspected.getSuperclass();
             }
             if (annotation != null) {
-                // FIXME
-                String qName = "(" + annotation.namespace() + "?revision=" + annotation.revision() + ")" + annotation.name();
-                result.add(qName);
+                result.add(QName.create(annotation.namespace(), annotation.revision(), annotation.name()).toString());
             }
         }
         return result;
index 8873596..2df28f0 100644 (file)
@@ -8,6 +8,11 @@
 
 package org.opendaylight.controller.config.manager.impl.util;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.ListIterator;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.BundleTracker;
@@ -15,12 +20,6 @@ import org.osgi.util.tracker.ServiceTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.ArrayList;
-import java.util.List;
-import java.util.ListIterator;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-
 public class OsgiRegistrationUtil {
     private static final Logger logger = LoggerFactory.getLogger(OsgiRegistrationUtil.class);
 
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BlankTransactionServiceTrackerTest.java
new file mode 100644 (file)
index 0000000..471c98a
--- /dev/null
@@ -0,0 +1,83 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.assertSame;
+import static junit.framework.Assert.fail;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import java.util.Collections;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ModuleIdentifier;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.ServiceReference;
+
+public class BlankTransactionServiceTrackerTest {
+
+    @Mock
+    private BlankTransactionServiceTracker.BlankTransaction blankTx;
+    private BlankTransactionServiceTracker tracker;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn(new CommitStatus(Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList(), Collections.<ObjectName>emptyList())).when(blankTx).hit();
+        tracker = new BlankTransactionServiceTracker(blankTx);
+    }
+
+    @Test
+    public void testBlankTransaction() throws Exception {
+        tracker.addingService(getMockServiceReference());
+        tracker.modifiedService(getMockServiceReference(), null);
+        tracker.removedService(getMockServiceReference(), null);
+        verify(blankTx, times(3)).hit();
+    }
+
+    @Test
+    public void testValidationException() throws Exception {
+        IllegalArgumentException argumentException = new IllegalArgumentException();
+        ValidationException validationException = ValidationException.createForSingleException(new ModuleIdentifier("m", "i"), argumentException);
+        doThrow(validationException).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(1)).hit();
+            assertNotNull(e.getCause());
+            assertSame(validationException, e.getCause());
+            return;
+        }
+
+        fail("Exception should have occurred for validation exception");
+    }
+
+    @Test
+    public void testConflictingException() throws Exception {
+        int maxAttempts = 2;
+        tracker = new BlankTransactionServiceTracker(blankTx, maxAttempts);
+
+        final ConflictingVersionException ex = new ConflictingVersionException();
+        doThrow(ex).when(blankTx).hit();
+        try {
+            tracker.addingService(getMockServiceReference());
+        } catch (Exception e) {
+            verify(blankTx, times(maxAttempts)).hit();
+            return;
+        }
+
+        fail("Exception should have occurred for conflicting exception");
+    }
+
+    private ServiceReference<ModuleFactory> getMockServiceReference() {
+        return mock(ServiceReference.class);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/BundleContextBackedModuleFactoriesResolverTest.java
new file mode 100644 (file)
index 0000000..dc3dedd
--- /dev/null
@@ -0,0 +1,104 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.fail;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+import com.google.common.collect.Lists;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+
+public class BundleContextBackedModuleFactoriesResolverTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    private BundleContextBackedModuleFactoriesResolver resolver;
+    private ServiceReference s1;
+    private ServiceReference s2;
+    private ModuleFactory f1;
+    private ModuleFactory f2;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        s1 = getServiceRef();
+        s2 = getServiceRef();
+        doReturn(Lists.newArrayList(s1, s2)).when(bundleContext).getServiceReferences(ModuleFactory.class, null);
+        f1 = getMockFactory("f1");
+        doReturn(f1).when(bundleContext).getService(s1);
+        f2 = getMockFactory("f2");
+        doReturn(f2).when(bundleContext).getService(s2);
+        resolver = new BundleContextBackedModuleFactoriesResolver(bundleContext);
+    }
+
+    private ModuleFactory getMockFactory(String name) {
+        ModuleFactory mock = mock(ModuleFactory.class);
+        doReturn(name).when(mock).toString();
+        doReturn(name).when(mock).getImplementationName();
+        return mock;
+    }
+
+    private ServiceReference getServiceRef() {
+        ServiceReference mock = mock(ServiceReference.class);
+        doReturn("serviceRef").when(mock).toString();
+        final Bundle bundle = mock(Bundle.class);
+        doReturn(bundleContext).when(bundle).getBundleContext();
+        doReturn(bundle).when(mock).getBundle();
+        return mock;
+    }
+
+    @Test
+    public void testGetAllFactories() throws Exception {
+        Map<String, Map.Entry<ModuleFactory, BundleContext>> allFactories = resolver.getAllFactories();
+        assertEquals(2, allFactories.size());
+        assertTrue(allFactories.containsKey(f1.getImplementationName()));
+        assertEquals(f1, allFactories.get(f1.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f1.getImplementationName()).getValue());
+        assertTrue(allFactories.containsKey(f2.getImplementationName()));
+        assertEquals(f2, allFactories.get(f2.getImplementationName()).getKey());
+        assertEquals(bundleContext, allFactories.get(f2.getImplementationName()).getValue());
+    }
+
+    @Test
+    public void testDuplicateFactories() throws Exception {
+        doReturn(f1).when(bundleContext).getService(s2);
+        try {
+            resolver.getAllFactories();
+        } catch (Exception e) {
+            assertThat(e.getMessage(), containsString(f1.getImplementationName()));
+            assertThat(e.getMessage(), containsString("unique"));
+            return;
+        }
+
+        fail("Should fail with duplicate factory name");
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullFactory() throws Exception {
+        doReturn(null).when(bundleContext).getService(s2);
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testNullFactoryName() throws Exception {
+        doReturn(null).when(f1).getImplementationName();
+        resolver.getAllFactories();
+    }
+
+    @Test(expected = NullPointerException.class)
+    public void testNullBundleName() throws Exception {
+        doReturn(null).when(s1).getBundle();
+        resolver.getAllFactories();
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ExtensibleBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..9a3ba64
--- /dev/null
@@ -0,0 +1,76 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import com.google.common.util.concurrent.Futures;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+
+public class ExtensibleBundleTrackerTest {
+
+    @Mock
+    private BundleContext bundleContext;
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleEvent bundleEvent;
+
+    @Mock
+    private BundleTrackerCustomizer<Object> primaryTracker;
+    @Mock
+    private BundleTrackerCustomizer<?> additionalTracker;
+
+    private ExtensibleBundleTracker<Object> extensibleBundleTracker;
+    private Object primaryValue = new Object();
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doReturn("bundle").when(bundle).toString();
+        doReturn("bundleEvent").when(bundleEvent).toString();
+
+        doReturn(primaryValue).when(primaryTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(primaryTracker).modifiedBundle(bundle, bundleEvent, primaryValue);
+        doNothing().when(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+
+        doReturn(new Object()).when(additionalTracker).addingBundle(bundle, bundleEvent);
+        doNothing().when(additionalTracker).modifiedBundle(bundle, bundleEvent, null);
+        doNothing().when(additionalTracker).removedBundle(bundle, bundleEvent, null);
+        extensibleBundleTracker = new ExtensibleBundleTracker<>(bundleContext, primaryTracker, additionalTracker);
+    }
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        assertEquals(primaryValue, extensibleBundleTracker.addingBundle(bundle, bundleEvent).get());
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).addingBundle(bundle, bundleEvent);
+        inOrder.verify(additionalTracker).addingBundle(bundle, bundleEvent);
+    }
+
+    @Test
+    public void testRemovedBundle() throws Exception {
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFuture(primaryValue));
+        InOrder inOrder = Mockito.inOrder(primaryTracker, additionalTracker);
+        inOrder.verify(primaryTracker).removedBundle(bundle, bundleEvent, primaryValue);
+        inOrder.verify(additionalTracker).removedBundle(bundle, bundleEvent, null);
+    }
+
+    @Test
+    public void testRemovedBundleWithEx() throws Exception {
+        IllegalStateException throwable = new IllegalStateException();
+        extensibleBundleTracker.removedBundle(bundle, bundleEvent, Futures.immediateFailedFuture(throwable));
+        verifyZeroInteractions(primaryTracker);
+        verifyZeroInteractions(additionalTracker);
+    }
+}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/osgi/ModuleFactoryBundleTrackerTest.java
new file mode 100644 (file)
index 0000000..5b83412
--- /dev/null
@@ -0,0 +1,193 @@
+package org.opendaylight.controller.config.manager.impl.osgi;
+
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
+import static junit.framework.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyObject;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyZeroInteractions;
+
+import java.util.Dictionary;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.opendaylight.controller.config.api.DependencyResolver;
+import org.opendaylight.controller.config.api.DependencyResolverFactory;
+import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
+import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.spi.Module;
+import org.opendaylight.controller.config.spi.ModuleFactory;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.ServiceRegistration;
+
+public class ModuleFactoryBundleTrackerTest {
+
+    @Mock
+    private Bundle bundle;
+    @Mock
+    private BundleContext context;
+    @Mock
+    private ServiceRegistration<?> reg;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        doAnswer(new Answer() {
+            @Override
+            public Object answer(final InvocationOnMock invocation) throws Throwable {
+                return getClass().getClassLoader().loadClass((String) invocation.getArguments()[0]);
+            }
+        }).when(bundle).loadClass(anyString());
+        doReturn("mockBundle").when(bundle).toString();
+        doReturn(context).when(bundle).getBundleContext();
+        doReturn(reg).when(context).registerService(anyString(), anyObject(), any(Dictionary.class));
+    }
+
+    @Test
+    public void testRegisterFactory() throws Exception {
+        ModuleFactoryBundleTracker.registerFactory(TestingFactory.class.getName(), bundle);
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateEx() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(WrongConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(InstantiationException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryInstantiateExAccess() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NoAccessConstructorTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(IllegalAccessException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without proper constructor");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExtending() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory(NotExtendingTestingFactory.class.getName(), bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Test
+    public void testRegisterFactoryNotExisting() throws Exception {
+        try {
+            ModuleFactoryBundleTracker.registerFactory("Unknown class", bundle);
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            assertNotNull(e.getCause());
+            assertEquals(ClassNotFoundException.class, e.getCause().getClass());
+            return;
+        }
+
+        fail("Cannot register without extend");
+    }
+
+    @Mock
+    private BlankTransactionServiceTracker blankTxTracker;
+
+    @Test
+    public void testAddingBundle() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-ok")).when(bundle).getEntry(anyString());
+        tracker.addingBundle(bundle, mock(BundleEvent.class));
+        verify(context).registerService(ModuleFactory.class.getName(), TestingFactory.currentInstance, null);
+    }
+
+    @Test
+    public void testAddingBundleError() throws Exception {
+        final ModuleFactoryBundleTracker tracker = new ModuleFactoryBundleTracker(blankTxTracker);
+        doReturn(getClass().getResource("/module-factories/module-factory-fail")).when(bundle).getEntry(anyString());
+        try {
+            tracker.addingBundle(bundle, mock(BundleEvent.class));
+        } catch (Exception e) {
+            verifyZeroInteractions(context);
+            return;
+        }
+
+        fail("Cannot register");
+    }
+
+    static class WrongConstructorTestingFactory extends TestingFactory {
+        WrongConstructorTestingFactory(String randomParam) {
+        }
+    }
+
+    static class NotExtendingTestingFactory {}
+
+    static class NoAccessConstructorTestingFactory extends TestingFactory {
+        private NoAccessConstructorTestingFactory() {
+        }
+    }
+
+    static class TestingFactory implements ModuleFactory {
+
+        static TestingFactory currentInstance;
+
+        TestingFactory() {
+            currentInstance = this;
+        }
+
+        @Override
+        public String getImplementationName() {
+            return "Testing";
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Module createModule(final String instanceName, final DependencyResolver dependencyResolver, final DynamicMBeanWithInstance old, final BundleContext bundleContext) throws Exception {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public boolean isModuleImplementingServiceInterface(final Class<? extends AbstractServiceInterface> serviceInterface) {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<Class<? extends AbstractServiceInterface>> getImplementedServiceIntefaces() {
+            throw new UnsupportedOperationException();
+        }
+
+        @Override
+        public Set<? extends Module> getDefaultModules(final DependencyResolverFactory dependencyResolverFactory, final BundleContext bundleContext) {
+            throw new UnsupportedOperationException();
+        }
+    }
+}
index 22ea528..220bef0 100644 (file)
@@ -9,20 +9,19 @@ package org.opendaylight.controller.config.manager.impl.util;
 
 import static org.junit.Assert.assertEquals;
 
+import com.google.common.collect.Sets;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.Set;
-
 import javax.management.MXBean;
-
 import org.junit.Test;
 import org.opendaylight.controller.config.api.annotations.AbstractServiceInterface;
+import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingScheduledThreadPoolServiceInterface;
 import org.opendaylight.controller.config.manager.testingservices.seviceinterface.TestingThreadPoolServiceInterface;
 import org.opendaylight.controller.config.spi.Module;
 import org.opendaylight.yangtools.concepts.Identifiable;
 
-import com.google.common.collect.Sets;
-
 public class InterfacesHelperTest {
 
     interface SuperA {
@@ -46,10 +45,19 @@ public class InterfacesHelperTest {
 
     }
 
+    @ServiceInterfaceAnnotation(value = "a", osgiRegistrationType = SuperA.class, namespace = "n", revision = "r", localName = "l")
+    interface Service extends AbstractServiceInterface{}
+    @ServiceInterfaceAnnotation(value = "b", osgiRegistrationType = SuperC.class, namespace = "n", revision = "r", localName = "l")
+    interface SubService extends Service{}
+
     abstract class SubClass extends SuperClass implements SubA, Module {
 
     }
 
+    abstract class SubClassWithService implements SubService, Module {
+
+    }
+
     @Test
     public void testGetAllInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperA.class, SuperBMXBean.class, SuperC.class,
@@ -58,6 +66,19 @@ public class InterfacesHelperTest {
                 InterfacesHelper.getAllInterfaces(SubClass.class));
     }
 
+    @Test
+    public void testGetServiceInterfaces() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getServiceInterfaces(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(Service.class, SubService.class), InterfacesHelper.getServiceInterfaces(SubClassWithService.class));
+    }
+
+    @Test
+    public void testGetOsgiRegistrationTypes() throws Exception {
+        assertEquals(Collections.<Class<?>>emptySet(), InterfacesHelper.getOsgiRegistrationTypes(SubClass.class));
+        assertEquals(Sets.<Class<?>>newHashSet(SuperA.class, SuperC.class),
+                InterfacesHelper.getOsgiRegistrationTypes(SubClassWithService.class));
+    }
+
     @Test
     public void testGetMXInterfaces() {
         Set<Class<?>> expected = Sets.<Class<?>> newHashSet(SuperBMXBean.class, SubA.class);
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/ObjectNameUtilTest.java
deleted file mode 100644 (file)
index fe32289..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2013 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.config.manager.impl.util;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.Sets;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
-import org.opendaylight.controller.config.manager.impl.AbstractLockedPlatformMBeanServerTest;
-
-import javax.management.ObjectName;
-import java.util.Set;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-
-public class ObjectNameUtilTest extends AbstractLockedPlatformMBeanServerTest {
-    private Set<ObjectName> unregisterONs;
-
-    @Before
-    public void initUnregisterList() {
-        unregisterONs = Sets.newHashSet();
-    }
-
-    @After
-    public void unregisterONs() {
-        Exception lastException = null;
-        for (ObjectName on : unregisterONs) {
-            try {
-                platformMBeanServer.unregisterMBean(on);
-            } catch (Exception e) {
-                lastException = e;
-            }
-        }
-        if (lastException != null) {
-            throw Throwables.propagate(lastException);
-        }
-    }
-
-    @Test
-    public void testQuotation() throws Exception {
-        String serviceQName = "(namespace?revision=r)qname";
-        String refName = "refName";
-        String transaction = "transaction";
-        ObjectName serviceReferenceON = ObjectNameUtil.createTransactionServiceON(transaction, serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(transaction, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-        serviceReferenceON = ObjectNameUtil.createReadOnlyServiceON(serviceQName, refName);
-        assertFalse(serviceReferenceON.isPattern());
-        assertEquals(serviceQName, ObjectNameUtil.getServiceQName(serviceReferenceON));
-        assertEquals(refName, ObjectNameUtil.getReferenceName(serviceReferenceON));
-        assertEquals(null, ObjectNameUtil.getTransactionName(serviceReferenceON));
-
-    }
-}
diff --git a/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java b/opendaylight/config/config-manager/src/test/java/org/opendaylight/controller/config/manager/impl/util/OsgiRegistrationUtilTest.java
new file mode 100644 (file)
index 0000000..fb59e3d
--- /dev/null
@@ -0,0 +1,61 @@
+package org.opendaylight.controller.config.manager.impl.util;
+
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+
+import org.junit.Test;
+import org.mockito.InOrder;
+import org.mockito.Mockito;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class OsgiRegistrationUtilTest {
+
+    @Test
+    public void testRegisterService() throws Exception {
+        final BundleContext bundleContext = mock(BundleContext.class);
+        ServiceRegistration<?> registration = mockServiceRegistration();
+        doReturn(registration).when(bundleContext).registerService(String.class, "string", null);
+        ServiceRegistration<?> registration2 = mockServiceRegistration();
+        doReturn(registration2).when(bundleContext).registerService(Object.class, "string", null);
+
+        AutoCloseable aggregatedRegister = OsgiRegistrationUtil.registerService(bundleContext, "string", String.class, Object.class);
+        aggregatedRegister.close();
+
+        InOrder inOrder = Mockito.inOrder(registration, registration2);
+        inOrder.verify(registration2).unregister();
+        inOrder.verify(registration).unregister();
+    }
+
+    @Test
+    public void testWrap() throws Exception {
+        final ServiceRegistration<?> serviceReg = mockServiceRegistration();
+        OsgiRegistrationUtil.wrap(serviceReg).close();
+        verify(serviceReg).unregister();
+
+        final BundleTracker tracker = mock(BundleTracker.class);
+        doNothing().when(tracker).close();
+        OsgiRegistrationUtil.wrap(tracker).close();
+        verify(tracker).close();
+
+        final ServiceTracker<?, ?> sTracker = mock(ServiceTracker.class);
+        doNothing().when(sTracker).close();
+        OsgiRegistrationUtil.wrap(sTracker).close();
+        verify(sTracker).close();
+    }
+
+    private ServiceRegistration<?> mockServiceRegistration() {
+        ServiceRegistration mock = mock(ServiceRegistration.class);
+        doNothing().when(mock).unregister();
+        return mock;
+    }
+
+    @Test
+    public void testAggregate() throws Exception {
+
+    }
+}
\ No newline at end of file
index 0286400..a7024ca 100644 (file)
@@ -9,6 +9,6 @@ package org.opendaylight.controller.config.manager.testingservices.threadpool;
 
 import org.opendaylight.yangtools.yang.binding.annotations.ModuleQName;
 
-@ModuleQName(namespace = "namespace", revision = "revision", name = "name")
+@ModuleQName(namespace = "namespace", revision = "2012-12-12", name = "name")
 public abstract class AbstractTestingFixedThreadPoolModuleFactory {
 }
index 97d1c63..4ba3dc8 100644 (file)
@@ -380,7 +380,8 @@ public class SimpleConfigurationTest extends AbstractConfigTest {
     @Test
     public void testQNames() {
         Set<String> availableModuleFactoryQNames = configRegistryClient.getAvailableModuleFactoryQNames();
-        String expected = "(namespace?revision=revision)name";
+        String expected = "(namespace?revision=2012-12-12)name";
+
         assertEquals(Sets.newHashSet(expected), availableModuleFactoryQNames);
     }
 
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-fail
new file mode 100644 (file)
index 0000000..fbd8108
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$NotExtendingTestingFactory
\ No newline at end of file
diff --git a/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok b/opendaylight/config/config-manager/src/test/resources/module-factories/module-factory-ok
new file mode 100644 (file)
index 0000000..031b622
--- /dev/null
@@ -0,0 +1 @@
+org.opendaylight.controller.config.manager.impl.osgi.ModuleFactoryBundleTrackerTest$TestingFactory
\ No newline at end of file
index b9d218e..1e5fcce 100644 (file)
       <groupId>${project.groupId}</groupId>
       <artifactId>netconf-client</artifactId>
     </dependency>
+
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <type>test-jar</type>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-manager</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>config-util</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-threadgroup-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>${project.groupId}</groupId>
+          <artifactId>netty-timer-config</artifactId>
+          <scope>test</scope>
+      </dependency>
+      <dependency>
+          <groupId>org.opendaylight.yangtools</groupId>
+          <artifactId>mockito-configuration</artifactId>
+          <scope>test</scope>
+      </dependency>
   </dependencies>
 
   <build>
diff --git a/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java b/opendaylight/config/netconf-config-dispatcher/src/test/java/org/opendaylight/controller/config/yang/config/netconf/client/dispatcher/NetconfClientDispatcherModuleTest.java
new file mode 100644 (file)
index 0000000..85477a0
--- /dev/null
@@ -0,0 +1,102 @@
+package org.opendaylight.controller.config.yang.config.netconf.client.dispatcher;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.InstanceNotFoundException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleFactory;
+import org.opendaylight.controller.config.yang.netty.threadgroup.NettyThreadgroupModuleMXBean;
+import org.opendaylight.controller.config.yang.netty.timer.HashedWheelTimerModuleFactory;
+
+public class NetconfClientDispatcherModuleTest extends AbstractConfigTest{
+
+    private NetconfClientDispatcherModuleFactory factory;
+    private final String instanceName = "dispatch";
+
+    @Before
+    public void setUp() {
+        factory = new NetconfClientDispatcherModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory,
+                new NettyThreadgroupModuleFactory(),
+                new HashedWheelTimerModuleFactory()));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException, ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName, "timer", "thGroup");
+        createInstance(transaction, instanceName + 2, "timer2", "thGroup2");
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(2, factory.getImplementationName());
+        assertStatus(status, 2 + 4, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException, ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 3);
+    }
+
+    @Test
+    public void testReconfigure() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException, InstanceNotFoundException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName, "timer", "thGroup");
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(
+                transaction.lookupConfigBean(NetconfClientDispatcherModuleFactory.NAME, instanceName),
+                NetconfClientDispatcherModuleMXBean.class);
+        mxBean.setBossThreadGroup(getThreadGroup(transaction, "group2"));
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 1, 2);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName, String timerName, String threadGroupName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        NetconfClientDispatcherModuleMXBean mxBean = transaction.newMBeanProxy(nameCreated, NetconfClientDispatcherModuleMXBean.class);
+        ObjectName thGroup = getThreadGroup(transaction, threadGroupName);
+        mxBean.setBossThreadGroup(thGroup);
+        mxBean.setWorkerThreadGroup(thGroup);
+        mxBean.setTimer(getTimer(transaction, timerName));
+        return nameCreated;
+    }
+
+    private ObjectName getTimer(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        return transaction.createModule(HashedWheelTimerModuleFactory.NAME, name);
+    }
+
+    private ObjectName getThreadGroup(ConfigTransactionJMXClient transaction, String name) throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(NettyThreadgroupModuleFactory.NAME, name);
+        NettyThreadgroupModuleMXBean mxBean = transaction.newMXBeanProxy(nameCreated, NettyThreadgroupModuleMXBean.class);
+        mxBean.setThreadCount(1);
+        return nameCreated;
+    }
+}
diff --git a/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java b/opendaylight/config/netty-event-executor-config/src/test/java/org/opendaylight/controller/config/yang/netty/eventexecutor/ImmediateEventExecutorModuleTest.java
new file mode 100644 (file)
index 0000000..4cc9cc3
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2013 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.config.yang.netty.eventexecutor;
+
+import javax.management.InstanceAlreadyExistsException;
+import javax.management.ObjectName;
+import org.junit.Before;
+import org.junit.Test;
+import org.opendaylight.controller.config.api.ConflictingVersionException;
+import org.opendaylight.controller.config.api.ValidationException;
+import org.opendaylight.controller.config.api.jmx.CommitStatus;
+import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
+import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
+import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
+
+public class ImmediateEventExecutorModuleTest extends AbstractConfigTest {
+
+    private GlobalEventExecutorModuleFactory factory;
+    private final String instanceName = ImmediateEventExecutorModuleFactory.SINGLETON_NAME;
+
+    @Before
+    public void setUp() {
+        factory = new GlobalEventExecutorModuleFactory();
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext,factory));
+    }
+
+    @Test
+    public void testCreateBean() throws InstanceAlreadyExistsException, ValidationException,
+            ConflictingVersionException {
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+
+        createInstance(transaction, instanceName);
+
+        transaction.validateConfig();
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 1, 0, 0);
+    }
+
+    @Test
+    public void testReusingOldInstance() throws InstanceAlreadyExistsException, ConflictingVersionException,
+            ValidationException {
+
+        ConfigTransactionJMXClient transaction = configRegistryClient.createTransaction();
+        createInstance(transaction, instanceName);
+
+        transaction.commit();
+
+        transaction = configRegistryClient.createTransaction();
+        assertBeanCount(1, factory.getImplementationName());
+        CommitStatus status = transaction.commit();
+
+        assertBeanCount(1, factory.getImplementationName());
+        assertStatus(status, 0, 0, 1);
+    }
+
+    private ObjectName createInstance(ConfigTransactionJMXClient transaction, String instanceName)
+            throws InstanceAlreadyExistsException {
+        ObjectName nameCreated = transaction.createModule(factory.getImplementationName(), instanceName);
+        transaction.newMBeanProxy(nameCreated, ImmediateEventExecutorModuleMXBean.class);
+        return nameCreated;
+    }
+
+}
@@ -34,7 +34,7 @@ public class HashedWheelTimerModuleTest extends AbstractConfigTest {
     public void setUp() {
         factory = new HashedWheelTimerModuleFactory();
         threadFactory = new NamingThreadFactoryModuleFactory();
-        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(factory, threadFactory));
+        super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(mockedContext, factory, threadFactory));
     }
 
     public void testValidationExceptionTickDuration() throws InstanceAlreadyExistsException {