package org.osgi.service.indexer.impl; import static org.mockito.Matchers.*; import static org.mockito.Mockito.*; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.StringWriter; import java.util.Collections; import java.util.Dictionary; import java.util.HashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import junit.framework.TestCase; import org.mockito.ArgumentCaptor; import org.osgi.framework.Filter; import org.osgi.framework.FrameworkUtil; import org.osgi.framework.ServiceReference; import org.osgi.service.indexer.Capability; import org.osgi.service.indexer.Requirement; import org.osgi.service.indexer.Resource; import org.osgi.service.indexer.ResourceAnalyzer; import org.osgi.service.indexer.ResourceIndexer; import org.osgi.service.indexer.impl.RepoIndex; import org.osgi.service.log.LogService; public class TestIndexer extends TestCase { public void testFragmentBsnVersion() throws Exception { assertFragmentMatch("testdata/fragment-01.txt", "testdata/01-bsn+version.jar"); } public void testFragmentLocalization() throws Exception { assertFragmentMatch("testdata/fragment-02.txt", "testdata/02-localization.jar"); } public void testFragmentExport() throws Exception { assertFragmentMatch("testdata/fragment-03.txt", "testdata/03-export.jar"); } public void testFragmentExportWithUses() throws Exception { assertFragmentMatch("testdata/fragment-04.txt", "testdata/04-export+uses.jar"); } public void testFragmentImport() throws Exception { assertFragmentMatch("testdata/fragment-05.txt", "testdata/05-import.jar"); } public void testFragmentRequireBundle() throws Exception { assertFragmentMatch("testdata/fragment-06.txt", "testdata/06-requirebundle.jar"); } public void testFragmentOptionalImport() throws Exception { assertFragmentMatch("testdata/fragment-07.txt", "testdata/07-optionalimport.jar"); } public void testFragmentFragmentHost() throws Exception { assertFragmentMatch("testdata/fragment-08.txt", "testdata/08-fragmenthost.jar"); } public void testFragmentSingletonBundle() throws Exception { assertFragmentMatch("testdata/fragment-09.txt", "testdata/09-singleton.jar"); } public void testFragmentExportService() throws Exception { assertFragmentMatch("testdata/fragment-10.txt", "testdata/10-exportservice.jar"); } public void testFragmentImportService() throws Exception { assertFragmentMatch("testdata/fragment-11.txt", "testdata/11-importservice.jar"); } public void testFragmentForbidFragments() throws Exception { assertFragmentMatch("testdata/fragment-12.txt", "testdata/12-nofragments.jar"); } public void testFragmentBREE() throws Exception { assertFragmentMatch("testdata/fragment-13.txt", "testdata/13-bree.jar"); } public void testFragmentProvideRequireCap() throws Exception { assertFragmentMatch("testdata/fragment-14.txt", "testdata/14-provide-require-cap.jar"); } public void testFragmentRequireSCR() throws Exception { assertFragmentMatch("testdata/fragment-15.txt", "testdata/15-scr.jar"); } public void testFragmentRequireSCR1_0() throws Exception { assertFragmentMatch("testdata/fragment-scr1_0.txt", "testdata/scr1_0.jar"); } public void testFragmentRequireSCR1_1() throws Exception { assertFragmentMatch("testdata/fragment-scr1_1.txt", "testdata/scr1_1.jar"); } public void testFragmentRequireSCR1_2() throws Exception { assertFragmentMatch("testdata/fragment-scr1_2.txt", "testdata/scr1_2.jar"); } private static void assertFragmentMatch(String expectedPath, String jarPath) throws Exception { RepoIndex indexer = new RepoIndex(); assertFragmentMatch(indexer, expectedPath, jarPath); } private static void assertFragmentMatch(RepoIndex indexer, String expectedPath, String jarPath) throws Exception { StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File(jarPath)), writer, null); String expected = Utils.readStream(new FileInputStream(expectedPath)); assertEquals(expected, writer.toString().trim()); } public void testEmptyIndex() throws Exception { RepoIndex indexer = new RepoIndex(); ByteArrayOutputStream out = new ByteArrayOutputStream(); Set<File> files = Collections.emptySet(); Map<String, String> config = new HashMap<String, String>(); config.put(RepoIndex.REPOSITORY_INCREMENT_OVERRIDE, "0"); config.put(ResourceIndexer.REPOSITORY_NAME, "empty"); config.put(ResourceIndexer.PRETTY, "true"); indexer.index(files, out, config); String expected = Utils.readStream(new FileInputStream("testdata/empty.txt")); assertEquals(expected, out.toString()); } public void testFullIndex() throws Exception { RepoIndex indexer = new RepoIndex(); ByteArrayOutputStream out = new ByteArrayOutputStream(); Set<File> files = new LinkedHashSet<File>(); files.add(new File("testdata/03-export.jar")); files.add(new File("testdata/06-requirebundle.jar")); Map<String, String> config = new HashMap<String, String>(); config.put(RepoIndex.REPOSITORY_INCREMENT_OVERRIDE, "0"); config.put(ResourceIndexer.REPOSITORY_NAME, "full-c+f"); indexer.index(files, out, config); String unpackedXML = Utils.readStream(new FileInputStream("testdata/unpacked.xml")); String expected = unpackedXML.replaceAll("[\\n\\t]*", ""); assertEquals(expected, Utils.decompress(out.toByteArray())); } public void testFullIndexPrettyPrint() throws Exception { RepoIndex indexer = new RepoIndex(); ByteArrayOutputStream out = new ByteArrayOutputStream(); Set<File> files = new LinkedHashSet<File>(); files.add(new File("testdata/03-export.jar")); files.add(new File("testdata/06-requirebundle.jar")); Map<String, String> config = new HashMap<String, String>(); config.put(RepoIndex.REPOSITORY_INCREMENT_OVERRIDE, "0"); config.put(ResourceIndexer.REPOSITORY_NAME, "full-c+f"); config.put(ResourceIndexer.PRETTY, "true"); indexer.index(files, out, config); String expected = Utils.readStream(new FileInputStream("testdata/full-03+06.txt")); assertEquals(expected, out.toString()); } public void testAddAnalyzer() throws Exception { RepoIndex indexer = new RepoIndex(); indexer.addAnalyzer(new WibbleAnalyzer(), null); StringWriter writer = new StringWriter(); LinkedHashSet<File> files = new LinkedHashSet<File>(); files.add(new File("testdata/01-bsn+version.jar")); files.add(new File("testdata/02-localization.jar")); indexer.indexFragment(files, writer, null); String expected = Utils.readStream(new FileInputStream("testdata/fragment-wibble.txt")); assertEquals(expected, writer.toString().trim()); } public void testAddAnalyzerWithFilter() throws Exception { RepoIndex indexer = new RepoIndex(); indexer.addAnalyzer(new WibbleAnalyzer(), FrameworkUtil.createFilter("(location=*sion.jar)")); StringWriter writer = new StringWriter(); LinkedHashSet<File> files = new LinkedHashSet<File>(); files.add(new File("testdata/01-bsn+version.jar")); files.add(new File("testdata/02-localization.jar")); indexer.indexFragment(files, writer, null); String expected = Utils.readStream(new FileInputStream("testdata/fragment-wibble-filtered.txt")); assertEquals(expected, writer.toString().trim()); } public void testRootInSubdirectory() throws Exception { RepoIndex indexer = new RepoIndex(); Map<String, String> props = new HashMap<String, String>(); props.put(ResourceIndexer.ROOT_URL, new File("testdata").getAbsoluteFile().toURI().toURL().toString()); StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File("testdata/01-bsn+version.jar")), writer, props); String expected = Utils.readStream(new FileInputStream("testdata/fragment-subdir1.txt")); assertEquals(expected, writer.toString().trim()); } public void testRootInSubSubdirectory() throws Exception { RepoIndex indexer = new RepoIndex(); Map<String, String> props = new HashMap<String, String>(); props.put(ResourceIndexer.ROOT_URL, new File("testdata").getAbsoluteFile().toURI().toURL().toString()); StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File("testdata/subdir/01-bsn+version.jar")), writer, props); String expected = Utils.readStream(new FileInputStream("testdata/fragment-subdir2.txt")); assertEquals(expected, writer.toString().trim()); } public void testLogErrorsFromAnalyzer() throws Exception { ResourceAnalyzer badAnalyzer = new ResourceAnalyzer() { public void analyzeResource(Resource resource, List<Capability> capabilities, List<Requirement> requirements) throws Exception { throw new Exception("Bang!"); } }; ResourceAnalyzer goodAnalyzer = mock(ResourceAnalyzer.class); LogService log = mock(LogService.class); RepoIndex indexer = new RepoIndex(log); indexer.addAnalyzer(badAnalyzer, null); indexer.addAnalyzer(goodAnalyzer, null); // Run the indexer Map<String, String> props = new HashMap<String, String>(); props.put(ResourceIndexer.ROOT_URL, new File("testdata").getAbsoluteFile().toURI().toURL().toString()); StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File("testdata/subdir/01-bsn+version.jar")), writer, props); // The "good" analyzer should have been called verify(goodAnalyzer).analyzeResource(any(Resource.class), anyListOf(Capability.class), anyListOf(Requirement.class)); // The log service should have been notified about the exception ArgumentCaptor<Exception> exceptionCaptor = ArgumentCaptor.forClass(Exception.class); verify(log).log(eq(LogService.LOG_ERROR), any(String.class), exceptionCaptor.capture()); assertEquals("Bang!", exceptionCaptor.getValue().getMessage()); } public void testBundleOutsideRootDirectory() throws Exception { LogService log = mock(LogService.class); RepoIndex indexer = new RepoIndex(log); Map<String, String> props = new HashMap<String, String>(); props.put(ResourceIndexer.ROOT_URL, new File("testdata/subdir").getAbsoluteFile().toURI().toURL().toString()); StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File("testdata/01-bsn+version.jar")), writer, props); verify(log).log(eq(LogService.LOG_ERROR), anyString(), isA(IllegalArgumentException.class)); } public void testRemoveDisallowed() throws Exception { LogService log = mock(LogService.class); RepoIndex indexer = new RepoIndex(log); indexer.addAnalyzer(new NaughtyAnalyzer(), null); Map<String, String> props = new HashMap<String, String>(); props.put(ResourceIndexer.ROOT_URL, new File("testdata").getAbsoluteFile().toURI().toURL().toString()); StringWriter writer = new StringWriter(); indexer.indexFragment(Collections.singleton(new File("testdata/subdir/01-bsn+version.jar")), writer, props); verify(log).log(eq(LogService.LOG_ERROR), anyString(), isA(UnsupportedOperationException.class)); } public void testRecogniseFelixSCR() throws Exception { Properties props = new Properties(); props.load(new FileInputStream("testdata/known-bundles.properties")); RepoIndex indexer = new RepoIndex(); indexer.addAnalyzer(new KnownBundleAnalyzer(props), FrameworkUtil.createFilter("(name=*)")); assertFragmentMatch(indexer, "testdata/org.apache.felix.scr-1.6.0.xml", "testdata/org.apache.felix.scr-1.6.0.jar"); } public void testMacroExpansion() throws Exception { Properties props = new Properties(); props.load(new FileInputStream("testdata/known-bundles.properties")); RepoIndex indexer = new RepoIndex(); indexer.addAnalyzer(new KnownBundleAnalyzer(props), FrameworkUtil.createFilter("(name=*)")); assertFragmentMatch(indexer, "testdata/org.apache.felix.eventadmin.xml", "testdata/org.apache.felix.eventadmin-1.2.14.jar"); } }