package org.forgerock.openidm.maintenance.upgrade; import org.forgerock.commons.launcher.OSGiFrameworkService; import org.forgerock.openidm.util.FileUtil; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.wiring.FrameworkWiring; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.DataProvider; import org.testng.annotations.Factory; import org.testng.annotations.Test; import java.io.File; import java.net.URI; import java.net.URLDecoder; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNull; public class BundleHandlerTest { private String[] arguments; private OSGiFrameworkService service; private BundleHandler bundleHandler; // Path to the helloworld bundle jar private Path bundlePath; private static final String ARCHIVE_EXTENSION = ".test.bak"; private Map<String, Bundle> installedBundles = new HashMap<String, Bundle>(); private void setInstalledBundles() { for (Bundle bundle : service.getSystemBundle().getBundleContext().getBundles()) { installedBundles.put(bundle.getLocation(), bundle); } } private void updateInstalledBundles() { for (Bundle bundle : service.getSystemBundle().getBundleContext().getBundles()) { installedBundles.put(bundle.getLocation(), bundle); } } @Factory(dataProvider = "provider") public BundleHandlerTest( String[] args) { this.arguments = args; } @DataProvider public static Object[][] provider() throws Exception { String bundleHandlerDir = URLDecoder.decode(new File(BundleHandlerTest.class.getResource("/bundleHandler/") .toURI()).toString(), "utf-8"); String install = URLDecoder.decode(new File(BundleHandlerTest.class.getResource("/") .toURI().resolve("../osgi/")).toString(), "utf-8"); return new Object[][] { new Object[] { new String[] { "-i", install, "-p", bundleHandlerDir, "-w", bundleHandlerDir, "-c", "bin/launcher.json", "-s", "felix-cache" } } }; } @BeforeClass public void beforeClass() throws Exception { service = new OSGiFrameworkService(); service.init(arguments); service.setNewThread(true); service.start(); System.out.println("Framework Started - OK"); assertNotNull(service.getSystemBundle()); setInstalledBundles(); bundleHandler = new BundleHandler(service.getSystemBundle().getBundleContext(), ARCHIVE_EXTENSION, new LogHandler() { @Override public void log(Path filePath, Path backupPath) { } }); bundlePath = Paths.get(service.getProjectURI().resolve("bundle/HelloWorld-1.0-SNAPSHOT.jar")); } @AfterClass public void afterClass() throws Exception { service.stop(); } private void stopBundle(Bundle bundle) throws Exception{ bundleHandler.stopBundle(bundle); // wait 2 seconds for the framework to finish Thread.sleep(2000); } private void uninstallBundle(Bundle bundle) throws Exception { bundleHandler.uninstallBundle(bundle); updateInstalledBundles(); } private Bundle installBundle(Path path) throws Exception { bundleHandler.installBundle(path); updateInstalledBundles(); return installedBundles.get(path.toUri().toString()); } private void startBundle(Bundle bundle) throws Exception { bundleHandler.startBundle(bundle); // Wait for bundle to start Thread.sleep(2000); } @Test public void testStopBundle() throws Exception { // install the bundle Bundle bundle = installBundle(bundlePath); // start the bundle startBundle(bundle); // Assert that the bundle is installed and running assertEquals(bundle.getState(), Bundle.ACTIVE); // stop the bundle stopBundle(bundle); // assert that bundle is in stopped state assertEquals(bundle.getState(), Bundle.RESOLVED); } @Test public void testUninstallBundle() throws Exception { // install bundle Bundle bundle = installBundle(bundlePath); // start bundle startBundle(bundle); // assert that the bundle is installed in the framework assertNotNull(bundle); // stop bundle stopBundle(bundle); // after uninstalling we want to refresh the packages to use this new bundle Set<Bundle> bundlesToRefresh = new HashSet<Bundle>(); bundlesToRefresh.add(bundle); // uninstall bundle uninstallBundle(bundle); // refresh to show uninstalled bundle FrameworkWiring frameworkWiring = service.getSystemBundle().adapt(FrameworkWiring.class); frameworkWiring.refreshBundles(bundlesToRefresh); // assert that the bundle is in uninstalled state bundle = installedBundles.get(bundlePath.toUri().toString()); assertEquals(bundle.getState(), Bundle.UNINSTALLED); // at the "system" level remove the bundle from the bundles/directory now } @Test public void testInstallBundle() throws Exception { // create bundle info for installing Bundle bundle = installedBundles.get(bundlePath); // check that the bundle does not exist already in the framework assertNull(bundle); // install the bundle bundle = installBundle(bundlePath); // validate that the bundle has actually been installed assertNotNull(bundle); assertEquals(bundle.getState(), Bundle.INSTALLED); } @Test public void testStartBundle() throws Exception { // install bundle Bundle bundle = installBundle(bundlePath); // start the bundle startBundle(bundle); // assert that the bundle is now started in the Active state assertEquals(bundle.getState(), Bundle.ACTIVE); } /** * This test updates a bundle that has the same version as * the previous but contains a different class implementation. */ @Test public void testUpdateBundle() throws Exception { Path backupFile = null; try { // Start API testStartBundle(); // install bundle Path bundlePathV1 = Paths.get(service.getProjectURI().resolve("bundle/HelloImplementation-1.0-SNAPSHOT.jar")); Bundle bundle = installBundle(bundlePathV1); // start the bundle startBundle(bundle); // assert that the bundle is now started in the Active state assertEquals(bundle.getState(), Bundle.ACTIVE); String bundle1Version = FileUtil.readManifest(bundlePathV1.toFile()).getValue("Bundle-Version"); assertEquals(bundle1Version, bundle.getVersion().toString()); Path bundlePathV2 = Paths.get(service.getProjectURI().resolve("bundle/updated/HelloImplementation-1.0-SNAPSHOT.jar")); bundleHandler.upgradeBundle(bundlePathV2, "HelloImplementation"); // assert that the old file has been backed up with archive extension backupFile = Paths.get(new URI(bundlePathV1.toUri().toString().concat(ARCHIVE_EXTENSION))); assertNotNull(backupFile); // update bundle bundleHandler.updateBundle(bundle); // refresh all bundles that would need the new import from bundle2 FrameworkWiring frameworkWiring = service.getSystemBundle().adapt(FrameworkWiring.class); frameworkWiring.refreshBundles(null); } finally { // cleanup this test if (backupFile != null) { Files.delete(backupFile); } } } }