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