This is an automated email from the ASF dual-hosted git repository. kwin pushed a commit to branch feature/SLING-8291_expose-error in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-provider-installhook.git
commit a373a922b7fa773bf3c2c188eb9c514b3319d173 Author: Georg Henzler <[email protected]> AuthorDate: Wed Aug 22 20:25:14 2018 +0200 SLING-7790 JUnit Tests --- pom.xml | 19 ++- .../provider/installhook/OsgiInstallerHook.java | 61 +++++----- .../installhook/OsgiInstallerListener.java | 6 +- .../installhook/OsgiInstallerHookTest.java | 129 +++++++++++++++++++++ .../installhook/OsgiInstallerListenerTest.java | 72 ++++++++++++ 5 files changed, 249 insertions(+), 38 deletions(-) diff --git a/pom.xml b/pom.xml index 533af9b..7dc69c3 100644 --- a/pom.xml +++ b/pom.xml @@ -102,7 +102,22 @@ <artifactId>osgi.cmpn</artifactId> <scope>provided</scope> </dependency> - - </dependencies> + + <!-- Basic dependencies for Unit Tests --> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + </dependency> + <dependency> + <groupId>org.slf4j</groupId> + <artifactId>slf4j-simple</artifactId> + </dependency> + <dependency> + <groupId>org.mockito</groupId> + <artifactId>mockito-core</artifactId> + <version>2.13.0</version> + <scope>test</scope> + </dependency> + </dependencies> </project> diff --git a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java index 362ae6e..a8d910b 100644 --- a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java +++ b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHook.java @@ -34,7 +34,6 @@ import java.util.jar.JarInputStream; import java.util.jar.Manifest; import javax.jcr.Node; -import javax.jcr.PathNotFoundException; import javax.jcr.RepositoryException; import javax.jcr.Session; @@ -68,26 +67,27 @@ public class OsgiInstallerHook implements InstallHook { private static final Logger LOG = LoggerFactory.getLogger(OsgiInstallerHook.class); private static final String PACKAGE_PROPERTY_MAX_WAIT_IN_SEC = "maxWaitForOsgiInstallerInSec"; - private static final int DEFAULT_MAX_WAIT_IN_SEC = 120; + private static final String PACKAGE_PROP_INSTALL_PATH_REGEX = "installPathRegex"; - private static final String MANIFEST_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName"; - private static final String MANIFEST_BUNDLE_VERSION = "Bundle-Version"; - - private static final String JCR_CONTENT = "jcr:content"; - private static final String JCR_CONTENT_DATA = JCR_CONTENT + "/jcr:data"; - private static final String JCR_LAST_MODIFIED = "jcr:lastModified"; - private static final String JCR_CONTENT_LAST_MODIFIED = JCR_CONTENT + "/" + JCR_LAST_MODIFIED; + public static final int DEFAULT_PRIORITY_INSTALL_HOOK = 2000; + private static final int DEFAULT_MAX_WAIT_IN_SEC = 60; public static final String URL_SCHEME = "jcrinstall"; public static final String CONFIG_SUFFIX = ".config"; public static final String JAR_SUFFIX = ".jar"; - public static final String PACKAGE_PROP_INSTALL_PATH_REGEX = "installPathRegex"; + private static final String MANIFEST_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName"; + private static final String MANIFEST_BUNDLE_VERSION = "Bundle-Version"; + private static final String FOLDER_META_INF = "META-INF"; + + static final String JCR_CONTENT = "jcr:content"; + static final String JCR_CONTENT_DATA = JCR_CONTENT + "/jcr:data"; + static final String JCR_LAST_MODIFIED = "jcr:lastModified"; + static final String JCR_CONTENT_LAST_MODIFIED = JCR_CONTENT + "/" + JCR_LAST_MODIFIED; public static final String DOT = "."; - public static final int PRIORITY_INSTALL_HOOK = 2000; - private InstallHookLogger logger = new InstallHookLogger(); + InstallHookLogger logger = new InstallHookLogger(); @Override public void execute(InstallContext context) throws PackageException { @@ -210,7 +210,7 @@ public class OsgiInstallerHook implements InstallHook { private Set<String> getConfigPidsToInstall(List<String> configResourcePaths, Session session, List<InstallableResource> installableResources, ConfigurationAdmin confAdmin) - throws IOException, InvalidSyntaxException, PathNotFoundException, RepositoryException { + throws IOException, InvalidSyntaxException, RepositoryException { Set<String> configIdsToInstall = new HashSet<>(); for (String configResourcePath : configResourcePaths) { boolean needsInstallation = false; @@ -247,8 +247,7 @@ public class OsgiInstallerHook implements InstallHook { private Set<String> getBundlesToInstall(List<BundleInPackage> bundleResources, Map<String, String> bundleVersionsBySymbolicId, Session session, - List<InstallableResource> installableResources) - throws PathNotFoundException, RepositoryException, IOException { + List<InstallableResource> installableResources) throws RepositoryException, IOException { Set<String> bundleSymbolicNamesToInstall = new HashSet<>(); Iterator<BundleInPackage> bundlesIt = bundleResources.iterator(); while (bundlesIt.hasNext()) { @@ -278,37 +277,35 @@ public class OsgiInstallerHook implements InstallHook { return bundleSymbolicNamesToInstall; } - private void collectResources(Archive archive, Entry entry, String dirPath, List<BundleInPackage> bundleResources, + void collectResources(Archive archive, Entry entry, String dirPath, List<BundleInPackage> bundleResources, List<String> configResources, String installPathRegex, Set<String> actualRunmodes) { String entryName = entry.getName(); - if(entryName.equals("META-INF")) { + if (entryName.equals(FOLDER_META_INF)) { return; - } + } String dirPathWithoutJcrRoot = StringUtils.substringAfter(dirPath, "/jcr_root"); String entryPath = dirPathWithoutJcrRoot + entryName; String dirPathWithoutSlash = StringUtils.chomp(dirPathWithoutJcrRoot, "/"); - String dirPathWithoutRunmodes; boolean runmodesMatch; if (dirPathWithoutSlash.contains(DOT)) { - String[] bits = dirPathWithoutSlash.split("\\"+DOT, 2); - dirPathWithoutRunmodes = bits[0]; - List<String> runmodesOfResource = Arrays.asList(bits[1].split("\\"+DOT)); + String[] bits = dirPathWithoutSlash.split("\\" + DOT, 2); + List<String> runmodesOfResource = Arrays.asList(bits[1].split("\\" + DOT)); Set<String> matchingRunmodes = new HashSet<String>(runmodesOfResource); matchingRunmodes.retainAll(actualRunmodes); - LOG.debug("Entry with runmode(s): entryPath={} runmodesOfResource={} actualRunmodes={} matchingRunmodes={}", entryPath, runmodesOfResource, actualRunmodes, matchingRunmodes); + LOG.debug("Entry with runmode(s): entryPath={} runmodesOfResource={} actualRunmodes={} matchingRunmodes={}", + entryPath, runmodesOfResource, actualRunmodes, matchingRunmodes); runmodesMatch = matchingRunmodes.size() == runmodesOfResource.size(); if (!runmodesMatch) { logger.log("Skipping installation of " + entryPath + " because the path is not matching all actual runmodes " + actualRunmodes); } } else { - dirPathWithoutRunmodes = dirPathWithoutSlash; runmodesMatch = true; } - if (dirPathWithoutRunmodes.matches(installPathRegex) && runmodesMatch) { + if (entryPath.matches(installPathRegex) && runmodesMatch) { if (entryName.endsWith(CONFIG_SUFFIX)) { configResources.add(entryPath); @@ -334,18 +331,18 @@ public class OsgiInstallerHook implements InstallHook { } } - private InstallableResource convert(final Node node, final String path) throws IOException, RepositoryException { + InstallableResource convert(final Node node, final String path) throws IOException, RepositoryException { logger.log("Converting " + node + " at path " + path); final String digest = String.valueOf(node.getProperty(JCR_CONTENT_LAST_MODIFIED).getDate().getTimeInMillis()); final InputStream is = node.getProperty(JCR_CONTENT_DATA).getStream(); final Dictionary<String, Object> dict = new Hashtable<String, Object>(); dict.put(InstallableResource.INSTALLATION_HINT, node.getParent().getName()); - return new InstallableResource(path, is, dict, digest, null, PRIORITY_INSTALL_HOOK); + return new InstallableResource(path, is, dict, digest, null, DEFAULT_PRIORITY_INSTALL_HOOK); } // always get fresh bundle context to avoid "Dynamic class loader has already // been deactivated" exceptions - public BundleContext getBundleContext() { + private BundleContext getBundleContext() { // use the vault bundle to hook into the OSGi world Bundle currentBundle = FrameworkUtil.getBundle(InstallHook.class); if (currentBundle == null) { @@ -378,16 +375,15 @@ public class OsgiInstallerHook implements InstallHook { } - class InstallHookLogger { + static class InstallHookLogger { - private ImportOptions options; + private ProgressTrackerListener listener; public void setOptions(ImportOptions options) { - this.options = options; + this.listener = options.getListener(); } public void logError(Logger logger, String message, Throwable throwable) { - ProgressTrackerListener listener = options.getListener(); if (listener != null) { listener.onMessage(ProgressTrackerListener.Mode.TEXT, "ERROR: " + message, ""); } @@ -399,7 +395,6 @@ public class OsgiInstallerHook implements InstallHook { } public void log(Logger logger, String message) { - ProgressTrackerListener listener = options.getListener(); if (listener != null) { listener.onMessage(ProgressTrackerListener.Mode.TEXT, message, ""); logger.debug(message); diff --git a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListener.java b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListener.java index ae15a24..c0b1ace 100644 --- a/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListener.java +++ b/src/main/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListener.java @@ -33,8 +33,8 @@ public class OsgiInstallerListener implements InstallationListener { private static final Logger LOG = LoggerFactory.getLogger(OsgiInstallerListener.class); - private static final String ENTITY_ID_PREFIX_BUNDLE = "bundle:"; - private static final String ENTITY_ID_PREFIX_CONFIG = "config:"; + static final String ENTITY_ID_PREFIX_BUNDLE = "bundle:"; + static final String ENTITY_ID_PREFIX_CONFIG = "config:"; private final Set<String> requiredBundleSymbolicNames; private final Set<String> requiredConfigPids; @@ -78,7 +78,7 @@ public class OsgiInstallerListener implements InstallationListener { LOG.trace("requiredConfigPids: {}", requiredConfigPids); LOG.trace("installedConfigPids: {}", installedConfigPids); HashSet<String> configsLeftToInstall = new HashSet<String>(requiredConfigPids); - requiredConfigPids.removeAll(installedConfigPids); + configsLeftToInstall.removeAll(installedConfigPids); LOG.debug("configsLeftToInstall: {}", configsLeftToInstall); return bundlesLeftToInstall.isEmpty() && configsLeftToInstall.isEmpty(); diff --git a/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHookTest.java b/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHookTest.java new file mode 100644 index 0000000..7d347d1 --- /dev/null +++ b/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerHookTest.java @@ -0,0 +1,129 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.sling.installer.provider.installhook; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.HashSet; +import java.util.List; + +import javax.jcr.Node; +import javax.jcr.Property; +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.vault.fs.io.Archive; +import org.apache.jackrabbit.vault.fs.io.Archive.Entry; +import org.apache.sling.installer.api.InstallableResource; +import org.apache.sling.installer.provider.installhook.OsgiInstallerHook.BundleInPackage; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.junit.MockitoJUnitRunner; + +@RunWith(MockitoJUnitRunner.class) +public class OsgiInstallerHookTest { + + OsgiInstallerHook osgiInstallerHook; + + @Mock + Node node; + + @Mock + Node parentNode; + + @Mock + Property lastModifiedProperty; + + @Mock + Property contentDataProperty; + + @Mock + Archive archive; + + @Mock + Entry entry; + + Calendar now; + + @Before + public void setup() throws RepositoryException { + osgiInstallerHook = new OsgiInstallerHook(); + + now = Calendar.getInstance(); + when(node.getProperty(OsgiInstallerHook.JCR_CONTENT_LAST_MODIFIED)).thenReturn(lastModifiedProperty); + when(lastModifiedProperty.getDate()).thenReturn(now); + when(node.getProperty(OsgiInstallerHook.JCR_CONTENT_DATA)).thenReturn(contentDataProperty); + when(node.getParent()).thenReturn(parentNode); + + } + + @Test + public void testConvert() throws IOException, RepositoryException { + + File pathToTest = new File("/apps/myproj/install/mybundle.jar"); + when(parentNode.getName()).thenReturn(pathToTest.getParentFile().getName()); + + InstallableResource installableResource = osgiInstallerHook.convert(node, pathToTest.getAbsolutePath()); + + assertEquals(String.valueOf(now.getTimeInMillis()), installableResource.getDigest()); + assertEquals(pathToTest.getParentFile().getName(), installableResource.getDictionary().get(InstallableResource.INSTALLATION_HINT)); + + } + + public void testCollectResources() throws IOException, RepositoryException { + + File pathToTest = new File("/apps/myproj/install.author/myconfig.config"); + String dirPath = "/jcr_root" + pathToTest.getParentFile().getPath() + "/"; + + when(entry.getName()).thenReturn(pathToTest.getName()); + + List<BundleInPackage> bundleResources = new ArrayList<BundleInPackage>(); + List<String> configResources = new ArrayList<String>(); + + osgiInstallerHook.collectResources(archive, entry, dirPath, bundleResources, configResources, + "/apps/other.*", new HashSet<String>(Arrays.asList("author", "dev"))); + + assertTrue(bundleResources.isEmpty()); + assertTrue(configResources.isEmpty()); + + osgiInstallerHook.collectResources(archive, entry, dirPath, bundleResources, configResources, + "/apps/myproj.*", new HashSet<String>(Arrays.asList("publish", "dev"))); + + assertTrue(bundleResources.isEmpty()); + assertTrue(configResources.isEmpty()); + + + osgiInstallerHook.collectResources(archive, entry, dirPath, bundleResources, configResources, + "/apps/myproj.*", new HashSet<String>(Arrays.asList("author", "dev"))); + + assertTrue(bundleResources.isEmpty()); + assertEquals(1, configResources.size()); + assertEquals(pathToTest.getAbsolutePath(), configResources.get(0)); + + } + +} diff --git a/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListenerTest.java b/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListenerTest.java new file mode 100644 index 0000000..6cd02ea --- /dev/null +++ b/src/test/java/org/apache/sling/installer/provider/installhook/OsgiInstallerListenerTest.java @@ -0,0 +1,72 @@ +/* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*/ +package org.apache.sling.installer.provider.installhook; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.apache.sling.installer.api.event.InstallationEvent; +import org.apache.sling.installer.api.event.InstallationEvent.TYPE; +import org.apache.sling.installer.api.tasks.TaskResource; +import org.junit.Test; + +public class OsgiInstallerListenerTest { + + private OsgiInstallerListener osgiInstallerListener; + + @Test + public void testOsgiInstallerListener() { + + String bundleSymbolicId1 = "org.prj.bundle1"; + String bundleSymbolicId2 = "org.prj.bundle2"; + Set<String> requiredBundleSymbolicNames = new HashSet<String>(Arrays.asList(bundleSymbolicId1, bundleSymbolicId2)); + String configPid1 = "org.prj.config1"; + String configPid2 = "org.prj.config2"; + Set<String> requiredConfigPids = new HashSet<String>(Arrays.asList(configPid1, configPid2)); + + osgiInstallerListener = new OsgiInstallerListener(requiredBundleSymbolicNames, requiredConfigPids); + + assertFalse(osgiInstallerListener.isDone()); + osgiInstallerListener.onEvent(getInstallationEventMock(OsgiInstallerListener.ENTITY_ID_PREFIX_BUNDLE + bundleSymbolicId1)); + assertFalse(osgiInstallerListener.isDone()); + osgiInstallerListener.onEvent(getInstallationEventMock(OsgiInstallerListener.ENTITY_ID_PREFIX_BUNDLE + bundleSymbolicId2)); + assertFalse(osgiInstallerListener.isDone()); + osgiInstallerListener.onEvent(getInstallationEventMock(OsgiInstallerListener.ENTITY_ID_PREFIX_CONFIG + configPid1)); + assertFalse(osgiInstallerListener.isDone()); + osgiInstallerListener.onEvent(getInstallationEventMock(OsgiInstallerListener.ENTITY_ID_PREFIX_CONFIG + configPid2)); + assertTrue(osgiInstallerListener.isDone()); + + } + + public InstallationEvent getInstallationEventMock(String entityId) { + InstallationEvent event = mock(InstallationEvent.class); + when(event.getType()).thenReturn(TYPE.PROCESSED); + TaskResource taskResource = mock(TaskResource.class); + when(event.getSource()).thenReturn(taskResource); + when(taskResource.getEntityId()).thenReturn(entityId); + return event; + } + +}
