Tests to ensure the behavior of the specialized empty List, Set, Map implementations is same as of non-specialized ones.

This commit is contained in:
Ilya Gorbunov
2015-05-15 19:51:30 +03:00
parent edc471c8ec
commit ebe578dbc5
3 changed files with 161 additions and 0 deletions
@@ -151,6 +151,7 @@ class CollectionJVMTest {
test fun emptySetIsSerializable() = testSingletonSerialization(emptySet<Any>())
test fun emptyMapIsSerializable() = testSingletonSerialization(emptyMap<Any, Any>())
private fun testSingletonSerialization(value: Any) {
val outputStream = ByteArrayOutputStream()
@@ -168,3 +169,8 @@ class CollectionJVMTest {
assertTrue(value === result)
}
}
public fun assertTypeEquals(expected: Any?, actual: Any?) {
assertEquals(expected?.javaClass, actual?.javaClass)
}
@@ -520,4 +520,137 @@ class CollectionTest {
assertEquals(d, 4)
assertEquals(e, 5)
}
test fun specialLists() {
compare(arrayListOf<Int>(), listOf<Int>()) { listBehavior() }
compare(arrayListOf<Double>(), emptyList<Double>()) { listBehavior() }
compare(arrayListOf("value"), listOf("value")) { listBehavior() }
}
test fun specialSets() {
compare(linkedSetOf<Int>(), setOf<Int>()) { setBehavior() }
compare(hashSetOf<Double>(), emptySet<Double>()) { setBehavior() }
compare(listOf("value").toMutableSet(), setOf("value")) { setBehavior() }
}
test fun specialMaps() {
compare(hashMapOf<String, Int>(), mapOf<String, Int>()) { mapBehavior() }
compare(linkedMapOf<Int, String>(), emptyMap<Int, String>()) { mapBehavior() }
compare(linkedMapOf(2 to 3), mapOf(2 to 3)) { mapBehavior() }
}
private fun <T> CompareContext<List<T>>.listBehavior() {
equalityBehavior()
collectionBehavior()
compareProperty( { listIterator() }, { listIteratorBehavior() })
compareProperty( { listIterator(0) }, { listIteratorBehavior() })
propertyFails { listIterator(-1) }
propertyFails { listIterator(size() + 1) }
for (index in expected.indices)
propertyEquals { this[index] }
propertyFails { this[size()] }
propertyEquals { indexOf(elementAtOrNull(0)) }
propertyEquals { lastIndexOf(elementAtOrNull(0)) }
propertyFails { subList(0, size() + 1)}
propertyFails { subList(-1, 0)}
propertyEquals { subList(0, size()) }
}
private fun <T> CompareContext<ListIterator<T>>.listIteratorBehavior() {
listIteratorProperties()
while (expected.hasNext()) {
propertyEquals { next() }
listIteratorProperties()
}
propertyFails { next() }
while (expected.hasPrevious()) {
propertyEquals { previous() }
listIteratorProperties()
}
propertyFails { previous() }
}
private fun CompareContext<ListIterator<*>>.listIteratorProperties() {
propertyEquals { hasNext() }
propertyEquals { hasPrevious() }
propertyEquals { nextIndex() }
propertyEquals { previousIndex() }
}
private fun <T> CompareContext<Iterator<T>>.iteratorBehavior() {
propertyEquals { hasNext() }
while (expected.hasNext()) {
propertyEquals { next() }
propertyEquals { hasNext() }
}
propertyFails { next() }
}
private fun <T> CompareContext<Set<T>>.setBehavior(objectName: String = "") {
equalityBehavior(objectName)
collectionBehavior(objectName)
compareProperty({ iterator() }, { iteratorBehavior() })
}
private fun <K, V> CompareContext<Map<K, V>>.mapBehavior() {
equalityBehavior()
propertyEquals { size() }
propertyEquals { isEmpty() }
(object {}).let { propertyEquals { containsKey(it)} }
if (expected.isEmpty().not())
propertyEquals { contains(keySet().first()) }
compareProperty( { keySet() }, { setBehavior("keySet") } )
compareProperty( { entrySet() }, { setBehavior("entrySet") } )
compareProperty( { values() }, { collectionBehavior("values") })
}
private fun <T> CompareContext<T>.equalityBehavior(objectName: String = "") {
val prefix = objectName + if (objectName.isNotEmpty()) "." else ""
equals(objectName)
propertyEquals(prefix + "hashCode") { hashCode() }
propertyEquals(prefix + "toString") { toString() }
}
private fun <T> CompareContext<Collection<T>>.collectionBehavior(objectName: String = "") {
val prefix = objectName + if (objectName.isNotEmpty()) "." else ""
propertyEquals (prefix + "size") { size() }
propertyEquals (prefix + "isEmpty") { isEmpty() }
(object {}).let { propertyEquals { contains(it)} }
propertyEquals { contains(firstOrNull()) }
propertyEquals { containsAll(this) }
}
}
private fun compare<T>(expected: T, actual: T, block: CompareContext<T>.() -> Unit) = CompareContext(expected, actual).block()
private class CompareContext<out T>(public val expected: T, public val actual: T) {
public fun equals(message: String = "") { assertEquals(expected, actual, message) }
public fun propertyEquals<P>(message: String = "", getter: T.() -> P) { assertEquals(expected.getter(), actual.getter(), message) }
public fun propertyFails(getter: T.() -> Unit) { assertFailEquals({expected.getter()}, {actual.getter()}) }
public fun compareProperty<P>(getter: T.() -> P, block: CompareContext<P>.() -> Unit) {
compare(expected.getter(), actual.getter(), block)
}
private fun assertFailEquals(expected: () -> Unit, actual: () -> Unit) {
val expectedFail = fails(expected)
val actualFail = fails(actual)
//assertEquals(expectedFail != null, actualFail != null)
assertTypeEquals(expectedFail, actualFail)
}
}