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