You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AbstractExtensionFinderTest.java 8.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249
  1. /*
  2. * Copyright (C) 2012-present the original author or authors.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.pf4j;
  17. import com.google.common.collect.ImmutableList;
  18. import com.google.common.io.ByteStreams;
  19. import com.google.testing.compile.Compilation;
  20. import org.junit.jupiter.api.AfterEach;
  21. import org.junit.jupiter.api.BeforeEach;
  22. import org.junit.jupiter.api.Test;
  23. import org.pf4j.plugin.FailTestPlugin;
  24. import org.pf4j.plugin.TestExtensionPoint;
  25. import javax.tools.JavaFileObject;
  26. import java.io.IOException;
  27. import java.util.ArrayList;
  28. import java.util.Collections;
  29. import java.util.HashMap;
  30. import java.util.HashSet;
  31. import java.util.LinkedHashMap;
  32. import java.util.List;
  33. import java.util.Map;
  34. import java.util.Set;
  35. import static com.google.testing.compile.CompilationSubject.assertThat;
  36. import static com.google.testing.compile.Compiler.javac;
  37. import static org.junit.jupiter.api.Assertions.assertEquals;
  38. import static org.junit.jupiter.api.Assertions.assertNotNull;
  39. import static org.mockito.Mockito.eq;
  40. import static org.mockito.Mockito.mock;
  41. import static org.mockito.Mockito.when;
  42. /**
  43. * @author Mario Franco
  44. */
  45. public class AbstractExtensionFinderTest {
  46. private PluginManager pluginManager;
  47. @BeforeEach
  48. public void setUp() {
  49. PluginWrapper pluginStarted = mock(PluginWrapper.class);
  50. when(pluginStarted.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
  51. when(pluginStarted.getPluginState()).thenReturn(PluginState.STARTED);
  52. PluginWrapper pluginStopped = mock(PluginWrapper.class);
  53. when(pluginStopped.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
  54. when(pluginStopped.getPluginState()).thenReturn(PluginState.STOPPED);
  55. pluginManager = mock(PluginManager.class);
  56. when(pluginManager.getPlugin(eq("plugin1"))).thenReturn(pluginStarted);
  57. when(pluginManager.getPlugin(eq("plugin2"))).thenReturn(pluginStopped);
  58. when(pluginManager.getPluginClassLoader(eq("plugin1"))).thenReturn(getClass().getClassLoader());
  59. when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory());
  60. }
  61. @AfterEach
  62. public void tearDown() {
  63. pluginManager = null;
  64. }
  65. /**
  66. * Test of {@link AbstractExtensionFinder#find(Class)}.
  67. */
  68. @Test
  69. public void testFindFailType() {
  70. ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
  71. @Override
  72. public Map<String, Set<String>> readPluginsStorages() {
  73. return Collections.emptyMap();
  74. }
  75. @Override
  76. public Map<String, Set<String>> readClasspathStorages() {
  77. return Collections.emptyMap();
  78. }
  79. };
  80. List<ExtensionWrapper<FailTestPlugin>> list = instance.find(FailTestPlugin.class);
  81. assertEquals(0, list.size());
  82. }
  83. /**
  84. * Test of {@link AbstractExtensionFinder#find(Class)}.
  85. */
  86. @Test
  87. public void testFindFromClasspath() {
  88. ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
  89. @Override
  90. public Map<String, Set<String>> readPluginsStorages() {
  91. return Collections.emptyMap();
  92. }
  93. @Override
  94. public Map<String, Set<String>> readClasspathStorages() {
  95. Map<String, Set<String>> entries = new LinkedHashMap<>();
  96. Set<String> bucket = new HashSet<>();
  97. bucket.add("org.pf4j.plugin.TestExtension");
  98. bucket.add("org.pf4j.plugin.FailTestExtension");
  99. entries.put(null, bucket);
  100. return entries;
  101. }
  102. };
  103. List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
  104. assertEquals(2, list.size());
  105. }
  106. /**
  107. * Test of {@link AbstractExtensionFinder#find(Class, String)}.
  108. */
  109. @Test
  110. public void testFindFromPlugin() {
  111. ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
  112. @Override
  113. public Map<String, Set<String>> readPluginsStorages() {
  114. Map<String, Set<String>> entries = new LinkedHashMap<>();
  115. Set<String> bucket = new HashSet<>();
  116. bucket.add("org.pf4j.plugin.TestExtension");
  117. bucket.add("org.pf4j.plugin.FailTestExtension");
  118. entries.put("plugin1", bucket);
  119. bucket = new HashSet<>();
  120. bucket.add("org.pf4j.plugin.TestExtension");
  121. entries.put("plugin2", bucket);
  122. return entries;
  123. }
  124. @Override
  125. public Map<String, Set<String>> readClasspathStorages() {
  126. return Collections.emptyMap();
  127. }
  128. };
  129. List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
  130. assertEquals(2, list.size());
  131. list = instance.find(TestExtensionPoint.class, "plugin1");
  132. assertEquals(2, list.size());
  133. list = instance.find(TestExtensionPoint.class, "plugin2");
  134. assertEquals(0, list.size());
  135. }
  136. /**
  137. * Test of {@link AbstractExtensionFinder#findClassNames(String)}.
  138. */
  139. @Test
  140. public void testFindClassNames() {
  141. ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
  142. @Override
  143. public Map<String, Set<String>> readPluginsStorages() {
  144. Map<String, Set<String>> entries = new LinkedHashMap<>();
  145. Set<String> bucket = new HashSet<>();
  146. bucket.add("org.pf4j.plugin.TestExtension");
  147. entries.put("plugin1", bucket);
  148. return entries;
  149. }
  150. @Override
  151. public Map<String, Set<String>> readClasspathStorages() {
  152. Map<String, Set<String>> entries = new LinkedHashMap<>();
  153. Set<String> bucket = new HashSet<>();
  154. bucket.add("org.pf4j.plugin.TestExtension");
  155. bucket.add("org.pf4j.plugin.FailTestExtension");
  156. entries.put(null, bucket);
  157. return entries;
  158. }
  159. };
  160. Set<String> result = instance.findClassNames(null);
  161. assertEquals(2, result.size());
  162. result = instance.findClassNames("plugin1");
  163. assertEquals(1, result.size());
  164. }
  165. @Test
  166. public void findExtensionAnnotation() throws Exception {
  167. Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting,
  168. ExtensionAnnotationProcessorTest.WhazzupGreeting);
  169. assertThat(compilation).succeededWithoutWarnings();
  170. ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles();
  171. assertEquals(2, generatedFiles.size());
  172. JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
  173. Map<String, Class<?>> loadedClasses = classLoader.loadClasses(new ArrayList<>(generatedFiles));
  174. Class<?> clazz = loadedClasses.get("test.WhazzupGreeting");
  175. Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz);
  176. assertNotNull(extension);
  177. }
  178. static class JavaFileObjectClassLoader extends ClassLoader {
  179. public Map<String, Class<?>> loadClasses(List<JavaFileObject> classes) throws IOException {
  180. // Sort generated ".class" by lastModified field
  181. classes.sort((c1, c2) -> (int) (c1.getLastModified() - c2.getLastModified()));
  182. // Load classes
  183. Map<String, Class<?>> loadedClasses = new HashMap<>(classes.size());
  184. for (JavaFileObject clazz : classes) {
  185. String className = getClassName(clazz);
  186. byte[] data = ByteStreams.toByteArray(clazz.openInputStream());
  187. Class<?> loadedClass = defineClass(className, data,0, data.length);
  188. loadedClasses.put(className, loadedClass);
  189. }
  190. return loadedClasses;
  191. }
  192. private static String getClassName(JavaFileObject object) {
  193. String name = object.getName();
  194. // Remove "/CLASS_OUT/" from head and ".class" from tail
  195. name = name.substring(14, name.length() - 6);
  196. name = name.replace('/', '.');
  197. return name;
  198. }
  199. }
  200. }