/* * Copyright 2012 Red Hat, Inc. and/or its affiliates. * * Licensed under the Eclipse Public License version 1.0, available at * http://www.eclipse.org/legal/epl-v10.html */ package org.jboss.forge.furnace; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.forge.furnace.addons.AddonId; import org.jboss.forge.furnace.impl.FurnaceImpl; import org.jboss.forge.furnace.impl.addons.*; import org.jboss.forge.furnace.impl.util.Files; import org.jboss.forge.furnace.repositories.*; import org.jboss.forge.furnace.util.OperatingSystemUtils; import org.jboss.forge.furnace.versions.SingleVersion; import org.jboss.forge.furnace.versions.Version; import org.junit.Assert; import org.junit.Test; public class AddonRepositoryImplTest { @Test public void testMinorVersionCompatible() throws Exception { AddonId entry = AddonId.fromCoordinates("com.example.plugin,40,1.0.0-SNAPSHOT"); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2000.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2-SNAPSHOT"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1000-SNAPSHOT"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1000-adsfasfsd"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.1.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.1.1.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.2.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.2.1.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("2.0.0.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("s1.0.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(null, entry)); } @Test public void testMinorVersionCompatibleBackwards() throws Exception { AddonId entry = AddonId.fromCoordinates("com.example.plugin,20.0i,1.1.0-SNAPSHOT"); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2000.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.2-SNAPSHOT"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1000-SNAPSHOT"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.0.1000-adsfasfsd"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.1.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.1.1.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.2.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("1.2.1.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("2.0.0.Final"), entry)); Assert.assertFalse(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf("s1.0.0.Final"), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(SingleVersion.valueOf(""), entry)); Assert.assertTrue(AddonRepositoryImpl.isApiCompatible(null, entry)); } @Test public void testAddonDirNaming() throws Exception { File temp = File.createTempFile("addonDir", "test"); temp.deleteOnExit(); MutableAddonRepository repository = AddonRepositoryImpl.forDirectory(new FurnaceImpl(), temp); File dir = repository.getAddonBaseDir(AddonId.from("123#$%456", "!@#789*-0")); Assert.assertEquals("123-456-789-0", dir.getName()); } @Test public void testDeployAddonEntryNoDependencies() throws Exception { File temp = File.createTempFile("addonDir", "test"); temp.deleteOnExit(); MutableAddonRepository repository = AddonRepositoryImpl.forDirectory(new FurnaceImpl(), temp); AddonId addon = AddonId.from("1", "2"); ArrayList<File> resourceJars = new ArrayList<File>(); File tempJar = File.createTempFile("addon" + addon.getName(), ".jar"); tempJar.createNewFile(); resourceJars.add(tempJar); Assert.assertFalse(repository.isDeployed(addon)); repository.deploy(addon, new ArrayList<AddonDependencyEntry>(), resourceJars); Assert.assertTrue(repository.isDeployed(addon)); Assert.assertFalse(repository.isEnabled(addon)); repository.enable(addon); Assert.assertTrue(repository.isEnabled(addon)); Assert.assertEquals(0, repository.getAddonDependencies(addon).size()); } @Test public void testDeployAddonEntryNoDependenciesOrResources() throws Exception { File temp = File.createTempFile("addonDir", "test"); temp.deleteOnExit(); MutableAddonRepository repository = AddonRepositoryImpl.forDirectory(new FurnaceImpl(), temp); AddonId addon = AddonId.from("1", "2"); Assert.assertFalse(repository.isDeployed(addon)); repository.deploy(addon, new ArrayList<AddonDependencyEntry>(), new ArrayList<File>()); Assert.assertTrue(repository.isDeployed(addon)); Assert.assertFalse(repository.isEnabled(addon)); repository.enable(addon); Assert.assertTrue(repository.isEnabled(addon)); Assert.assertEquals(0, repository.getAddonDependencies(addon).size()); } @Test public void testDeployAddonEntrySingleDependency() throws Exception { File temp = File.createTempFile("addonDir", "test"); temp.deleteOnExit(); MutableAddonRepository repository = AddonRepositoryImpl.forDirectory(new FurnaceImpl(), temp); AddonId addon = AddonId.from("1", "2"); AddonDependencyEntry dependency = AddonDependencyEntry.create("nm", "ver", false, true); repository.deploy(addon, Arrays.asList(dependency), new ArrayList<File>()); Assert.assertEquals(1, repository.getAddonDependencies(addon).size()); Assert.assertTrue(repository.getAddonDependencies(addon).contains(dependency)); } @Test public void testDeployAddonEntryMultipleDependencies() throws Exception { File temp = File.createTempFile("addonDir", "test"); temp.deleteOnExit(); MutableAddonRepository repository = AddonRepositoryImpl.forDirectory(new FurnaceImpl(), temp); AddonId addon = AddonId.from("1", "2"); AddonDependencyEntry dependency0 = AddonDependencyEntry.create("nm1", "ver", true, false); AddonDependencyEntry dependency1 = AddonDependencyEntry.create("nm2", "ver"); repository.deploy(addon, Arrays.asList(dependency0, dependency1), new ArrayList<File>()); Assert.assertEquals(2, repository.getAddonDependencies(addon).size()); Assert.assertTrue(repository.getAddonDependencies(addon).contains(dependency0)); Assert.assertTrue(repository.getAddonDependencies(addon).contains(dependency1)); } @Test public void testPluggableStateRepository() throws Exception { Furnace furnace = new FurnaceImpl(); File temp = OperatingSystemUtils.createTempDir(); MutableAddonRepositoryStorageStrategy storageRepository = new AddonRepositoryStorageStrategyImpl(furnace.getLockManager(), temp); MutableAddonRepositoryStateStrategy stateRepository = new TestInMemoryAddonRepositoryStateStrategy(); MutableAddonRepository repository = new AddonRepositoryImpl(storageRepository, stateRepository, temp); AddonId addon = TestInMemoryAddonRepositoryStateStrategy.TEST_ADDON; repository.enable(addon); Assert.assertTrue(repository.isEnabled(addon)); // Delete storage directory to demonstrate that filesystem is not used to store the state Files.delete(temp, true); // Addon still enabled state wasn't affected Assert.assertTrue(repository.isEnabled(addon)); } @Test public void testSharedStateRepository() throws Exception { Furnace furnace = new FurnaceImpl(); MutableAddonRepositoryStateStrategy stateRepository = new TestInMemoryAddonRepositoryStateStrategy(); MutableAddonRepository firstRepo = createTempRepository(furnace, stateRepository); MutableAddonRepository secondRepo = createTempRepository(furnace, stateRepository); AddonId addon = TestInMemoryAddonRepositoryStateStrategy.TEST_ADDON; Assert.assertFalse(firstRepo.isEnabled(addon)); Assert.assertFalse(secondRepo.isEnabled(addon)); stateRepository.enable(addon); Assert.assertTrue(firstRepo.isEnabled(addon)); Assert.assertTrue(secondRepo.isEnabled(addon)); } @Test public void testSharedStorageRepository() throws Exception { Furnace furnace = new FurnaceImpl(); File temp = OperatingSystemUtils.createTempDir(); MutableAddonRepositoryStorageStrategy storageRepository = new AddonRepositoryStorageStrategyImpl(furnace.getLockManager(), temp); AddonRepositoryStateStrategyImpl firstStateRepository = new AddonRepositoryStateStrategyImpl(furnace, OperatingSystemUtils.createTempDir()); MutableAddonRepository firstRepo = new AddonRepositoryImpl(storageRepository, firstStateRepository, temp); AddonRepositoryStateStrategyImpl secondStateRepository = new AddonRepositoryStateStrategyImpl(furnace, OperatingSystemUtils.createTempDir()); MutableAddonRepository secondRepo = new AddonRepositoryImpl(storageRepository, secondStateRepository, temp); AddonId addon = TestInMemoryAddonRepositoryStateStrategy.TEST_ADDON; Assert.assertFalse(firstRepo.isDeployed(addon)); Assert.assertFalse(secondRepo.isDeployed(addon)); // Since storage is shared, addon will be deployed to both repositories firstRepo.deploy(addon, Collections.emptyList(), Collections.emptyList()); Assert.assertTrue(firstRepo.isDeployed(addon)); Assert.assertTrue(secondRepo.isDeployed(addon)); firstRepo.enable(addon); Assert.assertTrue(firstRepo.isEnabled(addon)); Assert.assertFalse(secondRepo.isEnabled(addon)); } private static AddonRepositoryImpl createTempRepository(Furnace furnace, MutableAddonRepositoryStateStrategy stateRepository) { File temp = OperatingSystemUtils.createTempDir(); MutableAddonRepositoryStorageStrategy storageRepository = new AddonRepositoryStorageStrategyImpl(furnace.getLockManager(), temp); return new AddonRepositoryImpl(storageRepository, stateRepository, temp); } private static class TestInMemoryAddonRepositoryStateStrategy implements MutableAddonRepositoryStateStrategy { static final AddonId TEST_ADDON = AddonId.from("com.example.addon", "1.2.3"); private final ConcurrentMap<AddonId, Boolean> state = new ConcurrentHashMap<>(); private final AtomicInteger version = new AtomicInteger(1); @Override public boolean disable(AddonId addon) { state.compute(addon, (key, oldValue) -> { version.incrementAndGet(); return false; }); return true; } @Override public boolean enable(AddonId addon) { state.compute(addon, (key, oldValue) -> { version.incrementAndGet(); return true; }); return true; } @Override public boolean isEnabled(AddonId addon) { return state.getOrDefault(addon, false); } @Override public List<AddonId> listAll() { return Collections.singletonList(TEST_ADDON); } @Override public List<AddonId> listEnabled() { return listAll(); } @Override public List<AddonId> listEnabledCompatibleWithVersion(Version version) { return listAll(); } @Override public int getVersion() { return version.get(); } @Override public DirtyChecker createDirtyChecker() { return new VersionDirtyChecker(this::getVersion); } } }