2 * Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved.
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
8 package org.opendaylight.controller.config.yangjmxgenerator.plugin;
10 import static org.hamcrest.CoreMatchers.containsString;
11 import static org.hamcrest.CoreMatchers.equalTo;
12 import static org.hamcrest.CoreMatchers.is;
13 import static org.junit.Assert.assertEquals;
14 import static org.junit.Assert.assertFalse;
15 import static org.junit.Assert.assertNotNull;
16 import static org.junit.Assert.assertThat;
17 import static org.junit.Assert.assertTrue;
18 import static org.junit.Assert.fail;
19 import static org.mockito.Mockito.doReturn;
20 import static org.mockito.Mockito.mock;
21 import com.google.common.base.Predicate;
22 import com.google.common.collect.Collections2;
23 import com.google.common.collect.Lists;
24 import com.google.common.collect.Maps;
25 import com.google.common.collect.Sets;
26 import com.google.common.io.Files;
28 import java.io.IOException;
29 import java.nio.charset.Charset;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.Collection;
33 import java.util.Collections;
34 import java.util.HashMap;
35 import java.util.HashSet;
36 import java.util.List;
39 import javax.xml.parsers.DocumentBuilder;
40 import javax.xml.parsers.DocumentBuilderFactory;
41 import org.apache.commons.io.FileUtils;
42 import org.apache.maven.project.MavenProject;
43 import org.eclipse.jdt.core.JavaCore;
44 import org.eclipse.jdt.core.compiler.IProblem;
45 import org.eclipse.jdt.core.dom.AST;
46 import org.eclipse.jdt.core.dom.ASTParser;
47 import org.eclipse.jdt.core.dom.ASTVisitor;
48 import org.eclipse.jdt.core.dom.CompilationUnit;
49 import org.eclipse.jdt.core.dom.FieldDeclaration;
50 import org.eclipse.jdt.core.dom.MethodDeclaration;
51 import org.eclipse.jdt.core.dom.NormalAnnotation;
52 import org.eclipse.jdt.core.dom.PackageDeclaration;
53 import org.eclipse.jdt.core.dom.TypeDeclaration;
54 import org.junit.Before;
55 import org.junit.Test;
56 import org.opendaylight.controller.config.api.DependencyResolver;
57 import org.opendaylight.controller.config.api.DependencyResolverFactory;
58 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
59 import org.opendaylight.controller.config.api.annotations.Description;
60 import org.opendaylight.controller.config.api.annotations.RequireInterface;
61 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
62 import org.opendaylight.controller.config.spi.AbstractModule;
63 import org.opendaylight.controller.config.spi.Module;
64 import org.opendaylight.controller.config.spi.ModuleFactory;
65 import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
66 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslatorTest;
67 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntryTest;
68 import org.osgi.framework.BundleContext;
69 import org.xml.sax.ErrorHandler;
70 import org.xml.sax.InputSource;
71 import org.xml.sax.SAXException;
72 import org.xml.sax.SAXParseException;
75 public class JMXGeneratorTest extends AbstractGeneratorTest {
77 JMXGenerator jmxGenerator;
79 protected final HashMap<String, String> map = Maps.newHashMap();
80 protected File outputBaseDir;
81 File generatedResourcesDir;
83 private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest
84 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
86 private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
87 .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " +
88 "BgpListenerImplModule.java, " + "BgpListenerImplModuleFactory.java, " +
89 "BgpListenerImplModuleMXBean.java, Peers.java]");
91 private static final List<String> expectedNetconfNames = ServiceInterfaceEntryTest
92 .toFileNames("[AbstractNetconfTestImplModule.java, " + "AbstractNetconfTestImplModuleFactory.java, " +
93 "AbstractTestImplModule.java, " + "AbstractTestImplModuleFactory.java, " +
94 "AutoCloseableServiceInterface.java, " + "ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
95 "DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java," + "NetconfTestImplModule.java, NetconfTestImplModuleFactory.java," + "NetconfTestImplModuleMXBean.java, Peer.java, SimpleList.java, TestImplModule.java, " + "TestImplModuleFactory.java," + " TestImplModuleMXBean.java" + "]");
96 private static final List<String> expectedTestFiles = ServiceInterfaceEntryTest
97 .toFileNames("[AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
98 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
99 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
100 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, DtoA.java, " +
101 "DtoA.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
102 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
103 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
104 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
105 "NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java]");
106 private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest
107 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AbstractThreadPoolRegistryImplModule.java, AbstractThreadPoolRegistryImplModuleFactory.java, AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, FromGrouping.java, InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, NetconfTestFiles1ImplRuntimeRegistration.java, NetconfTestFiles1ImplRuntimeRegistrator.java, NetconfTestImplModule.java, NetconfTestImplModuleFactory.java, NetconfTestImplModuleMXBean.java, NetconfTestImplRuntimeMXBean.java, NetconfTestImplRuntimeRegistration.java, NetconfTestImplRuntimeRegistrator.java, Peer.java, Peer.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java, ScheduledThreadPoolServiceInterface.java, SimpleList.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, TestFileImplModule.java, TestFileImplModuleFactory.java, TestFileImplModuleMXBean.java, TestFileImplRuntimeMXBean.java, TestFileImplRuntimeRegistration.java, TestFileImplRuntimeRegistrator.java, TestFiles1ImplModule.java, TestFiles1ImplModuleFactory.java, TestFiles1ImplModuleMXBean.java, TestFiles1ImplRuntimeMXBean.java, TestFiles1ImplRuntimeRegistration.java, TestFiles1ImplRuntimeRegistrator.java, TestImplModule.java, TestImplModuleFactory.java, TestImplModuleMXBean.java, TestImplRuntimeMXBean.java, TestImplRuntimeRegistration.java, TestImplRuntimeRegistrator.java, ThreadFactoryServiceInterface.java, ThreadPoolRegistryImplModule.java, ThreadPoolRegistryImplModuleFactory.java, ThreadPoolRegistryImplModuleMXBean.java, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
108 private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest
109 .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");
112 public void setUp() {
113 map.put(JMXGenerator.NAMESPACE_TO_PACKAGE_PREFIX + "1",
114 ConfigConstants.CONFIG_NAMESPACE
115 + JMXGenerator.NAMESPACE_TO_PACKAGE_DIVIDER
116 + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX);
117 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "false");
118 jmxGenerator = new JMXGenerator(new CodeWriter());
119 jmxGenerator.setAdditionalConfig(map);
120 File targetDir = new File(generatorOutputPath, "target");
121 generatedResourcesDir = new File(targetDir, "generated-resources");
122 jmxGenerator.setResourceBaseDir(generatedResourcesDir);
123 MavenProject project = mock(MavenProject.class);
124 doReturn(generatorOutputPath).when(project).getBasedir();
125 jmxGenerator.setMavenProject(project);
126 outputBaseDir = JMXGenerator.concatFolders(targetDir,
127 "generated-sources", "config");
131 public void generateSIsMBsTest() {
132 Collection<File> files = jmxGenerator.generateSources(context,
133 outputBaseDir, context.getModules());
134 List<String> expectedFileNames = new ArrayList<>();
136 .addAll(ServiceInterfaceEntryTest.expectedSIEFileNames);
137 expectedFileNames.addAll(expectedModuleFileNames);
139 expectedFileNames.addAll(expectedBGPNames);
140 expectedFileNames.addAll(expectedNetconfNames);
141 expectedFileNames.addAll(expectedTestFiles);
142 Collections.sort(expectedFileNames);
143 // TODO: separate expectedAllFileNames into expectedBGPNames,
144 // expectedNetconfNames
145 assertEquals(expectedAllFileNames, toFileNames(files));
147 verifyModuleFactoryFile(false);
150 private void verifyModuleFactoryFile(final boolean shouldBePresent) {
151 File factoryFile = new File(generatedResourcesDir, "META-INF"
152 + File.separator + "services" + File.separator
153 + ModuleFactory.class.getName());
154 if (!shouldBePresent) {
155 assertFalse("Factory file should not be generated",
156 factoryFile.exists());
158 assertTrue("Factory file should be generated", factoryFile.exists());
162 public static List<String> toFileNames(final Collection<File> files) {
163 List<String> result = new ArrayList<>();
164 for (File f : files) {
165 result.add(f.getName());
167 Collections.sort(result);
172 public void generateSIEsTest() throws IOException {
173 Collection<File> files = jmxGenerator.generateSources(context,
174 outputBaseDir, Sets.newHashSet(threadsModule));
175 assertEquals(ServiceInterfaceEntryTest.expectedSIEFileNames,
178 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
180 for (File file : files) {
181 verifiers.put(file.getName(), new SieASTVisitor());
184 processGeneratedCode(files, verifiers);
186 for (File file : files) {
187 String fileName = file.getName();
188 SieASTVisitor verifier = (SieASTVisitor) verifiers.get(fileName);
190 assertEquals(fileName.substring(0, fileName.length() - 5),
194 containsString("org.opendaylight.controller.config.api.annotations.AbstractServiceInterface"));
195 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
196 + ".threads", verifier.packageName);
197 assertNotNull(verifier.javadoc);
199 if ("ThreadPoolServiceInterface.java".equals(fileName)) {
200 assertContains(verifier.descriptionAnotValue,
201 "A simple pool of threads able to execute work.");
202 assertContains(verifier.sieAnnotValue, "threadpool");
203 assertContains(verifier.sieAnnotOsgiRegistrationType,
204 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
205 + ".threadpool.ThreadPool.class");
206 } else if ("ScheduledThreadPoolServiceInterface.java"
208 assertContains(verifier.extnds,
209 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
210 + ".threads.ThreadPoolServiceInterface");
212 verifier.descriptionAnotValue,
213 "An extension of the simple pool of threads able to schedule work to be executed at some point in time.");
214 assertContains(verifier.sieAnnotValue, "scheduled-threadpool");
215 assertContains(verifier.sieAnnotOsgiRegistrationType,
216 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
217 + ".threadpool.ScheduledThreadPool.class");
218 } else if ("EventBusServiceInterface.java".equals(fileName)) {
220 verifier.descriptionAnotValue,
221 "Service representing an event bus. The service acts as message router between event producers and event consumers");
222 assertContains(verifier.sieAnnotValue, "eventbus");
223 assertContains(verifier.sieAnnotOsgiRegistrationType,
224 "com.google.common.eventbus.EventBus.class");
225 } else if ("ThreadFactoryServiceInterface.java".equals(fileName)) {
227 verifier.descriptionAnotValue,
228 "Service representing a ThreadFactory instance. It is directly useful in Java world, where various library pieces need to create threads and you may want to inject a customized thread implementation.");
229 assertContains(verifier.sieAnnotValue, "threadfactory");
230 assertContains(verifier.sieAnnotOsgiRegistrationType,
231 "java.util.concurrent.ThreadFactory.class");
233 } else if ("ScheduledExecutorServiceServiceInterface.java"
235 assertContains(verifier.sieAnnotOsgiRegistrationType,
236 "java.util.concurrent.ScheduledExecutorService.class");
238 fail("Unknown generated sie " + fileName);
244 public void generateMBEsListTest() throws Exception {
245 // default value for module factory file is true
246 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
247 jmxGenerator.setAdditionalConfig(map);
249 Collection<File> files = jmxGenerator.generateSources(context,
250 outputBaseDir, Sets.newHashSet(bgpListenerJavaModule));
252 assertEquals(expectedGenerateMBEsListNames, toFileNames(files));
256 public void generateMBEsTest() throws Exception {
257 // default value for module factory file is true
258 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
259 jmxGenerator.setAdditionalConfig(map);
261 Collection<File> files = jmxGenerator.generateSources(context,
262 outputBaseDir, Sets.newHashSet(threadsJavaModule));
264 assertEquals(expectedModuleFileNames, toFileNames(files));
266 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
268 Collection<File> xmlFiles = Collections2.filter(files,
269 new Predicate<File>() {
272 public boolean apply(final File input) {
273 return input.getName().endsWith("xml");
277 Collection<File> javaFiles = Collections2.filter(files,
278 new Predicate<File>() {
281 public boolean apply(final File input) {
282 return input.getName().endsWith("java");
286 MbeASTVisitor abstractDynamicThreadPoolModuleVisitor = null;
287 MbeASTVisitor asyncEventBusModuleMXBeanVisitor = null;
288 MbeASTVisitor abstractNamingThreadFactoryModuleFactoryVisitor = null;
289 MbeASTVisitor asyncEventBusModuleVisitor = null;
290 MbeASTVisitor eventBusModuleFactoryVisitor = null;
292 for (File file : javaFiles) {
293 String name = file.getName();
294 MbeASTVisitor visitor = new MbeASTVisitor();
295 verifiers.put(name, visitor);
296 if (name.equals("AbstractDynamicThreadPoolModule.java")) {
297 abstractDynamicThreadPoolModuleVisitor = visitor;
299 if (name.equals("AsyncEventBusModuleMXBean.java")) {
300 asyncEventBusModuleMXBeanVisitor = visitor;
302 if (name.equals("AbstractNamingThreadFactoryModuleFactory.java")) {
303 abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
305 if (name.equals("AsyncEventBusModule.java")) {
306 asyncEventBusModuleVisitor = visitor;
308 if (name.equals("EventBusModuleFactory.java")) {
309 eventBusModuleFactoryVisitor = visitor;
313 processGeneratedCode(javaFiles, verifiers);
315 assertAbstractDynamicThreadPoolModule(abstractDynamicThreadPoolModuleVisitor);
316 assertAsyncEventBusModuleMXBean(asyncEventBusModuleMXBeanVisitor);
317 assertAbstractNamingThreadFactoryModuleFactory(abstractNamingThreadFactoryModuleFactoryVisitor);
318 assertAsyncEventBusModule(asyncEventBusModuleVisitor);
319 assertEventBusModuleFactory(eventBusModuleFactoryVisitor);
321 verifyXmlFiles(xmlFiles);
322 // verify ModuleFactory file
323 File moduleFactoryFile = JMXGenerator.concatFolders(
324 generatedResourcesDir, "META-INF", "services",
325 ModuleFactory.class.getName());
326 assertThat(moduleFactoryFile.exists(), is(true));
327 Set<String> lines = Sets.newHashSet(FileUtils
328 .readLines(moduleFactoryFile));
329 Set<String> expectedLines = Sets.newHashSet(//
330 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
331 + ".threads.java.EventBusModuleFactory",//
332 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
333 + ".threads.java.AsyncEventBusModuleFactory", //
334 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
335 + ".threads.java.DynamicThreadPoolModuleFactory",//
336 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
337 + ".threads.java.NamingThreadFactoryModuleFactory", //
338 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
339 + ".threads.java.ThreadPoolRegistryImplModuleFactory");
342 assertThat(lines, equalTo(expectedLines));
346 private void verifyXmlFiles(final Collection<File> xmlFiles) throws Exception {
347 ErrorHandler errorHandler = new ErrorHandler() {
350 public void warning(final SAXParseException exception)
351 throws SAXException {
352 fail("Generated blueprint xml is not well formed "
353 + exception.getMessage());
357 public void fatalError(final SAXParseException exception)
358 throws SAXException {
359 fail("Generated blueprint xml is not well formed "
360 + exception.getMessage());
364 public void error(final SAXParseException exception) throws SAXException {
365 fail("Generated blueprint xml is not well formed "
366 + exception.getMessage());
370 for (File file : xmlFiles) {
371 DocumentBuilderFactory factory = DocumentBuilderFactory
373 factory.setValidating(false);
374 factory.setNamespaceAware(true);
376 DocumentBuilder builder = factory.newDocumentBuilder();
378 builder.setErrorHandler(errorHandler);
379 builder.parse(new InputSource(file.getPath()));
384 private void assertEventBusModuleFactory(final MbeASTVisitor visitor) {
385 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
386 + ".threads.java", visitor.packageName);
387 assertEquals("EventBusModuleFactory", visitor.type);
388 assertContains(visitor.extnds,
389 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
390 + ".threads.java.AbstractEventBusModuleFactory");
392 assertEquals(0, visitor.fieldDeclarations.size());
394 assertEquals("Incorrenct number of generated methods", 0,
395 visitor.methods.size());
396 assertEquals("Incorrenct number of generated constructors", 0,
397 visitor.constructors.size());
398 assertEquals("Incorrenct number of generated method descriptions", 0,
399 visitor.methodDescriptions.size());
400 assertEquals("Incorrenct number of generated method javadoc", 0,
401 visitor.methodJavadoc.size());
404 private void assertAsyncEventBusModule(final MbeASTVisitor visitor) {
405 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
406 + ".threads.java", visitor.packageName);
407 assertEquals("AsyncEventBusModule", visitor.type);
408 assertContains(visitor.extnds,
409 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
410 + ".threads.java.AbstractAsyncEventBusModule");
412 assertEquals(0, visitor.fieldDeclarations.size());
414 assertEquals("Incorrenct number of generated methods", 2,
415 visitor.methods.size());
416 assertEquals("Incorrenct number of generated constructors", 2,
417 visitor.constructors.size());
418 assertEquals("Incorrenct number of generated method descriptions", 0,
419 visitor.methodDescriptions.size());
420 assertEquals("Incorrenct number of generated method javadoc", 0,
421 visitor.methodJavadoc.size());
424 private void assertAbstractNamingThreadFactoryModuleFactory(
425 final MbeASTVisitor visitor) {
426 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
427 + ".threads.java", visitor.packageName);
428 assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
429 assertContains(visitor.implmts,
430 "org.opendaylight.controller.config.spi.ModuleFactory");
431 Set<String> fieldDeclarations = visitor.fieldDeclarations;
432 assertDeclaredField(fieldDeclarations,
433 "public static final java.lang.String NAME=\"threadfactory-naming\"");
436 "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs");
438 assertEquals(2, fieldDeclarations.size());
440 assertFactoryMethods(visitor.methods, 9);
441 assertEquals("Incorrenct number of generated method descriptions", 0,
442 visitor.methodDescriptions.size());
443 assertEquals("Incorrenct number of generated method javadoc", 0,
444 visitor.methodJavadoc.size());
448 private void assertFactoryMethods(final Set<String> methods, final int expectedSize) {
450 List<ArgumentAssertion> args = Lists.newArrayList();
451 ArgumentAssertion oldInstanceArg = new ArgumentAssertion(DynamicMBeanWithInstance.class.getCanonicalName(), "old");
452 ArgumentAssertion instanceNameArg = new ArgumentAssertion(String.class.getSimpleName(), "instanceName");
453 ArgumentAssertion dependencyResolverArg = new ArgumentAssertion(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
454 ArgumentAssertion bundleContextArg = new ArgumentAssertion(BundleContext.class.getCanonicalName(), "bundleContext");
456 assertMethodPresent(methods, new MethodAssertion(String.class.getSimpleName(), "getImplementationName"));
458 args.add(instanceNameArg);
459 args.add(dependencyResolverArg);
460 args.add(bundleContextArg);
461 assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));
463 args.add(2, oldInstanceArg);
464 assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));
467 args.add(oldInstanceArg);
468 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "handleChangedClass", args));
471 args.add(instanceNameArg);
472 args.add(dependencyResolverArg);
473 args.add(bundleContextArg);
474 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "instantiateModule", args));
477 args.add(2, new ArgumentAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "oldModule"));
478 args.add(3, new ArgumentAssertion(AutoCloseable.class.getCanonicalName(), "oldInstance"));
479 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "instantiateModule", args));
482 args.add(new ArgumentAssertion(DependencyResolverFactory.class.getCanonicalName(), "dependencyResolverFactory"));
483 args.add(bundleContextArg);
484 assertMethodPresent(methods, new MethodAssertion("java.util.Set<org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule>", "getDefaultModules", args));
487 args.add(new ArgumentAssertion("Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>", "serviceInterface"));
488 assertMethodPresent(methods, new MethodAssertion("boolean", "isModuleImplementingServiceInterface", args));
490 assertEquals(methods.size(), expectedSize);
494 private void assertMethodPresent(final Set<String> methods, final MethodAssertion methodAssertion) {
495 assertTrue(String.format("Generated methods did not contain %s, generated methods: %s",
496 methodAssertion.toString(), methods), methods.contains(methodAssertion.toString()));
499 private void assertAsyncEventBusModuleMXBean(final MbeASTVisitor visitor) {
500 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
501 + ".threads.java", visitor.packageName);
502 assertEquals("AsyncEventBusModuleMXBean", visitor.type);
504 assertEquals("Incorrenct number of generated methods", 4,
505 visitor.methods.size());
509 private void assertAbstractDynamicThreadPoolModule(final MbeASTVisitor visitor) {
510 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
511 + ".threads.java", visitor.packageName);
512 assertNotNull(visitor.javadoc);
513 assertContains(visitor.descriptionAnotValue,
514 "threadpool-dynamic description");
515 assertEquals("AbstractDynamicThreadPoolModule", visitor.type);
516 assertContains(visitor.implmts,
517 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
518 + ".threads.java.DynamicThreadPoolModuleMXBean",
519 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
520 + ".threads.ScheduledThreadPoolServiceInterface",
521 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
522 + ".threads.ThreadPoolServiceInterface");
523 assertContains(visitor.extnds, AbstractModule.class.getCanonicalName());
524 assertEquals(2, visitor.constructors.size());
525 Set<String> fieldDeclarations = visitor.fieldDeclarations;
526 assertDeclaredField(fieldDeclarations,
527 "private java.lang.Long maximumSize");
528 assertDeclaredField(fieldDeclarations,
529 "private javax.management.ObjectName threadfactory");
530 assertDeclaredField(fieldDeclarations,
531 "private java.util.concurrent.ThreadFactory threadfactoryDependency");
532 assertDeclaredField(fieldDeclarations,
533 "private java.lang.Long keepAlive=new java.lang.Long(\"10\")");
534 assertDeclaredField(fieldDeclarations,
535 "private java.lang.Long coreSize");
536 assertDeclaredField(fieldDeclarations, "private byte[] binary");
537 assertEquals(17, fieldDeclarations.size());
539 assertEquals(1, visitor.requireIfc.size());
540 String reqIfc = visitor.requireIfc.get("setThreadfactory");
541 assertNotNull("Missing generated setter for threadfactory", reqIfc);
542 assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
543 + ".threads.ThreadFactoryServiceInterface");
545 assertEquals("Incorrenct number of generated methods", 26,
546 visitor.methods.size());
547 assertEquals("Incorrenct number of generated method descriptions", 3,
548 visitor.methodDescriptions.size());
549 assertEquals("Incorrenct number of generated method javadoc", 3,
550 visitor.methodJavadoc.size());
551 assertNotNull("Missing javadoc for setMaximumSize method " + visitor.methodJavadoc,
552 visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
555 private void assertDeclaredField(final Set<String> fieldDeclarations,
556 final String declaration) {
557 assertTrue("Missing field " + declaration + ", got: "
559 fieldDeclarations.contains(declaration + ";\n"));
562 private static class SieASTVisitor extends ASTVisitor {
563 protected String packageName, descriptionAnotValue, sieAnnotValue,
564 sieAnnotOsgiRegistrationType, type, extnds, javadoc;
565 protected Map<String, String> methodDescriptions = Maps.newHashMap();
568 public boolean visit(final PackageDeclaration node) {
569 packageName = node.getName().toString();
570 return super.visit(node);
574 public boolean visit(final NormalAnnotation node) {
575 if (node.getTypeName().toString()
576 .equals(Description.class.getCanonicalName())) {
577 if (node.getParent() instanceof TypeDeclaration) {
578 descriptionAnotValue = node.values().get(0).toString();
579 } else if (node.getParent() instanceof MethodDeclaration) {
580 String descr = node.values().get(0).toString();
581 methodDescriptions.put(((MethodDeclaration) node
582 .getParent()).getName().toString(), descr);
587 .equals(ServiceInterfaceAnnotation.class.getCanonicalName())) {
588 String text1 = node.values().get(0).toString();
589 String text2 = node.values().get(1).toString();
590 if (text1.contains("value")) {
591 sieAnnotValue = text1;
592 sieAnnotOsgiRegistrationType = text2;
594 sieAnnotValue = text2;
595 sieAnnotOsgiRegistrationType = text1;
598 return super.visit(node);
602 public boolean visit(final TypeDeclaration node) {
603 javadoc = node.getJavadoc() == null ? null : node.getJavadoc()
605 type = node.getName().toString();
606 List<?> superIfcs = node.superInterfaceTypes();
607 extnds = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
609 return super.visit(node);
613 private static class MbeASTVisitor extends SieASTVisitor {
614 private String implmts;
615 private final Set<String> fieldDeclarations = Sets.newHashSet();
616 private final Set<String> constructors = Sets.newHashSet();
617 private final Set<String> methods = new HashSet<String>();
618 private final Map<String, String> requireIfc = Maps.newHashMap();
619 private final Map<String, String> methodJavadoc = Maps.newHashMap();
622 public boolean visit(final NormalAnnotation node) {
623 boolean result = super.visit(node);
624 if (node.getTypeName().toString()
625 .equals(RequireInterface.class.getCanonicalName())
626 && node.getParent() instanceof MethodDeclaration) {
627 // remember only top level description annotation
628 String reqVal = node.values().get(0).toString();
629 requireIfc.put(((MethodDeclaration) node.getParent()).getName()
630 .toString(), reqVal);
636 public boolean visit(final FieldDeclaration node) {
637 fieldDeclarations.add(node.toString());
638 return super.visit(node);
642 public boolean visit(final MethodDeclaration node) {
643 if (node.isConstructor()) {
644 constructors.add(node.toString());
646 String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
647 boolean first = true;
648 for (Object o : node.parameters()) {
652 methodSignature += ",";
654 methodSignature += o.toString();
656 methodSignature += ")";
657 methods.add(methodSignature);
658 if (node.getJavadoc() != null) {
659 methodJavadoc.put(methodSignature, node.getJavadoc().toString());
662 return super.visit(node);
666 public boolean visit(final TypeDeclaration node) {
667 boolean visit = super.visit(node);
668 List<?> superIfcs = node.superInterfaceTypes();
669 implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
671 extnds = node.getSuperclassType() == null ? null : node
672 .getSuperclassType().toString();
678 private void assertContains(final String source, final String... contained) {
679 for (String string : contained) {
680 assertThat(source, containsString(string));
684 private void processGeneratedCode(final Collection<File> files,
685 final Map<String, ASTVisitor> verifiers) throws IOException {
686 ASTParser parser = ASTParser.newParser(AST.JLS3);
687 Map<?, ?> options = JavaCore.getOptions();
688 JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
689 parser.setCompilerOptions(options);
691 parser.setKind(ASTParser.K_COMPILATION_UNIT);
693 for (File file : files) {
694 char[] source = readFileAsChars(file);
695 parser.setSource(source);
696 parser.setResolveBindings(true);
698 CompilationUnit cu = (CompilationUnit) parser.createAST(null);
699 // Check for compilation problems in generated file
700 for (IProblem c : cu.getProblems()) {
701 // 1610613332 = Syntax error, annotations are only available if
702 // source level is 5.0
703 if (c.getID() == 1610613332) {
706 // 1610613332 = Syntax error, parameterized types are only
707 // available if source level is 5.0
708 if (c.getID() == 1610613329) {
711 if (c.getID() == 1610613328) {
714 fail("Error in generated source code " + file + ":"
715 + c.getSourceLineNumber() + " id: " + c.getID() + " message:" + c.toString());
718 ASTVisitor visitor = verifiers.get(file.getName());
719 if (visitor == null) {
720 fail("Unknown generated file " + file.getName());
727 public static char[] readFileAsChars(final File file) throws IOException {
728 List<String> readLines = Files
729 .readLines(file, Charset.forName("utf-8"));
730 char[] retVal = new char[0];
731 for (String string : readLines) {
732 char[] line = string.toCharArray();
733 int beforeLength = retVal.length;
734 retVal = Arrays.copyOf(retVal, retVal.length + line.length + 1);
735 System.arraycopy(line, 0, retVal, beforeLength, line.length);
736 retVal[retVal.length - 1] = '\n';
741 private static class MethodAssertion extends ArgumentAssertion{
743 private final List<ArgumentAssertion> arguments;
746 MethodAssertion(final String type, final String name, final List<ArgumentAssertion> arguments) {
748 this.arguments = arguments;
751 MethodAssertion(final String type, final String name) {
752 this(type, name, Collections.<ArgumentAssertion>emptyList());
756 public String toString() {
757 final StringBuffer sb = new StringBuffer();
758 sb.append(type).append(' ');
759 sb.append(name).append('(');
762 for (ArgumentAssertion argument : arguments) {
763 sb.append(argument.type).append(' ');
764 sb.append(argument.name);
765 if(++i != arguments.size()) {
770 return sb.toString();
774 private static class ArgumentAssertion {
776 protected final String type, name;
778 private ArgumentAssertion(final String type, final String name) {
784 public String toString() {
785 final StringBuffer sb = new StringBuffer();
786 sb.append(type).append(' ');
788 return sb.toString();