Prevent ConfigPusher from killing its thread
[controller.git] / opendaylight / northbound / bundlescanner / implementation / src / test / java / org / opendaylight / controller / northbound / bundlescanner / internal / BundleScannerTest.java
1 package org.opendaylight.controller.northbound.bundlescanner.internal;
2
3
4
5 import java.io.File;
6 import java.io.FileFilter;
7 import java.net.MalformedURLException;
8 import java.net.URISyntaxException;
9 import java.net.URL;
10 import java.util.ArrayList;
11 import java.util.Collections;
12 import java.util.Dictionary;
13 import java.util.Enumeration;
14 import java.util.HashSet;
15 import java.util.Hashtable;
16 import java.util.List;
17 import java.util.Set;
18 import java.util.regex.Pattern;
19
20 import org.junit.AfterClass;
21 import org.junit.Before;
22 import org.junit.BeforeClass;
23 import org.junit.Rule;
24 import org.junit.Test;
25 import org.junit.rules.TestName;
26 import org.osgi.framework.Bundle;
27 import org.osgi.framework.BundleContext;
28 import org.osgi.framework.BundleEvent;
29 import org.osgi.framework.Constants;
30 import org.springframework.osgi.mock.MockBundle;
31 import org.springframework.osgi.mock.MockBundleContext;
32
33 import static junit.framework.Assert.assertNotNull;
34 import static org.junit.Assert.assertFalse;
35 import static org.junit.Assert.assertTrue;
36
37 public class BundleScannerTest {
38
39     private static BundleScanner bundleScanner;
40     private static List<Bundle> bundles;
41     @Rule
42     public final TestName testName = new TestName();
43
44     @BeforeClass
45     public static void init() throws Exception {
46         bundles = makeMockBundles();
47         bundleScanner = new BundleScanner(bundles.toArray(new Bundle[bundles.size()]));
48     }
49
50     @AfterClass
51     public static void destroy() throws Exception {
52     }
53
54     @Before
55     public void setup() {
56         System.out.println("==== " + testName.getMethodName());
57     }
58
59     @Test
60     public void testValidateBundles() {
61         assertNotNull(bundleScanner);
62         BundleContext context = bundles.get(0).getBundleContext();
63         assertNotNull(context.getBundle());
64         assertNotNull(context.getBundles());
65         assertNotNull(context.getBundles().length >= 4);
66     }
67
68     @Test
69     public void testBundleEvents() throws Exception {
70         MockBundle newBundle = new TestMockBundle("misc", "", "bundle_misc");
71         assertTrue(bundleScanner.getAnnotatedClasses(
72                 newBundle.getBundleContext(), null, null, false).size() == 0);
73         BundleEvent event = new BundleEvent(BundleEvent.RESOLVED, newBundle);
74         bundleScanner.bundleChanged(event);
75         assertTrue(bundleScanner.getAnnotatedClasses(
76                 newBundle.getBundleContext(), null, null, false).size() == 1);
77     }
78
79     @Test
80     public void testAnnotatedClassesWithDependencies() throws Exception {
81         for (Bundle bundle : bundles) {
82             List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
83                     bundle.getBundleContext(), null, null, true);
84             String name = bundle.getSymbolicName();
85             System.out.println("name:" + name + " classes:" + classes.size());
86             if ("misc".equals(name)) {
87                 assertTrue(classes.size() == 1);
88             } else if ("base".equals(name)) {
89                 assertTrue(classes.size() == 5);
90             } else if ("sub1".equals(name)) {
91                 assertTrue(classes.size() == 6);
92             } else if ("sub2".equals(name)) {
93                 assertTrue(classes.size() == 7);
94             }
95         }
96     }
97
98     @Test
99     public void testExactFiltering() {
100         Bundle bundle = findBundle("sub1");
101         String[] annos = { "javax.xml.bind.annotation.XmlTransient" };
102         List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
103                 bundle.getBundleContext(), annos, null, true);
104         assertTrue(classes.size() == 1);
105     }
106
107     @Test
108     public void testNonExactFiltering() {
109         Bundle bundle = findBundle("sub1");
110         String[] annos = { "javax.xml.bind.annotation.*" };
111         List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
112                 bundle.getBundleContext(), annos, null, true);
113         assertTrue(classes.size() == 6);
114     }
115
116     @Test
117     public void testFilteringUnmatched() {
118         Bundle bundle = findBundle("sub1");
119         String[] annos = { "non.existent.pkg" };
120         List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
121                 bundle.getBundleContext(), annos, null, true);
122         assertTrue(classes.size() == 0);
123     }
124
125     @Test
126     public void testRegexMerge() {
127         Pattern pattern = BundleScanner.mergePatterns(
128                 new String[] {
129                         "javax.xml.bind.annotation.*",
130                         "javax.ws.rs.Path"
131                     },
132                 true
133             );
134         assertTrue(pattern.matcher("Ljavax/xml/bind/annotation/FOO;").find());
135         assertFalse(pattern.matcher("Ljavax/servlet/FOO;").find());
136     }
137
138     @Test
139     public void testExclude() {
140         Set<String> excludes = new HashSet<String>();
141         excludes.add("bundle_base.Animal");
142         Bundle bundle = findBundle("sub1");
143         String[] annos = { "javax.xml.bind.annotation.*" };
144         List<Class<?>> classes = bundleScanner.getAnnotatedClasses(
145                 bundle.getBundleContext(), annos, excludes, true);
146         assertTrue(classes.size() == 5);
147     }
148
149     private static Bundle findBundle(String symName) {
150         for (Bundle bundle : bundles) {
151             if (bundle.getSymbolicName().equals(symName)) return bundle;
152         }
153         return null;
154     }
155
156     private static List<Bundle> makeMockBundles() throws Exception {
157         List<Bundle> result = new ArrayList<Bundle>();
158         result.add(new MockBundle());
159         result.add(new TestMockBundle("base", "", "bundle_base"));
160         result.add(new TestMockBundle("sub1", "bundle_base", "bundle_sub1"));
161         result.add(new TestMockBundle("sub2", "bundle_base", "bundle_sub2"));
162         return result;
163     }
164
165     private static List<URL> findClasses(String pkg) throws URISyntaxException {
166         if (pkg == null) return Collections.EMPTY_LIST;
167         String npkg = pkg.replaceAll("\\.", "/");
168         URL dirUrl = BundleScannerTest.class.getClassLoader().getResource(npkg);
169         final List<URL> result = new ArrayList<URL>();
170         File dir = new File(dirUrl.toURI());
171         dir.listFiles(new FileFilter() {
172
173             @Override
174             public boolean accept(File file) {
175                 if (file.isFile() && file.getName().endsWith(".class")) {
176                     try {
177                         result.add(file.toURI().toURL());
178                     } catch (MalformedURLException e) {
179                         throw new IllegalStateException(e);
180                     }
181                 }
182                 return false;
183             }
184
185         });
186         return result;
187     }
188
189     public static class TestMockBundle extends MockBundle {
190         List<URL> classes;
191         public TestMockBundle(String name, String imports, String exports) throws Exception {
192             super(name, makeHeaders(name, imports, exports), new MockBundleContext() {
193                 @Override
194                 public Bundle[] getBundles() {
195                     return bundles.toArray(new Bundle[bundles.size()]);
196                 }
197             });
198             MockBundleContext ctx = (MockBundleContext) this.getBundleContext();
199             ctx.setBundle(this);
200             this.classes = findClasses(exports);
201         }
202
203         private static Dictionary<String,String> makeHeaders(
204                 String name, String imports, String exports)
205         {
206             Dictionary<String,String> headers = new Hashtable<String,String>();
207             headers.put(Constants.IMPORT_PACKAGE, imports);
208             headers.put(Constants.EXPORT_PACKAGE, exports);
209             headers.put(Constants.BUNDLE_SYMBOLICNAME, name);
210             return headers;
211         }
212
213         @Override
214         public Enumeration findEntries(String path, String filePattern, boolean recurse) {
215             return Collections.enumeration(classes);
216         }
217
218         @Override
219         public long getBundleId() {
220             return hashCode();
221         }
222     }
223 }