[go: nahoru, domu]

blob: 52e4a71a4eeacdd3e1df1ba23ec92dcd580a8723 [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 java.lang.IllegalStateException
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue
import androidx.compose.runtime.ExperimentalComposeApi
import androidx.compose.runtime.mutableStateListOf
class SnapshotStateListTests {
@Test
fun canCreateAStateList() {
mutableStateListOf<Any>()
}
@Test
fun canCreateAStateListOfInts() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
list.forEachIndexed { index, item ->
assertEquals(index, item)
}
}
@Test
fun validateSize() {
val list = mutableStateListOf(0, 1, 2, 3)
assertEquals(4, list.size)
}
@Test
fun validateContains() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
(0..4).forEach {
assertTrue(list.contains(it))
}
assertFalse(list.contains(5))
}
@Test
fun validateContainsAll() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
assertTrue(list.containsAll(listOf(1, 2, 3)))
assertFalse(list.containsAll(listOf(0, 2, 3, 5)))
}
@Test
fun validateGet() {
val list = mutableStateListOf(0, 1, 2, 3)
(0..3).forEach { assertEquals(it, list[it]) }
}
@Test(expected = IndexOutOfBoundsException::class)
fun validateGet_IndexOutOfBound() {
val list = mutableStateListOf(0, 1, 2, 3)
list[4]
}
@Test
fun validateIsEmpty() {
val list = mutableStateListOf(0, 1, 2)
assertFalse(list.isEmpty())
val emptyList = mutableStateListOf<Any>()
assertTrue(emptyList.isEmpty())
}
@Test
fun validateIterator() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
var expected = 0
for (item in list) {
assertEquals(expected++, item)
}
assertEquals(5, expected)
}
@Test(expected = IllegalStateException::class)
fun validateIterator_remove() {
validate(mutableStateListOf(0, 1, 2, 3, 4)) { normalList ->
val iterator = normalList.iterator()
iterator.next()
iterator.next()
iterator.remove()
iterator.remove()
iterator.next()
iterator.remove()
}
}
@Test
fun validateLastIndexOf() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 0, 1, 2, 3, 4)
(0..4).forEach {
assertEquals(it + 5, list.lastIndexOf(it))
}
}
@Test
fun validateListIterator() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
val iterator = list.listIterator()
repeat(list.size) {
assertTrue(iterator.hasNext())
assertEquals(it, list[iterator.nextIndex()])
assertEquals(it, iterator.next())
}
assertFalse(iterator.hasNext())
repeat(list.size) {
assertTrue(iterator.hasPrevious())
assertEquals(list.size - it - 1, list[iterator.previousIndex()])
assertEquals(list.size - it - 1, iterator.previous())
}
assertFalse(iterator.hasPrevious())
}
@Test
fun validateListIterator_add() {
validate(mutableStateListOf(0, 1, 2, 3, 4, 5, 6)) { list ->
val iterator = list.listIterator()
iterator.next()
iterator.next()
iterator.add(100)
iterator.add(101)
iterator.next()
iterator.add(102)
iterator.previous()
iterator.previous()
iterator.add(103)
}
}
@Test
fun validateListIterator_mutationError_set() {
validate(mutableStateListOf(0, 1, 2, 3, 4)) { list ->
val iterator = list.listIterator()
iterator.next()
iterator.set(100)
iterator.next()
iterator.next()
iterator.set(101)
}
}
@Test
fun validateListIterator_index() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5)
val iterator = list.listIterator(3)
repeat(3) {
assertTrue(iterator.hasNext())
assertEquals(it + 3, iterator.next())
}
assertFalse(iterator.hasNext())
}
@Test
fun validate_subList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = listOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
val normalSubList = normalList.subList(2, 5)
expected(normalSubList, subList)
}
@Test
fun validate_subList_contains() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
assertFalse(subList.contains(0))
assertFalse(subList.contains(1))
assertTrue(subList.contains(2))
assertTrue(subList.contains(3))
assertTrue(subList.contains(4))
assertFalse(subList.contains(5))
assertFalse(subList.contains(6))
}
@Test
fun validate_subList_containsAll() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
assertTrue(subList.containsAll(listOf(2, 3, 4)))
assertFalse(subList.containsAll(listOf(2, 3, 4, 5)))
}
@Test
fun validate_subList_get() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
repeat(3) { assertEquals(it + 2, subList[it]) }
}
@Test(java.lang.IndexOutOfBoundsException::class)
fun validate_subList_get_outOfRange() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList[4]
}
@Test
fun validate_subList_indexOf() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
repeat(subList.size) {
assertEquals(it, subList.indexOf(it + 2))
}
assertEquals(-1, subList.indexOf(0))
assertEquals(-1, subList.indexOf(5))
}
@Test
fun validate_subList_add() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.add(100)
val normalSubList = normalList.subList(2, 5)
normalSubList.add(100)
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_add_index() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.add(1, 100)
val normalSubList = normalList.subList(2, 5)
normalSubList.add(1, 100)
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_addAll() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.addAll(listOf(100, 101, 102))
val normalSubList = normalList.subList(2, 5)
normalSubList.addAll(listOf(100, 101, 102))
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_addAll_index() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.addAll(1, listOf(100, 101, 102))
val normalSubList = normalList.subList(2, 5)
normalSubList.addAll(1, listOf(100, 101, 102))
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_clear() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.clear()
val normalSubList = normalList.subList(2, 5)
normalSubList.clear()
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_listIterator() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
val subList = list.subList(1, 4)
val iterator = subList.listIterator()
repeat(subList.size) {
assertTrue(iterator.hasNext())
assertEquals(it + 1, subList[iterator.nextIndex()])
assertEquals(it + 1, iterator.next())
}
assertFalse(iterator.hasNext())
repeat(subList.size) {
assertTrue(iterator.hasPrevious())
val expectedIndex = subList.size - it - 1
assertEquals(expectedIndex + 1, subList[iterator.previousIndex()])
assertEquals(expectedIndex + 1, iterator.previous())
}
assertFalse(iterator.hasPrevious())
}
@Test(expected = IllegalStateException::class)
fun validate_subList_listIterator_add() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
val subList = list.subList(1, 4)
val iterator = subList.listIterator()
iterator.next()
iterator.add(1)
}
@Test(expected = IllegalStateException::class)
fun validate_subList_listIterator_remove() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
val subList = list.subList(1, 4)
val iterator = subList.listIterator()
iterator.next()
iterator.remove()
}
@Test(expected = IllegalStateException::class)
fun validate_subList_listIterator_set() {
val list = mutableStateListOf(0, 1, 2, 3, 4)
val subList = list.subList(1, 4)
val iterator = subList.listIterator()
iterator.next()
iterator.set(1)
}
@Test
fun validate_subList_remove() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.remove(3)
val normalSubList = normalList.subList(2, 5)
normalSubList.remove(3)
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_removeAll() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.removeAll(listOf(2, 3))
val normalSubList = normalList.subList(2, 5)
normalSubList.removeAll(listOf(2, 3))
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_removeAt() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(2, 5)
subList.removeAt(1)
val normalSubList = normalList.subList(2, 5)
normalSubList.removeAt(1)
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_retainAll() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(1, 6)
subList.retainAll(listOf(2, 4, 6, 8))
val normalSubList = normalList.subList(1, 6)
normalSubList.retainAll(listOf(2, 4, 6, 8))
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_set() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(1, 6)
subList[1] = 100
val normalSubList = normalList.subList(1, 6)
normalSubList[1] = 100
expected(normalSubList, subList)
expected(normalList, list)
}
@Test
fun validate_subList_subList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
val subList = list.subList(1, 6)
val subListSubList = subList.subList(1, 3)
val normalSubList = normalList.subList(1, 6)
val normalSubListSubList = normalSubList.subList(1, 3)
expected(normalSubListSubList, subListSubList)
expected(normalSubList, subList)
expected(normalList, list)
}
@Test(expected = ConcurrentModificationException::class)
fun validate_subList_concurrentChanges() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val subList1 = list.subList(1, 6)
val subList2 = list.subList(1, 6)
subList1.remove(3)
subList2.remove(4)
}
@Test
fun validate_indexOf() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6, 7)
(0..7).forEach { assertEquals(it, list.indexOf(it)) }
assertEquals(-1, list.indexOf(10))
}
@Test
fun canModifyAStateList_add() {
val list = mutableStateListOf(0, 1, 2)
list.add(3)
assertEquals(4, list.size)
list.forEachIndexed { index, item ->
assertEquals(index, item)
}
}
@Test
fun canModifyAStateList_addIndex() {
val list = mutableStateListOf(0, 1, 2)
list.add(0, 3)
assertEquals(4, list.size)
assertEquals(3, list[0])
}
@Test
fun canRemoveFromAStateList() {
val list = mutableStateListOf(0, 1, 2)
list.remove(1)
assertEquals(2, list.size)
assertEquals(0, list[0])
assertEquals(2, list[1])
}
@Test
fun canRemoveAllFromAStateList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5)
list.removeAll(listOf(2, 4))
normalList.removeAll(listOf(2, 4))
expected(normalList, list)
}
@Test
fun canRemoveAtFromAStateList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5)
list.removeAt(2)
normalList.removeAt(2)
expected(normalList, list)
}
@Test
fun canRetainAllOfAStateList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
list.retainAll(listOf(2, 4, 6, 8))
normalList.retainAll(listOf(2, 4, 6, 8))
expected(normalList, list)
}
@Test
fun canSetAnElementOfAStateList() {
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val normalList = mutableListOf(0, 1, 2, 3, 4, 5, 6)
list[2] = 100
normalList[2] = 100
expected(normalList, list)
}
@OptIn(ExperimentalComposeApi::class)
@Test
fun stateListsCanBeSnapshot() {
val original = listOf(0, 1, 2, 3, 4, 5, 6)
val mutableList = original.toMutableList()
val list = mutableStateListOf(0, 1, 2, 3, 4, 5, 6)
val snapshot = takeSnapshot()
try {
list[1] = 100
mutableList[1] = 100
expected(mutableList, list)
snapshot.enter {
expected(original, list)
}
} finally {
snapshot.dispose()
}
expected(mutableList, list)
}
private fun <T> validate(list: MutableList<T>, block: (list: MutableList<T>) -> Unit) {
val normalList = list.toMutableList()
block(normalList)
block(list)
expected(normalList, list)
}
private fun <T> expected(expected: List<T>, actual: List<T>) {
assertEquals(expected.size, actual.size)
(0 until expected.size).forEach {
assertEquals(expected[it], actual[it])
}
}
}