You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/05/23 21:20:05 UTC

[groovy] branch master updated: InvokerHelper#createScript makes fewer assumtions about non-Script class

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 7a56d71  InvokerHelper#createScript makes fewer assumtions about non-Script class
7a56d71 is described below

commit 7a56d7130aaf7b5244fa5a82fa0505fb7509f51f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 23 16:19:40 2021 -0500

    InvokerHelper#createScript makes fewer assumtions about non-Script class
---
 .../org/codehaus/groovy/runtime/InvokerHelper.java |  39 +++----
 src/test/gls/innerClass/InnerClassTest.groovy      |   6 +-
 src/test/groovy/bugs/Groovy5802Bug.groovy          |  51 --------
 .../codehaus/groovy/runtime/InvokerHelperTest.java | 129 ++++++++++++++-------
 4 files changed, 110 insertions(+), 115 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/InvokerHelper.java b/src/main/java/org/codehaus/groovy/runtime/InvokerHelper.java
index 6d64276..7620b9b 100644
--- a/src/main/java/org/codehaus/groovy/runtime/InvokerHelper.java
+++ b/src/main/java/org/codehaus/groovy/runtime/InvokerHelper.java
@@ -76,8 +76,6 @@ import static java.lang.Math.max;
  * A static helper class to make bytecode generation easier and act as a facade over the Invoker
  */
 public class InvokerHelper {
-    private static final Object[] EMPTY_MAIN_ARGS = new Object[]{new String[0]};
-
     public static final Object[] EMPTY_ARGS = {};
     protected static final Object[] EMPTY_ARGUMENTS = EMPTY_ARGS;
     protected static final Class[] EMPTY_TYPES = {};
@@ -230,7 +228,6 @@ public class InvokerHelper {
         setProperty(object, property, newValue);
     }
 
-
     /**
      * This is so we don't have to reorder the stack when we call this method.
      * At some point a better name might be in order.
@@ -243,7 +240,6 @@ public class InvokerHelper {
         return object.getProperty(property);
     }
 
-
     /**
      * This is so we don't have to reorder the stack when we call this method.
      * At some point a better name might be in order.
@@ -461,38 +457,33 @@ public class InvokerHelper {
                 if (Script.class.isAssignableFrom(scriptClass)) {
                     script = newScript(scriptClass, context);
                 } else {
-                    final GroovyObject object = (GroovyObject) scriptClass.getDeclaredConstructor().newInstance();
-                    // it could just be a class, so let's wrap it in a Script
-                    // wrapper; though the bindings will be ignored
+                    // wrap call "ScriptClass.main(args)" with a Script instance
                     script = new Script(context) {
                         @Override
                         public Object run() {
-                            Object argsToPass = EMPTY_MAIN_ARGS;
+                            Object[] mainArgs = {new String[0]};
                             try {
                                 Object args = getProperty("args");
                                 if (args instanceof String[]) {
-                                    argsToPass = args;
+                                    mainArgs[0] = args;
                                 }
-                            } catch (MissingPropertyException e) {
-                                // They'll get empty args since none exist in the context.
+                            } catch (MissingPropertyException mpe) {
+                                // call with empty array
                             }
-                            object.invokeMethod(MAIN_METHOD_NAME, argsToPass);
-                            return null;
+                            return InvokerHelper.invokeStaticMethod(scriptClass, MAIN_METHOD_NAME, mainArgs);
                         }
                     };
-                    Map variables = context.getVariables();
-                    MetaClass mc = getMetaClass(object);
-                    for (Object o : variables.entrySet()) {
-                        Map.Entry entry = (Map.Entry) o;
-                        String key = entry.getKey().toString();
-                        // assume underscore variables are for the wrapper script
-                        setPropertySafe(key.startsWith("_") ? script : object, mc, key, entry.getValue());
-                    }
+
+                    MetaClass smc = getMetaClass(scriptClass);
+                    ((Map<?,?>) context.getVariables()).forEach((key, value) -> {
+                        String name = key.toString();
+                        if (!name.startsWith("_")) { // assume underscore variables are for the wrapper
+                            setPropertySafe(scriptClass, smc, name, value);
+                        }
+                    });
                 }
             } catch (Exception e) {
-                throw new GroovyRuntimeException(
-                        "Failed to create Script instance for class: "
-                                + scriptClass + ". Reason: " + e, e);
+                throw new GroovyRuntimeException("Failed to create Script instance for class: " + scriptClass + ". Reason: " + e, e);
             }
         }
         return script;
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 2a5e340..c13cc5a 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1121,7 +1121,11 @@ final class InnerClassTest {
             class A {
                 static field = 10
 
-                void main(a) {
+                static main(args) {
+                    new A().test()
+                }
+
+                void test() {
                     assert new C().m() == [10,12,14,16]
                 }
 
diff --git a/src/test/groovy/bugs/Groovy5802Bug.groovy b/src/test/groovy/bugs/Groovy5802Bug.groovy
deleted file mode 100644
index 4f33888..0000000
--- a/src/test/groovy/bugs/Groovy5802Bug.groovy
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *  Licensed to the Apache Software Foundation (ASF) under one
- *  or more contributor license agreements.  See the NOTICE file
- *  distributed with this work for additional information
- *  regarding copyright ownership.  The ASF licenses this file
- *  to you 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 groovy.bugs
-
-import groovy.test.GroovyTestCase
-import org.codehaus.groovy.runtime.InvokerHelper
-
-class Groovy5802Bug extends GroovyTestCase {
-
-    void testBindingVariablesSetPropertiesInSingleClassScripts() {
-        def binding = new Binding(first: 'John', last: 'Smith')
-        def saved = System.out
-        def baos = new ByteArrayOutputStream()
-        System.out = new PrintStream(baos)
-        new GroovyShell(binding).parse('''
-        class Person {
-            static String first, last, result
-            static void main(String[] args) { println "$first $last" }
-        }
-        ''').run()
-        System.out = saved
-        assert baos.toString().trim() == "John Smith"
-    }
-
-    void testInvokerHelperNotConfusedByScriptVariables() {
-        InvokerHelper.createScript(MyList5802, new Binding('_': []))
-    }
-
-    void testMissingVariablesForSingleListClassScripts() {
-        InvokerHelper.createScript(MyList5802, new Binding('x': []))
-    }
-
-}
-
-class MyList5802 extends ArrayList {}
diff --git a/src/test/org/codehaus/groovy/runtime/InvokerHelperTest.java b/src/test/org/codehaus/groovy/runtime/InvokerHelperTest.java
index d80ae14..7dcd0cb 100644
--- a/src/test/org/codehaus/groovy/runtime/InvokerHelperTest.java
+++ b/src/test/org/codehaus/groovy/runtime/InvokerHelperTest.java
@@ -21,58 +21,109 @@ package org.codehaus.groovy.runtime;
 import groovy.lang.Binding;
 import groovy.lang.GroovyClassLoader;
 import groovy.lang.GroovyCodeSource;
+import groovy.lang.GroovyShell;
 import groovy.lang.Script;
-import junit.framework.TestCase;
+import org.junit.Test;
 
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
+import java.util.Map;
 
-import static org.codehaus.groovy.runtime.InvokerHelper.initialCapacity;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
 
+public final class InvokerHelperTest {
 
-public class InvokerHelperTest extends TestCase {
-    private HashMap bindingVariables;
+    private final Map<String, Object> variables = new HashMap<>();
 
-    protected void setUp() throws Exception {
-        bindingVariables = new HashMap();
-        bindingVariables.put("name", "hans");
+    @Test
+    public void testCreateScriptWithNullClass() {
+        Script script = InvokerHelper.createScript(null, new Binding(variables));
+
+        assertSame(variables, script.getBinding().getVariables());
     }
 
-    public void testCreateScriptWithNullClass() {
-        Script script = InvokerHelper.createScript(null, new Binding(bindingVariables));
-        assertEquals(bindingVariables, script.getBinding().getVariables());
+    @Test
+    public void testCreateScriptWithScriptClass() throws Exception {
+        try (GroovyClassLoader classLoader = new GroovyClassLoader()) {
+            String controlProperty = "text", controlValue = "I am a script";
+            Class<?> scriptClass = classLoader.parseClass(new GroovyCodeSource(
+                    controlProperty + " = '" + controlValue + "'", "testscript", "/groovy/shell"), false);
+
+            Script script = InvokerHelper.createScript(scriptClass, new Binding(variables));
+
+            assertSame(variables, script.getBinding().getVariables());
+
+            script.run();
+
+            assertEquals(controlValue, script.getProperty(controlProperty));
+        }
+    }
+
+    @Test // GROOVY-5802
+    public void testBindingVariablesSetPropertiesInSingleClassScripts() {
+        variables.put("first", "John");
+        variables.put("last", "Smith");
+
+        PrintStream sysout = System.out;
+        try {
+            ByteArrayOutputStream baos = new ByteArrayOutputStream();
+            System.setOut(new PrintStream(baos));
+            String source =
+                "class Person {\n" +
+                "    static String first, last, unused\n" +
+                "    static main(args) { print \"$first $last\" }\n" +
+                "}\n";
+            new GroovyShell(new Binding(variables)).parse(source).run();
+
+            assertEquals("John Smith", baos.toString());
+        } finally {
+            System.setOut(sysout);
+        }
     }
 
-    public void testCreateScriptWithScriptClass() {
-        GroovyClassLoader classLoader = new GroovyClassLoader();
-        String controlProperty = "text";
-        String controlValue = "I am a script";
-        String code = controlProperty + " = '" + controlValue + "'";
-        GroovyCodeSource codeSource = new GroovyCodeSource(code, "testscript", "/groovy/shell");
-        Class scriptClass = classLoader.parseClass(codeSource, false);
-        Script script = InvokerHelper.createScript(scriptClass, new Binding(bindingVariables));
-        assertEquals(bindingVariables, script.getBinding().getVariables());
-        script.run();
-        assertEquals(controlValue, script.getProperty(controlProperty));
+    @Test // GROOVY-5802
+    public void testInvokerHelperNotConfusedByScriptVariables() {
+        variables.put("_", Collections.emptyList());
+
+        InvokerHelper.createScript(MyList5802.class, new Binding(variables));
     }
 
+    @Test // GROOVY-5802
+    public void testMissingVariablesForSingleListClassScripts() {
+        variables.put("x", Collections.emptyList());
+
+        InvokerHelper.createScript(MyList5802.class, new Binding(variables));
+    }
+
+    @Test
     public void testInitialCapacity() {
-        assertEquals(16, initialCapacity(0));
-        assertEquals(2, initialCapacity(1));
-        assertEquals(4, initialCapacity(2));
-        assertEquals(4, initialCapacity(3));
-        assertEquals(8, initialCapacity(4));
-        assertEquals(8, initialCapacity(5));
-        assertEquals(8, initialCapacity(6));
-        assertEquals(8, initialCapacity(7));
-        assertEquals(16, initialCapacity(8));
-        assertEquals(16, initialCapacity(9));
-        assertEquals(16, initialCapacity(10));
-        assertEquals(16, initialCapacity(11));
-        assertEquals(16, initialCapacity(12));
-        assertEquals(16, initialCapacity(13));
-        assertEquals(16, initialCapacity(14));
-        assertEquals(16, initialCapacity(15));
-        assertEquals(32, initialCapacity(16));
-        assertEquals(32, initialCapacity(17));
+        assertEquals(16, InvokerHelper.initialCapacity(0));
+        assertEquals( 2, InvokerHelper.initialCapacity(1));
+        assertEquals( 4, InvokerHelper.initialCapacity(2));
+        assertEquals( 4, InvokerHelper.initialCapacity(3));
+        assertEquals( 8, InvokerHelper.initialCapacity(4));
+        assertEquals( 8, InvokerHelper.initialCapacity(5));
+        assertEquals( 8, InvokerHelper.initialCapacity(6));
+        assertEquals( 8, InvokerHelper.initialCapacity(7));
+        assertEquals(16, InvokerHelper.initialCapacity(8));
+        assertEquals(16, InvokerHelper.initialCapacity(9));
+        assertEquals(16, InvokerHelper.initialCapacity(10));
+        assertEquals(16, InvokerHelper.initialCapacity(11));
+        assertEquals(16, InvokerHelper.initialCapacity(12));
+        assertEquals(16, InvokerHelper.initialCapacity(13));
+        assertEquals(16, InvokerHelper.initialCapacity(14));
+        assertEquals(16, InvokerHelper.initialCapacity(15));
+        assertEquals(32, InvokerHelper.initialCapacity(16));
+        assertEquals(32, InvokerHelper.initialCapacity(17));
+    }
+
+    //--------------------------------------------------------------------------
+
+    private static class MyList5802 extends ArrayList<Object> {
+        private static final long serialVersionUID = 0;
     }
 }