diff --git a/src/main/scala/scala/collection/MultiDict.scala b/src/main/scala/scala/collection/MultiDict.scala index 978dda4..b7e621c 100644 --- a/src/main/scala/scala/collection/MultiDict.scala +++ b/src/main/scala/scala/collection/MultiDict.scala @@ -13,6 +13,8 @@ trait MultiDict[K, V] with MultiDictOps[K, V, MultiDict, MultiDict[K, V]] with Equals { + override protected[this] def className: String = "MultiDict" + def multiDictFactory: MapFactory[MultiDict] = MultiDict override protected def fromSpecific(coll: IterableOnce[(K, V)]): MultiDict[K, V] = multiDictFactory.from(coll) override protected def newSpecificBuilder: mutable.Builder[(K, V), MultiDict[K, V]] = multiDictFactory.newBuilder @@ -196,6 +198,8 @@ trait MultiDictOps[K, V, +CC[X, Y] <: MultiDict[X, Y], +C <: MultiDict[K, V]] def filterSets(p: ((K, Set[V])) => Boolean): C = fromSpecificSets(new View.Filter(sets, p, isFlipped = false)) + override def addString(sb: StringBuilder, start: String, sep: String, end: String): StringBuilder = + iterator.map { case (k, v) => s"$k -> $v" }.addString(sb, start, sep, end) } object MultiDictOps { diff --git a/src/main/scala/scala/collection/MultiSet.scala b/src/main/scala/scala/collection/MultiSet.scala index ad1a402..ba42d58 100644 --- a/src/main/scala/scala/collection/MultiSet.scala +++ b/src/main/scala/scala/collection/MultiSet.scala @@ -12,6 +12,8 @@ trait MultiSet[A] with MultiSetOps[A, MultiSet, MultiSet[A]] with Equals { + override protected[this] def className: String = "MultiSet" + override def iterableFactory: IterableFactory[MultiSet] = MultiSet override protected def fromSpecific(coll: IterableOnce[A]): MultiSet[A] = iterableFactory.from(coll) override protected def newSpecificBuilder: mutable.Builder[A, MultiSet[A]] = iterableFactory.newBuilder diff --git a/src/test/scala/scala/collection/MultiMapTest.scala b/src/test/scala/scala/collection/MultiDictTest.scala similarity index 58% rename from src/test/scala/scala/collection/MultiMapTest.scala rename to src/test/scala/scala/collection/MultiDictTest.scala index fec6408..c0a5efe 100644 --- a/src/test/scala/scala/collection/MultiMapTest.scala +++ b/src/test/scala/scala/collection/MultiDictTest.scala @@ -6,7 +6,7 @@ import scala.collection.immutable.List import org.junit.{Assert, Test} @RunWith(classOf[JUnit4]) -class MultiMapTest { +class MultiDictTest { @Test def equality(): Unit = { @@ -72,5 +72,51 @@ class MultiMapTest { val filteredT: MultiDict[String, Int] = filtered Assert.assertEquals(Seq.empty, filtered.toSeq) } + @Test + def testToString(): Unit = { + + val prefix = "MultiDict(" + val suffix = ")" + + def run(ms: MultiDict[Int, Int]): Unit = { + val actual = ms.toString + assert(actual.startsWith(prefix), s"`$actual` does not start with `$prefix`") + assert(actual.endsWith(suffix), s"`$actual` does not end with `$suffix`") + + // The order of elements in the multiset are not defined, so this test should be robust to order changes + + val expected = + actual + .stripPrefix(prefix) + .stripSuffix(suffix) + .split(",") + .iterator + .flatMap { s => + if (s.isEmpty) None + else { + val Array(keyString, valueString) = s.split("->") + Some(keyString.trim.toInt -> valueString.trim.toInt) + } + } + .to(MultiDict) + Assert.assertEquals(ms, expected) + } + + def runForFactory(factory: MapFactory[MultiDict]): Unit = { + Assert.assertEquals(factory().toString, s"$prefix$suffix") + Assert.assertEquals(factory(1 -> 1).toString, s"${prefix}1 -> 1${suffix}") + + run(factory()) + run(factory(1 -> 1)) + run(factory(1234 -> 2)) + run(factory(1 -> 5,2 -> 6,3 -> 7)) + run(factory(1 -> 1,1 -> 2,1 -> 3,2 -> 1,3 -> 3)) + run(factory(1 -> 1,1 -> 2,1 -> 3,2 -> 4,2 -> 5,2 -> 6,2 -> 7,3 -> 8)) + } + + runForFactory(MultiDict) + runForFactory(mutable.MultiDict) + runForFactory(immutable.MultiDict) + } } diff --git a/src/test/scala/scala/collection/MultiSetTest.scala b/src/test/scala/scala/collection/MultiSetTest.scala index a1ac526..143e92a 100644 --- a/src/test/scala/scala/collection/MultiSetTest.scala +++ b/src/test/scala/scala/collection/MultiSetTest.scala @@ -46,4 +46,43 @@ class MultiSetTest { ) } + @Test + def testToString(): Unit = { + + def run(ms: MultiSet[Int]): Unit = { + val actual = ms.toString + assert(actual.startsWith("MultiSet("), s"`$actual` does not start with `MultiSet(`") + assert(actual.endsWith(")"), s"`$actual` does not end with `)`") + + // The order of elements in the multiset are not defined, so this test should be robust to order changes + Assert.assertEquals(ms, + actual + .stripPrefix("MultiSet(") + .stripSuffix(")") + .split(",") + .iterator + .flatMap (_.trim match { + case "" => None + case s => Some(s.toInt) + }) + .to(MultiSet)) + } + + def runForFactory(factory: IterableFactory[MultiSet]): Unit = { + Assert.assertEquals(factory().toString, "MultiSet()") + Assert.assertEquals(factory(1).toString, "MultiSet(1)") + + run(factory()) + run(factory(1)) + run(factory(1234)) + run(factory(1,2,3)) + run(factory(1,1,1,2,3)) + run(factory(1,1,1,2,2,2,2,3)) + } + + runForFactory(MultiSet) + runForFactory(mutable.MultiSet) + runForFactory(immutable.MultiSet) + } + }