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 com.google.common.base.Predicate;
11 import com.google.common.collect.Collections2;
12 import com.google.common.collect.Maps;
13 import com.google.common.collect.Sets;
14 import com.google.common.io.Files;
15 import org.apache.commons.io.FileUtils;
16 import org.apache.maven.plugin.logging.Log;
17 import org.apache.maven.project.MavenProject;
18 import org.eclipse.jdt.core.JavaCore;
19 import org.eclipse.jdt.core.compiler.IProblem;
20 import org.eclipse.jdt.core.dom.*;
21 import org.junit.Before;
22 import org.junit.Test;
23 import org.opendaylight.controller.config.api.annotations.Description;
24 import org.opendaylight.controller.config.api.annotations.RequireInterface;
25 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
26 import org.opendaylight.controller.config.spi.Module;
27 import org.opendaylight.controller.config.spi.ModuleFactory;
28 import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
29 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslatorTest;
30 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntryTest;
31 import org.xml.sax.ErrorHandler;
32 import org.xml.sax.InputSource;
33 import org.xml.sax.SAXException;
34 import org.xml.sax.SAXParseException;
36 import javax.xml.parsers.DocumentBuilder;
37 import javax.xml.parsers.DocumentBuilderFactory;
39 import java.io.IOException;
40 import java.nio.charset.Charset;
43 import static org.hamcrest.CoreMatchers.equalTo;
44 import static org.hamcrest.CoreMatchers.is;
45 import static org.junit.Assert.*;
46 import static org.junit.matchers.JUnitMatchers.containsString;
47 import static org.mockito.Matchers.any;
48 import static org.mockito.Mockito.*;
50 public class JMXGeneratorTest extends AbstractGeneratorTest {
52 JMXGenerator jmxGenerator;
54 protected final HashMap<String, String> map = Maps.newHashMap();
55 protected File outputBaseDir;
56 File generatedResourcesDir;
58 private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest
59 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
60 "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
61 "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
62 "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
63 "AsyncEventBusModule.java, AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
64 "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
65 "AsyncEventBusRuntimeRegistrator.java, DynamicThreadPoolModule.java, " +
66 "DynamicThreadPoolModuleFactory.java, DynamicThreadPoolModuleMXBean.java, " +
67 "DynamicThreadPoolRuntimeMXBean.java, DynamicThreadPoolRuntimeRegistration.java, " +
68 "DynamicThreadPoolRuntimeRegistrator.java, EventBusModule.java, EventBusModuleFactory.java, " +
69 "EventBusModuleMXBean.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
70 "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
71 "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, Peer.java, StreamRuntimeMXBean.java, StreamRuntimeRegistration.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
73 private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
74 .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " +
75 "BgpListenerImplModule.java, " + "BgpListenerImplModuleFactory.java, " +
76 "BgpListenerImplModuleMXBean.java, Peers.java]");
78 private static final List<String> expectedNetconfNames = ServiceInterfaceEntryTest
79 .toFileNames("[AbstractNetconfTestImplModule.java, " + "AbstractNetconfTestImplModuleFactory.java, " +
80 "AbstractTestImplModule.java, " + "AbstractTestImplModuleFactory.java, " +
81 "AutoCloseableServiceInterface.java, " + "ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
82 "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" + "]");
83 private static final List<String> expectedTestFiles = ServiceInterfaceEntryTest
84 .toFileNames("[AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
85 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
86 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
87 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, DtoA.java, " +
88 "DtoA.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
89 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
90 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
91 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
92 "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]");
93 private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest
94 .toFileNames("[AbstractAsyncEventBusModule.java, AbstractAsyncEventBusModuleFactory.java, " +
95 "AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, " +
96 "AbstractDynamicThreadPoolModule.java, AbstractDynamicThreadPoolModuleFactory.java, " +
97 "AbstractEventBusModule.java, AbstractEventBusModuleFactory.java, " +
98 "AbstractNamingThreadFactoryModule.java, AbstractNamingThreadFactoryModuleFactory.java, " +
99 "AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
100 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
101 "AbstractNetconfTestImplModule.java, AbstractNetconfTestImplModuleFactory.java, " +
102 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
103 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, " +
104 "AbstractTestImplModule.java, AbstractTestImplModuleFactory.java, AsyncEventBusModule.java, " +
105 "AsyncEventBusModuleFactory.java, AsyncEventBusModuleMXBean.java, " +
106 "AsyncEventBusRuntimeMXBean.java, AsyncEventBusRuntimeRegistration.java, " +
107 "AsyncEventBusRuntimeRegistrator.java, AutoCloseableServiceInterface.java, " +
108 "BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java," +
109 " BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, " +
110 "BgpListenerImplRuntimeRegistrator.java, ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
111 "DtoA.java, DtoA.java, DtoA.java, DtoA1.java, DtoAInner.java, DtoAInnerInner.java, DtoB.java, " +
112 "DtoC.java, DynamicThreadPoolModule.java, DynamicThreadPoolModuleFactory.java, " +
113 "DynamicThreadPoolModuleMXBean.java, DynamicThreadPoolRuntimeMXBean.java, " +
114 "DynamicThreadPoolRuntimeRegistration.java, DynamicThreadPoolRuntimeRegistrator.java, " +
115 "EventBusModule.java, EventBusModuleFactory.java, EventBusModuleMXBean.java, " +
116 "EventBusServiceInterface.java, EventRuntimeMXBean.java, EventRuntimeRegistration.java, " +
117 "InnerStreamList.java, NamingThreadFactoryModule.java, NamingThreadFactoryModuleFactory.java, " +
118 "NamingThreadFactoryModuleMXBean.java, NamingThreadFactoryRuntimeMXBean.java, " +
119 "NamingThreadFactoryRuntimeRegistration.java, NamingThreadFactoryRuntimeRegistrator.java, " +
120 "NetconfTestFileImplModule.java, NetconfTestFileImplModuleFactory.java, " +
121 "NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
122 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
123 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
124 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
125 "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, ThreadPoolServiceInterface.java, ThreadRuntimeMXBean.java, ThreadRuntimeRegistration.java, ThreadStreamRuntimeMXBean.java, ThreadStreamRuntimeRegistration.java]");
126 private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest
127 .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");
130 public void setUp() {
131 map.put(JMXGenerator.NAMESPACE_TO_PACKAGE_PREFIX + "1",
132 ConfigConstants.CONFIG_NAMESPACE
133 + JMXGenerator.NAMESPACE_TO_PACKAGE_DIVIDER
134 + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX);
135 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "false");
136 jmxGenerator = new JMXGenerator(new FreeMarkerCodeWriterImpl());
137 jmxGenerator.setAdditionalConfig(map);
138 File targetDir = new File(generatorOutputPath, "target");
139 generatedResourcesDir = new File(targetDir, "generated-resources");
140 jmxGenerator.setResourceBaseDir(generatedResourcesDir);
141 Log mockedLog = mock(Log.class);
142 doReturn(false).when(mockedLog).isDebugEnabled();
143 doNothing().when(mockedLog).debug(any(CharSequence.class));
144 doNothing().when(mockedLog).info(any(CharSequence.class));
145 doNothing().when(mockedLog).error(any(CharSequence.class),
146 any(Throwable.class));
147 jmxGenerator.setLog(mockedLog);
148 MavenProject project = mock(MavenProject.class);
149 doReturn(generatorOutputPath).when(project).getBasedir();
150 jmxGenerator.setMavenProject(project);
151 outputBaseDir = JMXGenerator.concatFolders(targetDir,
152 "generated-sources", "config");
156 public void generateSIsMBsTest() {
157 Collection<File> files = jmxGenerator.generateSources(context,
158 outputBaseDir, context.getModules());
159 List<String> expectedFileNames = new ArrayList<>();
161 .addAll(ServiceInterfaceEntryTest.expectedSIEFileNames);
162 expectedFileNames.addAll(expectedModuleFileNames);
164 expectedFileNames.addAll(expectedBGPNames);
165 expectedFileNames.addAll(expectedNetconfNames);
166 expectedFileNames.addAll(expectedTestFiles);
167 Collections.sort(expectedFileNames);
168 // TODO: separate expectedAllFileNames into expectedBGPNames,
169 // expectedNetconfNames
170 assertEquals(expectedAllFileNames, toFileNames(files));
172 verifyModuleFactoryFile(false);
175 private void verifyModuleFactoryFile(boolean shouldBePresent) {
176 File factoryFile = new File(generatedResourcesDir, "META-INF"
177 + File.separator + "services" + File.separator
178 + ModuleFactory.class.getName());
179 if (!shouldBePresent)
180 assertFalse("Factory file should not be generated",
181 factoryFile.exists());
183 assertTrue("Factory file should be generated", factoryFile.exists());
186 public static List<String> toFileNames(Collection<File> files) {
187 List<String> result = new ArrayList<>();
188 for (File f : files) {
189 result.add(f.getName());
191 Collections.sort(result);
196 public void generateSIEsTest() throws IOException {
197 Collection<File> files = jmxGenerator.generateSources(context,
198 outputBaseDir, Sets.newHashSet(threadsModule));
199 assertEquals(ServiceInterfaceEntryTest.expectedSIEFileNames,
202 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
204 for (File file : files) {
205 verifiers.put(file.getName(), new SieASTVisitor());
208 processGeneratedCode(files, verifiers);
210 for (File file : files) {
211 String fileName = file.getName();
212 SieASTVisitor verifier = (SieASTVisitor) verifiers.get(fileName);
214 assertEquals(fileName.substring(0, fileName.length() - 5),
218 containsString("org.opendaylight.controller.config.api.annotations.AbstractServiceInterface"));
219 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
220 + ".threads", verifier.packageName);
221 assertNotNull(verifier.javadoc);
223 if ("ThreadPoolServiceInterface.java".equals(fileName)) {
224 assertContains(verifier.descriptionAnotValue,
225 "A simple pool of threads able to execute work.");
226 assertContains(verifier.sieAnnotValue, "threadpool");
227 assertContains(verifier.sieAnnotOsgiRegistrationType,
228 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
229 + ".threadpool.ThreadPool.class");
230 } else if ("ScheduledThreadPoolServiceInterface.java"
232 assertContains(verifier.extnds,
233 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
234 + ".threads.ThreadPoolServiceInterface");
236 verifier.descriptionAnotValue,
237 "An extension of the simple pool of threads able to schedule work to be executed at some point in time.");
238 assertContains(verifier.sieAnnotValue, "scheduled-threadpool");
239 assertContains(verifier.sieAnnotOsgiRegistrationType,
240 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
241 + ".threadpool.ScheduledThreadPool.class");
242 } else if ("EventBusServiceInterface.java".equals(fileName)) {
244 verifier.descriptionAnotValue,
245 "Service representing an event bus. The service acts as message router between event producers and event consumers");
246 assertContains(verifier.sieAnnotValue, "eventbus");
247 assertContains(verifier.sieAnnotOsgiRegistrationType,
248 "com.google.common.eventbus.EventBus.class");
249 } else if ("ThreadFactoryServiceInterface.java".equals(fileName)) {
251 verifier.descriptionAnotValue,
252 "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.");
253 assertContains(verifier.sieAnnotValue, "threadfactory");
254 assertContains(verifier.sieAnnotOsgiRegistrationType,
255 "java.util.concurrent.ThreadFactory.class");
257 } else if ("ScheduledExecutorServiceServiceInterface.java"
259 assertContains(verifier.sieAnnotOsgiRegistrationType,
260 "java.util.concurrent.ScheduledExecutorService.class");
262 fail("Unknown generated sie " + fileName);
268 public void generateMBEsListTest() throws Exception {
269 // default value for module factory file is true
270 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
271 jmxGenerator.setAdditionalConfig(map);
273 Collection<File> files = jmxGenerator.generateSources(context,
274 outputBaseDir, Sets.newHashSet(bgpListenerJavaModule));
276 assertEquals(expectedGenerateMBEsListNames, toFileNames(files));
280 public void generateMBEsTest() throws Exception {
281 // default value for module factory file is true
282 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
283 jmxGenerator.setAdditionalConfig(map);
285 Collection<File> files = jmxGenerator.generateSources(context,
286 outputBaseDir, Sets.newHashSet(threadsJavaModule));
288 assertEquals(expectedModuleFileNames, toFileNames(files));
290 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
292 Collection<File> xmlFiles = Collections2.filter(files,
293 new Predicate<File>() {
296 public boolean apply(File input) {
297 return input.getName().endsWith("xml");
301 Collection<File> javaFiles = Collections2.filter(files,
302 new Predicate<File>() {
305 public boolean apply(File input) {
306 return input.getName().endsWith("java");
310 MbeASTVisitor abstractDynamicThreadPoolModuleVisitor = null;
311 MbeASTVisitor asyncEventBusModuleMXBeanVisitor = null;
312 MbeASTVisitor abstractNamingThreadFactoryModuleFactoryVisitor = null;
313 MbeASTVisitor asyncEventBusModuleVisitor = null;
314 MbeASTVisitor eventBusModuleFactoryVisitor = null;
316 for (File file : javaFiles) {
317 String name = file.getName();
318 MbeASTVisitor visitor = new MbeASTVisitor();
319 verifiers.put(name, visitor);
320 if (name.equals("AbstractDynamicThreadPoolModule.java"))
321 abstractDynamicThreadPoolModuleVisitor = visitor;
322 if (name.equals("AsyncEventBusModuleMXBean.java"))
323 asyncEventBusModuleMXBeanVisitor = visitor;
324 if (name.equals("AbstractNamingThreadFactoryModuleFactory.java"))
325 abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
326 if (name.equals("AsyncEventBusModule.java"))
327 asyncEventBusModuleVisitor = visitor;
328 if (name.equals("EventBusModuleFactory.java"))
329 eventBusModuleFactoryVisitor = visitor;
332 processGeneratedCode(javaFiles, verifiers);
334 assertAbstractDynamicThreadPoolModule(abstractDynamicThreadPoolModuleVisitor);
335 assertAsyncEventBusModuleMXBean(asyncEventBusModuleMXBeanVisitor);
336 assertAbstractNamingThreadFactoryModuleFactory(abstractNamingThreadFactoryModuleFactoryVisitor);
337 assertAsyncEventBusModule(asyncEventBusModuleVisitor);
338 assertEventBusModuleFactory(eventBusModuleFactoryVisitor);
340 verifyXmlFiles(xmlFiles);
341 // verify ModuleFactory file
342 File moduleFactoryFile = JMXGenerator.concatFolders(
343 generatedResourcesDir, "META-INF", "services",
344 ModuleFactory.class.getName());
345 assertThat(moduleFactoryFile.exists(), is(true));
346 Set<String> lines = Sets.newHashSet(FileUtils
347 .readLines(moduleFactoryFile));
348 Set<String> expectedLines = Sets.newHashSet(//
349 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
350 + ".threads.java.EventBusModuleFactory",//
351 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
352 + ".threads.java.AsyncEventBusModuleFactory", //
353 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
354 + ".threads.java.DynamicThreadPoolModuleFactory",//
355 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
356 + ".threads.java.NamingThreadFactoryModuleFactory");
357 assertThat(lines, equalTo(expectedLines));
361 private void verifyXmlFiles(Collection<File> xmlFiles) throws Exception {
362 ErrorHandler errorHandler = new ErrorHandler() {
365 public void warning(SAXParseException exception)
366 throws SAXException {
367 fail("Generated blueprint xml is not well formed "
368 + exception.getMessage());
372 public void fatalError(SAXParseException exception)
373 throws SAXException {
374 fail("Generated blueprint xml is not well formed "
375 + exception.getMessage());
379 public void error(SAXParseException exception) throws SAXException {
380 fail("Generated blueprint xml is not well formed "
381 + exception.getMessage());
385 for (File file : xmlFiles) {
386 DocumentBuilderFactory factory = DocumentBuilderFactory
388 factory.setValidating(false);
389 factory.setNamespaceAware(true);
391 DocumentBuilder builder = factory.newDocumentBuilder();
393 builder.setErrorHandler(errorHandler);
394 builder.parse(new InputSource(file.getPath()));
399 private void assertEventBusModuleFactory(MbeASTVisitor visitor) {
400 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
401 + ".threads.java", visitor.packageName);
402 assertEquals("EventBusModuleFactory", visitor.type);
403 assertContains(visitor.extnds,
404 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
405 + ".threads.java.AbstractEventBusModuleFactory");
407 assertEquals(0, visitor.fieldDeclarations.size());
409 assertEquals("Incorrenct number of generated methods", 0,
410 visitor.methods.size());
411 assertEquals("Incorrenct number of generated constructors", 0,
412 visitor.constructors.size());
413 assertEquals("Incorrenct number of generated method descriptions", 0,
414 visitor.methodDescriptions.size());
415 assertEquals("Incorrenct number of generated method javadoc", 0,
416 visitor.methodJavadoc.size());
419 private void assertAsyncEventBusModule(MbeASTVisitor visitor) {
420 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
421 + ".threads.java", visitor.packageName);
422 assertEquals("AsyncEventBusModule", visitor.type);
423 assertContains(visitor.extnds,
424 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
425 + ".threads.java.AbstractAsyncEventBusModule");
427 assertEquals(0, visitor.fieldDeclarations.size());
429 assertEquals("Incorrenct number of generated methods", 2,
430 visitor.methods.size());
431 assertEquals("Incorrenct number of generated constructors", 2,
432 visitor.constructors.size());
433 assertEquals("Incorrenct number of generated method descriptions", 0,
434 visitor.methodDescriptions.size());
435 assertEquals("Incorrenct number of generated method javadoc", 0,
436 visitor.methodJavadoc.size());
439 private void assertAbstractNamingThreadFactoryModuleFactory(
440 MbeASTVisitor visitor) {
441 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
442 + ".threads.java", visitor.packageName);
443 assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
444 assertContains(visitor.implmts,
445 "org.opendaylight.controller.config.spi.ModuleFactory");
446 Set<String> fieldDeclarations = visitor.fieldDeclarations;
447 assertDeclaredField(fieldDeclarations,
448 "public static final java.lang.String NAME=\"threadfactory-naming\"");
451 "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs=new java.util.HashSet<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>>()");
453 assertEquals(2, fieldDeclarations.size());
455 Set<String> expectedMethods = new HashSet<>(Arrays.asList("String getImplementationName()",
456 "org.opendaylight.controller.config.spi.Module createModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.osgi.framework.BundleContext bundleContext)",
457 "org.opendaylight.controller.config.spi.Module createModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.opendaylight.controller.config.api.DynamicMBeanWithInstance old,org.osgi.framework.BundleContext bundleContext)",
458 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule handleChangedClass(org.opendaylight.controller.config.api.DynamicMBeanWithInstance old)",
459 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule instantiateModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule oldModule,java.lang.AutoCloseable oldInstance,org.osgi.framework.BundleContext bundleContext)",
460 "org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule instantiateModule(String instanceName,org.opendaylight.controller.config.api.DependencyResolver dependencyResolver,org.osgi.framework.BundleContext bundleContext)",
461 "java.util.Set<org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule> getDefaultModules(org.opendaylight.controller.config.api.DependencyResolverFactory dependencyResolverFactory,org.osgi.framework.BundleContext bundleContext)",
462 "boolean isModuleImplementingServiceInterface(Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface> serviceInterface)"));
463 assertEquals("Incorrenct number of generated methods", expectedMethods, visitor.methods);
464 assertEquals("Incorrenct number of generated method descriptions", 0,
465 visitor.methodDescriptions.size());
466 assertEquals("Incorrenct number of generated method javadoc", 0,
467 visitor.methodJavadoc.size());
471 private void assertAsyncEventBusModuleMXBean(MbeASTVisitor visitor) {
472 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
473 + ".threads.java", visitor.packageName);
474 assertEquals("AsyncEventBusModuleMXBean", visitor.type);
476 assertEquals("Incorrenct number of generated methods", 2,
477 visitor.methods.size());
480 private void assertAbstractDynamicThreadPoolModule(MbeASTVisitor visitor) {
481 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
482 + ".threads.java", visitor.packageName);
483 assertNotNull(visitor.javadoc);
484 assertContains(visitor.descriptionAnotValue,
485 "threadpool-dynamic description");
486 assertEquals("AbstractDynamicThreadPoolModule", visitor.type);
487 assertContains(visitor.implmts,
488 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
489 + ".threads.java.DynamicThreadPoolModuleMXBean",
490 Module.class.getCanonicalName(),
491 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
492 + ".threads.ScheduledThreadPoolServiceInterface",
493 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
494 + ".threads.ThreadPoolServiceInterface");
495 assertEquals(2, visitor.constructors.size());
496 Set<String> fieldDeclarations = visitor.fieldDeclarations;
497 assertDeclaredField(fieldDeclarations,
498 "private java.lang.Long maximumSize");
499 assertDeclaredField(fieldDeclarations,
500 "private javax.management.ObjectName threadfactory");
501 assertDeclaredField(fieldDeclarations,
502 "private java.util.concurrent.ThreadFactory threadfactoryDependency");
503 assertDeclaredField(fieldDeclarations,
504 "private java.lang.Long keepAlive=10");
505 assertDeclaredField(fieldDeclarations,
506 "private java.lang.Long coreSize");
507 assertDeclaredField(fieldDeclarations, "private byte[] binary");
508 assertEquals(22, fieldDeclarations.size());
510 assertEquals(1, visitor.requireIfc.size());
511 String reqIfc = visitor.requireIfc.get("setThreadfactory");
512 assertNotNull("Missing generated setter for threadfactory", reqIfc);
513 assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
514 + ".threads.ThreadFactoryServiceInterface");
516 assertEquals("Incorrenct number of generated methods", 24,
517 visitor.methods.size());
518 assertEquals("Incorrenct number of generated method descriptions", 3,
519 visitor.methodDescriptions.size());
520 assertEquals("Incorrenct number of generated method javadoc", 3,
521 visitor.methodJavadoc.size());
522 assertNotNull("Missing javadoc for setMaximumSize method " + visitor.methodJavadoc,
523 visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
526 private void assertDeclaredField(Set<String> fieldDeclarations,
527 String declaration) {
528 assertTrue("Missing field " + declaration + ", got: "
530 fieldDeclarations.contains(declaration + ";\n"));
533 private static class SieASTVisitor extends ASTVisitor {
534 protected String packageName, descriptionAnotValue, sieAnnotValue,
535 sieAnnotOsgiRegistrationType, type, extnds, javadoc;
536 protected Map<String, String> methodDescriptions = Maps.newHashMap();
539 public boolean visit(PackageDeclaration node) {
540 packageName = node.getName().toString();
541 return super.visit(node);
545 public boolean visit(NormalAnnotation node) {
546 if (node.getTypeName().toString()
547 .equals(Description.class.getCanonicalName())) {
548 if (node.getParent() instanceof TypeDeclaration) {
549 descriptionAnotValue = node.values().get(0).toString();
550 } else if (node.getParent() instanceof MethodDeclaration) {
551 String descr = node.values().get(0).toString();
552 methodDescriptions.put(((MethodDeclaration) node
553 .getParent()).getName().toString(), descr);
558 .equals(ServiceInterfaceAnnotation.class.getCanonicalName())) {
559 String text1 = node.values().get(0).toString();
560 String text2 = node.values().get(1).toString();
561 if (text1.contains("value")) {
562 sieAnnotValue = text1;
563 sieAnnotOsgiRegistrationType = text2;
565 sieAnnotValue = text2;
566 sieAnnotOsgiRegistrationType = text1;
569 return super.visit(node);
573 public boolean visit(TypeDeclaration node) {
574 javadoc = node.getJavadoc() == null ? null : node.getJavadoc()
576 type = node.getName().toString();
577 List<?> superIfcs = node.superInterfaceTypes();
578 extnds = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
580 return super.visit(node);
584 private static class MbeASTVisitor extends SieASTVisitor {
585 private String implmts;
586 private final Set<String> fieldDeclarations = Sets.newHashSet();
587 private final Set<String> constructors = Sets.newHashSet();
588 private final Set<String> methods = new HashSet<String>();
589 private final Map<String, String> requireIfc = Maps.newHashMap();
590 private final Map<String, String> methodJavadoc = Maps.newHashMap();
593 public boolean visit(NormalAnnotation node) {
594 boolean result = super.visit(node);
595 if (node.getTypeName().toString()
596 .equals(RequireInterface.class.getCanonicalName())
597 && node.getParent() instanceof MethodDeclaration) {
598 // remember only top level description annotation
599 String reqVal = node.values().get(0).toString();
600 requireIfc.put(((MethodDeclaration) node.getParent()).getName()
601 .toString(), reqVal);
607 public boolean visit(FieldDeclaration node) {
608 fieldDeclarations.add(node.toString());
609 return super.visit(node);
613 public boolean visit(MethodDeclaration node) {
614 if (node.isConstructor())
615 constructors.add(node.toString());
617 String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
618 boolean first = true;
619 for (Object o : node.parameters()) {
623 methodSignature += ",";
625 methodSignature += o.toString();
627 methodSignature += ")";
628 methods.add(methodSignature);
629 if (node.getJavadoc() != null) {
630 methodJavadoc.put(methodSignature, node.getJavadoc().toString());
633 return super.visit(node);
637 public boolean visit(TypeDeclaration node) {
638 boolean visit = super.visit(node);
639 List<?> superIfcs = node.superInterfaceTypes();
640 implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
642 extnds = node.getSuperclassType() == null ? null : node
643 .getSuperclassType().toString();
649 private void assertContains(String source, String... contained) {
650 for (String string : contained) {
651 assertThat(source, containsString(string));
655 private void processGeneratedCode(Collection<File> files,
656 Map<String, ASTVisitor> verifiers) throws IOException {
657 ASTParser parser = ASTParser.newParser(AST.JLS3);
658 Map<?, ?> options = JavaCore.getOptions();
659 JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
660 parser.setCompilerOptions(options);
662 parser.setKind(ASTParser.K_COMPILATION_UNIT);
664 for (File file : files) {
665 char[] source = readFileAsChars(file);
666 parser.setSource(source);
667 parser.setResolveBindings(true);
669 CompilationUnit cu = (CompilationUnit) parser.createAST(null);
670 // Check for compilation problems in generated file
671 for (IProblem c : cu.getProblems()) {
672 // 1610613332 = Syntax error, annotations are only available if
673 // source level is 5.0
674 if (c.getID() == 1610613332)
676 // 1610613332 = Syntax error, parameterized types are only
677 // available if source level is 5.0
678 if (c.getID() == 1610613329)
680 fail("Error in generated source code " + file + ":"
681 + c.getSourceLineNumber() + " " + c.toString());
684 ASTVisitor visitor = verifiers.get(file.getName());
686 fail("Unknown generated file " + file.getName());
692 public static char[] readFileAsChars(File file) throws IOException {
693 List<String> readLines = Files
694 .readLines(file, Charset.forName("utf-8"));
695 char[] retVal = new char[0];
696 for (String string : readLines) {
697 char[] line = string.toCharArray();
698 int beforeLength = retVal.length;
699 retVal = Arrays.copyOf(retVal, retVal.length + line.length + 1);
700 System.arraycopy(line, 0, retVal, beforeLength, line.length);
701 retVal[retVal.length - 1] = '\n';