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