[go: nahoru, domu]

blob: a6bb58845103152b6f77aad1b6583def89d4ba2e [file] [log] [blame]
/*
* Copyright 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.compose.runtime.snapshots
import androidx.compose.runtime.ExperimentalComposeApi
import androidx.compose.runtime.mutableStateMapOf
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
class SnapshotStateMapTests {
@Test
fun canCreateAnMapEmpty() {
mutableStateMapOf<Int, Float>()
}
@Test
fun canCreateAnInitializedMap() {
mutableStateMapOf(1 to 1f, 2 to 2f, 3 to 3f)
}
@Test
fun validateSize() {
validateRead { map, normalMap ->
assertEquals(normalMap.size, map.size)
}
}
@Test
fun validateContainsKey() {
validateRead { map, normalMap ->
for (value in listOf(1, 2, 3, 100, 200)) {
assertEquals(normalMap.containsKey(value), map.containsKey(value))
}
}
}
@Test
fun validate_containsValue() {
validateRead { map, normalMap ->
for (value in listOf(1f, 2f, 3f, 100f, 200f)) {
assertEquals(normalMap.containsValue(value), map.containsValue(value))
}
}
}
@Test
fun validateGet() {
validateRead { map, normalMap ->
for (entry in normalMap) {
assertEquals(entry.value, map[entry.key])
}
assertEquals(normalMap[100], map[100])
}
}
@Test
fun validateIsEmpty() {
validateRead { map, normalMap ->
assertEquals(normalMap.isEmpty(), map.isEmpty())
}
validateRead(mutableStateMapOf()) { map, normalMap ->
assertEquals(normalMap.isEmpty(), map.isEmpty())
}
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapEntriesAdd() {
val map = defaultMap().toMutableMap()
val entriesToAdd = mutableMapOf(100 to 100f)
map.entries.add(entriesToAdd.entries.first())
}
@Test(expected = UnsupportedOperationException::class)
fun validateEntriesAdd() {
val map = defaultMap()
val entriesToAdd = mutableMapOf(100 to 100f)
map.entries.add(entriesToAdd.entries.first())
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapEntriesAddAll() {
val map = defaultMap().toMutableMap()
val entriesToAdd = mutableMapOf(100 to 100f, 200 to 200f)
map.entries.addAll(entriesToAdd.entries)
}
@Test(expected = UnsupportedOperationException::class)
fun validateEntriesAddAll() {
val map = defaultMap()
val entriesToAdd = mutableMapOf(100 to 100f, 200 to 200f)
map.entries.addAll(entriesToAdd.entries)
}
@Test
fun validateEntriesSize() {
validateRead { map, normalMap ->
assertEquals(normalMap.entries.size, map.entries.size)
}
}
@Test
fun validateEntriesClear() {
validateWrite { map ->
map.entries.clear()
}
}
@Test
fun validateEntriesIterator() {
validateRead { map, normalMap ->
for (entries in map.entries.zip(normalMap.entries)) {
assertEquals(entries.second, entries.first)
}
}
}
@Test
fun validateEntriesIteratorRemove() {
validateWrite { map ->
val iterator = map.entries.iterator()
iterator.next()
iterator.remove()
iterator.next()
iterator.next()
iterator.remove()
}
}
@Test
fun validateEntriesContains() {
validateRead { map, normalMap ->
val one = map.entries.first()
val normalOne = normalMap.entries.first()
assertEquals(normalMap.entries.contains(normalOne), map.entries.contains(one))
assertEquals(normalMap.entries.contains(one), map.entries.contains(normalOne))
val independent = object : MutableMap.MutableEntry<Int, Float> {
override val key = 1
override var value = 1f
override fun setValue(newValue: Float) = error("not supported")
}
assertEquals(normalMap.entries.contains(independent), map.entries.contains(independent))
}
}
@Test
fun validateEntriesContainsAll() {
validateRead { map, normalMap ->
val normalOne = normalMap.entries.first()
val normalTwo = normalMap.entries.drop(1).first()
val one = map.entries.first()
val two = map.entries.drop(1).first()
assertEquals(
normalMap.entries.containsAll(listOf(normalOne, normalTwo)),
map.entries.containsAll(listOf(one, two))
)
assertEquals(
normalMap.entries.containsAll(listOf(one, two)),
map.entries.containsAll(listOf(normalOne, normalTwo))
)
val independentOne = object : MutableMap.MutableEntry<Int, Float> {
override val key = 1
override var value = 1f
override fun setValue(newValue: Float) = error("not supported")
}
val independentTwo = object : MutableMap.MutableEntry<Int, Float> {
override val key = 1
override var value = 1f
override fun setValue(newValue: Float) = error("not supported")
}
assertEquals(
normalMap.entries.containsAll(listOf(independentOne, independentTwo)),
map.entries.containsAll(listOf(independentOne, independentTwo))
)
}
}
@Test
fun validateEntriesRemove() {
validateWrite { map ->
map.entries.remove(map.entries.first())
}
}
@Test
fun validateEntriesRemoveAll() {
validateWrite { map ->
map.entries.removeAll(map.entries.filter { it.key % 2 == 0 })
}
}
@Test
fun validateEntriesRetainAll() {
validateWrite { map ->
map.entries.retainAll(map.entries.filter { it.key % 2 == 0 })
}
}
@Test
fun validateKeysSize() {
validateRead { map, normalMap ->
assertEquals(normalMap.keys.size, map.keys.size)
}
}
@Test
fun validateKeysClear() {
validateWrite { map ->
map.keys.clear()
}
}
@Test
fun validateKeysIsEmpty() {
validateRead { map, normalMap ->
assertEquals(normalMap.keys.isEmpty(), map.keys.isEmpty())
}
validateRead(mutableStateMapOf()) { map, normalMap ->
assertEquals(normalMap.keys.isEmpty(), map.keys.isEmpty())
}
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapKeysAdd() {
val map = mutableMapOf<Int, Float>()
map.keys.add(1)
}
@Test(expected = UnsupportedOperationException::class)
fun validateKeysAdd() {
val map = mutableStateMapOf<Int, Float>()
map.keys.add(1)
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapKeysAddAll() {
val map = mutableMapOf<Int, Float>()
map.keys.addAll(listOf(1, 2))
}
@Test(expected = UnsupportedOperationException::class)
fun validateKeysAddAll() {
val map = mutableStateMapOf<Int, Float>()
map.keys.addAll(listOf(1, 2))
}
@Test
fun validateKeysIterator() {
validateRead { map, normalMap ->
map.keys.zip(normalMap.keys).forEach {
assertEquals(it.second, it.first)
}
}
}
@Test
fun validateKeysRemove() {
validateWrite { map ->
map.keys.remove(1)
map.keys.remove(10)
}
}
@Test
fun validateKeysRemoveAll() {
validateWrite { map ->
map.keys.removeAll(map.keys.filter { it % 2 == 0 })
}
}
@Test
fun validateKeysRetainAll() {
validateWrite { map ->
map.keys.retainAll(map.keys.filter { it % 2 == 0 })
}
}
@Test
fun validateKeysContains() {
validateRead { map, normalMap ->
assertEquals(normalMap.keys.contains(1), map.keys.contains(1))
assertEquals(normalMap.keys.contains(100), map.keys.contains(100))
}
}
@Test
fun validateKeysContainsAll() {
validateRead { map, normalMap ->
val l1 = listOf(1, 2, 3)
val l2 = listOf(1, 2, 3, 100)
assertEquals(
normalMap.keys.containsAll(l1),
map.keys.containsAll(l1)
)
assertEquals(
normalMap.keys.containsAll(l2),
map.keys.containsAll(l2)
)
}
}
@Test
fun validateValuesSize() {
validateRead { map, normalMap ->
assertEquals(normalMap.values.size, map.values.size)
}
}
@Test
fun validateValuesClear() {
validateWrite { map ->
map.values.clear()
}
}
@Test
fun validateValuesIsEmpty() {
validateRead { map, normalMap ->
assertEquals(normalMap.values.isEmpty(), map.values.isEmpty())
}
validateRead(mutableStateMapOf()) { map, normalMap ->
assertEquals(normalMap.values.isEmpty(), map.values.isEmpty())
}
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapValuesAdd() {
val map = mutableMapOf<Int, Float>()
map.values.add(1f)
}
@Test(expected = UnsupportedOperationException::class)
fun validateValuesAdd() {
val map = mutableStateMapOf<Int, Float>()
map.values.add(1f)
}
@Test(expected = UnsupportedOperationException::class)
fun verifyMutableMapValuesAddAll() {
val map = mutableMapOf<Int, Float>()
map.values.addAll(listOf(1f, 2f))
}
@Test(expected = UnsupportedOperationException::class)
fun validateValuesAddAll() {
val map = mutableStateMapOf<Int, Float>()
map.values.addAll(listOf(1f, 2f))
}
@Test
fun validateValuesIterator() {
validateRead { map, normalMap ->
map.values.zip(normalMap.values).forEach {
assertEquals(it.second, it.first)
}
}
}
@Test
fun validateValuesRemove() {
validateWrite { map ->
map.values.remove(1f)
map.values.remove(10f)
}
}
@Test
fun validateValuesRemoveAll() {
validateWrite { map ->
map.values.removeAll(map.values.filter { it > 2f })
}
}
@Test
fun validateValuesRetainAll() {
validateWrite { map ->
map.values.retainAll(map.values.filter { it > 2f })
}
}
@Test
fun validateValuesContains() {
validateRead { map, normalMap ->
assertEquals(normalMap.values.contains(1f), map.values.contains(1f))
assertEquals(normalMap.values.contains(100f), map.values.contains(100f))
}
}
@Test
fun validateValuesContainsAll() {
validateRead { map, normalMap ->
val l1 = listOf(1f, 2f, 3f)
val l2 = listOf(1f, 2f, 3f, 100f)
assertEquals(
normalMap.values.containsAll(l1),
map.values.containsAll(l1)
)
assertEquals(
normalMap.values.containsAll(l2),
map.values.containsAll(l2)
)
}
}
@Test
fun validateClear() {
validateWrite { map ->
map.clear()
}
}
@Test
fun validatePut() {
validateWrite { map ->
assertEquals(null, map.put(10, 10f))
assertEquals(1f, map.put(1, 100f))
}
}
@Test
fun validatePutAll() {
validateWrite { map ->
map.putAll(listOf(1 to 20f, 100 to 100f))
}
}
@Test
fun validateRemove() {
validateWrite { map ->
assertEquals(1f, map.remove(1))
assertEquals(null, map.remove(100))
}
}
@OptIn(ExperimentalComposeApi::class)
@Test
fun validateMapsCanBeSnapshot() {
val map = defaultMap()
val snapshot = takeSnapshot()
try {
map[100] = 100f
assertTrue(map.contains(100))
snapshot.enter { assertFalse(map.contains(100)) }
} finally {
snapshot.dispose()
}
}
private fun validateRead(
initialMap: MutableMap<Int, Float> = defaultMap(),
block: (Map<Int, Float>, Map<Int, Float>) -> Unit
) {
validateMaps(initialMap) { map, normalMap ->
block(map, normalMap)
}
}
private fun validateWrite(
initialMap: MutableMap<Int, Float> = defaultMap(),
block: (MutableMap<Int, Float>) -> Unit
) {
validateMaps(initialMap) { map, normalMap ->
block(normalMap)
block(map)
expected(normalMap, map)
}
}
private fun validateMaps(
map: MutableMap<Int, Float> = defaultMap(),
block: (MutableMap<Int, Float>, MutableMap<Int, Float>) -> Unit
) {
val normalMap = map.toMutableMap()
block(map, normalMap)
}
private fun <K, V> expected(normalMap: Map<K, V>, map: Map<K, V>) {
assertEquals(normalMap.size, map.size)
for (entry in normalMap.entries) {
assertEquals(map[entry.key], entry.value)
}
}
private fun defaultMap() = mutableStateMapOf(
1 to 1f, 2 to 2f, 3 to 3f, 4 to 4f, 5 to 1f, 6 to 2f, 7 to 3f, 8 to 4f
)
}