From 2f84096af17f201b07b5155fdff7458c64c21e0e Mon Sep 17 00:00:00 2001 From: Stephane Nicoll Date: Tue, 20 Sep 2022 13:03:03 +0200 Subject: [PATCH] Polish --- .../io/support/MockSpringFactoriesLoader.java | 16 +++++----- .../core/test/tools/CompilationException.java | 4 +-- .../test/tools/DynamicClassFileObject.java | 9 ++++-- .../core/test/tools/DynamicClassLoader.java | 14 +++++++-- .../core/test/tools/DynamicFileAssert.java | 31 +++++++++++++------ .../test/tools/DynamicResourceFileObject.java | 9 ++++-- .../core/test/tools/TestCompiler.java | 4 +-- .../MockSpringFactoriesLoaderTests.java | 2 +- .../test/tools/SourceFileAssertTests.java | 4 +-- 9 files changed, 61 insertions(+), 32 deletions(-) diff --git a/spring-core-test/src/main/java/org/springframework/core/test/io/support/MockSpringFactoriesLoader.java b/spring-core-test/src/main/java/org/springframework/core/test/io/support/MockSpringFactoriesLoader.java index 2eb96c2a8c..288e4070de 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/io/support/MockSpringFactoriesLoader.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/io/support/MockSpringFactoriesLoader.java @@ -17,6 +17,7 @@ package org.springframework.core.test.io.support; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; @@ -58,7 +59,8 @@ public class MockSpringFactoriesLoader extends SpringFactoriesLoader { this(classLoader, new LinkedHashMap<>()); } - protected MockSpringFactoriesLoader(ClassLoader classLoader, Map> factories) { + protected MockSpringFactoriesLoader(@Nullable ClassLoader classLoader, + Map> factories) { super(classLoader, factories); this.factories = factories; } @@ -66,8 +68,8 @@ public class MockSpringFactoriesLoader extends SpringFactoriesLoader { @Override @SuppressWarnings("unchecked") - protected T instantiateFactory(String implementationName, Class type, ArgumentResolver argumentResolver, - FailureHandler failureHandler) { + protected T instantiateFactory(String implementationName, Class type, + @Nullable ArgumentResolver argumentResolver, FailureHandler failureHandler) { if (implementationName.startsWith("!")) { Object implementation = this.implementations.get(implementationName); if (implementation != null) { @@ -83,7 +85,6 @@ public class MockSpringFactoriesLoader extends SpringFactoriesLoader { * @param factoryImplementations the implementation classes */ @SafeVarargs - @SuppressWarnings("unchecked") public final void add(Class factoryType, Class... factoryImplementations) { for (Class factoryImplementation : factoryImplementations) { add(factoryType.getName(), factoryImplementation.getName()); @@ -96,10 +97,9 @@ public class MockSpringFactoriesLoader extends SpringFactoriesLoader { * @param factoryImplementations the implementation class names */ public void add(String factoryType, String... factoryImplementations) { - List implementations = this.factories.computeIfAbsent(factoryType, key -> new ArrayList<>()); - for (String factoryImplementation : factoryImplementations) { - implementations.add(factoryImplementation); - } + List implementations = this.factories.computeIfAbsent( + factoryType, key -> new ArrayList<>()); + Collections.addAll(implementations, factoryImplementations); } /** diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/CompilationException.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/CompilationException.java index 1bbc7bf9c0..5e93ef9687 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/CompilationException.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/CompilationException.java @@ -38,12 +38,12 @@ public class CompilationException extends RuntimeException { message.append(errors); message.append("\n\n"); for (SourceFile sourceFile : sourceFiles) { - message.append("---- source: " + sourceFile.getPath() + "\n\n"); + message.append("---- source: ").append(sourceFile.getPath()).append("\n\n"); message.append(sourceFile.getContent()); message.append("\n\n"); } for (ResourceFile resourceFile : resourceFiles) { - message.append("---- resource: " + resourceFile.getPath() + "\n\n"); + message.append("---- resource: ").append(resourceFile.getPath()).append("\n\n"); message.append(resourceFile.getContent()); message.append("\n\n"); } diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassFileObject.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassFileObject.java index 6640ed7274..cd395d4a46 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassFileObject.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassFileObject.java @@ -26,6 +26,8 @@ import java.net.URI; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; +import org.springframework.lang.Nullable; + /** * In-memory {@link JavaFileObject} used to hold class bytecode. * @@ -36,6 +38,7 @@ class DynamicClassFileObject extends SimpleJavaFileObject { private final String className; + @Nullable private volatile byte[] bytes; @@ -57,10 +60,11 @@ class DynamicClassFileObject extends SimpleJavaFileObject { @Override public InputStream openInputStream() throws IOException { - if (this.bytes == null) { + byte[] content = this.bytes; + if (content == null) { throw new IOException("No data written"); } - return new ByteArrayInputStream(this.bytes); + return new ByteArrayInputStream(content); } @Override @@ -76,6 +80,7 @@ class DynamicClassFileObject extends SimpleJavaFileObject { return this.className; } + @Nullable byte[] getBytes() { return this.bytes; } diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java index 15109ebf59..1dba5feb84 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicClassLoader.java @@ -30,6 +30,7 @@ import java.util.function.Function; import java.util.function.Supplier; import org.springframework.lang.Nullable; +import org.springframework.util.Assert; import org.springframework.util.ReflectionUtils; /** @@ -65,12 +66,12 @@ public class DynamicClassLoader extends ClassLoader { this.dynamicResourceFiles = dynamicResourceFiles; Class parentClass = parent.getClass(); if (parentClass.getName().equals(CompileWithForkedClassLoaderClassLoader.class.getName())) { - Method setClassResourceLookupMethod = ReflectionUtils.findMethod(parentClass, + Method setClassResourceLookupMethod = lookupMethod(parentClass, "setClassResourceLookup", Function.class); ReflectionUtils.makeAccessible(setClassResourceLookupMethod); ReflectionUtils.invokeMethod(setClassResourceLookupMethod, getParent(), (Function) this::findClassBytes); - this.defineClassMethod = ReflectionUtils.findMethod(parentClass, + this.defineClassMethod = lookupMethod(parentClass, "defineDynamicClass", String.class, byte[].class, int.class, int.class); ReflectionUtils.makeAccessible(this.defineClassMethod); this.dynamicClassFiles.forEach((name, file) -> defineClass(name, file.getBytes())); @@ -84,12 +85,13 @@ public class DynamicClassLoader extends ClassLoader { @Override protected Class findClass(String name) throws ClassNotFoundException { byte[] bytes = findClassBytes(name); - if(bytes != null) { + if (bytes != null) { return defineClass(name, bytes); } return super.findClass(name); } + @Nullable private byte[] findClassBytes(String name) { ClassFile classFile = this.classFiles.get(name); if (classFile != null) { @@ -141,6 +143,12 @@ public class DynamicClassLoader extends ClassLoader { } } + private static Method lookupMethod(Class target, String name, Class... parameterTypes) { + Method method = ReflectionUtils.findMethod(target, name, parameterTypes); + Assert.notNull(method, "Expected method '" + name + "' on '" + target.getName()); + return method; + } + private static class SingletonEnumeration implements Enumeration { diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicFileAssert.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicFileAssert.java index 24fce58624..a9d26207cf 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicFileAssert.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicFileAssert.java @@ -26,6 +26,7 @@ import static org.assertj.core.api.Assertions.assertThat; * Assertion methods for {@code DynamicFile} instances. * * @author Phillip Webb + * @author Stephane Nicoll * @since 6.0 * @param the assertion type * @param the file type @@ -38,25 +39,35 @@ public class DynamicFileAssert, F extends Dyna super(actual, selfType); } + /** + * Verify that the actual content is equal to the given one. + * @param content the expected content of the file + * @return {@code this}, to facilitate method chaining + */ + public A hasContent(@Nullable CharSequence content) { + assertThat(this.actual.getContent()).isEqualTo( + content != null ? content.toString() : null); + return this.myself; + } + /** + * Verify that the actual content contains all the given values. + * @param values the values to look for + * @return {@code this}, to facilitate method chaining + */ public A contains(CharSequence... values) { assertThat(this.actual.getContent()).contains(values); return this.myself; } + /** + * Verify that the actual content does not contain any of the given values. + * @param values the values to look for + * @return {@code this}, to facilitate method chaining + */ public A doesNotContain(CharSequence... values) { assertThat(this.actual.getContent()).doesNotContain(values); return this.myself; } - @Override - public A isEqualTo(@Nullable Object expected) { - if (expected instanceof DynamicFile) { - return super.isEqualTo(expected); - } - assertThat(this.actual.getContent()).isEqualTo( - expected != null ? expected.toString() : null); - return this.myself; - } - } diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicResourceFileObject.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicResourceFileObject.java index dcebb24e87..5e09f46e54 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicResourceFileObject.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/DynamicResourceFileObject.java @@ -26,6 +26,8 @@ import java.net.URI; import javax.tools.JavaFileObject; import javax.tools.SimpleJavaFileObject; +import org.springframework.lang.Nullable; + /** * In-memory {@link JavaFileObject} used to hold generated resource file contents. * @@ -35,6 +37,7 @@ import javax.tools.SimpleJavaFileObject; */ class DynamicResourceFileObject extends SimpleJavaFileObject { + @Nullable private volatile byte[] bytes; @@ -54,10 +57,11 @@ class DynamicResourceFileObject extends SimpleJavaFileObject { @Override public InputStream openInputStream() throws IOException { - if (this.bytes == null) { + byte[] content = this.bytes; + if (content == null) { throw new IOException("No data written"); } - return new ByteArrayInputStream(this.bytes); + return new ByteArrayInputStream(content); } @Override @@ -69,6 +73,7 @@ class DynamicResourceFileObject extends SimpleJavaFileObject { this.bytes = bytes; } + @Nullable byte[] getBytes() { return this.bytes; } diff --git a/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java b/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java index 5d45c6ab5a..a4b783791a 100644 --- a/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java +++ b/spring-core-test/src/main/java/org/springframework/core/test/tools/TestCompiler.java @@ -309,12 +309,12 @@ public final class TestCompiler { */ public TestCompiler printFiles(PrintStream printStream) { for (SourceFile sourceFile : this.sourceFiles) { - printStream.append("---- source: " + sourceFile.getPath() + "\n\n"); + printStream.append("---- source: ").append(sourceFile.getPath()).append("\n\n"); printStream.append(sourceFile.getContent()); printStream.append("\n\n"); } for (ResourceFile resourceFile : this.resourceFiles) { - printStream.append("---- resource: " + resourceFile.getPath() + "\n\n"); + printStream.append("---- resource: ").append(resourceFile.getPath()).append("\n\n"); printStream.append(resourceFile.getContent()); printStream.append("\n\n"); } diff --git a/spring-core-test/src/test/java/org/springframework/core/test/io/support/MockSpringFactoriesLoaderTests.java b/spring-core-test/src/test/java/org/springframework/core/test/io/support/MockSpringFactoriesLoaderTests.java index c330629814..c8a469fbb7 100644 --- a/spring-core-test/src/test/java/org/springframework/core/test/io/support/MockSpringFactoriesLoaderTests.java +++ b/spring-core-test/src/test/java/org/springframework/core/test/io/support/MockSpringFactoriesLoaderTests.java @@ -66,7 +66,7 @@ class MockSpringFactoriesLoaderTests { assertThat(factories.get(1)).isInstanceOf(TestFactoryTwo.class); } - static interface TestFactoryType { + interface TestFactoryType { } diff --git a/spring-core-test/src/test/java/org/springframework/core/test/tools/SourceFileAssertTests.java b/spring-core-test/src/test/java/org/springframework/core/test/tools/SourceFileAssertTests.java index cfbfb7c08b..efc254c399 100644 --- a/spring-core-test/src/test/java/org/springframework/core/test/tools/SourceFileAssertTests.java +++ b/spring-core-test/src/test/java/org/springframework/core/test/tools/SourceFileAssertTests.java @@ -65,13 +65,13 @@ class SourceFileAssertTests { @Test void isEqualToWhenEqual() { - assertThat(this.sourceFile).isEqualTo(SAMPLE); + assertThat(this.sourceFile).hasContent(SAMPLE); } @Test void isEqualToWhenNotEqualThrowsException() { assertThatExceptionOfType(AssertionError.class).isThrownBy( - () -> assertThat(this.sourceFile).isEqualTo("no")).withMessageContaining( + () -> assertThat(this.sourceFile).hasContent("no")).withMessageContaining( "expected", "but was"); }