2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
4 * This program and the accompanying materials are made available under the
5 * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6 * and is available at http://www.eclipse.org/legal/epl-v10.html
8 package org.opendaylight.controller.config.manager.impl;
10 import com.google.common.base.Preconditions;
11 import junit.framework.Assert;
12 import org.junit.After;
13 import org.mockito.Matchers;
14 import org.mockito.invocation.InvocationOnMock;
15 import org.mockito.stubbing.Answer;
16 import org.opendaylight.controller.config.api.jmx.CommitStatus;
17 import org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver;
18 import org.opendaylight.controller.config.manager.impl.jmx.BaseJMXRegistrator;
19 import org.opendaylight.controller.config.manager.impl.jmx.ConfigRegistryJMXRegistrator;
20 import org.opendaylight.controller.config.manager.impl.jmx.InternalJMXRegistrator;
21 import org.opendaylight.controller.config.manager.testingservices.scheduledthreadpool.TestingScheduledThreadPoolImpl;
22 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
23 import org.opendaylight.controller.config.spi.Module;
24 import org.opendaylight.controller.config.util.ConfigRegistryJMXClient;
25 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
26 import org.osgi.framework.BundleContext;
27 import org.osgi.framework.ServiceRegistration;
28 import org.slf4j.Logger;
29 import org.slf4j.LoggerFactory;
31 import javax.management.InstanceAlreadyExistsException;
32 import javax.management.MBeanServer;
33 import javax.management.ObjectName;
34 import java.io.Closeable;
35 import java.io.InputStream;
36 import java.lang.management.ManagementFactory;
37 import java.util.ArrayList;
38 import java.util.Collection;
39 import java.util.Collections;
40 import java.util.Dictionary;
41 import java.util.List;
44 import static org.junit.Assert.assertEquals;
45 import static org.mockito.Matchers.any;
46 import static org.mockito.Mockito.doAnswer;
47 import static org.mockito.Mockito.doNothing;
48 import static org.mockito.Mockito.mock;
51 * Each test that relies on
52 * {@link org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl}
53 * needs to subclass this test.
54 * {@link org.opendaylight.controller.config.manager.impl.ConfigRegistryImpl} is
55 * registered to platform MBean Server using
56 * {@link #initConfigTransactionManagerImpl(org.opendaylight.controller.config.manager.impl.factoriesresolver.ModuleFactoriesResolver)}
57 * typically during setting up the each test.
59 public abstract class AbstractConfigTest extends
60 AbstractLockedPlatformMBeanServerTest {
61 protected ConfigRegistryJMXRegistrator configRegistryJMXRegistrator;
62 protected ConfigRegistryImpl configRegistry;
63 protected ConfigRegistryJMXClient configRegistryClient;
64 protected BaseJMXRegistrator baseJmxRegistrator;
65 protected InternalJMXRegistrator internalJmxRegistrator;
66 protected BundleContext mockedContext = mock(BundleContext.class);
67 protected ServiceRegistration<?> mockedServiceRegistration;
69 private static final Logger logger = LoggerFactory.getLogger(AbstractConfigTest.class);
71 // Default handler for OSGi service registration
72 private static final BundleContextServiceRegistrationHandler noopServiceRegHandler = new BundleContextServiceRegistrationHandler() {
74 public void handleServiceRegistration(Object serviceInstance) {}
77 protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(Class<?> serviceType) {
78 return noopServiceRegHandler;
81 // this method should be called in @Before
82 protected void initConfigTransactionManagerImpl(
83 ModuleFactoriesResolver resolver) {
84 final MBeanServer platformMBeanServer = ManagementFactory
85 .getPlatformMBeanServer();
87 configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
91 internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
92 baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
94 configRegistry = new ConfigRegistryImpl(resolver,
95 platformMBeanServer, baseJmxRegistrator);
98 configRegistryJMXRegistrator.registerToJMX(configRegistry);
99 } catch (InstanceAlreadyExistsException e) {
100 throw new RuntimeException(e);
102 configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
105 private void initBundleContext() {
106 this.mockedServiceRegistration = mock(ServiceRegistration.class);
107 doNothing().when(mockedServiceRegistration).unregister();
109 RegisterServiceAnswer answer = new RegisterServiceAnswer();
111 doAnswer(answer).when(mockedContext).registerService(Matchers.any(String[].class),
112 any(Closeable.class), Matchers.<Dictionary<String, ?>>any());
113 doAnswer(answer).when(mockedContext).registerService(Matchers.<Class<Closeable>>any(), any(Closeable.class),
114 Matchers.<Dictionary<String, ?>>any());
118 public Collection<InputStream> getFilesAsInputStreams(List<String> paths) {
119 final Collection<InputStream> resources = new ArrayList<>();
120 List<String> failedToFind = new ArrayList<>();
121 for (String path : paths) {
122 InputStream resourceAsStream = getClass().getResourceAsStream(path);
123 if (resourceAsStream == null) {
124 failedToFind.add(path);
126 resources.add(resourceAsStream);
129 Assert.assertEquals("Some files were not found", Collections.<String>emptyList(), failedToFind);
135 public final void cleanUpConfigTransactionManagerImpl() {
136 configRegistryJMXRegistrator.close();
137 configRegistry.close();
138 TestingFixedThreadPool.cleanUp();
139 TestingScheduledThreadPoolImpl.cleanUp();
143 * Can be called in @After of tests if some other cleanup is needed that
144 * would be discarded by closing config beans in this method
146 protected void destroyAllConfigBeans() throws Exception {
147 ConfigTransactionJMXClient transaction = configRegistryClient
148 .createTransaction();
149 Set<ObjectName> all = transaction.lookupConfigBeans();
150 // workaround for getting same Module more times
151 while (all.size() > 0) {
152 transaction.destroyModule(all.iterator().next());
153 all = transaction.lookupConfigBeans();
155 transaction.commit();
158 protected void assertSame(ObjectName oN1, ObjectName oN2) {
159 assertEquals(oN1.getKeyProperty("instanceName"),
160 oN2.getKeyProperty("instanceName"));
161 assertEquals(oN1.getKeyProperty("interfaceName"),
162 oN2.getKeyProperty("interfaceName"));
165 protected void assertStatus(CommitStatus status, int expectedNewInstances,
166 int expectedRecreatedInstances, int expectedReusedInstances) {
167 assertEquals("New instances mismatch in " + status, expectedNewInstances, status.getNewInstances().size());
168 assertEquals("Recreated instances mismatch in " + status, expectedRecreatedInstances, status.getRecreatedInstances()
170 assertEquals("Reused instances mismatch in " + status, expectedReusedInstances, status.getReusedInstances()
174 protected ObjectName createTestConfigBean(
175 ConfigTransactionJMXClient transaction, String implementationName,
176 String name) throws InstanceAlreadyExistsException {
177 return transaction.createModule(implementationName,
181 protected void assertBeanCount(int i, String configMXBeanName) {
182 assertEquals(i, configRegistry.lookupConfigBeans(configMXBeanName)
186 protected void assertBeanExists(int count, String moduleName,
187 String instanceName) {
189 configRegistry.lookupConfigBeans(moduleName, instanceName)
195 * @param configBeanClass
196 * Empty constructor class of config bean to be instantiated
198 * @param implementationName
201 protected ClassBasedModuleFactory createClassBasedCBF(
202 Class<? extends Module> configBeanClass, String implementationName) {
203 return new ClassBasedModuleFactory(implementationName, configBeanClass);
207 public static interface BundleContextServiceRegistrationHandler {
209 void handleServiceRegistration(Object serviceInstance);
213 private class RegisterServiceAnswer implements Answer {
216 public Object answer(InvocationOnMock invocation) throws Throwable {
217 Object[] args = invocation.getArguments();
219 Preconditions.checkArgument(args.length == 3, "Unexpected arguments size (expected 3 was %s)", args.length);
221 Object serviceTypeRaw = args[0];
222 Object serviceInstance = args[1];
224 if (serviceTypeRaw instanceof Class) {
225 Class<?> serviceType = (Class<?>) serviceTypeRaw;
226 invokeServiceHandler(serviceInstance, serviceType);
228 } else if(serviceTypeRaw instanceof String[]) {
229 for (String className : (String[]) serviceTypeRaw) {
231 Class<?> serviceType = Class.forName(className);
232 invokeServiceHandler(serviceInstance, serviceType);
233 } catch (ClassNotFoundException e) {
234 logger.warn("Not handling service registration of type {} ", className, e);
239 logger.debug("Not handling service registration of type {}, Unknown type", serviceTypeRaw);
241 return mockedServiceRegistration;
244 private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType) {
245 BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandler(serviceType);
247 if (serviceRegistrationHandler != null) {
248 serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance));