aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDecebal Suiu <decebal.suiu@gmail.com>2023-02-02 20:05:51 +0200
committerGitHub <noreply@github.com>2023-02-02 20:05:51 +0200
commitcce6e1334c4d1401a08d56e77d1b3c03142faf98 (patch)
tree75499f7d4a7504c8cb06ad71a9920ccd7d4896b7
parent21a28546dd30197ebd6d307225baf7a86102620b (diff)
downloadpf4j-cce6e1334c4d1401a08d56e77d1b3c03142faf98.tar.gz
pf4j-cce6e1334c4d1401a08d56e77d1b3c03142faf98.zip
Improve class generation for testing (#515)
-rw-r--r--pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java112
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java24
-rw-r--r--pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java59
-rw-r--r--pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java93
-rw-r--r--pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java3
-rw-r--r--pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java32
-rw-r--r--pf4j/src/test/java/org/pf4j/test/AnotherTestPlugin.java34
-rw-r--r--pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java20
-rw-r--r--pf4j/src/test/java/org/pf4j/test/FailTestExtension.java37
-rw-r--r--pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java26
-rw-r--r--pf4j/src/test/java/org/pf4j/test/JavaFileObjectClassLoader.java73
-rw-r--r--pf4j/src/test/java/org/pf4j/test/JavaFileObjectDataProvider.java62
-rw-r--r--pf4j/src/test/java/org/pf4j/test/JavaFileObjectUtils.java52
-rw-r--r--pf4j/src/test/java/org/pf4j/test/JavaSources.java64
-rw-r--r--pf4j/src/test/java/org/pf4j/test/TestPlugin.java3
15 files changed, 409 insertions, 285 deletions
diff --git a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
index eff6ebe..1e4b5eb 100644
--- a/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
+++ b/pf4j/src/test/java/org/pf4j/AbstractExtensionFinderTest.java
@@ -15,34 +15,26 @@
*/
package org.pf4j;
-import com.google.common.collect.ImmutableList;
-import com.google.common.io.ByteStreams;
-import com.google.testing.compile.Compilation;
-import java.util.Comparator;
-import java.util.UUID;
import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.pf4j.test.FailTestPlugin;
+import org.pf4j.test.JavaFileObjectClassLoader;
+import org.pf4j.test.JavaFileObjectUtils;
+import org.pf4j.test.JavaSources;
+import org.pf4j.test.TestExtension;
import org.pf4j.test.TestExtensionPoint;
import javax.tools.JavaFileObject;
-import java.io.IOException;
-import java.util.ArrayList;
import java.util.Collections;
-import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.UUID;
-import static com.google.testing.compile.CompilationSubject.assertThat;
-import static com.google.testing.compile.Compiler.javac;
-import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -64,9 +56,9 @@ public class AbstractExtensionFinderTest {
when(pluginStopped.getPluginState()).thenReturn(PluginState.STOPPED);
pluginManager = mock(PluginManager.class);
- when(pluginManager.getPlugin(eq("plugin1"))).thenReturn(pluginStarted);
- when(pluginManager.getPlugin(eq("plugin2"))).thenReturn(pluginStopped);
- when(pluginManager.getPluginClassLoader(eq("plugin1"))).thenReturn(getClass().getClassLoader());
+ when(pluginManager.getPlugin("plugin1")).thenReturn(pluginStarted);
+ when(pluginManager.getPlugin("plugin2")).thenReturn(pluginStopped);
+ when(pluginManager.getPluginClassLoader("plugin1")).thenReturn(getClass().getClassLoader());
when(pluginManager.getExtensionFactory()).thenReturn(new DefaultExtensionFactory());
}
@@ -93,7 +85,7 @@ public class AbstractExtensionFinderTest {
}
};
- List<ExtensionWrapper<FailTestPlugin>> list = instance.find(FailTestPlugin.class);
+ List<ExtensionWrapper<TestExtension>> list = instance.find(TestExtension.class);
assertEquals(0, list.size());
}
@@ -115,7 +107,6 @@ public class AbstractExtensionFinderTest {
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put(null, bucket);
return entries;
@@ -124,7 +115,7 @@ public class AbstractExtensionFinderTest {
};
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
}
/**
@@ -140,7 +131,6 @@ public class AbstractExtensionFinderTest {
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put("plugin1", bucket);
bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
@@ -157,12 +147,13 @@ public class AbstractExtensionFinderTest {
};
List<ExtensionWrapper<TestExtensionPoint>> list = instance.find(TestExtensionPoint.class);
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
list = instance.find(TestExtensionPoint.class, "plugin1");
- assertEquals(2, list.size());
+ assertEquals(1, list.size());
list = instance.find(TestExtensionPoint.class, "plugin2");
+ // "0" because the status of "plugin2" is STOPPED => no extensions
assertEquals(0, list.size());
}
@@ -210,6 +201,16 @@ public class AbstractExtensionFinderTest {
*/
@Test
public void testFindExtensionWrappersFromPluginId() {
+ // complicate the test to show hot to deal with dynamic Java classes (generated at runtime from sources)
+ PluginWrapper plugin3 = mock(PluginWrapper.class);
+ JavaFileObject object = JavaSources.compile(DefaultExtensionFactoryTest.FailTestExtension);
+ JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
+ classLoader.load(object);
+ when(plugin3.getPluginClassLoader()).thenReturn(classLoader);
+ when(plugin3.getPluginState()).thenReturn(PluginState.STARTED);
+ when(pluginManager.getPluginClassLoader("plugin3")).thenReturn(classLoader);
+ when(pluginManager.getPlugin("plugin3")).thenReturn(plugin3);
+
ExtensionFinder instance = new AbstractExtensionFinder(pluginManager) {
@Override
@@ -218,11 +219,13 @@ public class AbstractExtensionFinderTest {
Set<String> bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
- bucket.add("org.pf4j.test.FailTestExtension");
entries.put("plugin1", bucket);
bucket = new HashSet<>();
bucket.add("org.pf4j.test.TestExtension");
entries.put("plugin2", bucket);
+ bucket = new HashSet<>();
+ bucket.add(JavaFileObjectUtils.getClassName(object));
+ entries.put("plugin3", bucket);
return entries;
}
@@ -235,73 +238,40 @@ public class AbstractExtensionFinderTest {
};
List<ExtensionWrapper> plugin1Result = instance.find("plugin1");
- assertEquals(2, plugin1Result.size());
+ assertEquals(1, plugin1Result.size());
List<ExtensionWrapper> plugin2Result = instance.find("plugin2");
assertEquals(0, plugin2Result.size());
- List<ExtensionWrapper> plugin3Result = instance.find(UUID.randomUUID().toString());
- assertEquals(0, plugin3Result.size());
+ List<ExtensionWrapper> plugin3Result = instance.find("plugin3");
+ assertEquals(1, plugin3Result.size());
+
+ List<ExtensionWrapper> plugin4Result = instance.find(UUID.randomUUID().toString());
+ assertEquals(0, plugin4Result.size());
}
@Test
- public void findExtensionAnnotation() throws Exception {
- Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting,
- ExtensionAnnotationProcessorTest.WhazzupGreeting);
- assertThat(compilation).succeededWithoutWarnings();
- ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles();
+ public void findExtensionAnnotation() {
+ List<JavaFileObject> generatedFiles = JavaSources.compileAll(JavaSources.Greeting, JavaSources.WhazzupGreeting);
assertEquals(2, generatedFiles.size());
- JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
- Map<String, Class<?>> loadedClasses = classLoader.loadClasses(new ArrayList<>(generatedFiles));
+ Map<String, Class<?>> loadedClasses = new JavaFileObjectClassLoader().load(generatedFiles);
Class<?> clazz = loadedClasses.get("test.WhazzupGreeting");
Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz);
- assertNotNull(extension);
+ Assertions.assertNotNull(extension);
}
@Test
- public void findExtensionAnnotationThatMissing() throws Exception {
- Compilation compilation = javac().compile(ExtensionAnnotationProcessorTest.Greeting,
+ public void findExtensionAnnotationThatMissing() {
+ List<JavaFileObject> generatedFiles = JavaSources.compileAll(JavaSources.Greeting,
ExtensionAnnotationProcessorTest.SpinnakerExtension_NoExtension,
ExtensionAnnotationProcessorTest.WhazzupGreeting_SpinnakerExtension);
- assertThat(compilation).succeededWithoutWarnings();
- ImmutableList<JavaFileObject> generatedFiles = compilation.generatedFiles();
assertEquals(3, generatedFiles.size());
- JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
- Map<String, Class<?>> loadedClasses = classLoader.loadClasses(new ArrayList<>(generatedFiles));
+ Map<String, Class<?>> loadedClasses = new JavaFileObjectClassLoader().load(generatedFiles);
Class<?> clazz = loadedClasses.get("test.WhazzupGreeting");
Extension extension = AbstractExtensionFinder.findExtensionAnnotation(clazz);
- assertNull(extension);
- }
-
- static class JavaFileObjectClassLoader extends ClassLoader {
-
- public Map<String, Class<?>> loadClasses(List<JavaFileObject> classes) throws IOException {
- // Sort generated ".class" by lastModified field
- classes.sort(Comparator.comparingLong(JavaFileObject::getLastModified));
-
- // Load classes
- Map<String, Class<?>> loadedClasses = new HashMap<>(classes.size());
- for (JavaFileObject clazz : classes) {
- String className = getClassName(clazz);
- byte[] data = ByteStreams.toByteArray(clazz.openInputStream());
- Class<?> loadedClass = defineClass(className, data,0, data.length);
- loadedClasses.put(className, loadedClass);
- }
-
- return loadedClasses;
- }
-
- private static String getClassName(JavaFileObject object) {
- String name = object.getName();
- // Remove "/CLASS_OUT/" from head and ".class" from tail
- name = name.substring(14, name.length() - 6);
- name = name.replace('/', '.');
-
- return name;
- }
-
+ Assertions.assertNull(extension);
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
index 9d73b5e..47eb2d3 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultExtensionFactoryTest.java
@@ -15,12 +15,16 @@
*/
package org.pf4j;
+import com.google.testing.compile.JavaFileObjects;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.pf4j.test.FailTestExtension;
+import org.pf4j.test.JavaFileObjectClassLoader;
+import org.pf4j.test.JavaSources;
import org.pf4j.test.TestExtension;
+import javax.tools.JavaFileObject;
+
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -29,6 +33,19 @@ import static org.junit.jupiter.api.Assertions.assertThrows;
*/
public class DefaultExtensionFactoryTest {
+ public static final JavaFileObject FailTestExtension = JavaFileObjects.forSourceLines("FailTestExtension",
+ "package test;",
+ "import org.pf4j.test.TestExtensionPoint;",
+ "import org.pf4j.Extension;",
+ "",
+ "@Extension",
+ "public class FailTestExtension implements TestExtensionPoint {",
+ " public FailTestExtension(String name) {}",
+ "",
+ " @Override",
+ " public String saySomething() { return \"I am a fail test extension\";}",
+ "}");
+
private ExtensionFactory extensionFactory;
@BeforeEach
@@ -54,7 +71,10 @@ public class DefaultExtensionFactoryTest {
*/
@Test
public void testCreateFailConstructor() {
- assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(FailTestExtension.class));
+ JavaFileObject object = JavaSources.compile(FailTestExtension);
+ JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
+ Class<?> extensionClass = (Class<?>) classLoader.load(object).values().toArray()[0];
+ assertThrows(PluginRuntimeException.class, () -> extensionFactory.create(extensionClass));
}
}
diff --git a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
index c453e38..24ed40c 100644
--- a/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/DefaultPluginFactoryTest.java
@@ -15,14 +15,18 @@
*/
package org.pf4j;
+import com.google.testing.compile.JavaFileObjects;
import org.junit.jupiter.api.Test;
-import org.pf4j.test.AnotherFailTestPlugin;
-import org.pf4j.test.AnotherTestPlugin;
-import org.pf4j.test.FailTestPlugin;
+import org.pf4j.test.JavaFileObjectClassLoader;
+import org.pf4j.test.JavaFileObjectUtils;
+import org.pf4j.test.JavaSources;
import org.pf4j.test.TestPlugin;
+import javax.tools.JavaFileObject;
+
import static org.hamcrest.CoreMatchers.instanceOf;
import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.Mockito.mock;
@@ -33,6 +37,29 @@ import static org.mockito.Mockito.when;
*/
public class DefaultPluginFactoryTest {
+ public static final JavaFileObject FailTestPlugin = JavaFileObjects.forSourceLines("FailTestPlugin",
+ "package test;",
+ "import org.pf4j.Plugin;",
+ "",
+ "public class FailTestPlugin {",
+ "}");
+
+ public static final JavaFileObject AnotherFailTestPlugin = JavaFileObjects.forSourceLines("AnotherFailTestPlugin",
+ "package test;",
+ "import org.pf4j.Plugin;",
+ "",
+ "public class AnotherFailTestPlugin extends Plugin {",
+ " public AnotherFailTestPlugin() { super(null); }",
+ "}");
+
+ public static final JavaFileObject AnotherTestPlugin = JavaFileObjects.forSourceLines("AnotherTestPlugin",
+ "package test;",
+ "import org.pf4j.Plugin;",
+ "",
+ "public class AnotherTestPlugin extends Plugin {",
+ " public AnotherTestPlugin() { super(); }",
+ "}");
+
@Test
public void testCreate() {
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
@@ -52,27 +79,35 @@ public class DefaultPluginFactoryTest {
@Test
public void pluginConstructorNoParameters() {
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
- when(pluginDescriptor.getPluginClass()).thenReturn(AnotherTestPlugin.class.getName());
+ JavaFileObject object = JavaSources.compile(AnotherTestPlugin);
+ String pluginClassName = JavaFileObjectUtils.getClassName(object);
+ when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName);
PluginWrapper pluginWrapper = mock(PluginWrapper.class);
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor);
- when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
+ JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
+ classLoader.load(AnotherTestPlugin);
+ when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader);
PluginFactory pluginFactory = new DefaultPluginFactory();
Plugin result = pluginFactory.create(pluginWrapper);
assertNotNull(result);
- assertThat(result, instanceOf(AnotherTestPlugin.class));
+ assertEquals(pluginClassName, result.getClass().getName());
}
@Test
public void testCreateFail() {
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
- when(pluginDescriptor.getPluginClass()).thenReturn(FailTestPlugin.class.getName());
+ JavaFileObject object = JavaSources.compile(FailTestPlugin);
+ String pluginClassName = JavaFileObjectUtils.getClassName(object);
+ when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName);
PluginWrapper pluginWrapper = mock(PluginWrapper.class);
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor);
- when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
+ JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
+ classLoader.load(FailTestPlugin);
+ when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader);
PluginFactory pluginFactory = new DefaultPluginFactory();
@@ -98,11 +133,15 @@ public class DefaultPluginFactoryTest {
@Test
public void testCreateFailConstructor() {
PluginDescriptor pluginDescriptor = mock(PluginDescriptor.class);
- when(pluginDescriptor.getPluginClass()).thenReturn(AnotherFailTestPlugin.class.getName());
+ JavaFileObject object = JavaSources.compile(AnotherFailTestPlugin);
+ String pluginClassName = JavaFileObjectUtils.getClassName(object);
+ when(pluginDescriptor.getPluginClass()).thenReturn(pluginClassName);
PluginWrapper pluginWrapper = mock(PluginWrapper.class);
when(pluginWrapper.getDescriptor()).thenReturn(pluginDescriptor);
- when(pluginWrapper.getPluginClassLoader()).thenReturn(getClass().getClassLoader());
+ JavaFileObjectClassLoader classLoader = new JavaFileObjectClassLoader();
+ classLoader.load(AnotherFailTestPlugin);
+ when(pluginWrapper.getPluginClassLoader()).thenReturn(classLoader);
PluginFactory pluginFactory = new DefaultPluginFactory();
diff --git a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
index f966523..2b3241d 100644
--- a/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
+++ b/pf4j/src/test/java/org/pf4j/ExtensionAnnotationProcessorTest.java
@@ -16,12 +16,16 @@
package org.pf4j;
import com.google.testing.compile.Compilation;
+import com.google.testing.compile.Compiler;
import com.google.testing.compile.JavaFileObjects;
+import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.pf4j.processor.ExtensionAnnotationProcessor;
import org.pf4j.processor.LegacyExtensionStorage;
+import org.pf4j.test.JavaSources;
import javax.tools.JavaFileObject;
+import java.io.IOException;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
@@ -38,30 +42,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
*/
public class ExtensionAnnotationProcessorTest {
- public static final JavaFileObject Greeting = JavaFileObjects.forSourceLines(
- "Greeting",
- "package test;",
- "import org.pf4j.ExtensionPoint;",
- "",
- "public interface Greeting extends ExtensionPoint {",
- " String getGreeting();",
- "}");
-
- public static final JavaFileObject WhazzupGreeting = JavaFileObjects.forSourceLines(
- "WhazzupGreeting",
- "package test;",
- "import org.pf4j.Extension;",
- "",
- "@Extension",
- "public class WhazzupGreeting implements Greeting {",
- " @Override",
- " public String getGreeting() {",
- " return \"Whazzup\";",
- " }",
- "}");
-
- public static final JavaFileObject WhazzupGreeting_NoExtensionPoint = JavaFileObjects.forSourceLines(
- "WhazzupGreeting",
+ public static final JavaFileObject WhazzupGreeting_NoExtensionPoint = JavaFileObjects.forSourceLines("WhazzupGreeting",
"package test;",
"import org.pf4j.Extension;",
"",
@@ -73,8 +54,7 @@ public class ExtensionAnnotationProcessorTest {
" }",
"}");
- public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines(
- "SpinnakerExtension",
+ public static final JavaFileObject SpinnakerExtension = JavaFileObjects.forSourceLines("SpinnakerExtension",
"package test;",
"",
"import org.pf4j.Extension;",
@@ -91,8 +71,7 @@ public class ExtensionAnnotationProcessorTest {
"public @interface SpinnakerExtension {",
"}");
- public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines(
- "WhazzupGreeting",
+ public static final JavaFileObject WhazzupGreeting_SpinnakerExtension = JavaFileObjects.forSourceLines("WhazzupGreeting",
"package test;",
"",
"@SpinnakerExtension",
@@ -104,10 +83,9 @@ public class ExtensionAnnotationProcessorTest {
"}");
/**
- * The same like {@link #SpinnakerExtension} but without {@code Extension} annotation.
+ * The same as {@link #SpinnakerExtension} but without {@code Extension} annotation.
*/
- public static final JavaFileObject SpinnakerExtension_NoExtension = JavaFileObjects.forSourceLines(
- "SpinnakerExtension",
+ public static final JavaFileObject SpinnakerExtension_NoExtension = JavaFileObjects.forSourceLines("SpinnakerExtension",
"package test;",
"",
"import org.pf4j.Extension;",
@@ -124,52 +102,53 @@ public class ExtensionAnnotationProcessorTest {
"public @interface SpinnakerExtension {",
"}");
+ private ExtensionAnnotationProcessor annotationProcessor;
+
+ @BeforeEach
+ public void setUp() throws IOException {
+ annotationProcessor = new ExtensionAnnotationProcessor();
+ }
+
@Test
public void getSupportedAnnotationTypes() {
- ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor();
- Set<String> result = instance.getSupportedAnnotationTypes();
+ Set<String> result = annotationProcessor.getSupportedAnnotationTypes();
assertEquals(1, result.size());
assertEquals("*", result.iterator().next());
}
@Test
public void getSupportedOptions() {
- ExtensionAnnotationProcessor instance = new ExtensionAnnotationProcessor();
- Set<String> result = instance.getSupportedOptions();
+ Set<String> result = annotationProcessor.getSupportedOptions();
assertEquals(2, result.size());
}
@Test
public void options() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).withOptions("-Ab=2", "-Ac=3")
- .compile(Greeting, WhazzupGreeting);
- assertEquals(compilation.status(), Compilation.Status.SUCCESS);
+ Compilation compilation = compiler().withOptions("-Ab=2", "-Ac=3")
+ .compile(JavaSources.Greeting, JavaSources.WhazzupGreeting);
+ assertEquals(Compilation.Status.SUCCESS, compilation.status());
Map<String, String> options = new HashMap<>();
options.put("b", "2");
options.put("c", "3");
- assertEquals(options, processor.getProcessingEnvironment().getOptions());
+ assertEquals(options, annotationProcessor.getProcessingEnvironment().getOptions());
}
@Test
public void storage() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting);
- assertEquals(compilation.status(), Compilation.Status.SUCCESS);
- assertEquals(processor.getStorage().getClass(), LegacyExtensionStorage.class);
+ Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting);
+ assertEquals(Compilation.Status.SUCCESS, compilation.status());
+ assertEquals(annotationProcessor.getStorage().getClass(), LegacyExtensionStorage.class);
}
@Test
public void compileWithoutError() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting);
+ Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting);
assertThat(compilation).succeededWithoutWarnings();
}
@Test
public void compileWithError() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting_NoExtensionPoint);
+ Compilation compilation = compile(JavaSources.Greeting, WhazzupGreeting_NoExtensionPoint);
assertThat(compilation).failed();
assertThat(compilation).hadErrorContaining("it doesn't implement ExtensionPoint")
.inFile(WhazzupGreeting_NoExtensionPoint)
@@ -179,22 +158,28 @@ public class ExtensionAnnotationProcessorTest {
@Test
public void getExtensions() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).compile(Greeting, WhazzupGreeting);
+ Compilation compilation = compile(JavaSources.Greeting, JavaSources.WhazzupGreeting);
assertThat(compilation).succeededWithoutWarnings();
Map<String, Set<String>> extensions = new HashMap<>();
extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting")));
- assertEquals(extensions, processor.getExtensions());
+ assertEquals(extensions, annotationProcessor.getExtensions());
}
@Test
public void compileNestedExtensionAnnotation() {
- ExtensionAnnotationProcessor processor = new ExtensionAnnotationProcessor();
- Compilation compilation = javac().withProcessors(processor).compile(Greeting, SpinnakerExtension, WhazzupGreeting_SpinnakerExtension);
+ Compilation compilation = compile(JavaSources.Greeting, SpinnakerExtension, WhazzupGreeting_SpinnakerExtension);
assertThat(compilation).succeededWithoutWarnings();
Map<String, Set<String>> extensions = new HashMap<>();
extensions.put("test.Greeting", new HashSet<>(Collections.singletonList("test.WhazzupGreeting")));
- assertEquals(extensions, processor.getExtensions());
+ assertEquals(extensions, annotationProcessor.getExtensions());
+ }
+
+ private Compiler compiler() {
+ return javac().withProcessors(annotationProcessor);
+ }
+
+ private Compilation compile(JavaFileObject... sources) {
+ return compiler().compile(sources);
}
}
diff --git a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
index ddfd2a4..ff3d65a 100644
--- a/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
+++ b/pf4j/src/test/java/org/pf4j/SingletonExtensionFactoryTest.java
@@ -18,7 +18,6 @@ package org.pf4j;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
-import org.pf4j.test.FailTestExtension;
import org.pf4j.test.TestExtension;
import java.io.File;
@@ -57,7 +56,7 @@ public class SingletonExtensionFactoryTest {
@Test
public void createNewEachTime() {
- ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, FailTestExtension.class.getName());
+ ExtensionFactory extensionFactory = new SingletonExtensionFactory(pluginManager, "FailTestExtension.class");
Object extensionOne = extensionFactory.create(TestExtension.class);
Object extensionTwo = extensionFactory.create(TestExtension.class);
assertNotSame(extensionOne, extensionTwo);
diff --git a/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java b/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java
deleted file mode 100644
index 79aa41b..0000000
--- a/pf4j/src/test/java/org/pf4j/test/AnotherFailTestPlugin.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.test;
-
-import org.pf4j.Plugin;
-
-/**
- * A wrong {@link org.pf4j.Plugin}.
- * It's wrong because it calls super constructor with {@code null} for ({@link org.pf4j.PluginWrapper} parameter).
- *
- * @author Mario Franco
- */
-public class AnotherFailTestPlugin extends Plugin {
-
- public AnotherFailTestPlugin() {
- super(null);
- }
-
-}
diff --git a/pf4j/src/test/java/org/pf4j/test/AnotherTestPlugin.java b/pf4j/src/test/java/org/pf4j/test/AnotherTestPlugin.java
deleted file mode 100644
index f2e10c1..0000000
--- a/pf4j/src/test/java/org/pf4j/test/AnotherTestPlugin.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.test;
-
-import org.pf4j.Plugin;
-
-/**
- * A simple {@link Plugin}.
- *
- * In real applications you don't need to create a plugin like this if you are not interested in lifecycle events.
- * {@code PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified.
- *
- * @author Decebal Suiu
- */
-public class AnotherTestPlugin extends Plugin {
-
- public AnotherTestPlugin() {
- super();
- }
-
-}
diff --git a/pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java b/pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java
index 6a203aa..473f948 100644
--- a/pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java
+++ b/pf4j/src/test/java/org/pf4j/test/DefaultClassDataProvider.java
@@ -15,10 +15,10 @@
*/
package org.pf4j.test;
-import java.io.ByteArrayOutputStream;
+import com.google.common.io.ByteStreams;
+
import java.io.IOException;
import java.io.InputStream;
-import java.io.OutputStream;
/**
* Get class data from the class path.
@@ -35,20 +35,10 @@ public class DefaultClassDataProvider implements ClassDataProvider {
throw new RuntimeException("Cannot find class data");
}
- try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
- copyStream(classDataStream, outputStream);
- return outputStream.toByteArray();
+ try {
+ return ByteStreams.toByteArray(classDataStream);
} catch (IOException e) {
- throw new RuntimeException(e.getMessage(), e);
- }
- }
-
- private void copyStream(InputStream in, OutputStream out) throws IOException {
- byte[] buffer = new byte[1024];
-
- int bytesRead;
- while ((bytesRead = in.read(buffer)) != -1) {
- out.write(buffer, 0, bytesRead);
+ throw new IllegalStateException(e);
}
}
diff --git a/pf4j/src/test/java/org/pf4j/test/FailTestExtension.java b/pf4j/src/test/java/org/pf4j/test/FailTestExtension.java
deleted file mode 100644
index 1ce2aa8..0000000
--- a/pf4j/src/test/java/org/pf4j/test/FailTestExtension.java
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * 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.test;
-
-import org.pf4j.Extension;
-
-/**
- * A wrong {@link org.pf4j.Extension}.
- * It's wrong because it doesn't contain a constructor with empty parameters (or only the default constructor).
- *
- * @author Mario Franco
- */
-@Extension
-public class FailTestExtension implements TestExtensionPoint {
-
- public FailTestExtension(String name) {
- }
-
- @Override
- public String saySomething() {
- return "I am a fail test extension";
- }
-
-}
diff --git a/pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java b/pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java
deleted file mode 100644
index 3a1824f..0000000
--- a/pf4j/src/test/java/org/pf4j/test/FailTestPlugin.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * 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.test;
-
-/**
- * A wrong {@link org.pf4j.Plugin}.
- * It's wrong because it doesn't extends {@link org.pf4j.Plugin}.
- *
- * @author Mario Franco
- */
-public class FailTestPlugin {
-
-}
diff --git a/pf4j/src/test/java/org/pf4j/test/JavaFileObjectClassLoader.java b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectClassLoader.java
new file mode 100644
index 0000000..2afe0d2
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectClassLoader.java
@@ -0,0 +1,73 @@
+/*
+ * 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.test;
+
+import javax.tools.JavaFileObject;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * {@link ClassLoader} that loads {@link JavaFileObject.Kind#CLASS}s.
+ * If {@code JavaFileObject} type is {@link JavaFileObject.Kind#SOURCE} them the source is compiled.
+ *
+ * @author Decebal Suiu
+ */
+public class JavaFileObjectClassLoader extends ClassLoader {
+
+ public Map<String, Class<?>> load(JavaFileObject... objects) {
+ return load(Arrays.asList(objects));
+ }
+
+ public Map<String, Class<?>> load(List<JavaFileObject> objects) {
+ Objects.requireNonNull(objects);
+
+ List<JavaFileObject> mutableObjects = new ArrayList<>(objects);
+
+ // Sort generated ".class" by lastModified field
+ mutableObjects.sort(Comparator.comparingLong(JavaFileObject::getLastModified));
+
+ // Compile Java sources (if exists)
+ for (int i = 0; i < mutableObjects.size(); i++) {
+ JavaFileObject object = mutableObjects.get(i);
+ if (object.getKind() == JavaFileObject.Kind.CLASS) {
+ continue;
+ }
+
+ if (object.getKind() == JavaFileObject.Kind.SOURCE) {
+ mutableObjects.set(i, JavaSources.compile(object));
+ } else {
+ throw new IllegalStateException("Type " + object.getKind() + " is not supported");
+ }
+ }
+
+ // Load objects
+ Map<String, Class<?>> loadedClasses = new HashMap<>();
+ for (JavaFileObject object : mutableObjects) {
+ String className = JavaFileObjectUtils.getClassName(object);
+ byte[] data = JavaFileObjectUtils.getAllBytes(object);
+ Class<?> loadedClass = defineClass(className, data, 0, data.length);
+ loadedClasses.put(className, loadedClass);
+ }
+
+ return loadedClasses;
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/test/JavaFileObjectDataProvider.java b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectDataProvider.java
new file mode 100644
index 0000000..d729721
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectDataProvider.java
@@ -0,0 +1,62 @@
+/*
+ * 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.test;
+
+import javax.tools.FileObject;
+import javax.tools.JavaFileObject;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * Get class data from {@link JavaFileObject}.
+ * If {@code JavaFileObject} type is {@link JavaFileObject.Kind#SOURCE} them the source is compiled.
+ *
+ * @author Decebal Suiu
+ */
+public class JavaFileObjectDataProvider implements ClassDataProvider {
+
+ private final Map<String, JavaFileObject> classes;
+
+ public JavaFileObjectDataProvider(Map<String, JavaFileObject> classes) {
+ this.classes = classes;
+ }
+
+ public static JavaFileObjectDataProvider of(List<JavaFileObject> objects) {
+ List<JavaFileObject> tmp = new ArrayList<>(objects.size());
+ for (JavaFileObject object : objects) {
+ if (object.getKind() == JavaFileObject.Kind.CLASS) {
+ tmp.add(object);
+ } else if (object.getKind() == JavaFileObject.Kind.SOURCE) {
+ tmp.add(JavaSources.compile(object));
+ } else {
+ throw new IllegalStateException("Type " + object.getKind() + " is not supported");
+ }
+ }
+
+ // TODO JavaFileObjectUtils.getClassName() ?!
+ Map<String, JavaFileObject> classes = tmp.stream().collect(Collectors.toMap(FileObject::getName, c -> c));
+
+ return new JavaFileObjectDataProvider(classes);
+ }
+
+ @Override
+ public byte[] getClassData(String className) {
+ return JavaFileObjectUtils.getAllBytes(classes.get(className));
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/test/JavaFileObjectUtils.java b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectUtils.java
new file mode 100644
index 0000000..4e7c32c
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/test/JavaFileObjectUtils.java
@@ -0,0 +1,52 @@
+/*
+ * 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.test;
+
+import com.google.common.io.ByteStreams;
+
+import javax.tools.JavaFileObject;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @author Decebal Suiu
+ */
+public class JavaFileObjectUtils {
+
+ private JavaFileObjectUtils() {}
+
+ public static String getClassName(JavaFileObject object) {
+ if (object.getKind() != JavaFileObject.Kind.CLASS) {
+ throw new IllegalStateException("Only Kind.CLASS is supported");
+ }
+
+ String name = object.getName();
+ // Remove "/CLASS_OUT/" from head and ".class" from tail
+ name = name.substring(14, name.length() - 6);
+ name = name.replace('/', '.');
+
+ return name;
+ }
+
+ public static byte[] getAllBytes(JavaFileObject object) {
+ try (InputStream in = object.openInputStream()) {
+ return ByteStreams.toByteArray(in);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/test/JavaSources.java b/pf4j/src/test/java/org/pf4j/test/JavaSources.java
new file mode 100644
index 0000000..2031edc
--- /dev/null
+++ b/pf4j/src/test/java/org/pf4j/test/JavaSources.java
@@ -0,0 +1,64 @@
+/*
+ * 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.test;
+
+import com.google.testing.compile.JavaFileObjects;
+
+import javax.tools.JavaFileObject;
+import java.util.List;
+
+import static com.google.testing.compile.Compiler.javac;
+
+/**
+ * Keep common Java sources (useful in many tests).
+ * For Java 13+ is recommended to use Text Block feature (it's more clear).
+ *
+ * @author Decebal Suiu
+ */
+public class JavaSources {
+
+ public static final JavaFileObject Greeting = JavaFileObjects.forSourceLines("Greeting",
+ "package test;",
+ "import org.pf4j.ExtensionPoint;",
+ "",
+ "public interface Greeting extends ExtensionPoint {",
+ " String getGreeting();",
+ "}");
+
+ public static final JavaFileObject WhazzupGreeting = JavaFileObjects.forSourceLines("WhazzupGreeting",
+ "package test;",
+ "import org.pf4j.Extension;",
+ "",
+ "@Extension",
+ "public class WhazzupGreeting implements Greeting {",
+ " @Override",
+ " public String getGreeting() {",
+ " return \"Whazzup\";",
+ " }",
+ "}");
+
+ /**
+ * Compile a list of sources using javac compiler.
+ */
+ public static List<JavaFileObject> compileAll(JavaFileObject... sources) {
+ return javac().compile(sources).generatedFiles();
+ }
+
+ public static JavaFileObject compile(JavaFileObject source) {
+ return compileAll(source).get(0);
+ }
+
+}
diff --git a/pf4j/src/test/java/org/pf4j/test/TestPlugin.java b/pf4j/src/test/java/org/pf4j/test/TestPlugin.java
index bab85b3..59b818d 100644
--- a/pf4j/src/test/java/org/pf4j/test/TestPlugin.java
+++ b/pf4j/src/test/java/org/pf4j/test/TestPlugin.java
@@ -20,9 +20,8 @@ import org.pf4j.PluginWrapper;
/**
* A simple {@link Plugin}.
- *
* In real applications you don't need to create a plugin like this if you are not interested in lifecycle events.
- * {@codes PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified.
+ * {@code PF4J} will automatically create a plugin similar to this (empty / dummy) if no class plugin is specified.
*
* @author Mario Franco
*/