From c71fa58a35690672bc4626d18b5016b98bfcc5f8 Mon Sep 17 00:00:00 2001 From: Aleksandar Prokopec Date: Thu, 30 May 2013 14:37:01 +0200 Subject: [backport] SI-7498 ParTrieMap.foreach no longer crashes Previously, the `split` method of the `ParTrieMap` iterator threw an exception when splitting a splitter that iterated over nodes whose hash codes collide. This was due to reusing the iterator of the list of colliding keys rather than creating a new splitter. This commit changes the `subdivide` method to create a new iterator using the factory method of the current trie map iterator rather than returning a `LinearSeqLike` iterator. --- test/files/run/t7498.scala | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 test/files/run/t7498.scala (limited to 'test/files') diff --git a/test/files/run/t7498.scala b/test/files/run/t7498.scala new file mode 100644 index 0000000000..1dbf0597e0 --- /dev/null +++ b/test/files/run/t7498.scala @@ -0,0 +1,20 @@ + + + + + + + +object Test extends App { + import scala.collection.concurrent.TrieMap + + class Collision(val idx: Int) { + override def hashCode = idx % 10 + } + + val tm = TrieMap[Collision, Unit]() + for (i <- 0 until 1000) tm(new Collision(i)) = () + + tm.par.foreach(kv => ()) +} + -- cgit v1.2.3 From 173e709017f5cd489e5526bec92da8dc904fc436 Mon Sep 17 00:00:00 2001 From: Grzegorz Kossakowski Date: Sun, 16 Jun 2013 18:26:10 -0400 Subject: Move WeakHashSetTest to junit tests. The WeakHashSetTest was written as unit test but put into partest's `run` category as we were missing direct unit testing support. That got fixed so moving the test now. --- test/files/run/WeakHashSetTest.scala | 174 --------------------- .../reflect/internal/util/WeakHashSetTest.scala | 171 ++++++++++++++++++++ 2 files changed, 171 insertions(+), 174 deletions(-) delete mode 100644 test/files/run/WeakHashSetTest.scala create mode 100644 test/junit/scala/reflect/internal/util/WeakHashSetTest.scala (limited to 'test/files') diff --git a/test/files/run/WeakHashSetTest.scala b/test/files/run/WeakHashSetTest.scala deleted file mode 100644 index 3c8f380150..0000000000 --- a/test/files/run/WeakHashSetTest.scala +++ /dev/null @@ -1,174 +0,0 @@ -object Test { - def main(args: Array[String]) { - val test = scala.reflect.internal.util.WeakHashSetTest - test.checkEmpty - test.checkPlusEquals - test.checkPlusEqualsCollisions - test.checkRehashing - test.checkRehashCollisions - test.checkFindOrUpdate - test.checkMinusEquals - test.checkMinusEqualsCollisions - test.checkClear - test.checkIterator - test.checkIteratorCollisions - - // This test is commented out because it relies on gc behavior which isn't reliable enough in an automated environment - // test.checkRemoveUnreferencedObjects - } -} - -// put the main test object in the same package as WeakHashSet because -// it uses the package private "diagnostics" method -package scala.reflect.internal.util { - - object WeakHashSetTest { - // a class guaranteed to provide hash collisions - case class Collider(x : String) extends Comparable[Collider] with Serializable { - override def hashCode = 0 - def compareTo(y : Collider) = this.x compareTo y.x - } - - // basic emptiness check - def checkEmpty { - val hs = new WeakHashSet[String]() - assert(hs.size == 0) - hs.diagnostics.fullyValidate - } - - // make sure += works - def checkPlusEquals { - val hs = new WeakHashSet[String]() - val elements = List("hello", "goodbye") - elements foreach (hs += _) - assert(hs.size == 2) - assert(hs contains "hello") - assert(hs contains "goodbye") - hs.diagnostics.fullyValidate - } - - // make sure += works when there are collisions - def checkPlusEqualsCollisions { - val hs = new WeakHashSet[Collider]() - val elements = List("hello", "goodbye") map Collider - elements foreach (hs += _) - assert(hs.size == 2) - assert(hs contains Collider("hello")) - assert(hs contains Collider("goodbye")) - hs.diagnostics.fullyValidate - } - - // add a large number of elements to force rehashing and then validate - def checkRehashing { - val size = 200 - val hs = new WeakHashSet[String]() - val elements = (0 until size).toList map ("a" + _) - elements foreach (hs += _) - elements foreach {i => assert(hs contains i)} - hs.diagnostics.fullyValidate - } - - // make sure rehashing works properly when the set is rehashed - def checkRehashCollisions { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - elements foreach {i => assert(hs contains i)} - hs.diagnostics.fullyValidate - } - - // test that unreferenced objects are removed - // not run in an automated environment because gc behavior can't be relied on - def checkRemoveUnreferencedObjects { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - // don't throw the following into a retained collection so gc - // can remove them - for (i <- 0 until size) { - hs += Collider("b" + i) - } - System.gc() - Thread.sleep(1000) - assert(hs.size == 200) - elements foreach {i => assert(hs contains i)} - for (i <- 0 until size) { - assert(!(hs contains Collider("b" + i))) - } - hs.diagnostics.fullyValidate - } - - // make sure findOrUpdate returns the originally entered element - def checkFindOrUpdate { - val size = 200 - val hs = new WeakHashSet[Collider]() - val elements = (0 until size).toList map {x => Collider("a" + x)} - elements foreach {x => assert(hs findEntryOrUpdate x eq x)} - for (i <- 0 until size) { - // when we do a lookup the result should be the same reference we - // original put in - assert(hs findEntryOrUpdate(Collider("a" + i)) eq elements(i)) - } - hs.diagnostics.fullyValidate - } - - // check -= functionality - def checkMinusEquals { - val hs = new WeakHashSet[String]() - val elements = List("hello", "goodbye") - elements foreach (hs += _) - hs -= "goodbye" - assert(hs.size == 1) - assert(hs contains "hello") - assert(!(hs contains "goodbye")) - hs.diagnostics.fullyValidate - } - - // check -= when there are collisions - def checkMinusEqualsCollisions { - val hs = new WeakHashSet[Collider] - val elements = List(Collider("hello"), Collider("goodbye")) - elements foreach (hs += _) - hs -= Collider("goodbye") - assert(hs.size == 1) - assert(hs contains Collider("hello")) - assert(!(hs contains Collider("goodbye"))) - hs -= Collider("hello") - assert(hs.size == 0) - assert(!(hs contains Collider("hello"))) - hs.diagnostics.fullyValidate - } - - // check that the clear method actually cleans everything - def checkClear { - val size = 200 - val hs = new WeakHashSet[String]() - val elements = (0 until size).toList map ("a" + _) - elements foreach (hs += _) - hs.clear() - assert(hs.size == 0) - elements foreach {i => assert(!(hs contains i))} - hs.diagnostics.fullyValidate - } - - // check that the iterator covers all the contents - def checkIterator { - val hs = new WeakHashSet[String]() - val elements = (0 until 20).toList map ("a" + _) - elements foreach (hs += _) - assert(elements.iterator.toList.sorted == elements.sorted) - hs.diagnostics.fullyValidate - } - - // check that the iterator covers all the contents even when there is a collision - def checkIteratorCollisions { - val hs = new WeakHashSet[Collider] - val elements = (0 until 20).toList map {x => Collider("a" + x)} - elements foreach (hs += _) - assert(elements.iterator.toList.sorted == elements.sorted) - hs.diagnostics.fullyValidate - } - } -} diff --git a/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala b/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala new file mode 100644 index 0000000000..7e3b35c7d6 --- /dev/null +++ b/test/junit/scala/reflect/internal/util/WeakHashSetTest.scala @@ -0,0 +1,171 @@ +package scala.reflect.internal.util + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class WeakHashSetTest { + + // a class guaranteed to provide hash collisions + case class Collider(x : String) extends Comparable[Collider] with Serializable { + override def hashCode = 0 + def compareTo(y : Collider) = this.x compareTo y.x + } + + // basic emptiness check + @Test + def checkEmpty { + val hs = new WeakHashSet[String]() + assert(hs.size == 0) + hs.diagnostics.fullyValidate + } + + // make sure += works + @Test + def checkPlusEquals { + val hs = new WeakHashSet[String]() + val elements = List("hello", "goodbye") + elements foreach (hs += _) + assert(hs.size == 2) + assert(hs contains "hello") + assert(hs contains "goodbye") + hs.diagnostics.fullyValidate + } + + // make sure += works when there are collisions + @Test + def checkPlusEqualsCollisions { + val hs = new WeakHashSet[Collider]() + val elements = List("hello", "goodbye") map Collider + elements foreach (hs += _) + assert(hs.size == 2) + assert(hs contains Collider("hello")) + assert(hs contains Collider("goodbye")) + hs.diagnostics.fullyValidate + } + + // add a large number of elements to force rehashing and then validate + @Test + def checkRehashing { + val size = 200 + val hs = new WeakHashSet[String]() + val elements = (0 until size).toList map ("a" + _) + elements foreach (hs += _) + elements foreach {i => assert(hs contains i)} + hs.diagnostics.fullyValidate + } + + // make sure rehashing works properly when the set is rehashed + @Test + def checkRehashCollisions { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + elements foreach {i => assert(hs contains i)} + hs.diagnostics.fullyValidate + } + + // test that unreferenced objects are removed + // not run in an automated environment because gc behavior can't be relied on + //@Test + def checkRemoveUnreferencedObjects { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + // don't throw the following into a retained collection so gc + // can remove them + for (i <- 0 until size) { + hs += Collider("b" + i) + } + System.gc() + Thread.sleep(1000) + assert(hs.size == 200) + elements foreach {i => assert(hs contains i)} + for (i <- 0 until size) { + assert(!(hs contains Collider("b" + i))) + } + hs.diagnostics.fullyValidate + } + + // make sure findOrUpdate returns the originally entered element + @Test + def checkFindOrUpdate { + val size = 200 + val hs = new WeakHashSet[Collider]() + val elements = (0 until size).toList map {x => Collider("a" + x)} + elements foreach {x => assert(hs findEntryOrUpdate x eq x)} + for (i <- 0 until size) { + // when we do a lookup the result should be the same reference we + // original put in + assert(hs findEntryOrUpdate(Collider("a" + i)) eq elements(i)) + } + hs.diagnostics.fullyValidate + } + + // check -= functionality + @Test + def checkMinusEquals { + val hs = new WeakHashSet[String]() + val elements = List("hello", "goodbye") + elements foreach (hs += _) + hs -= "goodbye" + assert(hs.size == 1) + assert(hs contains "hello") + assert(!(hs contains "goodbye")) + hs.diagnostics.fullyValidate + } + + // check -= when there are collisions + @Test + def checkMinusEqualsCollisions { + val hs = new WeakHashSet[Collider] + val elements = List(Collider("hello"), Collider("goodbye")) + elements foreach (hs += _) + hs -= Collider("goodbye") + assert(hs.size == 1) + assert(hs contains Collider("hello")) + assert(!(hs contains Collider("goodbye"))) + hs -= Collider("hello") + assert(hs.size == 0) + assert(!(hs contains Collider("hello"))) + hs.diagnostics.fullyValidate + } + + // check that the clear method actually cleans everything + @Test + def checkClear { + val size = 200 + val hs = new WeakHashSet[String]() + val elements = (0 until size).toList map ("a" + _) + elements foreach (hs += _) + hs.clear() + assert(hs.size == 0) + elements foreach {i => assert(!(hs contains i))} + hs.diagnostics.fullyValidate + } + + // check that the iterator covers all the contents + @Test + def checkIterator { + val hs = new WeakHashSet[String]() + val elements = (0 until 20).toList map ("a" + _) + elements foreach (hs += _) + assert(elements.iterator.toList.sorted == elements.sorted) + hs.diagnostics.fullyValidate + } + + // check that the iterator covers all the contents even when there is a collision + @Test + def checkIteratorCollisions { + val hs = new WeakHashSet[Collider] + val elements = (0 until 20).toList map {x => Collider("a" + x)} + elements foreach (hs += _) + assert(elements.iterator.toList.sorted == elements.sorted) + hs.diagnostics.fullyValidate + } + +} -- cgit v1.2.3