Decommonize collection builder implementations

This commit is contained in:
Abduqodiri Qurbonzoda
2020-04-30 11:40:17 +03:00
parent 379c6944a2
commit f3145454f2
20 changed files with 471 additions and 169 deletions
@@ -6,35 +6,55 @@ import test.collections.behaviors.setBehavior
import kotlin.test.*
class ContainerBuilderTest {
private fun <E> mutableCollectionOperations(e: E) = listOf<MutableCollection<E>.() -> Unit>(
{ add(e) },
{ addAll(listOf(e)) },
{ remove(e) },
{ removeAll(listOf(e)) },
{ retainAll(listOf(e)) },
{ clear() },
{ iterator().apply { next() }.remove() }
private fun <E> mutableCollectionOperations(present: E, absent: E) = listOf<Pair<String, MutableCollection<E>.() -> Unit>>(
"add(present)" to { add(present) },
"add(absent)" to { add(absent) },
"addAll(listOf(present))" to { addAll(listOf(present)) },
"addAll(listOf(absent))" to { addAll(listOf(absent)) },
"addAll(emptyList())" to { addAll(emptyList()) },
"remove(present)" to { remove(present) },
"remove(absent)" to { remove(absent) },
"removeAll(listOf(present))" to { removeAll(listOf(present)) },
"removeAll(emptyList())" to { removeAll(emptyList()) },
"removeAll(this.toList())" to { removeAll(this.toList()) },
"retainAll(listOf(present))" to { retainAll(listOf(present)) },
"retainAll(emptyList())" to { retainAll(emptyList()) },
"retainAll(this.toList())" to { retainAll(this.toList()) },
"clear()" to { clear() },
"iterator().apply { next() }.remove()" to { iterator().apply { next() }.remove() }
)
private fun <E> mutableListOperations(e: E) = mutableCollectionOperations(e) + listOf<MutableList<E>.() -> Unit>(
{ add(0, e) },
{ addAll(0, listOf(e)) },
{ removeAt(0) },
{ set(0, e) },
{ listIterator().apply { next() }.remove() },
{ listIterator(0).apply { next() }.remove() },
{ listIterator().add(e) }
private fun <E> mutableListOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableList<E>.() -> Unit>>(
"add(0, present)" to { add(0, present) },
"addAll(0, listOf(present))" to { addAll(0, listOf(present)) },
"addAll(0, emptyList())" to { addAll(0, emptyList()) },
"removeAt(0)" to { removeAt(0) },
"set(0, present)" to { set(0, present) },
"listIterator().apply { next() }.remove()" to { listIterator().apply { next() }.remove() },
"listIterator(0).apply { next() }.remove()" to { listIterator(0).apply { next() }.remove() },
"listIterator().apply { next() }.set(present)" to { listIterator().apply { next() }.set(present) },
"listIterator().add(present)" to { listIterator().add(present) }
)
private fun <E> mutableSetOperations(e: E): List<MutableSet<E>.() -> Unit> = mutableCollectionOperations(e)
private fun <E> mutableSetOperations(present: E, absent: E) = mutableCollectionOperations(present, absent) + listOf<Pair<String, MutableSet<E>.() -> Unit>>(
// check java.util.AbstractSet.removeAll optimisation
"removeAll(List(this.size) { absent })" to { removeAll(List(this.size) { absent }) }
)
private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<MutableMap<K, V>.() -> Unit>(
{ put(k, v) },
{ remove(k) },
{ putAll(mapOf(k to v)) },
{ clear() },
{ entries.first().setValue(v) },
{ entries.iterator().next().setValue(v) }
private fun <K, V> mutableMapOperations(k: K, v: V) = listOf<Pair<String, MutableMap<K, V>.() -> Unit>>(
"put(k, v)" to { put(k, v) },
"remove(k)" to { remove(k) },
"putAll(mapOf(k to v))" to { putAll(mapOf(k to v)) },
"putAll(emptyMap())" to { putAll(emptyMap()) },
"clear()" to { clear() },
"entries.first().setValue(v)" to { entries.first().setValue(v) },
"entries.iterator().next().setValue(v)" to { entries.iterator().next().setValue(v) }
)
@Test
@@ -44,10 +64,14 @@ class ContainerBuilderTest {
add('c')
}
val y = buildList(4) {
val subList: MutableList<Char>
val y = buildList<Char>(4) {
add('a')
addAll(x)
add('d')
subList = subList(0, 4)
}
compare(listOf('a', 'b', 'c', 'd'), y) { listBehavior() }
@@ -60,9 +84,10 @@ class ContainerBuilderTest {
}
assertTrue(y is MutableList<Char>)
for (operation in mutableListOperations('a')) {
assertFailsWith<UnsupportedOperationException> { y.operation() }
assertFailsWith<UnsupportedOperationException> { y.subList(1, 3).operation() }
for ((fName, operation) in mutableListOperations('b', 'x')) {
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
assertFailsWith<UnsupportedOperationException>("y.subList(1, 3).$fName") { y.subList(1, 3).operation() }
assertFailsWith<UnsupportedOperationException>("subList.$fName") { subList.operation() }
}
}
@@ -90,10 +115,12 @@ class ContainerBuilderTest {
val subSubList = subList.subList(2, 4)
// buffer reallocation should happen
repeat(20) { subSubList.add('x') }
repeat(20) { subSubList.add(subSubList.size - 2 * it, 'y') }
compare("ab123${"x".repeat(20)}e".toList(), this) { listBehavior() }
compare("b123${"x".repeat(20)}".toList(), subList) { listBehavior() }
compare("23${"x".repeat(20)}".toList(), subSubList) { listBehavior() }
val addedChars = "xy".repeat(20)
compare("ab123${addedChars}e".toList(), this) { listBehavior() }
compare("b123$addedChars".toList(), subList) { listBehavior() }
compare("23$addedChars".toList(), subSubList) { listBehavior() }
}
}
@@ -118,8 +145,8 @@ class ContainerBuilderTest {
}
assertTrue(y is MutableSet<Char>)
for (operation in mutableSetOperations('b')) {
assertFailsWith<UnsupportedOperationException> { y.operation() }
for ((fName, operation) in mutableSetOperations('b', 'x')) {
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
}
}
@@ -145,17 +172,23 @@ class ContainerBuilderTest {
}
assertTrue(y is MutableMap<Char, Int>)
for (operation in mutableMapOperations('a', 0)) {
assertFailsWith<UnsupportedOperationException> { y.operation() }
for ((fName, operation) in mutableMapOperations('a', 1) + mutableMapOperations('x', 10)) {
assertFailsWith<UnsupportedOperationException>("y.$fName") { y.operation() }
}
for (operation in mutableSetOperations('a')) {
assertFailsWith<UnsupportedOperationException> { y.keys.operation() }
for ((fName, operation) in mutableSetOperations('a', 'x')) {
assertFailsWith<UnsupportedOperationException>("y.keys.$fName") { y.keys.operation() }
}
for (operation in mutableCollectionOperations(1)) {
assertFailsWith<UnsupportedOperationException> { y.values.operation() }
for ((fName, operation) in mutableCollectionOperations(1, 10)) {
assertFailsWith<UnsupportedOperationException>("y.values.$fName") { y.values.operation() }
}
for (operation in mutableSetOperations(y.entries.first())) {
assertFailsWith<UnsupportedOperationException> { y.entries.operation() }
val presentEntry = y.entries.first()
val absentEntry: MutableMap.MutableEntry<Char, Int> = object : MutableMap.MutableEntry<Char, Int> {
override val key: Char get() = 'x'
override val value: Int get() = 10
override fun setValue(newValue: Int): Int = fail("Unreachable")
}
for ((fName, operation) in mutableSetOperations(presentEntry, absentEntry)) {
assertFailsWith<UnsupportedOperationException>("y.entries.$fName") { y.entries.operation() }
}
}
}