Skip to content

Commit

Permalink
Jave Map wrapper respects put/remove contract
Browse files Browse the repository at this point in the history
If map contains key, always return nonEmpty.
If binding to null, return Some(null) instead of None.
  • Loading branch information
som-snytt committed Nov 25, 2020
1 parent 867f63a commit 796563f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 2 deletions.
12 changes: 10 additions & 2 deletions src/library/scala/collection/convert/JavaCollectionWrappers.scala
Expand Up @@ -332,11 +332,19 @@ private[collection] object JavaCollectionWrappers extends Serializable {
def addOne(kv: (K, V)): this.type = { underlying.put(kv._1, kv._2); this }
def subtractOne(key: K): this.type = { underlying remove key; this }

override def put(k: K, v: V): Option[V] = Option(underlying.put(k, v))
override def put(k: K, v: V): Option[V] = {
val present = underlying.containsKey(k)
val result = underlying.put(k, v)
if (present) Some(result) else None
}

override def update(k: K, v: V): Unit = { underlying.put(k, v) }

override def remove(k: K): Option[V] = Option(underlying remove k)
override def remove(k: K): Option[V] = {
val present = underlying.containsKey(k)
val result = underlying.remove(k)
if (present) Some(result) else None
}

def iterator: Iterator[(K, V)] = new AbstractIterator[(K, V)] {
val ui = underlying.entrySet.iterator
Expand Down
55 changes: 55 additions & 0 deletions test/junit/scala/jdk/CollectionConvertersTest.scala
@@ -0,0 +1,55 @@
/*
* Scala (https://www.scala-lang.org)
*
* Copyright EPFL and Lightbend, Inc.
*
* Licensed under Apache License 2.0
* (http://www.apache.org/licenses/LICENSE-2.0).
*
* See the NOTICE file distributed with this work for
* additional information regarding copyright ownership.
*/

package scala.jdk

import java.util.{
Dictionary,
HashMap => JMap,
Hashtable => JTable,
Properties => JProperties,
}

import org.junit.Assert.assertEquals
import org.junit.Test

import scala.tools.testkit.AssertUtil.assertThrows

import CollectionConverters._

class CollectionConvertersTest {
@Test def `t11894 Map wrapper respects put contract`(): Unit = {
val sut = new JMap[String, String].asScala
assertEquals(None, sut.put("one", null))
assertEquals(Some(null), sut.put("one", "eins"))
assertEquals(Some("eins"), sut.put("one", "uno"))
assertEquals(Some("uno"), sut.remove("one"))
assertEquals(None, sut.remove("one"))
assertEquals(None, sut.put("one", null))
assertEquals(Some(null), sut.remove("one"))
assertEquals(None, sut.remove("one"))
}
@Test def `t11894 Dictionary wrapper disallows nulls`(): Unit = {
val tbl = new JTable[String, String]
val sut = tbl.asInstanceOf[Dictionary[String, String]].asScala
assertThrows[NullPointerException](sut.put("any", null))
}
@Test def `t11894 Properties wrapper enforces Strings`(): Unit = {
val ps = new JProperties()
val sut = ps.asScala
assertThrows[NullPointerException](sut.put("any", null))
assertEquals(None, sut.put("one", "eins"))
assertEquals("eins", sut("one"))
ps.put("one", new Object())
assertThrows[ClassCastException](sut.put("one", "uno"))
}
}

0 comments on commit 796563f

Please sign in to comment.