This is an automated email from the ASF dual-hosted git repository. emilles pushed a commit to branch GROOVY_3_0_X in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 076ccf30c177990051b7673f2b74b16a90e6205b Author: Eric Milles <[email protected]> AuthorDate: Tue Apr 6 10:10:42 2021 -0500 GROOVY-10009: TracingInterceptor: "java.lang.Object" for null arguments --- src/main/java/groovy/lang/TracingInterceptor.java | 35 ++++++++++---------- src/test/groovy/lang/InterceptorTest.groovy | 39 +++++++++++++---------- 2 files changed, 39 insertions(+), 35 deletions(-) diff --git a/src/main/java/groovy/lang/TracingInterceptor.java b/src/main/java/groovy/lang/TracingInterceptor.java index f67de11..cd6f1d7 100644 --- a/src/main/java/groovy/lang/TracingInterceptor.java +++ b/src/main/java/groovy/lang/TracingInterceptor.java @@ -23,12 +23,12 @@ import java.io.PrintWriter; import java.io.Writer; /* - * This {@link Interceptor} traces method calls on the proxied object to a log. - * By default, the log is simply <pre>System.out</pre>; however, that can be + * This {@link Interceptor} traces method calls on the proxied object to a log. + * By default, the log is simply <pre>System.out</pre>; however, that can be * changed with the <pre>setWriter(Writer)</pre> method. * <p> * A message will be written to output before a method is invoked and after a method - * is invoked. If methods are nested, and invoke one another, then indentation + * is invoked. If methods are nested, and invoke one another, then indentation * of two spaces is written. * <p> * Here is an example usage on the ArrayList object: <br> @@ -41,7 +41,7 @@ import java.io.Writer; * assert list.contains(1) * } * </pre> - * Running this code produces this output: + * Running this code produces this output: * <pre> * before java.util.ArrayList.size() * after java.util.ArrayList.size() @@ -55,15 +55,15 @@ public class TracingInterceptor implements Interceptor { private int indent = 0; /** - * Returns the writer associated with this interceptor. - */ + * Returns the writer associated with this interceptor. + */ public Writer getWriter() { return writer; } /** - * Changes the writer associated with this interceptor. - */ + * Changes the writer associated with this interceptor. + */ public void setWriter(Writer writer) { this.writer = writer; } @@ -105,16 +105,13 @@ public class TracingInterceptor implements Interceptor { } } - protected void writeInfo(final Class aClass, String methodName, Object[] arguments) throws IOException { - writer.write(aClass.getName()); - writer.write("."); - writer.write(methodName); - writer.write("("); - for (int i = 0; i < arguments.length; i++) { - if (i > 0) writer.write(", "); - Object argument = arguments[i]; - writer.write(argument.getClass().getName()); - } - writer.write(")"); + protected void writeInfo(final Class aClass, final String methodName, final Object[] arguments) throws IOException { + String argumentTypes = java.util.stream.Stream.of(arguments) + .map(arg -> arg != null ? arg.getClass().getName() : "java.lang.Object") // GROOVY-10009 + .collect(java.util.stream.Collectors.joining(", ")); + StringBuilder result = new StringBuilder(aClass.getName()); + result.append('.').append(methodName).append('('); + result.append(argumentTypes).append(')'); + writer.write(result.toString()); } } diff --git a/src/test/groovy/lang/InterceptorTest.groovy b/src/test/groovy/lang/InterceptorTest.groovy index 13db0ff..95d84ed 100644 --- a/src/test/groovy/lang/InterceptorTest.groovy +++ b/src/test/groovy/lang/InterceptorTest.groovy @@ -23,25 +23,21 @@ import org.codehaus.groovy.runtime.StringBufferWriter /** * Test for the Interceptor Interface usage as implemented by the - * TracingInterceptor. Makes also use of the ProxyMetaClass and + * {@link TracingInterceptor}. Makes use of the {@link ProxyMetaClass} and * shows the collaboration. - * As a side Effect, the ProxyMetaClass is also partly tested. + * <p> + * As a side effect, the {@code ProxyMetaClass} is also partly tested. */ -class InterceptorTest extends GroovyTestCase { +final class InterceptorTest extends GroovyTestCase { - def Interceptor logInterceptor - def StringBuffer log - def interceptable // the object to intercept method calls on - def proxy + private final Interceptor interceptor = new TracingInterceptor() // class under test + private final String interceptable = 'Interceptable String' // the object to observe + private final ProxyMetaClass proxy = ProxyMetaClass.getInstance(interceptable.class) + private final StringBuffer log = new StringBuffer('\n') void setUp() { - logInterceptor = new TracingInterceptor() - log = new StringBuffer("\n") - logInterceptor.writer = new StringBufferWriter(log) - // we intercept calls from Groovy to the java.lang.String object - interceptable = 'Interceptable String' - proxy = ProxyMetaClass.getInstance(interceptable.class) - proxy.setInterceptor(logInterceptor) + interceptor.writer = new StringBufferWriter(log) + proxy.interceptor = interceptor } void testSimpleInterception() { @@ -90,7 +86,7 @@ after java.lang.String.valueOf(java.lang.Boolean) void testInterceptionOfGroovyClasses() { def slicer = new groovy.mock.example.CheeseSlicer() def proxy = ProxyMetaClass.getInstance(slicer.class) - proxy.setInterceptor(logInterceptor) + proxy.setInterceptor(interceptor) proxy.use(slicer) { slicer.coffeeBreak('') } @@ -101,6 +97,17 @@ after groovy.mock.example.CheeseSlicer.coffeeBreak(java.lang.String) } void testProxyMetaClassUseMethodShouldReturnTheResultOfClosure() { - assertEquals true, proxy.use { true } + assertTrue proxy.use { true } + } + + // GROOVY-10009 + void testNullArgumentToMethodCall() { + interceptable.metaClass = proxy + interceptable.equals(null) + + assertEquals ''' + |before java.lang.String.equals(java.lang.Object) + |after java.lang.String.equals(java.lang.Object) + |'''.stripMargin(), log.toString() } }
