Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-11058

plus() on UnmodifiableMap returns a new Map with changed data

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • 2.4.21, 2.5.14, 3.0.9, 4.0.12
    • None
    • Groovy Console
    • None

    Description

      Groovy UnmodifiableMap.plus() operations return a different Map class and modified data in the object, compromising common syntax like myView += myMap (which can happen e.g. during script refactoring from maps to read-only views and should throw when misused).

      Originally found in Jenkins with its built-in old groovy-2.4.21 (in-core for pipeline scripts) and http://tpcg.io/_R7VESY, but verified with a newer 2.5.14 version at e.g. https://groovyconsole.appspot.com/script/4819062429319168 (see "Output" tab since it shows stack trace by default) and groovy-3.0.9/jvm-17.0.1 as seen at https://jdoodle.com/ia/HVH and double-checked locally with GroovyConsole from a freshly fetched 4.0.12 tarball.

       

      // Repro case for Groovy
      println GroovySystem.version
      
      def m1 = [t: 'somestring', n: 1]
      def m2 = Collections.unmodifiableMap(m1)   // returns an @UnmodifiableView decorated Map
      
      println m1.getClass() // AS EXPECTED: class java.util.LinkedHashMap
      println m2.getClass() // AS EXPECTED: class java.util.Collections$UnmodifiableMap
      
      // NOTE: plus() operations return a different class and modified data:
      m2 += [m:2]
      //m2 = m2 + [m:2]
      println m2.getClass() // NOT AS EXPECTED: class java.util.LinkedHashMap
      println m2            // NOT AS EXPECTED: [t:somestring, n:1, m:2]
      
      // NOTE: Direct operations on the view (put, putAll, replace, remove,
      // leftShift and << operator) are constrained as expected:
      def m3 = Collections.unmodifiableMap(m1)
      //m3.putAll([m:2])
      m3 << [m:2]
      // THROWS AS EXPECTED: java.lang.UnsupportedOperationException ...
      

      With typical output like this:

      2.5.14
      class java.util.LinkedHashMap
      class java.util.Collections$UnmodifiableMap
      class java.util.LinkedHashMap
      [t:somestring, n:1, m:2]
      java.lang.UnsupportedOperationException
      	at Script1.run(Script1.groovy:20)

      For clarity, the expectation is that the "view" map m2 remains unmodifiable throughout the additions and other manipulations. I suppose that Collections$UnmodifiableMap should but does not override the plus() method in Groovy terms, but this is just an unverified educated guess based on another custom Map type I was making.

      Attachments

        Activity

          People

            Unassigned Unassigned
            jimklimov Jim Klimov
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

              Created:
              Updated: