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