Merge "Fix run.sh to work from any directory."
[controller.git] / opendaylight / config / config-manager / src / test / java / org / opendaylight / controller / config / manager / impl / AbstractConfigTest.java
1 /*
2  * Copyright (c) 2013 Cisco Systems, Inc. and others.  All rights reserved.
3  *
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
7  */
8 package org.opendaylight.controller.config.manager.impl;
9
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;
30
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;
42 import java.util.Set;
43
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;
49
50 /**
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.
58  */
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;
68
69     private static final Logger logger = LoggerFactory.getLogger(AbstractConfigTest.class);
70
71     // Default handler for OSGi service registration
72     private static final BundleContextServiceRegistrationHandler noopServiceRegHandler = new BundleContextServiceRegistrationHandler() {
73         @Override
74         public void handleServiceRegistration(Object serviceInstance) {}
75     };
76
77     protected BundleContextServiceRegistrationHandler getBundleContextServiceRegistrationHandler(Class<?> serviceType) {
78         return noopServiceRegHandler;
79     }
80
81     // this method should be called in @Before
82     protected void initConfigTransactionManagerImpl(
83             ModuleFactoriesResolver resolver) {
84         final MBeanServer platformMBeanServer = ManagementFactory
85                 .getPlatformMBeanServer();
86
87         configRegistryJMXRegistrator = new ConfigRegistryJMXRegistrator(
88                 platformMBeanServer);
89         initBundleContext();
90
91         internalJmxRegistrator = new InternalJMXRegistrator(platformMBeanServer);
92         baseJmxRegistrator = new BaseJMXRegistrator(internalJmxRegistrator);
93
94         configRegistry = new ConfigRegistryImpl(resolver,
95                 platformMBeanServer, baseJmxRegistrator);
96
97         try {
98             configRegistryJMXRegistrator.registerToJMX(configRegistry);
99         } catch (InstanceAlreadyExistsException e) {
100             throw new RuntimeException(e);
101         }
102         configRegistryClient = new ConfigRegistryJMXClient(platformMBeanServer);
103     }
104
105     private void initBundleContext() {
106         this.mockedServiceRegistration = mock(ServiceRegistration.class);
107         doNothing().when(mockedServiceRegistration).unregister();
108
109         RegisterServiceAnswer answer = new RegisterServiceAnswer();
110
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());
115     }
116
117
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);
125             } else {
126                 resources.add(resourceAsStream);
127             }
128         }
129         Assert.assertEquals("Some files were not found", Collections.<String>emptyList(), failedToFind);
130
131         return resources;
132     }
133
134     @After
135     public final void cleanUpConfigTransactionManagerImpl() {
136         configRegistryJMXRegistrator.close();
137         configRegistry.close();
138         TestingFixedThreadPool.cleanUp();
139         TestingScheduledThreadPoolImpl.cleanUp();
140     }
141
142     /**
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
145      */
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();
154         }
155         transaction.commit();
156     }
157
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"));
163     }
164
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()
169                 .size());
170         assertEquals("Reused instances mismatch in " + status, expectedReusedInstances, status.getReusedInstances()
171                 .size());
172     }
173
174     protected ObjectName createTestConfigBean(
175             ConfigTransactionJMXClient transaction, String implementationName,
176             String name) throws InstanceAlreadyExistsException {
177         return transaction.createModule(implementationName,
178                 name);
179     }
180
181     protected void assertBeanCount(int i, String configMXBeanName) {
182         assertEquals(i, configRegistry.lookupConfigBeans(configMXBeanName)
183                 .size());
184     }
185
186     protected void assertBeanExists(int count, String moduleName,
187             String instanceName) {
188         assertEquals(1,
189                 configRegistry.lookupConfigBeans(moduleName, instanceName)
190                         .size());
191     }
192
193     /**
194      *
195      * @param configBeanClass
196      *            Empty constructor class of config bean to be instantiated
197      *            whenever create
198      * @param implementationName
199      * @return
200      */
201     protected ClassBasedModuleFactory createClassBasedCBF(
202             Class<? extends Module> configBeanClass, String implementationName) {
203         return new ClassBasedModuleFactory(implementationName, configBeanClass);
204     }
205
206
207     public static interface BundleContextServiceRegistrationHandler {
208
209        void handleServiceRegistration(Object serviceInstance);
210
211     }
212
213     private class RegisterServiceAnswer implements Answer {
214
215         @Override
216         public Object answer(InvocationOnMock invocation) throws Throwable {
217             Object[] args = invocation.getArguments();
218
219             Preconditions.checkArgument(args.length == 3, "Unexpected arguments size (expected 3 was %s)", args.length);
220
221             Object serviceTypeRaw = args[0];
222             Object serviceInstance = args[1];
223
224             if (serviceTypeRaw instanceof Class) {
225                 Class<?> serviceType = (Class<?>) serviceTypeRaw;
226                 invokeServiceHandler(serviceInstance, serviceType);
227
228             } else if(serviceTypeRaw instanceof String[]) {
229                 for (String className : (String[]) serviceTypeRaw) {
230                     try {
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);
235                     }
236                 }
237
238             } else
239                 logger.debug("Not handling service registration of type {}, Unknown type", serviceTypeRaw);
240
241             return mockedServiceRegistration;
242         }
243
244         private void invokeServiceHandler(Object serviceInstance, Class<?> serviceType) {
245             BundleContextServiceRegistrationHandler serviceRegistrationHandler = getBundleContextServiceRegistrationHandler(serviceType);
246
247             if (serviceRegistrationHandler != null) {
248                 serviceRegistrationHandler.handleServiceRegistration(serviceType.cast(serviceInstance));
249             }
250         }
251     }
252 }