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;
22 import com.google.common.base.Predicate;
23 import com.google.common.collect.Collections2;
24 import com.google.common.collect.Lists;
25 import com.google.common.collect.Maps;
26 import com.google.common.collect.Sets;
27 import com.google.common.io.Files;
29 import java.io.IOException;
30 import java.nio.charset.Charset;
31 import java.nio.charset.StandardCharsets;
32 import java.util.ArrayList;
33 import java.util.Arrays;
34 import java.util.Collection;
35 import java.util.Collections;
36 import java.util.HashMap;
37 import java.util.HashSet;
38 import java.util.List;
41 import javax.xml.parsers.DocumentBuilder;
42 import javax.xml.parsers.DocumentBuilderFactory;
43 import org.apache.maven.project.MavenProject;
44 import org.eclipse.jdt.core.JavaCore;
45 import org.eclipse.jdt.core.compiler.IProblem;
46 import org.eclipse.jdt.core.dom.AST;
47 import org.eclipse.jdt.core.dom.ASTParser;
48 import org.eclipse.jdt.core.dom.ASTVisitor;
49 import org.eclipse.jdt.core.dom.CompilationUnit;
50 import org.eclipse.jdt.core.dom.FieldDeclaration;
51 import org.eclipse.jdt.core.dom.MethodDeclaration;
52 import org.eclipse.jdt.core.dom.NormalAnnotation;
53 import org.eclipse.jdt.core.dom.PackageDeclaration;
54 import org.eclipse.jdt.core.dom.TypeDeclaration;
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.opendaylight.controller.config.api.DependencyResolver;
58 import org.opendaylight.controller.config.api.DependencyResolverFactory;
59 import org.opendaylight.controller.config.api.DynamicMBeanWithInstance;
60 import org.opendaylight.controller.config.api.annotations.Description;
61 import org.opendaylight.controller.config.api.annotations.RequireInterface;
62 import org.opendaylight.controller.config.api.annotations.ServiceInterfaceAnnotation;
63 import org.opendaylight.controller.config.spi.AbstractModule;
64 import org.opendaylight.controller.config.spi.Module;
65 import org.opendaylight.controller.config.spi.ModuleFactory;
66 import org.opendaylight.controller.config.yangjmxgenerator.ConfigConstants;
67 import org.opendaylight.controller.config.yangjmxgenerator.PackageTranslatorTest;
68 import org.opendaylight.controller.config.yangjmxgenerator.ServiceInterfaceEntryTest;
69 import org.osgi.framework.BundleContext;
70 import org.xml.sax.ErrorHandler;
71 import org.xml.sax.InputSource;
72 import org.xml.sax.SAXException;
73 import org.xml.sax.SAXParseException;
76 public class JMXGeneratorTest extends AbstractGeneratorTest {
78 JMXGenerator jmxGenerator;
80 protected final HashMap<String, String> map = Maps.newHashMap();
81 protected File outputBaseDir;
82 File generatedResourcesDir;
84 private static final List<String> expectedModuleFileNames = ServiceInterfaceEntryTest
85 .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]");
87 private static final List<String> expectedBGPNames = ServiceInterfaceEntryTest
88 .toFileNames("[AbstractBgpListenerImplModule.java, " + "AbstractBgpListenerImplModuleFactory.java, " +
89 "BgpListenerImplModule.java, " + "BgpListenerImplModuleFactory.java, " +
90 "BgpListenerImplModuleMXBean.java, Peers.java]");
92 private static final List<String> expectedNetconfNames = ServiceInterfaceEntryTest
93 .toFileNames("[AbstractNetconfTestImplModule.java, " + "AbstractNetconfTestImplModuleFactory.java, " +
94 "AbstractTestImplModule.java, " + "AbstractTestImplModuleFactory.java, " +
95 "AutoCloseableServiceInterface.java, " + "ComplexDtoBInner.java, ComplexList.java, Deep.java, " +
96 "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" + "]");
97 private static final List<String> expectedTestFiles = ServiceInterfaceEntryTest
98 .toFileNames("[AbstractNetconfTestFileImplModule.java, AbstractNetconfTestFileImplModuleFactory.java, " +
99 "AbstractNetconfTestFiles1ImplModule.java, AbstractNetconfTestFiles1ImplModuleFactory.java, " +
100 "AbstractTestFileImplModule.java, AbstractTestFileImplModuleFactory.java, " +
101 "AbstractTestFiles1ImplModule.java, AbstractTestFiles1ImplModuleFactory.java, DtoA.java, " +
102 "DtoA.java, NetconfTestFileImplModuleMXBean.java, NetconfTestFileImplRuntimeMXBean.java, " +
103 "NetconfTestFileImplRuntimeRegistration.java, NetconfTestFileImplRuntimeRegistrator.java, " +
104 "NetconfTestFiles1ImplModule.java, NetconfTestFiles1ImplModuleFactory.java, " +
105 "NetconfTestFiles1ImplModuleMXBean.java, NetconfTestFiles1ImplRuntimeMXBean.java, " +
106 "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]");
107 private static final List<String> expectedAllFileNames = ServiceInterfaceEntryTest
108 .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]");
109 private static final List<String> expectedGenerateMBEsListNames = ServiceInterfaceEntryTest
110 .toFileNames("[AbstractBgpListenerImplModule.java, AbstractBgpListenerImplModuleFactory.java, BgpListenerImplModule.java, BgpListenerImplModuleFactory.java, BgpListenerImplModuleMXBean.java, BgpListenerImplRuntimeMXBean.java, BgpListenerImplRuntimeRegistration.java, BgpListenerImplRuntimeRegistrator.java, PeersRuntimeMXBean.java, PeersRuntimeRegistration.java]");
113 public void setUp() {
114 map.put(JMXGenerator.NAMESPACE_TO_PACKAGE_PREFIX + "1",
115 ConfigConstants.CONFIG_NAMESPACE
116 + JMXGenerator.NAMESPACE_TO_PACKAGE_DIVIDER
117 + PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX);
118 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "false");
119 jmxGenerator = new JMXGenerator(new CodeWriter());
120 jmxGenerator.setAdditionalConfig(map);
121 File targetDir = new File(generatorOutputPath, "target");
122 generatedResourcesDir = new File(targetDir, "generated-resources");
123 jmxGenerator.setResourceBaseDir(generatedResourcesDir);
124 MavenProject project = mock(MavenProject.class);
125 doReturn(generatorOutputPath).when(project).getBasedir();
126 jmxGenerator.setMavenProject(project);
127 outputBaseDir = JMXGenerator.concatFolders(targetDir,
128 "generated-sources", "config");
132 public void generateSIsMBsTest() {
133 Collection<File> files = jmxGenerator.generateSources(context,
134 outputBaseDir, context.getModules());
135 List<String> expectedFileNames = new ArrayList<>();
137 .addAll(ServiceInterfaceEntryTest.expectedSIEFileNames);
138 expectedFileNames.addAll(expectedModuleFileNames);
140 expectedFileNames.addAll(expectedBGPNames);
141 expectedFileNames.addAll(expectedNetconfNames);
142 expectedFileNames.addAll(expectedTestFiles);
143 Collections.sort(expectedFileNames);
144 // TODO: separate expectedAllFileNames into expectedBGPNames,
145 // expectedNetconfNames
146 assertEquals(expectedAllFileNames, toFileNames(files));
148 verifyModuleFactoryFile(false);
151 private void verifyModuleFactoryFile(final boolean shouldBePresent) {
152 File factoryFile = new File(generatedResourcesDir, "META-INF"
153 + File.separator + "services" + File.separator
154 + ModuleFactory.class.getName());
155 if (!shouldBePresent) {
156 assertFalse("Factory file should not be generated",
157 factoryFile.exists());
159 assertTrue("Factory file should be generated", factoryFile.exists());
163 public static List<String> toFileNames(final Collection<File> files) {
164 List<String> result = new ArrayList<>();
165 for (File f : files) {
166 result.add(f.getName());
168 Collections.sort(result);
173 public void generateSIEsTest() throws IOException {
174 Collection<File> files = jmxGenerator.generateSources(context,
175 outputBaseDir, Sets.newHashSet(threadsModule));
176 assertEquals(ServiceInterfaceEntryTest.expectedSIEFileNames,
179 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
181 for (File file : files) {
182 verifiers.put(file.getName(), new SieASTVisitor());
185 processGeneratedCode(files, verifiers);
187 for (File file : files) {
188 String fileName = file.getName();
189 SieASTVisitor verifier = (SieASTVisitor) verifiers.get(fileName);
191 assertEquals(fileName.substring(0, fileName.length() - 5),
195 containsString("org.opendaylight.controller.config.api.annotations.AbstractServiceInterface"));
196 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
197 + ".threads", verifier.packageName);
198 assertNotNull(verifier.javadoc);
200 if ("ThreadPoolServiceInterface.java".equals(fileName)) {
201 assertContains(verifier.descriptionAnotValue,
202 "A simple pool of threads able to execute work.");
203 assertContains(verifier.sieAnnotValue, "threadpool");
204 assertContains(verifier.sieAnnotOsgiRegistrationType,
205 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
206 + ".threadpool.ThreadPool.class");
207 } else if ("ScheduledThreadPoolServiceInterface.java"
209 assertContains(verifier.extnds,
210 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
211 + ".threads.ThreadPoolServiceInterface");
213 verifier.descriptionAnotValue,
214 "An extension of the simple pool of threads able to schedule work to be executed at some point in time.");
215 assertContains(verifier.sieAnnotValue, "scheduled-threadpool");
216 assertContains(verifier.sieAnnotOsgiRegistrationType,
217 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
218 + ".threadpool.ScheduledThreadPool.class");
219 } else if ("EventBusServiceInterface.java".equals(fileName)) {
221 verifier.descriptionAnotValue,
222 "Service representing an event bus. The service acts as message router between event producers and event consumers");
223 assertContains(verifier.sieAnnotValue, "eventbus");
224 assertContains(verifier.sieAnnotOsgiRegistrationType,
225 "com.google.common.eventbus.EventBus.class");
226 } else if ("ThreadFactoryServiceInterface.java".equals(fileName)) {
228 verifier.descriptionAnotValue,
229 "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.");
230 assertContains(verifier.sieAnnotValue, "threadfactory");
231 assertContains(verifier.sieAnnotOsgiRegistrationType,
232 "java.util.concurrent.ThreadFactory.class");
234 } else if ("ScheduledExecutorServiceServiceInterface.java"
236 assertContains(verifier.sieAnnotOsgiRegistrationType,
237 "java.util.concurrent.ScheduledExecutorService.class");
239 fail("Unknown generated sie " + fileName);
245 public void generateMBEsListTest() throws Exception {
246 // default value for module factory file is true
247 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
248 jmxGenerator.setAdditionalConfig(map);
250 Collection<File> files = jmxGenerator.generateSources(context,
251 outputBaseDir, Sets.newHashSet(bgpListenerJavaModule));
253 assertEquals(expectedGenerateMBEsListNames, toFileNames(files));
257 public void generateMBEsTest() throws Exception {
258 // default value for module factory file is true
259 map.put(JMXGenerator.MODULE_FACTORY_FILE_BOOLEAN, "randomValue");
260 jmxGenerator.setAdditionalConfig(map);
262 Collection<File> files = jmxGenerator.generateSources(context,
263 outputBaseDir, Sets.newHashSet(threadsJavaModule));
265 assertEquals(expectedModuleFileNames, toFileNames(files));
267 Map<String, ASTVisitor> verifiers = Maps.newHashMap();
269 Collection<File> xmlFiles = Collections2.filter(files,
270 new Predicate<File>() {
273 public boolean apply(final File input) {
274 return input.getName().endsWith("xml");
278 Collection<File> javaFiles = Collections2.filter(files,
279 new Predicate<File>() {
282 public boolean apply(final File input) {
283 return input.getName().endsWith("java");
287 MbeASTVisitor abstractDynamicThreadPoolModuleVisitor = null;
288 MbeASTVisitor asyncEventBusModuleMXBeanVisitor = null;
289 MbeASTVisitor abstractNamingThreadFactoryModuleFactoryVisitor = null;
290 MbeASTVisitor asyncEventBusModuleVisitor = null;
291 MbeASTVisitor eventBusModuleFactoryVisitor = null;
293 for (File file : javaFiles) {
294 String name = file.getName();
295 MbeASTVisitor visitor = new MbeASTVisitor();
296 verifiers.put(name, visitor);
297 if (name.equals("AbstractDynamicThreadPoolModule.java")) {
298 abstractDynamicThreadPoolModuleVisitor = visitor;
300 if (name.equals("AsyncEventBusModuleMXBean.java")) {
301 asyncEventBusModuleMXBeanVisitor = visitor;
303 if (name.equals("AbstractNamingThreadFactoryModuleFactory.java")) {
304 abstractNamingThreadFactoryModuleFactoryVisitor = visitor;
306 if (name.equals("AsyncEventBusModule.java")) {
307 asyncEventBusModuleVisitor = visitor;
309 if (name.equals("EventBusModuleFactory.java")) {
310 eventBusModuleFactoryVisitor = visitor;
314 processGeneratedCode(javaFiles, verifiers);
316 assertAbstractDynamicThreadPoolModule(abstractDynamicThreadPoolModuleVisitor);
317 assertAsyncEventBusModuleMXBean(asyncEventBusModuleMXBeanVisitor);
318 assertAbstractNamingThreadFactoryModuleFactory(abstractNamingThreadFactoryModuleFactoryVisitor);
319 assertAsyncEventBusModule(asyncEventBusModuleVisitor);
320 assertEventBusModuleFactory(eventBusModuleFactoryVisitor);
322 verifyXmlFiles(xmlFiles);
323 // verify ModuleFactory file
324 File moduleFactoryFile = JMXGenerator.concatFolders(
325 generatedResourcesDir, "META-INF", "services",
326 ModuleFactory.class.getName());
327 assertThat(moduleFactoryFile.exists(), is(true));
328 Set<String> lines = Sets.newHashSet(Files
329 .readLines(moduleFactoryFile, StandardCharsets.UTF_8));
330 Set<String> expectedLines = Sets.newHashSet(//
331 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
332 + ".threads.java.EventBusModuleFactory",//
333 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
334 + ".threads.java.AsyncEventBusModuleFactory", //
335 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
336 + ".threads.java.DynamicThreadPoolModuleFactory",//
337 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
338 + ".threads.java.NamingThreadFactoryModuleFactory", //
339 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
340 + ".threads.java.ThreadPoolRegistryImplModuleFactory");
343 assertThat(lines, equalTo(expectedLines));
347 private void verifyXmlFiles(final Collection<File> xmlFiles) throws Exception {
348 ErrorHandler errorHandler = new ErrorHandler() {
351 public void warning(final SAXParseException exception)
352 throws SAXException {
353 fail("Generated blueprint xml is not well formed "
354 + exception.getMessage());
358 public void fatalError(final SAXParseException exception)
359 throws SAXException {
360 fail("Generated blueprint xml is not well formed "
361 + exception.getMessage());
365 public void error(final SAXParseException exception) throws SAXException {
366 fail("Generated blueprint xml is not well formed "
367 + exception.getMessage());
371 for (File file : xmlFiles) {
372 DocumentBuilderFactory factory = DocumentBuilderFactory
374 factory.setValidating(false);
375 factory.setNamespaceAware(true);
377 DocumentBuilder builder = factory.newDocumentBuilder();
379 builder.setErrorHandler(errorHandler);
380 builder.parse(new InputSource(file.getPath()));
385 private void assertEventBusModuleFactory(final MbeASTVisitor visitor) {
386 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
387 + ".threads.java", visitor.packageName);
388 assertEquals("EventBusModuleFactory", visitor.type);
389 assertContains(visitor.extnds,
390 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
391 + ".threads.java.AbstractEventBusModuleFactory");
393 assertEquals(0, visitor.fieldDeclarations.size());
395 assertEquals("Incorrenct number of generated methods", 0,
396 visitor.methods.size());
397 assertEquals("Incorrenct number of generated constructors", 0,
398 visitor.constructors.size());
399 assertEquals("Incorrenct number of generated method descriptions", 0,
400 visitor.methodDescriptions.size());
401 assertEquals("Incorrenct number of generated method javadoc", 0,
402 visitor.methodJavadoc.size());
405 private void assertAsyncEventBusModule(final MbeASTVisitor visitor) {
406 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
407 + ".threads.java", visitor.packageName);
408 assertEquals("AsyncEventBusModule", visitor.type);
409 assertContains(visitor.extnds,
410 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
411 + ".threads.java.AbstractAsyncEventBusModule");
413 assertEquals(0, visitor.fieldDeclarations.size());
415 assertEquals("Incorrenct number of generated methods", 2,
416 visitor.methods.size());
417 assertEquals("Incorrenct number of generated constructors", 2,
418 visitor.constructors.size());
419 assertEquals("Incorrenct number of generated method descriptions", 0,
420 visitor.methodDescriptions.size());
421 assertEquals("Incorrenct number of generated method javadoc", 0,
422 visitor.methodJavadoc.size());
425 private void assertAbstractNamingThreadFactoryModuleFactory(
426 final MbeASTVisitor visitor) {
427 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
428 + ".threads.java", visitor.packageName);
429 assertEquals("AbstractNamingThreadFactoryModuleFactory", visitor.type);
430 assertContains(visitor.implmts,
431 "org.opendaylight.controller.config.spi.ModuleFactory");
432 Set<String> fieldDeclarations = visitor.fieldDeclarations;
433 assertDeclaredField(fieldDeclarations,
434 "public static final java.lang.String NAME=\"threadfactory-naming\"");
437 "private static final java.util.Set<Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>> serviceIfcs");
439 assertEquals(2, fieldDeclarations.size());
441 assertFactoryMethods(visitor.methods, 9);
442 assertEquals("Incorrenct number of generated method descriptions", 0,
443 visitor.methodDescriptions.size());
444 assertEquals("Incorrenct number of generated method javadoc", 0,
445 visitor.methodJavadoc.size());
449 private void assertFactoryMethods(final Set<String> methods, final int expectedSize) {
451 List<ArgumentAssertion> args = Lists.newArrayList();
452 ArgumentAssertion oldInstanceArg = new ArgumentAssertion(DynamicMBeanWithInstance.class.getCanonicalName(), "old");
453 ArgumentAssertion instanceNameArg = new ArgumentAssertion(String.class.getSimpleName(), "instanceName");
454 ArgumentAssertion dependencyResolverArg = new ArgumentAssertion(DependencyResolver.class.getCanonicalName(), "dependencyResolver");
455 ArgumentAssertion bundleContextArg = new ArgumentAssertion(BundleContext.class.getCanonicalName(), "bundleContext");
457 assertMethodPresent(methods, new MethodAssertion(String.class.getSimpleName(), "getImplementationName"));
459 args.add(instanceNameArg);
460 args.add(dependencyResolverArg);
461 args.add(bundleContextArg);
462 assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));
464 args.add(2, oldInstanceArg);
465 assertMethodPresent(methods, new MethodAssertion(Module.class.getCanonicalName(), "createModule", args));
468 args.add(oldInstanceArg);
469 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "handleChangedClass", args));
472 args.add(instanceNameArg);
473 args.add(dependencyResolverArg);
474 args.add(bundleContextArg);
475 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "instantiateModule", args));
478 args.add(2, new ArgumentAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "oldModule"));
479 args.add(3, new ArgumentAssertion(AutoCloseable.class.getCanonicalName(), "oldInstance"));
480 assertMethodPresent(methods, new MethodAssertion("org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule", "instantiateModule", args));
483 args.add(new ArgumentAssertion(DependencyResolverFactory.class.getCanonicalName(), "dependencyResolverFactory"));
484 args.add(bundleContextArg);
485 assertMethodPresent(methods, new MethodAssertion("java.util.Set<org.opendaylight.controller.config.threads.java.NamingThreadFactoryModule>", "getDefaultModules", args));
488 args.add(new ArgumentAssertion("Class<? extends org.opendaylight.controller.config.api.annotations.AbstractServiceInterface>", "serviceInterface"));
489 assertMethodPresent(methods, new MethodAssertion("boolean", "isModuleImplementingServiceInterface", args));
491 assertEquals(methods.size(), expectedSize);
495 private void assertMethodPresent(final Set<String> methods, final MethodAssertion methodAssertion) {
496 assertTrue(String.format("Generated methods did not contain %s, generated methods: %s",
497 methodAssertion.toString(), methods), methods.contains(methodAssertion.toString()));
500 private void assertAsyncEventBusModuleMXBean(final MbeASTVisitor visitor) {
501 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
502 + ".threads.java", visitor.packageName);
503 assertEquals("AsyncEventBusModuleMXBean", visitor.type);
505 assertEquals("Incorrenct number of generated methods", 4,
506 visitor.methods.size());
510 private void assertAbstractDynamicThreadPoolModule(final MbeASTVisitor visitor) {
511 assertEquals(PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
512 + ".threads.java", visitor.packageName);
513 assertNotNull(visitor.javadoc);
514 assertContains(visitor.descriptionAnotValue,
515 "threadpool-dynamic description");
516 assertEquals("AbstractDynamicThreadPoolModule", visitor.type);
517 assertContains(visitor.implmts,
518 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
519 + ".threads.java.DynamicThreadPoolModuleMXBean",
520 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
521 + ".threads.ScheduledThreadPoolServiceInterface",
522 PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
523 + ".threads.ThreadPoolServiceInterface");
524 assertContains(visitor.extnds, AbstractModule.class.getCanonicalName());
525 assertEquals(2, visitor.constructors.size());
526 Set<String> fieldDeclarations = visitor.fieldDeclarations;
527 assertDeclaredField(fieldDeclarations,
528 "private java.lang.Long maximumSize");
529 assertDeclaredField(fieldDeclarations,
530 "private javax.management.ObjectName threadfactory");
531 assertDeclaredField(fieldDeclarations,
532 "private java.util.concurrent.ThreadFactory threadfactoryDependency");
533 assertDeclaredField(fieldDeclarations,
534 "private java.lang.Long keepAlive=new java.lang.Long(\"10\")");
535 assertDeclaredField(fieldDeclarations,
536 "private java.lang.Long coreSize");
537 assertDeclaredField(fieldDeclarations, "private byte[] binary");
538 assertEquals(17, fieldDeclarations.size());
540 assertEquals(1, visitor.requireIfc.size());
541 String reqIfc = visitor.requireIfc.get("setThreadfactory");
542 assertNotNull("Missing generated setter for threadfactory", reqIfc);
543 assertContains(reqIfc, PackageTranslatorTest.EXPECTED_PACKAGE_PREFIX
544 + ".threads.ThreadFactoryServiceInterface");
546 assertEquals("Incorrenct number of generated methods", 26,
547 visitor.methods.size());
548 assertEquals("Incorrenct number of generated method descriptions", 3,
549 visitor.methodDescriptions.size());
550 assertEquals("Incorrenct number of generated method javadoc", 3,
551 visitor.methodJavadoc.size());
552 assertNotNull("Missing javadoc for setMaximumSize method " + visitor.methodJavadoc,
553 visitor.methodJavadoc.get("void setMaximumSize(java.lang.Long maximumSize)"));
556 private void assertDeclaredField(final Set<String> fieldDeclarations,
557 final String declaration) {
558 assertTrue("Missing field " + declaration + ", got: "
560 fieldDeclarations.contains(declaration + ";\n"));
563 private static class SieASTVisitor extends ASTVisitor {
564 protected String packageName, descriptionAnotValue, sieAnnotValue,
565 sieAnnotOsgiRegistrationType, type, extnds, javadoc;
566 protected Map<String, String> methodDescriptions = Maps.newHashMap();
569 public boolean visit(final PackageDeclaration node) {
570 packageName = node.getName().toString();
571 return super.visit(node);
575 public boolean visit(final NormalAnnotation node) {
576 if (node.getTypeName().toString()
577 .equals(Description.class.getCanonicalName())) {
578 if (node.getParent() instanceof TypeDeclaration) {
579 descriptionAnotValue = node.values().get(0).toString();
580 } else if (node.getParent() instanceof MethodDeclaration) {
581 String descr = node.values().get(0).toString();
582 methodDescriptions.put(((MethodDeclaration) node
583 .getParent()).getName().toString(), descr);
588 .equals(ServiceInterfaceAnnotation.class.getCanonicalName())) {
589 String text1 = node.values().get(0).toString();
590 String text2 = node.values().get(1).toString();
591 if (text1.contains("value")) {
592 sieAnnotValue = text1;
593 sieAnnotOsgiRegistrationType = text2;
595 sieAnnotValue = text2;
596 sieAnnotOsgiRegistrationType = text1;
599 return super.visit(node);
603 public boolean visit(final TypeDeclaration node) {
604 javadoc = node.getJavadoc() == null ? null : node.getJavadoc()
606 type = node.getName().toString();
607 List<?> superIfcs = node.superInterfaceTypes();
608 extnds = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
610 return super.visit(node);
614 private static class MbeASTVisitor extends SieASTVisitor {
615 private String implmts;
616 private final Set<String> fieldDeclarations = Sets.newHashSet();
617 private final Set<String> constructors = Sets.newHashSet();
618 private final Set<String> methods = new HashSet<String>();
619 private final Map<String, String> requireIfc = Maps.newHashMap();
620 private final Map<String, String> methodJavadoc = Maps.newHashMap();
623 public boolean visit(final NormalAnnotation node) {
624 boolean result = super.visit(node);
625 if (node.getTypeName().toString()
626 .equals(RequireInterface.class.getCanonicalName())
627 && node.getParent() instanceof MethodDeclaration) {
628 // remember only top level description annotation
629 String reqVal = node.values().get(0).toString();
630 requireIfc.put(((MethodDeclaration) node.getParent()).getName()
631 .toString(), reqVal);
637 public boolean visit(final FieldDeclaration node) {
638 fieldDeclarations.add(node.toString());
639 return super.visit(node);
643 public boolean visit(final MethodDeclaration node) {
644 if (node.isConstructor()) {
645 constructors.add(node.toString());
647 String methodSignature = node.getReturnType2() + " " + node.getName() + "(";
648 boolean first = true;
649 for (Object o : node.parameters()) {
653 methodSignature += ",";
655 methodSignature += o.toString();
657 methodSignature += ")";
658 methods.add(methodSignature);
659 if (node.getJavadoc() != null) {
660 methodJavadoc.put(methodSignature, node.getJavadoc().toString());
663 return super.visit(node);
667 public boolean visit(final TypeDeclaration node) {
668 boolean visit = super.visit(node);
669 List<?> superIfcs = node.superInterfaceTypes();
670 implmts = superIfcs != null && !superIfcs.isEmpty() ? superIfcs
672 extnds = node.getSuperclassType() == null ? null : node
673 .getSuperclassType().toString();
679 private void assertContains(final String source, final String... contained) {
680 for (String string : contained) {
681 assertThat(source, containsString(string));
685 private void processGeneratedCode(final Collection<File> files,
686 final Map<String, ASTVisitor> verifiers) throws IOException {
687 ASTParser parser = ASTParser.newParser(AST.JLS3);
688 Map<?, ?> options = JavaCore.getOptions();
689 JavaCore.setComplianceOptions(JavaCore.VERSION_1_7, options);
690 parser.setCompilerOptions(options);
692 parser.setKind(ASTParser.K_COMPILATION_UNIT);
694 for (File file : files) {
695 char[] source = readFileAsChars(file);
696 parser.setSource(source);
697 parser.setResolveBindings(true);
699 CompilationUnit cu = (CompilationUnit) parser.createAST(null);
700 // Check for compilation problems in generated file
701 for (IProblem c : cu.getProblems()) {
702 // 1610613332 = Syntax error, annotations are only available if
703 // source level is 5.0
704 if (c.getID() == 1610613332) {
707 // 1610613332 = Syntax error, parameterized types are only
708 // available if source level is 5.0
709 if (c.getID() == 1610613329) {
712 if (c.getID() == 1610613328) {
715 fail("Error in generated source code " + file + ":"
716 + c.getSourceLineNumber() + " id: " + c.getID() + " message:" + c.toString());
719 ASTVisitor visitor = verifiers.get(file.getName());
720 if (visitor == null) {
721 fail("Unknown generated file " + file.getName());
728 public static char[] readFileAsChars(final File file) throws IOException {
729 List<String> readLines = Files
730 .readLines(file, Charset.forName("utf-8"));
731 char[] retVal = new char[0];
732 for (String string : readLines) {
733 char[] line = string.toCharArray();
734 int beforeLength = retVal.length;
735 retVal = Arrays.copyOf(retVal, retVal.length + line.length + 1);
736 System.arraycopy(line, 0, retVal, beforeLength, line.length);
737 retVal[retVal.length - 1] = '\n';
742 private static class MethodAssertion extends ArgumentAssertion{
744 private final List<ArgumentAssertion> arguments;
747 MethodAssertion(final String type, final String name, final List<ArgumentAssertion> arguments) {
749 this.arguments = arguments;
752 MethodAssertion(final String type, final String name) {
753 this(type, name, Collections.<ArgumentAssertion>emptyList());
757 public String toString() {
758 final StringBuffer sb = new StringBuffer();
759 sb.append(type).append(' ');
760 sb.append(name).append('(');
763 for (ArgumentAssertion argument : arguments) {
764 sb.append(argument.type).append(' ');
765 sb.append(argument.name);
766 if(++i != arguments.size()) {
771 return sb.toString();
775 private static class ArgumentAssertion {
777 protected final String type, name;
779 private ArgumentAssertion(final String type, final String name) {
785 public String toString() {
786 final StringBuffer sb = new StringBuffer();
787 sb.append(type).append(' ');
789 return sb.toString();