Merge "Fixed netconf monitoring."
[controller.git] / opendaylight / config / config-manager / src / test / java / org / opendaylight / controller / config / manager / testingservices / threadpool / test / SimpleConfigurationTest.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.testingservices.threadpool.test;
9
10 import com.google.common.collect.Sets;
11 import org.junit.After;
12 import org.junit.Before;
13 import org.junit.Test;
14 import org.opendaylight.controller.config.api.ConflictingVersionException;
15 import org.opendaylight.controller.config.api.ValidationException;
16 import org.opendaylight.controller.config.api.ValidationException.ExceptionMessageWithStackTrace;
17 import org.opendaylight.controller.config.api.jmx.CommitStatus;
18 import org.opendaylight.controller.config.api.jmx.ObjectNameUtil;
19 import org.opendaylight.controller.config.manager.impl.AbstractConfigTest;
20 import org.opendaylight.controller.config.manager.impl.factoriesresolver.HardcodedModuleFactoriesResolver;
21 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPool;
22 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolConfigMXBean;
23 import org.opendaylight.controller.config.manager.testingservices.threadpool.TestingFixedThreadPoolModuleFactory;
24 import org.opendaylight.controller.config.util.ConfigTransactionClient;
25 import org.opendaylight.controller.config.util.ConfigTransactionJMXClient;
26
27 import javax.management.DynamicMBean;
28 import javax.management.InstanceAlreadyExistsException;
29 import javax.management.InstanceNotFoundException;
30 import javax.management.MBeanException;
31 import javax.management.ObjectName;
32 import javax.management.ReflectionException;
33 import javax.management.RuntimeMBeanException;
34 import java.util.Arrays;
35 import java.util.Collections;
36 import java.util.List;
37 import java.util.Map;
38 import java.util.Set;
39 import java.util.concurrent.ThreadPoolExecutor;
40
41 import static org.junit.Assert.assertEquals;
42 import static org.junit.Assert.assertFalse;
43 import static org.junit.Assert.assertNotNull;
44 import static org.junit.Assert.assertTrue;
45 import static org.junit.Assert.fail;
46
47 /**
48  * Tests basic functionality of configuration registry:
49  * <ol>
50  * <li>Creation of instance</li>
51  * <li>Destruction of instance</li>
52  * <li>Reconfiguration of live object</li>
53  * <li>Reconfiguration that triggers new object creation</li>
54  * <li>Replacement of running instance with different one with same name</li>
55  * </ol>
56  * Only one bean is being configured - {@link TestingThreadPoolIfc} which has no
57  * dependencies.
58  */
59 public class SimpleConfigurationTest extends AbstractConfigTest {
60     private final int numberOfThreads = 5;
61     private final int numberOfThreads2 = 10;
62     private static final String fixed1 = "fixed1";
63     private static final List<ObjectName> emptyONs = Collections
64             .<ObjectName> emptyList();
65     private static final ObjectName platformFixed1ON = ObjectNameUtil
66             .createReadOnlyModuleON(TestingFixedThreadPoolModuleFactory.NAME, fixed1);
67     private static final List<ObjectName> fixed1List = Arrays
68             .asList(platformFixed1ON);
69
70     @Before
71     public void setUp() {
72         super.initConfigTransactionManagerImpl(new HardcodedModuleFactoriesResolver(
73                 new TestingFixedThreadPoolModuleFactory()));
74     }
75
76     @After
77     public void tearDown() {
78         TestingFixedThreadPool.cleanUp();
79     }
80
81     private ObjectName firstCommit() throws Exception {
82         ConfigTransactionJMXClient transaction = configRegistryClient
83                 .createTransaction();
84
85         ObjectName fixed1names = createFixedThreadPool(transaction);
86
87         // commit
88         assertEquals(1, configRegistryClient.getOpenConfigs().size());
89         CommitStatus commitStatus = transaction.commit();
90         assertEquals(0, configRegistryClient.getOpenConfigs().size());
91         CommitStatus expected = new CommitStatus(Arrays.asList(ObjectNameUtil
92                 .withoutTransactionName(fixed1names)), emptyONs, emptyONs);
93         assertEquals(expected, commitStatus);
94
95         assertEquals(1, TestingFixedThreadPool.allExecutors.size());
96         assertFalse(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
97         return fixed1names;
98     }
99
100     private ObjectName createFixedThreadPool(
101             ConfigTransactionJMXClient transaction)
102             throws InstanceAlreadyExistsException, InstanceNotFoundException {
103         transaction.assertVersion(0, 1);
104
105         ObjectName fixed1names = transaction.createModule(
106                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
107         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = transaction
108                 .newMXBeanProxy(fixed1names, TestingFixedThreadPoolConfigMXBean.class);
109         fixedConfigProxy.setThreadCount(numberOfThreads);
110
111         ObjectName retrievedNames = transaction.lookupConfigBean(
112                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
113         assertEquals(fixed1names, retrievedNames);
114         return fixed1names;
115     }
116
117     @Test
118     public void testCreateAndDestroyBeanInSameTransaction() throws Exception {
119         ConfigTransactionJMXClient transaction = configRegistryClient
120                 .createTransaction();
121         ObjectName fixed1names = createFixedThreadPool(transaction);
122         transaction.destroyModule(fixed1names);
123         CommitStatus commitStatus = transaction.commit();
124         assertStatus(commitStatus, 0, 0, 0);
125
126     }
127
128     @Test
129     public void testValidationUsingJMXClient() throws Exception {
130         ConfigTransactionClient transaction = configRegistryClient
131                 .createTransaction();
132         testValidation(transaction);
133     }
134
135
136     private void testValidation(ConfigTransactionClient transaction)
137             throws InstanceAlreadyExistsException, ReflectionException,
138             InstanceNotFoundException, MBeanException {
139         ObjectName fixed1names = transaction.createModule(
140                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
141         // call validate on config bean
142         try {
143             platformMBeanServer.invoke(fixed1names, "validate", new Object[0],
144                     new String[0]);
145             fail();
146         } catch (RuntimeMBeanException e) {
147             RuntimeException targetException = e.getTargetException();
148             assertNotNull(targetException);
149             assertEquals(ValidationException.class, targetException.getClass());
150         }
151
152         // validate config bean
153         try {
154             transaction.validateBean(fixed1names);
155             fail();
156         } catch (ValidationException e) {
157             for (Map.Entry<String, Map<String, ExceptionMessageWithStackTrace>> exception : e
158                     .getFailedValidations().entrySet()) {
159                 for (Map.Entry<String, ExceptionMessageWithStackTrace> entry : exception
160                         .getValue().entrySet()) {
161                     assertEquals(
162                             "Parameter 'threadCount' must be greater than 0",
163                             entry.getValue().getMessage());
164                 }
165             }
166         }
167         // validate transaction
168         try {
169             transaction.validateConfig();
170             fail();
171         } catch (ValidationException e) {
172             for (Map.Entry<String, Map<String, ExceptionMessageWithStackTrace>> exception : e
173                     .getFailedValidations().entrySet()) {
174                 for (Map.Entry<String, ExceptionMessageWithStackTrace> entry : exception
175                         .getValue().entrySet()) {
176                     assertEquals(
177                             "Parameter 'threadCount' must be greater than 0",
178                             entry.getValue().getMessage());
179                 }
180             }
181         }
182         try {
183             transaction.commit();
184         } catch (ValidationException e) {
185             for (Map.Entry<String, Map<String, ExceptionMessageWithStackTrace>> exception : e
186                     .getFailedValidations().entrySet()) {
187                 for (Map.Entry<String, ExceptionMessageWithStackTrace> entry : exception
188                         .getValue().entrySet()) {
189                     assertEquals(
190                             "Parameter 'threadCount' must be greater than 0",
191                             entry.getValue().getMessage());
192                 }
193             }
194         }
195     }
196
197     @Test
198     public void test_createThreadPool_changeNumberOfThreads() throws Exception {
199         firstCommit();
200         ConfigTransactionJMXClient transaction = configRegistryClient
201                 .createTransaction();
202         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = startReconfiguringFixed1ThreadPool(transaction);
203         assertEquals(numberOfThreads, fixedConfigProxy.getThreadCount());
204         fixedConfigProxy.setThreadCount(numberOfThreads2);
205         CommitStatus commitStatus = transaction.commit();
206         checkThreadPools(1, numberOfThreads2);
207         CommitStatus expected = new CommitStatus(emptyONs, fixed1List, emptyONs);
208         assertEquals(expected, commitStatus);
209     }
210
211     @Test
212     public void test_createFixedThreadPool_destroyIt() throws Exception {
213         // 1, start transaction, create new fixed thread pool
214         ObjectName fixed1name = firstCommit();
215
216         // 2, check that configuration was copied to platform
217         DynamicMBean dynamicMBean = configRegistryClient.newMBeanProxy(
218                 ObjectNameUtil.withoutTransactionName(fixed1name),
219                 DynamicMBean.class);
220         dynamicMBean.getMBeanInfo();
221         assertEquals(numberOfThreads, dynamicMBean.getAttribute("ThreadCount"));
222
223         // 3, shutdown fixed1 in new transaction
224         assertFalse(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
225         ConfigTransactionJMXClient transaction = configRegistryClient
226                 .createTransaction();
227
228         // check versions
229         transaction.assertVersion(1, 2);
230
231         // test that it was copied to new transaction
232         ObjectName retrievedName = transaction.lookupConfigBean(
233                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
234         assertNotNull(retrievedName);
235
236         // check that number of threads was copied from dynamic
237
238         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = transaction
239                 .newMXBeanProxy(retrievedName, TestingFixedThreadPoolConfigMXBean.class);
240         assertEquals(numberOfThreads, fixedConfigProxy.getThreadCount());
241
242         // destroy
243         transaction.destroyModule(ObjectNameUtil.createTransactionModuleON(
244                 transaction.getTransactionName(),
245                 TestingFixedThreadPoolModuleFactory.NAME, fixed1));
246         transaction.commit();
247
248         // 4, check
249         assertEquals(2, configRegistryClient.getVersion());
250         assertEquals(1, TestingFixedThreadPool.allExecutors.size());
251         assertTrue(TestingFixedThreadPool.allExecutors.get(0).isShutdown());
252
253         // dynamic config should be removed from platform
254         try {
255             dynamicMBean.getMBeanInfo();
256             fail();
257         } catch (Exception e) {
258             assertTrue(e.getCause() instanceof InstanceNotFoundException);
259         }
260     }
261
262     @Test
263     public void testReplaceFixed1() throws Exception {
264         // 1, start transaction, create new fixed thread pool
265         firstCommit();
266         // destroy and recreate with different # of threads
267         ConfigTransactionJMXClient transaction = configRegistryClient
268                 .createTransaction();
269
270         transaction.destroyModule(ObjectNameUtil.createTransactionModuleON(
271                 transaction.getTransactionName(),
272                 TestingFixedThreadPoolModuleFactory.NAME, fixed1));
273
274         ObjectName fixed1name = transaction.createModule(
275                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
276         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = transaction
277                 .newMXBeanProxy(fixed1name, TestingFixedThreadPoolConfigMXBean.class);
278         fixedConfigProxy.setThreadCount(numberOfThreads2);
279         // commit
280         transaction.commit();
281         // check that first threadpool is closed
282         checkThreadPools(2, numberOfThreads2);
283     }
284
285     private void checkThreadPools(int expectedTotalNumberOfExecutors,
286             int expectedNumberOfThreadsInLastExecutor) {
287         assertEquals(expectedTotalNumberOfExecutors,
288                 TestingFixedThreadPool.allExecutors.size());
289         for (int i = 0; i < expectedTotalNumberOfExecutors - 1; i++) {
290             assertTrue(TestingFixedThreadPool.allExecutors.get(i).isShutdown());
291         }
292         ThreadPoolExecutor lastExecutor = TestingFixedThreadPool.allExecutors
293                 .get(expectedTotalNumberOfExecutors - 1);
294         assertFalse(lastExecutor.isShutdown());
295         assertEquals(expectedNumberOfThreadsInLastExecutor,
296                 lastExecutor.getMaximumPoolSize());
297     }
298
299     @Test
300     public void testTriggerRecreatingInstance() throws Exception {
301         // 1, start transaction, create new fixed thread pool
302         firstCommit();
303         // switch boolean to create new instance
304         ConfigTransactionJMXClient transaction = configRegistryClient
305                 .createTransaction();
306         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = startReconfiguringFixed1ThreadPool(transaction);
307
308         fixedConfigProxy.setTriggerNewInstanceCreation(true);
309         // commit
310         CommitStatus commitStatus = transaction.commit();
311         // check that new threadpool is created and old one is closed
312         checkThreadPools(2, numberOfThreads);
313         CommitStatus expected = new CommitStatus(emptyONs, emptyONs, fixed1List);
314         assertEquals(expected, commitStatus);
315     }
316
317     // return MBeanProxy for 'fixed1' and current transaction
318     private TestingFixedThreadPoolConfigMXBean startReconfiguringFixed1ThreadPool(
319             ConfigTransactionJMXClient transaction)
320             throws InstanceNotFoundException {
321         ObjectName fixed1name = transaction.lookupConfigBean(
322                 TestingFixedThreadPoolModuleFactory.NAME, fixed1);
323
324         TestingFixedThreadPoolConfigMXBean fixedConfigProxy = transaction
325                 .newMXBeanProxy(fixed1name, TestingFixedThreadPoolConfigMXBean.class);
326         return fixedConfigProxy;
327     }
328
329     @Test
330     public void testAbort() {
331         ConfigTransactionJMXClient transaction = configRegistryClient
332                 .createTransaction();
333         assertEquals(1, configRegistryClient.getOpenConfigs().size());
334
335         transaction.abortConfig();
336         try {
337             transaction.createModule(TestingFixedThreadPoolModuleFactory.NAME,
338                     fixed1);
339             fail();
340         } catch (Exception e) {
341             assertTrue(e.getCause() instanceof InstanceNotFoundException);
342         }
343         try {
344             transaction.validateConfig();
345             fail();
346         } catch (Exception e) {
347             assertTrue(e.getCause() instanceof InstanceNotFoundException);
348         }
349         assertEquals(0, configRegistryClient.getOpenConfigs().size());
350     }
351
352     @Test
353     public void testOptimisticLock_ConfigTransactionClient() throws Exception {
354         ConfigTransactionJMXClient transaction1 = configRegistryClient
355                 .createTransaction();
356         ConfigTransactionJMXClient transaction2 = configRegistryClient
357                 .createTransaction();
358         transaction2.assertVersion(0, 2);
359         transaction2.commit();
360         try {
361             transaction1.commit();
362             fail();
363         } catch (ConflictingVersionException e) {
364             assertEquals(
365                     "Optimistic lock failed. Expected parent version 2, was 0",
366                     e.getMessage());
367         }
368     }
369
370     @Test
371     public void testOptimisticLock_ConfigRegistry() throws Exception {
372         ConfigTransactionJMXClient transaction1 = configRegistryClient
373                 .createTransaction();
374         ConfigTransactionJMXClient transaction2 = configRegistryClient
375                 .createTransaction();
376         transaction2.assertVersion(0, 2);
377         transaction2.commit();
378         try {
379             configRegistryClient.commitConfig(transaction1.getObjectName());
380             fail();
381         } catch (ConflictingVersionException e) {
382             assertEquals(
383                     "Optimistic lock failed. Expected parent version 2, was 0",
384                     e.getMessage());
385         }
386     }
387
388
389     @Test
390     public void testQNames() {
391         Set<String> availableModuleFactoryQNames = configRegistryClient.getAvailableModuleFactoryQNames();
392         String expected = "(namespace?revision=revision)name";
393         assertEquals(Sets.newHashSet(expected), availableModuleFactoryQNames);
394     }
395
396 }