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