28168bf230
This is a workaround for the problem KT-43321. Introduce an intermediate abstract set specialized for Map.Entry elements and implement 'contains(Map.Entry)' method there. Then inherit that intermediate set in entrysets of JS HashMap, JS LinkedHashMap, JVM MapBuilder, that are specialized for MutableMap.MutableEntry elements, so that no override of 'contains' is required anymore. This allows to avoid incorrect special 'contains' bridge being generated that otherwise rejects all arguments except ones of MutableEntry type.
557 lines
19 KiB
Kotlin
557 lines
19 KiB
Kotlin
/*
|
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
|
*/
|
|
|
|
package test.collections
|
|
|
|
import kotlin.test.*
|
|
import test.*
|
|
|
|
class MapTest {
|
|
|
|
@Test fun getOrElse() {
|
|
val data = mapOf<String, Int>()
|
|
val a = data.getOrElse("foo") { 2 }
|
|
assertEquals(2, a)
|
|
val a1 = data.getOrElse("foo") { data.get("bar") } ?: 1
|
|
assertEquals(1, a1)
|
|
|
|
val b = data.getOrElse("foo") { 3 }
|
|
assertEquals(3, b)
|
|
assertEquals(0, data.size)
|
|
|
|
val empty = mapOf<String, Int?>()
|
|
val c = empty.getOrElse("") { null }
|
|
assertEquals(null, c)
|
|
|
|
val nullable = mapOf(1 to null)
|
|
val d = nullable.getOrElse(1) { "x" }
|
|
assertEquals("x", d)
|
|
}
|
|
|
|
@Test fun getValue() {
|
|
val data: MutableMap<String, Int> = hashMapOf("bar" to 1)
|
|
assertFailsWith<NoSuchElementException> { data.getValue("foo") }.let { e ->
|
|
assertTrue("foo" in e.message!!)
|
|
}
|
|
assertEquals(1, data.getValue("bar"))
|
|
|
|
val mutableWithDefault = data.withDefault { 42 }
|
|
assertEquals(42, mutableWithDefault.getValue("foo"))
|
|
|
|
// verify that it is wrapper
|
|
mutableWithDefault["bar"] = 2
|
|
assertEquals(2, data["bar"])
|
|
data["bar"] = 3
|
|
assertEquals(3, mutableWithDefault["bar"])
|
|
|
|
val readonlyWithDefault = (data as Map<String, Int>).withDefault { it.length }
|
|
assertEquals(4, readonlyWithDefault.getValue("loop"))
|
|
|
|
val withReplacedDefault = readonlyWithDefault.withDefault { 42 }
|
|
assertEquals(42, withReplacedDefault.getValue("loop"))
|
|
}
|
|
|
|
@Test fun getOrPut() {
|
|
val data = hashMapOf<String, Int>()
|
|
val a = data.getOrPut("foo") { 2 }
|
|
assertEquals(2, a)
|
|
|
|
val b = data.getOrPut("foo") { 3 }
|
|
assertEquals(2, b)
|
|
|
|
assertEquals(1, data.size)
|
|
|
|
val empty = hashMapOf<String, Int?>()
|
|
val c = empty.getOrPut("") { null }
|
|
assertEquals(null, c)
|
|
|
|
val d = empty.getOrPut("") { 1 }
|
|
assertEquals(1, d)
|
|
}
|
|
|
|
@Test fun sizeAndEmpty() {
|
|
val data = hashMapOf<String, Int>()
|
|
assertTrue { data.none() }
|
|
assertEquals(data.size, 0)
|
|
}
|
|
|
|
@Test fun setViaIndexOperators() {
|
|
val map = hashMapOf<String, String>()
|
|
assertTrue { map.none() }
|
|
assertEquals(map.size, 0)
|
|
|
|
map["name"] = "James"
|
|
|
|
assertTrue { map.any() }
|
|
assertEquals(map.size, 1)
|
|
assertEquals("James", map["name"])
|
|
}
|
|
|
|
@Test fun iterate() {
|
|
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
|
|
val list = arrayListOf<String>()
|
|
for (e in map) {
|
|
list.add(e.key)
|
|
list.add(e.value)
|
|
}
|
|
|
|
assertEquals(6, list.size)
|
|
assertEquals("beverage,beer,location,Mells,name,James", list.joinToString(","))
|
|
}
|
|
|
|
@Test fun iterateAndMutate() {
|
|
val map = mutableMapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
|
|
val it = map.iterator()
|
|
for (e in it) {
|
|
when (e.key) {
|
|
"beverage" -> e.setValue("juice")
|
|
"location" -> it.remove()
|
|
}
|
|
}
|
|
assertEquals(mapOf("beverage" to "juice", "name" to "James"), map)
|
|
}
|
|
|
|
|
|
@Test
|
|
fun onEach() {
|
|
val map = mutableMapOf("beverage" to "beer", "location" to "Mells")
|
|
val result = StringBuilder()
|
|
val newMap = map.onEach { result.append(it.key).append("=").append(it.value).append(";") }
|
|
assertEquals("beverage=beer;location=Mells;", result.toString())
|
|
assertTrue(map === newMap)
|
|
|
|
// static types test
|
|
assertStaticTypeIs<HashMap<String, String>>(
|
|
hashMapOf("a" to "b").onEach { }
|
|
)
|
|
}
|
|
|
|
@Test
|
|
fun onEachIndexed() {
|
|
val map = mutableMapOf("beverage" to "beer", "location" to "Mells")
|
|
val result = StringBuilder()
|
|
val newMap = map.onEachIndexed { i, e -> result.append(i + 1).append('.').append(e.key).append("=").append(e.value).append(";") }
|
|
assertEquals("1.beverage=beer;2.location=Mells;", result.toString())
|
|
assertTrue(map === newMap)
|
|
|
|
// static types test
|
|
assertStaticTypeIs<HashMap<String, String>>(
|
|
hashMapOf("a" to "b").onEachIndexed { _, _ -> }
|
|
)
|
|
}
|
|
|
|
@Test fun stream() {
|
|
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
|
|
val named = map.asSequence().filter { it.key == "name" }.single()
|
|
assertEquals("James", named.value)
|
|
}
|
|
|
|
@Test fun iterateWithProperties() {
|
|
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
|
|
val list = arrayListOf<String>()
|
|
for (e in map) {
|
|
list.add(e.key)
|
|
list.add(e.value)
|
|
}
|
|
|
|
assertEquals(6, list.size)
|
|
assertEquals("beverage,beer,location,Mells,name,James", list.joinToString(","))
|
|
}
|
|
|
|
@Test fun iterateWithExtraction() {
|
|
val map = mapOf("beverage" to "beer", "location" to "Mells", "name" to "James")
|
|
val list = arrayListOf<String>()
|
|
for ((key, value) in map) {
|
|
list.add(key)
|
|
list.add(value)
|
|
}
|
|
|
|
assertEquals(6, list.size)
|
|
assertEquals("beverage,beer,location,Mells,name,James", list.joinToString(","))
|
|
}
|
|
|
|
@Test fun contains() {
|
|
val map = mapOf("a" to 1, "b" to 2)
|
|
assertTrue("a" in map)
|
|
assertTrue("c" !in map)
|
|
}
|
|
|
|
@Test fun map() {
|
|
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
|
|
val list = m1.map { it.value + " rocks" }
|
|
|
|
assertEquals(listOf("beer rocks", "Mells rocks"), list)
|
|
}
|
|
|
|
|
|
@Test fun mapNotNull() {
|
|
val m1 = mapOf("a" to 1, "b" to null)
|
|
val list = m1.mapNotNull { it.value?.let { v -> "${it.key}$v" } }
|
|
assertEquals(listOf("a1"), list)
|
|
}
|
|
|
|
@Test fun mapValues() {
|
|
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
|
|
val m2 = m1.mapValues { it.value + "2" }
|
|
|
|
assertEquals(mapOf("beverage" to "beer2", "location" to "Mells2"), m2)
|
|
|
|
val m1p: Map<out String, String> = m1
|
|
val m3 = m1p.mapValuesTo(hashMapOf()) { it.value.length }
|
|
assertStaticTypeIs<HashMap<String, Int>>(m3)
|
|
assertEquals(mapOf("beverage" to 4, "location" to 5), m3)
|
|
}
|
|
|
|
@Test fun mapKeys() {
|
|
val m1 = mapOf("beverage" to "beer", "location" to "Mells")
|
|
val m2 = m1.mapKeys { it.key + "2" }
|
|
|
|
assertEquals(mapOf("beverage2" to "beer", "location2" to "Mells"), m2)
|
|
|
|
val m1p: Map<out String, String> = m1
|
|
val m3 = m1p.mapKeysTo(mutableMapOf()) { it.key.length }
|
|
assertStaticTypeIs<MutableMap<Int, String>>(m3)
|
|
assertEquals(mapOf(8 to "Mells"), m3)
|
|
}
|
|
|
|
@Test fun flatMap() {
|
|
fun <T> list(entry: Map.Entry<T, T>): List<T> = listOf(entry.key, entry.value)
|
|
fun <T> seq(entry: Map.Entry<T, T>): Sequence<T> = sequenceOf(entry.key, entry.value)
|
|
val m = mapOf("x" to 1, "y" to 0)
|
|
val result1 = m.flatMap { list(it) }
|
|
val result2 = m.flatMap { seq(it) }
|
|
val result3 = m.flatMap(::list)
|
|
val result4 = m.flatMap(::seq)
|
|
val expected = listOf("x", 1, "y", 0)
|
|
assertEquals(expected, result1)
|
|
assertEquals(expected, result2)
|
|
assertEquals(expected, result3)
|
|
assertEquals(expected, result4)
|
|
}
|
|
|
|
@Test fun createFrom() {
|
|
val pairs = arrayOf("a" to 1, "b" to 2)
|
|
val expected = mapOf(*pairs)
|
|
|
|
assertEquals(expected, pairs.toMap())
|
|
assertEquals(expected, pairs.asIterable().toMap())
|
|
assertEquals(expected, pairs.asSequence().toMap())
|
|
assertEquals(expected, expected.toMap())
|
|
assertEquals(mapOf("a" to 1), expected.filterKeys { it == "a" }.toMap())
|
|
assertEquals(emptyMap(), expected.filter { false }.toMap())
|
|
|
|
val mutableMap = expected.toMutableMap()
|
|
assertEquals(expected, mutableMap)
|
|
mutableMap += "c" to 3
|
|
assertNotEquals(expected, mutableMap)
|
|
}
|
|
|
|
@Test fun populateTo() {
|
|
val pairs = arrayOf("a" to 1, "b" to 2)
|
|
val expected = mapOf(*pairs)
|
|
|
|
val linkedMap: LinkedHashMap<String, Int> = pairs.toMap(linkedMapOf())
|
|
assertEquals(expected, linkedMap)
|
|
|
|
val hashMap: HashMap<String, Int> = pairs.asIterable().toMap(hashMapOf())
|
|
assertEquals(expected, hashMap)
|
|
|
|
val mutableMap: MutableMap<String, Int> = pairs.asSequence().toMap(mutableMapOf())
|
|
assertEquals(expected, mutableMap)
|
|
|
|
val mutableMap2 = mutableMap.toMap(mutableMapOf())
|
|
assertEquals(expected, mutableMap2)
|
|
|
|
val mutableMap3 = mutableMap.toMap(hashMapOf<CharSequence, Any>())
|
|
assertEquals<Map<*, *>>(expected, mutableMap3)
|
|
}
|
|
|
|
@Test fun createWithSelector() {
|
|
val map = listOf("a", "bb", "ccc").associateBy { it.length }
|
|
assertEquals(3, map.size)
|
|
assertEquals("a", map.get(1))
|
|
assertEquals("bb", map.get(2))
|
|
assertEquals("ccc", map.get(3))
|
|
}
|
|
|
|
@Test fun createWithSelectorAndOverwrite() {
|
|
val map = listOf("aa", "bb", "ccc").associateBy { it.length }
|
|
assertEquals(2, map.size)
|
|
assertEquals("bb", map.get(2))
|
|
assertEquals("ccc", map.get(3))
|
|
}
|
|
|
|
@Test fun createWithSelectorForKeyAndValue() {
|
|
val map = listOf("a", "bb", "ccc").associateBy({ it.length }, { it.toUpperCase() })
|
|
assertEquals(3, map.size)
|
|
assertEquals("A", map[1])
|
|
assertEquals("BB", map[2])
|
|
assertEquals("CCC", map[3])
|
|
}
|
|
|
|
@Test fun createWithPairSelector() {
|
|
val map = listOf("a", "bb", "ccc").associate { it.length to it.toUpperCase() }
|
|
assertEquals(3, map.size)
|
|
assertEquals("A", map[1])
|
|
assertEquals("BB", map[2])
|
|
assertEquals("CCC", map[3])
|
|
}
|
|
|
|
@Test fun createUsingTo() {
|
|
val map = mapOf("a" to 1, "b" to 2)
|
|
assertEquals(2, map.size)
|
|
assertEquals(1, map["a"])
|
|
assertEquals(2, map["b"])
|
|
}
|
|
|
|
@Test fun createMutableMap() {
|
|
val map = mutableMapOf("b" to 1, "c" to 2)
|
|
map.put("a", 3)
|
|
assertEquals(listOf("b" to 1, "c" to 2, "a" to 3), map.toList())
|
|
}
|
|
|
|
@Test fun createLinkedMap() {
|
|
val map = linkedMapOf(Pair("c", 3), Pair("b", 2), Pair("a", 1))
|
|
assertEquals(1, map["a"])
|
|
assertEquals(2, map["b"])
|
|
assertEquals(3, map["c"])
|
|
assertEquals(listOf("c", "b", "a"), map.keys.toList())
|
|
}
|
|
|
|
@Test fun filter() {
|
|
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
val filteredByKey = map.filter { it.key[0] == 'b' }
|
|
assertEquals(mapOf("b" to 3), filteredByKey)
|
|
|
|
val filteredByKey2 = map.filterKeys { it[0] == 'b' }
|
|
assertEquals(mapOf("b" to 3), filteredByKey2)
|
|
|
|
val filteredByValue = map.filter { it.value == 2 }
|
|
assertEquals(mapOf("a" to 2, "c" to 2), filteredByValue)
|
|
|
|
val filteredByValue2 = map.filterValues { it % 2 == 0 }
|
|
assertEquals(mapOf("a" to 2, "c" to 2), filteredByValue2)
|
|
}
|
|
|
|
@Test fun filterOutProjectedTo() {
|
|
val map: Map<out String, Int> = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
|
|
val filteredByKey = map.filterTo(mutableMapOf()) { it.key[0] == 'b' }
|
|
assertStaticTypeIs<MutableMap<String, Int>>(filteredByKey)
|
|
assertEquals(mapOf("b" to 3), filteredByKey)
|
|
|
|
val filteredByKey2 = map.filterKeys { it[0] == 'b' }
|
|
assertStaticTypeIs<Map<String, Int>>(filteredByKey2)
|
|
assertEquals(mapOf("b" to 3), filteredByKey2)
|
|
|
|
val filteredByValue = map.filterNotTo(hashMapOf()) { it.value != 2 }
|
|
assertStaticTypeIs<HashMap<String, Int>>(filteredByValue)
|
|
assertEquals(mapOf("a" to 2, "c" to 2), filteredByValue)
|
|
|
|
val filteredByValue2 = map.filterValues { it % 2 == 0 }
|
|
assertStaticTypeIs<Map<String, Int>>(filteredByValue2)
|
|
assertEquals(mapOf("a" to 2, "c" to 2), filteredByValue2)
|
|
}
|
|
|
|
@Test fun any() {
|
|
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
assertTrue(map.any())
|
|
assertFalse(emptyMap<String, Int>().any())
|
|
|
|
assertTrue(map.any { it.key == "b" })
|
|
assertFalse(emptyMap<String, Int>().any { it.key == "b" })
|
|
|
|
assertTrue(map.any { it.value == 2 })
|
|
assertFalse(map.any { it.value == 5 })
|
|
}
|
|
|
|
@Test fun all() {
|
|
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
assertTrue(map.all { it.key != "d" })
|
|
assertTrue(emptyMap<String, Int>().all { it.key == "d" })
|
|
|
|
assertTrue(map.all { it.value > 0 })
|
|
assertFalse(map.all { it.value == 2 })
|
|
}
|
|
|
|
@Test fun countBy() {
|
|
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
assertEquals(3, map.count())
|
|
|
|
val filteredByKey = map.count { it.key == "b" }
|
|
assertEquals(1, filteredByKey)
|
|
|
|
val filteredByValue = map.count { it.value == 2 }
|
|
assertEquals(2, filteredByValue)
|
|
}
|
|
|
|
@Test fun filterNot() {
|
|
val map = mapOf(Pair("b", 3), Pair("c", 2), Pair("a", 2))
|
|
val filteredByKey = map.filterNot { it.key == "b" }
|
|
assertEquals(2, filteredByKey.size)
|
|
assertEquals(null, filteredByKey["b"])
|
|
assertEquals(2, filteredByKey["c"])
|
|
assertEquals(2, filteredByKey["a"])
|
|
|
|
val filteredByValue = map.filterNot { it.value == 2 }
|
|
assertEquals(1, filteredByValue.size)
|
|
assertEquals(3, filteredByValue["b"])
|
|
}
|
|
|
|
@Test
|
|
fun entriesCovariantContains() {
|
|
// Based on https://youtrack.jetbrains.com/issue/KT-42428.
|
|
fun doTest(implName: String, map: Map<String, Int>, key: String, value: Int) {
|
|
class SimpleEntry<out K, out V>(override val key: K, override val value: V) : Map.Entry<K, V> {
|
|
override fun toString(): String = "$key=$value"
|
|
override fun hashCode(): Int = key.hashCode() xor value.hashCode()
|
|
override fun equals(other: Any?): Boolean =
|
|
other is Map.Entry<*, *> && key == other.key && value == other.value
|
|
}
|
|
|
|
val mapDescription = "$implName: ${map::class}"
|
|
|
|
assertTrue(map.keys.contains(key), mapDescription)
|
|
assertEquals(value, map[key], mapDescription)
|
|
// This one requires special efforts to make it work this way.
|
|
// map.entries can in fact be `MutableSet<MutableMap.MutableEntry>`,
|
|
// which [contains] method takes [MutableEntry], so the compiler may generate special bridge
|
|
// returning false for values that aren't [MutableEntry] (including [SimpleEntry]).
|
|
assertTrue(map.entries.contains(SimpleEntry(key, value)), mapDescription)
|
|
assertTrue(map.entries.toSet().contains(SimpleEntry(key, value)), mapDescription)
|
|
}
|
|
|
|
val mapLetterToIndex = ('a'..'z').mapIndexed { i, c -> "$c" to i }.toMap()
|
|
doTest("default read-only", mapLetterToIndex, "h", 7)
|
|
doTest("default mutable", mapLetterToIndex.toMutableMap(), "b", 1)
|
|
doTest("HashMap", mapLetterToIndex.toMap(HashMap()), "c", 2)
|
|
doTest("LinkedHashMap", mapLetterToIndex.toMap(LinkedHashMap()), "d", 3)
|
|
|
|
val builtMap = buildMap {
|
|
putAll(mapLetterToIndex)
|
|
doTest("MapBuilder", this, "z", 25)
|
|
}
|
|
doTest("built Map", builtMap, "y", 24)
|
|
}
|
|
|
|
|
|
fun testPlusAssign(doPlusAssign: (MutableMap<String, Int>) -> Unit) {
|
|
val map = hashMapOf("a" to 1, "b" to 2)
|
|
doPlusAssign(map)
|
|
assertEquals(3, map.size)
|
|
assertEquals(1, map["a"])
|
|
assertEquals(4, map["b"])
|
|
assertEquals(3, map["c"])
|
|
}
|
|
|
|
@Test fun plusAssign() = testPlusAssign {
|
|
it += "b" to 4
|
|
it += "c" to 3
|
|
}
|
|
|
|
@Test fun plusAssignList() = testPlusAssign { it += listOf("c" to 3, "b" to 4) }
|
|
|
|
@Test fun plusAssignArray() = testPlusAssign { it += arrayOf("c" to 3, "b" to 4) }
|
|
|
|
@Test fun plusAssignSequence() = testPlusAssign { it += sequenceOf("c" to 3, "b" to 4) }
|
|
|
|
@Test fun plusAssignMap() = testPlusAssign { it += mapOf("c" to 3, "b" to 4) }
|
|
|
|
fun testPlus(doPlus: (Map<String, Int>) -> Map<String, Int>) {
|
|
val original = mapOf("A" to 1, "B" to 2)
|
|
val extended = doPlus(original)
|
|
assertEquals(3, extended.size)
|
|
assertEquals(1, extended["A"])
|
|
assertEquals(4, extended["B"])
|
|
assertEquals(3, extended["C"])
|
|
}
|
|
|
|
@Test fun plus() = testPlus { it + ("C" to 3) + ("B" to 4) }
|
|
|
|
@Test fun plusList() = testPlus { it + listOf("C" to 3, "B" to 4) }
|
|
|
|
@Test fun plusArray() = testPlus { it + arrayOf("C" to 3, "B" to 4) }
|
|
|
|
@Test fun plusSequence() = testPlus { it + sequenceOf("C" to 3, "B" to 4) }
|
|
|
|
@Test fun plusMap() = testPlus { it + mapOf("C" to 3, "B" to 4) }
|
|
|
|
@Test fun plusAny() {
|
|
testPlusAny(emptyMap<String, String>(), 1 to "A")
|
|
testPlusAny(mapOf("A" to null), "A" as CharSequence to 2)
|
|
}
|
|
|
|
fun <K, V> testPlusAny(mapObject: Any, pair: Pair<K, V>) {
|
|
val map = mapObject as Map<*, *>
|
|
fun assertContains(map: Map<*, *>) = assertEquals(pair.second, map[pair.first])
|
|
|
|
assertContains(map + pair)
|
|
assertContains(map + listOf(pair))
|
|
assertContains(map + arrayOf(pair))
|
|
assertContains(map + sequenceOf(pair))
|
|
assertContains(map + mapOf(pair))
|
|
}
|
|
|
|
|
|
fun testMinus(doMinus: (Map<String, Int>) -> Map<String, Int>) {
|
|
val original = mapOf("A" to 1, "B" to 2)
|
|
val shortened = doMinus(original)
|
|
assertEquals("A" to 1, shortened.entries.single().toPair())
|
|
}
|
|
|
|
@Test fun minus() = testMinus { it - "B" - "C" }
|
|
|
|
@Test fun minusList() = testMinus { it - listOf("B", "C") }
|
|
|
|
@Test fun minusArray() = testMinus { it - arrayOf("B", "C") }
|
|
|
|
@Test fun minusSequence() = testMinus { it - sequenceOf("B", "C") }
|
|
|
|
@Test fun minusSet() = testMinus { it - setOf("B", "C") }
|
|
|
|
|
|
|
|
fun testMinusAssign(doMinusAssign: (MutableMap<String, Int>) -> Unit) {
|
|
val original = hashMapOf("A" to 1, "B" to 2)
|
|
doMinusAssign(original)
|
|
assertEquals("A" to 1, original.entries.single().toPair())
|
|
}
|
|
|
|
@Test fun minusAssign() = testMinusAssign {
|
|
it -= "B"
|
|
it -= "C"
|
|
}
|
|
|
|
@Test fun minusAssignList() = testMinusAssign { it -= listOf("B", "C") }
|
|
|
|
@Test fun minusAssignArray() = testMinusAssign { it -= arrayOf("B", "C") }
|
|
|
|
@Test fun minusAssignSequence() = testMinusAssign { it -= sequenceOf("B", "C") }
|
|
|
|
|
|
fun testIdempotent(operation: (Map<String, Int>) -> Map<String, Int>) {
|
|
val original = mapOf("A" to 1, "B" to 2)
|
|
assertEquals(original, operation(original))
|
|
}
|
|
|
|
fun testIdempotentAssign(operation: (MutableMap<String, Int>) -> Unit) {
|
|
val original = hashMapOf("A" to 1, "B" to 2)
|
|
val result = HashMap(original)
|
|
operation(result)
|
|
assertEquals(original, result)
|
|
}
|
|
|
|
|
|
@Test fun plusEmptyList() = testIdempotent { it + listOf() }
|
|
|
|
@Test fun plusEmptySet() = testIdempotent { it + setOf() }
|
|
|
|
@Test fun plusAssignEmptyList() = testIdempotentAssign { it += listOf() }
|
|
|
|
@Test fun plusAssignEmptySet() = testIdempotentAssign { it += setOf() }
|
|
|
|
|
|
}
|