You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by gh...@apache.org on 2018/08/31 07:03:11 UTC

[sling-org-apache-sling-installer-provider-installhook] 04/05: SLING-7790 JUnit Tests

This is an automated email from the ASF dual-hosted git repository.

ghenzler pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-installer-provider-installhook.git

commit a373a922b7fa773bf3c2c188eb9c514b3319d173
Author: Georg Henzler <ge...@netcentric.biz>
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;
+	}
+
+}