/* * Copyright (C) 2012-present the original author or authors. * * Licensed 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.pf4j; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import org.pf4j.plugin.PluginZip; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.startsWith; import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; public class LoadPluginsTest { private DefaultPluginManager pluginManager; @TempDir Path pluginsPath; @BeforeEach public void setUp() { pluginManager = new DefaultPluginManager(pluginsPath); } @Test public void load() throws Exception { PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); assertTrue(Files.exists(pluginZip.path())); assertEquals(0, pluginManager.getPlugins().size()); pluginManager.loadPlugins(); assertTrue(Files.exists(pluginZip.path())); assertTrue(Files.exists(pluginZip.unzippedPath())); assertEquals(1, pluginManager.getPlugins().size()); assertEquals(pluginZip.pluginId(), pluginManager.idForPath(pluginZip.unzippedPath())); } @Test public void loadNonExisting() { assertThrows(IllegalArgumentException.class, () -> pluginManager.loadPlugin(Paths.get("nonexisting"))); } @Test public void loadTwiceFails() throws Exception { PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); assertNotNull(pluginManager.loadPluginFromPath(pluginZip.path())); assertThrows(PluginAlreadyLoadedException.class, () -> pluginManager.loadPluginFromPath(pluginZip.path())); } @Test public void loadPluginWithSameIdDifferentPathFails() throws Exception { String pluginId = "myPlugin"; String pluginVersion = "1.2.3"; Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) .pluginVersion(pluginVersion) .build(); Path plugin2Path = pluginsPath.resolve("my-plugin-1.2.3-renamed.zip"); PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) .pluginVersion(pluginVersion) .build(); // Verify the first plugin with the given id is loaded assertNotNull(pluginManager.loadPluginFromPath(plugin1.path())); Path loadedPlugin1Path = pluginManager.getPlugin(pluginId).getPluginPath(); try { // Verify the second plugin is not loaded as it has the same metadata pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { // Check the path of the loaded plugin remains the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); // Check the message includes relevant information String message = e.getMessage(); assertThat(message, startsWith("There is an already loaded plugin")); assertThat(message, containsString(pluginId)); assertThat(message, containsString("my-plugin-1.2.3-renamed")); } } /** * This test verifies the behaviour as of PF4J 2.x, where plugins of different * versions but with the pluginId cannot be loaded correctly because the API * uses pluginId as the unique identifier of the loaded plugin. */ @Test public void loadPluginWithSameIdDifferentVersionsFails() throws Exception { String pluginId = "myPlugin"; String plugin1Version = "1.2.3"; Path plugin1Path = pluginsPath.resolve("my-plugin-1.2.3.zip"); PluginZip plugin1 = new PluginZip.Builder(plugin1Path, pluginId) .pluginVersion(plugin1Version) .build(); String plugin2Version = "2.0.0"; Path plugin2Path = pluginsPath.resolve("my-plugin-2.0.0.zip"); PluginZip plugin2 = new PluginZip.Builder(plugin2Path, pluginId) .pluginVersion(plugin2Version) .build(); // Verify the first plugin with the given id is loaded assertNotNull(pluginManager.loadPluginFromPath(plugin1.path())); Path loadedPlugin1Path = pluginManager.getPlugin(pluginId).getPluginPath(); try { // Verify the second plugin is not loaded as it has the same pluginId pluginManager.loadPluginFromPath(plugin2.path()); fail("Expected loadPluginFromPath to fail"); } catch (PluginRuntimeException e) { // Check the path and version of the loaded plugin remain the same PluginWrapper loadedPlugin = pluginManager.getPlugin(pluginId); assertThat(loadedPlugin.getPluginPath(), equalTo(loadedPlugin1Path)); assertThat(loadedPlugin.getDescriptor().getVersion(), equalTo(plugin1Version)); } } @Test public void loadUnloadLoad() throws Exception { PluginZip pluginZip = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); pluginManager.loadPlugins(); assertEquals(1, pluginManager.getPlugins().size()); assertTrue(pluginManager.unloadPlugin(pluginManager.idForPath(pluginZip.unzippedPath()))); // duplicate check assertNull(pluginManager.idForPath(pluginZip.unzippedPath())); // Double unload ok assertFalse(pluginManager.unloadPlugin(pluginManager.idForPath(pluginZip.unzippedPath()))); assertNotNull(pluginManager.loadPlugin(pluginZip.unzippedPath())); } @Test public void upgrade() throws Exception { String pluginId = "myPlugin"; new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), pluginId) .pluginVersion("1.2.3") .build(); pluginManager.loadPlugins(); pluginManager.startPlugins(); assertEquals(1, pluginManager.getPlugins().size()); assertEquals(1, pluginManager.getStartedPlugins().size()); PluginZip pluginZip2 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-2.0.0.ZIP"), pluginId) .pluginVersion("2.0.0") .build(); assertEquals("1.2.3", pluginManager.getPlugin(pluginId).getDescriptor().getVersion()); pluginManager.unloadPlugin(pluginId); pluginManager.loadPlugin(pluginZip2.path()); // or `pluginManager.loadPlugins();` pluginManager.startPlugin(pluginId); assertEquals(1, pluginManager.getPlugins().size()); assertEquals("2.0.0", pluginManager.getPlugin(pluginId).getDescriptor().getVersion()); assertEquals("2.0.0", pluginManager.getStartedPlugins().get(0).getDescriptor().getVersion()); } @Test public void getRoot() { assertEquals(pluginsPath, pluginManager.getPluginsRoot()); } @Test public void notAPlugin() { pluginsPath.resolve("not-a-zip"); pluginManager.loadPlugins(); assertEquals(0, pluginManager.getPlugins().size()); } @Test public void deletePlugin() throws Exception { PluginZip pluginZip1 = new PluginZip.Builder(pluginsPath.resolve("my-plugin-1.2.3.zip"), "myPlugin") .pluginVersion("1.2.3") .build(); PluginZip pluginZip3 = new PluginZip.Builder(pluginsPath.resolve("other-3.0.0.Zip"), "other") .pluginVersion("3.0.0") .build(); pluginManager.loadPlugins(); pluginManager.startPlugins(); assertEquals(2, pluginManager.getPlugins().size()); pluginManager.deletePlugin(pluginZip1.pluginId()); assertEquals(1, pluginManager.getPlugins().size()); assertFalse(Files.exists(pluginZip1.path())); assertFalse(Files.exists(pluginZip1.unzippedPath())); assertTrue(Files.exists(pluginZip3.path())); assertTrue(Files.exists(pluginZip3.unzippedPath())); } }