groovy
  1. groovy
  2. GROOVY-4944

Presence of "assert" unexpectedly changes program semantics (in Groovlet)

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.8.0
    • Fix Version/s: 1.8.2, 1.9-beta-3, 1.7.11
    • Component/s: Groovlet / GSP
    • Labels:
      None
    • Environment:
      Red Hat Enterprise Linux Server release 5.6, Sun JDK build 1.6.0_26-b03
    • Number of attachments :
      0

      Description

      In a Groovlet:

      We have a function to map "stuff" to a boolean:

      boolean mapBoolean(def datum, boolean defaultValue) {
         ......
         return res
      }
      

      Immediately after the above in the Groovlet source, the function is tested:

      assert mapBoolean(null, false) == false
      assert mapBoolean(null, null)  == false
      

      One would expect the compiler to generate an error as 'null' cannot be passed as second parameter.

      But the asserts above are accepted and pass!

      If one removes the first assert and changes to solely

      assert mapBoolean(null, null)  == false
      

      THEN the compiler generates an error:

      message GroovyServlet Error: script: 'foo': Script processing failed.No signature of method: com.mplify.interact.InspectMsg.mapBoolean() is applicable for argument types: (null, null) values: [null, null] Possible solutions: mapBoolean(java.lang.Object, boolean), asBoolean()org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:54)
      

      A totally bared-down test "Simple.groovy" would be:

      boolean mapBoolean(def datum, boolean defaultValue) {
         return false
      }
      
      if (params['run']) {
         assert mapBoolean(null, false)  == false
      }
      
      assert mapBoolean(null, null) == false
      
      html.html {
          head { title "Testing" }
          body { div "PASSED" }
      }
      

      Called with Simple.groovy?run=true ---> PASSED
      Called with Simple.groovy ---> Script processing failed.No signature of method: Simple.mapBoolean() is applicable for argument types: (null, null)

        Activity

        Hide
        blackdrag blackdrag added a comment -

        David, we have not been able to reproduce this

        Show
        blackdrag blackdrag added a comment - David, we have not been able to reproduce this
        Hide
        David Tonhofer added a comment - - edited

        Hi,

        Ok, let's see what's different.

        Instead of a Groovlet, a script, same problem:

        // Script!
        
        // This method shall be called and cause trouble
        
        boolean shaky(boolean defaultValue) {
           return false
        }
        
        // Pass "skip" as first argument to skip the assertion
        
        if (args && args[0] == 'skip') {
           assert shaky(false)  == false
        }
        
        // This assertion will cause a runtime error if the previous assertion is not skipped
        
        assert shaky(null) == false
        
        System.out << "PASSED\n"
        

        Problem occurs on:

        Red Hat Enterprise Linux Server release 5.6 (Tikanga)
        Groovy Version: 1.8.0
        JVM: Java(TM) SE Runtime Environment (build 1.6.0_26-b03)

        Also on

        Fedora release 14 (Laughlin)
        Groovy Version: 1.8.0
        JVM: Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
        or
        JVM: IcedTea6 1.9.8

        Show
        David Tonhofer added a comment - - edited Hi, Ok, let's see what's different. Instead of a Groovlet, a script, same problem: // Script! // This method shall be called and cause trouble boolean shaky( boolean defaultValue) { return false } // Pass "skip" as first argument to skip the assertion if (args && args[0] == 'skip') { assert shaky( false ) == false } // This assertion will cause a runtime error if the previous assertion is not skipped assert shaky( null ) == false System .out << "PASSED\n" Problem occurs on: Red Hat Enterprise Linux Server release 5.6 (Tikanga) Groovy Version: 1.8.0 JVM: Java(TM) SE Runtime Environment (build 1.6.0_26-b03) Also on Fedora release 14 (Laughlin) Groovy Version: 1.8.0 JVM: Java(TM) SE Runtime Environment (build 1.6.0_26-b03) or JVM: IcedTea6 1.9.8
        Hide
        Guillaume Laforge added a comment -

        Can you tell us also what's on your classpath?

        Also is it intentional that you're using boolean vs Boolean and passing null into that primitive method parameter?

        Show
        Guillaume Laforge added a comment - Can you tell us also what's on your classpath? Also is it intentional that you're using boolean vs Boolean and passing null into that primitive method parameter?
        Hide
        David Tonhofer added a comment -

        Hi Guillaume,

        >is it intentional that you're using boolean vs Boolean

        Yes. I wanted to have a function that as non-null parameters coming in. I then added the assertion passing null to see what Groovy would do, and it did something surprising.

        Furthermore, the CLASSPATH is empty.

        Show
        David Tonhofer added a comment - Hi Guillaume, >is it intentional that you're using boolean vs Boolean Yes. I wanted to have a function that as non-null parameters coming in. I then added the assertion passing null to see what Groovy would do, and it did something surprising. Furthermore, the CLASSPATH is empty.
        Hide
        blackdrag blackdrag added a comment -

        I can reduce the script to

        boolean shaky(boolean defaultValue) {false}
        shaky(false)
        shaky(null)
        System.out << "PASSED\n"
        Show
        blackdrag blackdrag added a comment - I can reduce the script to boolean shaky( boolean defaultValue) { false } shaky( false ) shaky( null ) System .out << "PASSED\n"
        Hide
        David Tonhofer added a comment -

        Jochen's script passes.

        However

        boolean shaky(boolean defaultValue) {false}
        shaky(null)
        System.out << "PASSED\n"
        

        yields groovy.lang.MissingMethodException

        Show
        David Tonhofer added a comment - Jochen's script passes. However boolean shaky( boolean defaultValue) { false } shaky( null ) System .out << "PASSED\n" yields groovy.lang.MissingMethodException
        Hide
        blackdrag blackdrag added a comment -

        I seems the bug appears only if there is one method and there had been an invocation cached before. And then it is only wrong if there is the usage of null as value, as you did here in the second invocation.

        So a big thank you for finding this one. It should be fixed now.

        Show
        blackdrag blackdrag added a comment - I seems the bug appears only if there is one method and there had been an invocation cached before. And then it is only wrong if there is the usage of null as value, as you did here in the second invocation. So a big thank you for finding this one. It should be fixed now.
        Hide
        David Tonhofer added a comment -

        It me thanking you. Keep up the excellent work!

        Show
        David Tonhofer added a comment - It me thanking you. Keep up the excellent work!

          People

          • Assignee:
            blackdrag blackdrag
            Reporter:
            David Tonhofer
          • Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: