Skip to content

Commit 133372f

Browse files
author
Abduqodiri Qurbonzoda
committed
Add tests from guava-testlib
1 parent 0faa1c7 commit 133372f

File tree

8 files changed

+821
-0
lines changed

8 files changed

+821
-0
lines changed

kotlinx-collections-immutable/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ dependencies {
4444
project('tests') {
4545
dependencies {
4646
compile project(path: ':kotlinx-collections-immutable', configuration: 'shadow')
47+
testCompile 'com.google.guava:guava-testlib:18.0'
4748
}
4849
}
4950

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.contractTests
18+
19+
import com.google.common.collect.testing.testers.CollectionClearTester
20+
import com.google.common.collect.testing.testers.ListRemoveAtIndexTester
21+
import com.google.common.collect.testing.testers.ListSubListTester
22+
import junit.framework.*
23+
24+
open class GuavaImmutableCollectionBaseTest: TestListener {
25+
override fun addFailure(test: Test, e: AssertionFailedError) = throw e
26+
override fun addError(test: Test, e: Throwable) {
27+
if (e is ConcurrentModificationException
28+
&& test is ListSubListTester<*>
29+
&& test.testMethodName in listOf("testSubList_originalListSetAffectsSubList", "testSubList_originalListSetAffectsSubListLargeList")) {
30+
// These test cases check that changes in sublist are reflected in backed list, and vice-versa.
31+
// Backed list is structurally modified due to `set` function invocation,
32+
// leading to CME when `sublist.listIterator()` gets invoked to iterate elements of sublist to make sure changes are reflected.
33+
// The `sublist.listIterator()` method has the comodification check.
34+
//
35+
// The guava-testlib doesn't expect any exceptions to be thrown,
36+
// despite `List.subList` javadoc statement "The semantics of the list returned by this method become undefined" is such case.
37+
return
38+
}
39+
if (e is NoSuchElementException
40+
// Removing the only element from the sublist and calling `next()` on it's earlier created iterator throws NSEE.
41+
&& (test is ListRemoveAtIndexTester<*> && test.testMethodName == "testRemoveAtIndexConcurrentWithIteration"
42+
// Removing all elements from the sublist and calling `next()` on it's earlier created iterator throws NSEE.
43+
|| test is CollectionClearTester<*> && test.testMethodName == "testClearConcurrentWithIteration")) {
44+
// These test cases check that sublist iterator is fail-fast.
45+
//
46+
// `AbstractList` implementation of sublist iterator is not fail-fast.
47+
// Seems we need to override the `subList()` method in `PersistentVectorBuilder`
48+
// to return custom sublist implementation with fail-fast iterator.
49+
return
50+
}
51+
throw e
52+
}
53+
override fun startTest(test: Test) { }
54+
override fun endTest(test: Test) { }
55+
56+
fun runTestSuite(suite: TestSuite) {
57+
for (t in suite.tests()) {
58+
val r = TestResult()
59+
r.addListener(this)
60+
t.run(r)
61+
}
62+
}
63+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.contractTests.immutableList
18+
19+
import com.google.common.collect.testing.ListTestSuiteBuilder
20+
import com.google.common.collect.testing.TestListGenerator
21+
import com.google.common.collect.testing.features.CollectionFeature
22+
import com.google.common.collect.testing.features.CollectionSize
23+
import com.google.common.collect.testing.features.ListFeature
24+
import kotlinx.collections.immutable.contractTests.GuavaImmutableCollectionBaseTest
25+
import kotlinx.collections.immutable.contractTests.immutableList.PersistentListGenerator.PList
26+
import kotlin.test.Test
27+
28+
class GuavaImmutableListTest: GuavaImmutableCollectionBaseTest() {
29+
private fun <E> runImmutableListTestsUsing(generator: TestListGenerator<E>) {
30+
ListTestSuiteBuilder
31+
.using(generator)
32+
.named(generator.javaClass.simpleName)
33+
.withFeatures(
34+
CollectionSize.ANY,
35+
CollectionFeature.ALLOWS_NULL_VALUES
36+
)
37+
.createTestSuite()
38+
.run { runTestSuite(this) }
39+
40+
}
41+
42+
private fun <E> runMutableListTestsUsing(generator: TestListGenerator<E>) {
43+
ListTestSuiteBuilder
44+
.using(generator)
45+
.named(generator.javaClass.simpleName)
46+
.withFeatures(
47+
CollectionSize.ANY,
48+
CollectionFeature.ALLOWS_NULL_VALUES,
49+
CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
50+
ListFeature.GENERAL_PURPOSE
51+
)
52+
.createTestSuite()
53+
.run { runTestSuite(this) }
54+
55+
}
56+
57+
@Test
58+
fun list() {
59+
listOf(
60+
PList.Of,
61+
PList.AddAll,
62+
PList.AddEach,
63+
PList.MutateAddAll,
64+
PList.MutateAddEach,
65+
PList.HeadSubList,
66+
PList.TailSubList,
67+
PList.MiddleSubList
68+
).forEach {
69+
runImmutableListTestsUsing(it)
70+
}
71+
}
72+
73+
@Test
74+
fun listBuilder() {
75+
listOf(
76+
PList.Builder.Of,
77+
PList.Builder.AddAll,
78+
PList.Builder.AddEach,
79+
PList.Builder.AddAt,
80+
PList.Builder.HeadSubList,
81+
PList.Builder.TailSubList,
82+
PList.Builder.MiddleSubList
83+
).forEach {
84+
runMutableListTestsUsing(it)
85+
}
86+
}
87+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/*
2+
* Copyright 2016-2019 JetBrains s.r.o.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package kotlinx.collections.immutable.contractTests.immutableList
18+
19+
import com.google.common.collect.testing.TestStringListGenerator
20+
import kotlinx.collections.immutable.mutate
21+
import kotlinx.collections.immutable.persistentListOf
22+
23+
class PersistentListGenerator {
24+
object PList {
25+
object Of : TestStringListGenerator() {
26+
override fun create(elements: Array<out String>): List<String> {
27+
return persistentListOf(*elements)
28+
}
29+
}
30+
31+
object AddAll : TestStringListGenerator() {
32+
override fun create(elements: Array<out String>): List<String> {
33+
return persistentListOf<String>().addAll(elements.toList())
34+
}
35+
}
36+
37+
object AddEach : TestStringListGenerator() {
38+
override fun create(elements: Array<out String>): List<String> {
39+
return elements.fold(persistentListOf()) { list, element -> list.add(element) }
40+
}
41+
}
42+
43+
object MutateAddAll : TestStringListGenerator() {
44+
override fun create(elements: Array<out String>): List<String> {
45+
return persistentListOf<String>().mutate { it.addAll(elements.toList()) }
46+
}
47+
}
48+
49+
object MutateAddEach : TestStringListGenerator() {
50+
override fun create(elements: Array<out String>): List<String> {
51+
return persistentListOf<String>().mutate { list -> elements.forEach { list.add(it) } }
52+
}
53+
}
54+
55+
object HeadSubList : TestStringListGenerator() {
56+
override fun create(elements: Array<out String>): List<String> {
57+
val suffix = arrayOf("f", "g")
58+
val all = Array(elements.size + suffix.size) {
59+
if (it < elements.size) elements[it] else suffix[it - elements.size]
60+
}
61+
return persistentListOf<String>().addAll(all.toList())
62+
.subList(0, elements.size)
63+
}
64+
}
65+
66+
object TailSubList : TestStringListGenerator() {
67+
override fun create(elements: Array<String>): List<String> {
68+
val prefix = arrayOf("f", "g")
69+
val all = Array(elements.size + prefix.size) {
70+
if (it < prefix.size) prefix[it] else elements[it - prefix.size]
71+
}
72+
return persistentListOf<String>().addAll(all.toList())
73+
.subList(2, elements.size + 2)
74+
}
75+
}
76+
77+
object MiddleSubList : TestStringListGenerator() {
78+
override fun create(elements: Array<String>): List<String> {
79+
val prefix = arrayOf("f", "g")
80+
val suffix = arrayOf("h", "i")
81+
82+
val all = arrayOfNulls<String>(2 + elements.size + 2)
83+
System.arraycopy(prefix, 0, all, 0, 2)
84+
System.arraycopy(elements, 0, all, 2, elements.size)
85+
System.arraycopy(suffix, 0, all, 2 + elements.size, 2)
86+
87+
return persistentListOf<String>().addAll(all.toList() as List<String>)
88+
.subList(2, elements.size + 2)
89+
}
90+
}
91+
92+
93+
object Builder {
94+
object Of : TestStringListGenerator() {
95+
override fun create(elements: Array<out String>): MutableList<String> {
96+
return persistentListOf(*elements).builder()
97+
}
98+
}
99+
100+
object AddAll : TestStringListGenerator() {
101+
override fun create(elements: Array<out String>): MutableList<String> {
102+
return persistentListOf<String>().builder().apply { this.addAll(elements.toList()) }
103+
}
104+
}
105+
106+
object AddEach : TestStringListGenerator() {
107+
override fun create(elements: Array<out String>): MutableList<String> {
108+
return persistentListOf<String>().builder().apply { elements.forEach { this.add(it) } }
109+
}
110+
}
111+
112+
object AddAt : TestStringListGenerator() {
113+
override fun create(elements: Array<out String>): MutableList<String> {
114+
val builder = persistentListOf<String>().builder()
115+
116+
val list = elements.mapIndexed { i, e -> Pair(i, e) }.toMutableList().apply { shuffle() }
117+
list.forEachIndexed { index, pair ->
118+
val preceded = list.subList(0, index).count { it.first < pair.first }
119+
builder.add(preceded, pair.second)
120+
}
121+
122+
return builder
123+
}
124+
}
125+
126+
object HeadSubList : TestStringListGenerator() {
127+
override fun create(elements: Array<out String>): MutableList<String> {
128+
val suffix = arrayOf("f", "g")
129+
val all = Array(elements.size + suffix.size) {
130+
if (it < elements.size) elements[it] else suffix[it - elements.size]
131+
}
132+
return persistentListOf<String>().builder().apply { addAll(all.toList()) }
133+
.subList(0, elements.size)
134+
}
135+
}
136+
137+
object TailSubList : TestStringListGenerator() {
138+
override fun create(elements: Array<String>): MutableList<String> {
139+
val prefix = arrayOf("f", "g")
140+
val all = Array(elements.size + prefix.size) {
141+
if (it < prefix.size) prefix[it] else elements[it - prefix.size]
142+
}
143+
return persistentListOf<String>().builder().apply { addAll(all.toList()) }
144+
.subList(2, elements.size + 2)
145+
}
146+
}
147+
148+
object MiddleSubList : TestStringListGenerator() {
149+
override fun create(elements: Array<String>): MutableList<String> {
150+
val prefix = arrayOf("f", "g")
151+
val suffix = arrayOf("h", "i")
152+
153+
val all = arrayOfNulls<String>(2 + elements.size + 2)
154+
System.arraycopy(prefix, 0, all, 0, 2)
155+
System.arraycopy(elements, 0, all, 2, elements.size)
156+
System.arraycopy(suffix, 0, all, 2 + elements.size, 2)
157+
158+
return persistentListOf<String>().builder().apply { addAll(all.toList() as List<String>) }
159+
.subList(2, elements.size + 2)
160+
}
161+
}
162+
}
163+
}
164+
}

0 commit comments

Comments
 (0)