[K/N] Migrate runtime/atomics tests to new testing infra ^KT-61259

This commit is contained in:
Alexander Shabalin
2023-08-30 18:10:34 +02:00
committed by Space Team
parent ba374bb45c
commit 2f22b0a6b0
12 changed files with 1028 additions and 1242 deletions
@@ -0,0 +1,570 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.concurrent
import kotlin.concurrent.*
import kotlin.test.*
class AtomicIntArrayTest {
@Test fun ctor() {
val arr1 = AtomicIntArray(6)
assertEquals(arr1[4], 0)
assertEquals(arr1.length, 6)
val arr2 = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(arr2[4], 40)
assertEquals(arr2.length, 10)
val emptyArr = AtomicIntArray(0)
assertEquals(emptyArr.length, 0)
assertFailsWith<IllegalArgumentException> {
val arrNegativeSize = AtomicIntArray(-5)
}
}
@Test fun getter() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
for (i in 0 until atomicIntArr.length) {
assertEquals(i * 10, atomicIntArr[i], "getter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr[22]
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr[-1]
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun setter() {
val atomicIntArr = AtomicIntArray(10)
for (i in 0 until atomicIntArr.length) {
atomicIntArr[i] = i * 10
}
for (i in 0 until atomicIntArr.length) {
assertEquals(i * 10, atomicIntArr[i], "setter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
atomicIntArr[22] = 100
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
atomicIntArr[-1] = 100
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun addAndGet() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(110, atomicIntArr.addAndGet(1, 100), "addAndGet: FAIL 1")
assertEquals(110, atomicIntArr[1], "addAndGet: FAIL 2")
assertEquals(10, atomicIntArr.addAndGet(1, -100), "addAndGet: FAIL 3")
assertEquals(10, atomicIntArr[1], "addAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.addAndGet(22, 33535)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.addAndGet(-1, 33535)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun compareAndExchange() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
val res1 = atomicIntArr.compareAndExchange(2, 20, 222) // success
assertTrue(res1 == 20 && atomicIntArr[2] == 222, "compareAndExchange: FAIL 1")
val res2 = atomicIntArr.compareAndExchange(2, 222, 2222) // success
assertTrue(res2 == 222 && atomicIntArr[2] == 2222, "compareAndExchange: FAIL 2")
val res3 = atomicIntArr.compareAndExchange(2, 223, 22222) // should fail
assertTrue(res3 == 2222 && atomicIntArr[2] == 2222, "compareAndExchange: FAIL 3")
val res4 = atomicIntArr.compareAndExchange(9, 10, 999) // should fail
assertTrue(res4 == 90 && atomicIntArr[9] == 90, "compareAndExchange: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.compareAndExchange(10, 33535, 39530)
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.compareAndExchange(-1, 33535, 39530)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun compareAndSet() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
val res1 = atomicIntArr.compareAndSet(2, 20, 222) // success
assertTrue(res1 && atomicIntArr[2] == 222, "compareAndSet: FAIL 1")
val res2 = atomicIntArr.compareAndSet(2, 222, 2222) // success
assertTrue(res2 && atomicIntArr[2] == 2222, "compareAndSet: FAIL 2")
val res3 = atomicIntArr.compareAndSet(2, 223, 22222) // should fail
assertTrue(!res3 && atomicIntArr[2] == 2222, "compareAndSet: FAIL 3")
val res4 = atomicIntArr.compareAndSet(9, 10, 999) // should fail
assertTrue(!res4 && atomicIntArr[9] == 90, "compareAndSet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.compareAndSet(10, 33535, 39530)
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.compareAndSet(-1, 33535, 39530)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun getAndSet() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(20, atomicIntArr.getAndSet(2, 200), "getAndSet: FAIL 1")
assertEquals(200, atomicIntArr.getAndSet(2, 2000), "getAndSet: FAIL 2")
assertEquals(2000, atomicIntArr[2], "getAndSet: FAIL 3")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndSet(22, 33535)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndSet(-1, 33535)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun getAndAdd() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(10, atomicIntArr.getAndAdd(1, 100), "getAndAdd: FAIL 1")
assertEquals(110, atomicIntArr[1], "getAndAdd: FAIL 2")
assertEquals(110, atomicIntArr.getAndAdd(1, -100), "getAndAdd: FAIL 3")
assertEquals(10, atomicIntArr[1], "getAndAdd: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndAdd(22, 33535)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndAdd(-1, 33535)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun getAndIncrement() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(10, atomicIntArr.getAndIncrement(1), "getAndIncrement: FAIL 1")
assertEquals(11, atomicIntArr[1], "getAndIncrement: FAIL 2")
assertEquals(11, atomicIntArr.getAndIncrement(1), "getAndIncrement: FAIL 3")
assertEquals(12, atomicIntArr[1], "getAndIncrement: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndIncrement(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndIncrement(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun incrementAndGet() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(11, atomicIntArr.incrementAndGet(1), "incrementAndGet: FAIL 1")
assertEquals(11, atomicIntArr[1], "incrementAndGet: FAIL 2")
assertEquals(12, atomicIntArr.incrementAndGet(1), "incrementAndGet: FAIL 3")
assertEquals(12, atomicIntArr[1], "incrementAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.incrementAndGet(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.incrementAndGet(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun getAndDecrement() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(10, atomicIntArr.getAndDecrement(1), "getAndDecrement: FAIL 1")
assertEquals(9, atomicIntArr[1], "getAndDecrement: FAIL 2")
assertEquals(9, atomicIntArr.getAndDecrement(1), "getAndDecrement: FAIL 3")
assertEquals(8, atomicIntArr[1], "getAndDecrement: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndDecrement(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.getAndDecrement(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
@Test fun decrementAndGet() {
val atomicIntArr = AtomicIntArray(10) { i: Int -> i * 10 }
assertEquals(9, atomicIntArr.decrementAndGet(1), "decrementAndGet: FAIL 1")
assertEquals(9, atomicIntArr[1], "decrementAndGet: FAIL 2")
assertEquals(8, atomicIntArr.decrementAndGet(1), "decrementAndGet: FAIL 3")
assertEquals(8, atomicIntArr[1], "decrementAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.decrementAndGet(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicIntArr.decrementAndGet(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicIntArray with size 10.", ex.message)
}
}
}
class AtomicLongArrayTest {
@Test fun ctor() {
val arr1 = AtomicLongArray(6)
assertEquals(arr1[4], 0L)
assertEquals(arr1.length, 6)
val arr2 = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(arr2[4], 40L)
assertEquals(arr2.length, 10)
val emptyArr = AtomicLongArray(0)
assertEquals(emptyArr.length, 0)
assertFailsWith<IllegalArgumentException> {
val arrNegativeSize = AtomicLongArray(-5)
}
}
@Test fun getter() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
for (i in 0 until atomicLongArr.length) {
assertEquals(i * 10L, atomicLongArr[i], "getter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr[22]
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr[-1]
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun setter() {
val atomicLongArr = AtomicLongArray(10)
for (i in 0 until atomicLongArr.length) {
atomicLongArr[i] = i * 10L
}
for (i in 0 until atomicLongArr.length) {
assertEquals(i * 10L, atomicLongArr[i], "setter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr[10] = 3998009
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr[-1] = 3998009
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun addAndGet() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(110L, atomicLongArr.addAndGet(1, 100L), "addAndGet: FAIL 1")
assertEquals(110L, atomicLongArr[1], "addAndGet: FAIL 2")
assertEquals(10L, atomicLongArr.addAndGet(1, -100L), "addAndGet: FAIL 3")
assertEquals(10L, atomicLongArr[1], "addAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.addAndGet(22, 33535)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.addAndGet(-1, 33535)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun compareAndExchange() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
val res1 = atomicLongArr.compareAndExchange(2, 20L, 222L) // success
assertTrue(res1 == 20L && atomicLongArr[2] == 222L, "compareAndExchange: FAIL 1")
val res2 = atomicLongArr.compareAndExchange(2, 222L, 2222L) // success
assertTrue(res2 == 222L && atomicLongArr[2] == 2222L, "compareAndExchange: FAIL 2")
val res3 = atomicLongArr.compareAndExchange(2, 223L, 22222L) // should fail
assertTrue(res3 == 2222L && atomicLongArr[2] == 2222L, "compareAndExchange: FAIL 3")
val res4 = atomicLongArr.compareAndExchange(9, 10L, 999L) // should fail
assertTrue(res4 == 90L && atomicLongArr[9] == 90L, "compareAndExchange: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr.compareAndExchange(10, 9353, 39058308)
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr.compareAndExchange(-1, 9353, 39058308)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun compareAndSet() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
val res1 = atomicLongArr.compareAndSet(2, 20L, 222L) // success
assertTrue(res1 && atomicLongArr[2] == 222L, "compareAndSet: FAIL 1")
val res2 = atomicLongArr.compareAndSet(2, 222L, 2222L) // success
assertTrue(res2 && atomicLongArr[2] == 2222L, "compareAndSet: FAIL 2")
val res3 = atomicLongArr.compareAndSet(2, 223L, 22222L) // should fail
assertTrue(!res3 && atomicLongArr[2] == 2222L, "compareAndSet: FAIL 3")
val res4 = atomicLongArr.compareAndSet(9, 10L, 999L) // should fail
assertTrue(!res4 && atomicLongArr[9] == 90L, "compareAndSet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr.compareAndSet(10, 9353, 39058308)
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
atomicLongArr.compareAndSet(-1, 9353, 39058308)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun getAndSet() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(20L, atomicLongArr.getAndSet(2, 200L), "getAndSet: FAIL 1")
assertEquals(200L, atomicLongArr.getAndSet(2, 2000L), "getAndSet: FAIL 2")
assertEquals(2000L, atomicLongArr[2], "getAndSet: FAIL 3")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndSet(22, 9353)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndSet(-1, 9353)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun getAndAdd() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(10L, atomicLongArr.getAndAdd(1, 100L), "getAndAdd: FAIL 1")
assertEquals(110L, atomicLongArr[1], "getAndAdd: FAIL 2")
assertEquals(110L, atomicLongArr.getAndAdd(1, -100L), "getAndAdd: FAIL 3")
assertEquals(10L, atomicLongArr[1], "getAndAdd: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndAdd(100, 9353)
}.let { ex ->
assertEquals("The index 100 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndAdd(-1, 9353)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun getAndIncrement() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(10L, atomicLongArr.getAndIncrement(1), "getAndIncrement: FAIL 1")
assertEquals(11L, atomicLongArr[1], "getAndIncrement: FAIL 2")
assertEquals(11L, atomicLongArr.getAndIncrement(1), "getAndIncrement: FAIL 3")
assertEquals(12L, atomicLongArr[1], "getAndIncrement: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndIncrement(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.addAndGet(-1, 33535)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun incrementAndGet() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(11L, atomicLongArr.incrementAndGet(1), "incrementAndGet: FAIL 1")
assertEquals(11L, atomicLongArr[1], "incrementAndGet: FAIL 2")
assertEquals(12L, atomicLongArr.incrementAndGet(1), "incrementAndGet: FAIL 3")
assertEquals(12L, atomicLongArr[1], "incrementAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.incrementAndGet(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.incrementAndGet(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun getAndDecrement() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(10L, atomicLongArr.getAndDecrement(1), "getAndDecrement: FAIL 1")
assertEquals(9L, atomicLongArr[1], "getAndDecrement: FAIL 2")
assertEquals(9L, atomicLongArr.getAndDecrement(1), "getAndDecrement: FAIL 3")
assertEquals(8L, atomicLongArr[1], "getAndDecrement: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndDecrement(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.getAndDecrement(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
@Test fun decrementAndGet() {
val atomicLongArr = AtomicLongArray(10) { i: Int -> i * 10L }
assertEquals(9L, atomicLongArr.decrementAndGet(1), "decrementAndGet: FAIL 1")
assertEquals(9L, atomicLongArr[1], "decrementAndGet: FAIL 2")
assertEquals(8L, atomicLongArr.decrementAndGet(1), "decrementAndGet: FAIL 3")
assertEquals(8L, atomicLongArr[1], "decrementAndGet: FAIL 4")
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.decrementAndGet(22)
}.let { ex ->
assertEquals("The index 22 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = atomicLongArr.decrementAndGet(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicLongArray with size 10.", ex.message)
}
}
}
class AtomicArrayTest {
@Test fun ctor() {
val arr2 = AtomicArray<Data?>(10) { null }
assertEquals(arr2[4], null)
assertEquals(arr2.length, 10)
val emptyArr = AtomicArray<Data?>(0) { Data(1) }
assertEquals(emptyArr.length, 0)
assertFailsWith<IllegalArgumentException> {
val arrNegativeSize = AtomicArray<Data?>(-5) { Data(1) }
}
}
@Test fun getter() {
val refArr = AtomicArray<Data?>(10) { i -> Data(i) }
for (i in 0 until refArr.length) {
assertEquals(Data(i), refArr[i], "getter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
val res = refArr[100]
}.let { ex ->
assertEquals("The index 100 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
val res = refArr[-1]
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
}
@Test fun setter() {
val refArr = AtomicArray<Data?>(10) { null }
for (i in 0 until refArr.length) {
refArr[i] = Data(i)
}
for (i in 0 until refArr.length) {
assertEquals(Data(i), refArr[i], "setter: FAIL $i")
}
assertFailsWith<IndexOutOfBoundsException> {
refArr[100] = Data(100)
}.let { ex ->
assertEquals("The index 100 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
refArr[-1] = Data(-1)
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
}
@Test fun compareAndExchange() {
val refArr = AtomicArray<Data?>(10) { null }
val newValue = Data(1)
val res1 = refArr.compareAndExchange(3, null, newValue)
assertTrue(res1 == null && refArr[3] == newValue, "compareAndExchange: FAIL 1")
val res2 = refArr.compareAndExchange(3, newValue, Data(2))
assertTrue(res2 == newValue && refArr[3] == Data(2), "compareAndExchange: FAIL 2")
val res3 = refArr.compareAndExchange(3, newValue, Data(3))
assertTrue(res3 == Data(2) && refArr[3] == Data(2), "compareAndExchange: FAIL 3")
assertFailsWith<IndexOutOfBoundsException> {
refArr.compareAndExchange(10, newValue, Data(4))
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
refArr.compareAndExchange(-1, newValue, Data(4))
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
}
@Test fun compareAndSet() {
val refArr = AtomicArray<Data?>(10) { null }
val newValue = Data(1)
val res1 = refArr.compareAndSet(3, null, newValue)
assertTrue(res1 && refArr[3] == newValue, "testAtomicArrayCompareAndSet: FAIL 1")
val res2 = refArr.compareAndSet(3, newValue, Data(2))
assertTrue(res2 && refArr[3] == Data(2), "testAtomicArrayCompareAndSet: FAIL 2")
val res3 = refArr.compareAndSet(3, newValue, Data(3))
assertTrue(!res3 && refArr[3] == Data(2), "testAtomicArrayCompareAndSet: FAIL 3")
assertFailsWith<IndexOutOfBoundsException> {
refArr.compareAndSet(10, newValue, Data(4))
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
refArr.compareAndSet(-1, newValue, Data(4))
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
}
@Test fun getAndSet() {
val refArr = AtomicArray<Data?>(10) { null }
val res4 = refArr.getAndSet(4, Data(1))
assertEquals(null, res4, "getAndSet: FAIL 1")
val res5 = refArr.getAndSet(4, Data(2))
assertEquals(Data(1), res5, "getAndSet: FAIL 2")
assertFailsWith<IndexOutOfBoundsException> {
refArr.getAndSet(10, Data(1))
}.let { ex ->
assertEquals("The index 10 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
assertFailsWith<IndexOutOfBoundsException> {
refArr.getAndSet(-1, Data(1))
}.let { ex ->
assertEquals("The index -1 is out of the bounds of the AtomicArray with size 10.", ex.message)
}
}
}
@@ -0,0 +1,238 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.concurrent
import kotlin.concurrent.*
import kotlin.native.concurrent.Future
import kotlin.native.concurrent.TransferMode
import kotlin.native.concurrent.Worker
import kotlin.test.*
object ThreadPool {
private var _workers: Array<Worker>? = null
public fun init(threadCount: Int) {
_workers = Array(threadCount) { Worker.start() }
}
public fun deinit() {
_workers?.forEach {
it.requestTermination().result
}
_workers = null
}
public fun <T> execute(f: (Int) -> T): List<Future<T>> = _workers?.mapIndexed { index, worker ->
worker.execute(TransferMode.SAFE, { Pair(f, index) }) { (f, index) ->
f(index)
}
} ?: error("Call ThreadPool.init() first")
}
class AtomicIntStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun addAndGet() {
val atomic = AtomicInt(10)
val futures = ThreadPool.execute {
atomic.addAndGet(1000)
}
futures.forEach {
it.result
}
assertEquals(10 + 1000 * futures.size, atomic.value)
}
@Test fun incrementAndGet() {
val initial = 15
val atomic = AtomicInt(initial)
val futures = ThreadPool.execute {
atomic.incrementAndGet()
}
futures.forEach {
it.result
}
assertEquals(initial + futures.size, atomic.value)
}
@Test fun mutex() {
val place = AtomicInt(1)
val counter = AtomicInt(0)
val futures = ThreadPool.execute { index ->
// Here we simulate mutex using [place] location to store tag of the current worker.
// When it is negative - worker executes exclusively.
val tag = index + 1
while (place.compareAndExchange(tag, -tag) != tag) {}
assertEquals(index + 1, counter.incrementAndGet())
// Now, let the next worker run.
val previousPlace = place.compareAndExchange(-tag, tag + 1)
assertEquals(-tag, previousPlace)
}
futures.forEach {
it.result
}
assertEquals(futures.size, counter.value)
}
}
class AtomicLongStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun addAndGet() {
val atomic = AtomicLong(10L)
val futures = ThreadPool.execute {
atomic.addAndGet(9999999999)
}
futures.forEach {
it.result
}
assertEquals(10L + 9999999999 * futures.size, atomic.value)
}
}
private class LockFreeStack<T> {
private val top = AtomicReference<Node<T>?>(null)
private class Node<T>(val value: T, val next: Node<T>?)
fun isEmpty(): Boolean = top.value == null
fun push(value: T) {
while(true) {
val cur = top.value
val upd = Node(value, cur)
if (top.compareAndSet(cur, upd)) return
}
}
fun pop(): T? {
while(true) {
val cur = top.value
if (cur == null) return null
if (top.compareAndSet(cur, cur.next)) return cur.value
}
}
}
class AtomicStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun mutex() {
val common = AtomicReference<Data?>(null)
val futures = ThreadPool.execute { index ->
// Try to publish our own data, until successful, in a tight loop.
while (!common.compareAndSet(null, Data(index))) {}
}
val seen = mutableListOf<Int>()
futures.forEach {
while(true) {
val current = common.value ?: continue
// Each worker publishes exactly once
assertFalse(seen.contains(current.value))
seen.add(current.value)
// Let others publish.
common.compareAndExchange(current, null)
break
}
}
futures.forEach {
it.result
}
assertContentEquals(futures.indices, seen.sorted())
}
@Test fun stackConcurrentPush() {
val stack = LockFreeStack<Int>()
val writers = ThreadPool.execute {
stack.push(it)
}
writers.forEach { it.result }
val seen = mutableSetOf<Int>()
while(!stack.isEmpty()) {
val value = stack.pop()
assertNotNull(value)
seen.add(value)
}
assertEquals(writers.size, seen.size)
}
}
class AtomicIntArrayStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun incrementAndGet() {
val intArr = AtomicIntArray(10)
val futures = ThreadPool.execute {
for (i in 0 until 500) {
val index = (0 until intArr.length).random()
intArr.incrementAndGet(index)
}
}
futures.forEach {
it.result
}
var sum = 0
for (i in 0 until intArr.length) {
sum += intArr[i]
}
assertEquals(futures.size * 500, sum)
}
}
class AtomicLongArrayStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun incrementAndGet() {
val longArr = AtomicLongArray(10)
val futures = ThreadPool.execute {
for (i in 0 until 500) {
val index = (0 until longArr.length).random()
longArr.incrementAndGet(index)
}
}
futures.forEach {
it.result
}
var sum = 0L
for (i in 0 until longArr.length) {
sum += longArr[i]
}
assertEquals(futures.size.toLong() * 500, sum)
}
}
class AtomicArrayStressTest {
@BeforeTest fun init() = ThreadPool.init(20)
@AfterTest fun deinit() = ThreadPool.deinit()
@Test fun compareAndSet() {
val refArr = AtomicArray(10) { Data(0) }
val futures = ThreadPool.execute {
for (i in 0 until 500) {
val index = (0 until refArr.length).random()
while(true) {
val cur = refArr[index]
val newValue = Data(cur.value + 1)
if (refArr.compareAndSet(index, cur, newValue)) break
}
}
}
futures.forEach {
it.result
}
var sum = 0
for (i in 0 until refArr.length) {
sum += refArr[i].value
}
assertEquals(futures.size * 500, sum)
}
}
@@ -0,0 +1,217 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package test.concurrent
import kotlin.concurrent.*
import kotlin.native.internal.NativePtr
import kotlin.test.*
data class Data(val value: Int)
class AtomicIntTest {
@Test fun ctor() {
val x = AtomicInt(0)
assertEquals(x.value, 0)
}
@Test fun setter() {
val x = AtomicInt(0)
x.value = 1
assertEquals(x.value, 1)
}
@Test fun addAndGet() {
val x = AtomicInt(1)
val result = x.addAndGet(2)
assertEquals(result, 1 + 2)
assertEquals(x.value, result)
}
@Test fun compareAndExchange() {
val x = AtomicInt(0)
val successValue = x.compareAndExchange(0, 1)
assertEquals(successValue, 0)
assertEquals(x.value, 1)
val failValue = x.compareAndExchange(0, 2)
assertEquals(failValue, 1)
assertEquals(x.value, 1)
}
@Test fun compareAndSet() {
val x = AtomicInt(0)
val successValue = x.compareAndSet(0, 1)
assertTrue(successValue)
assertEquals(x.value, 1)
val failValue = x.compareAndSet(0, 2)
assertFalse(failValue)
assertEquals(x.value, 1)
}
@Test fun smoke() {
val atomic = AtomicInt(3)
assertEquals(3, atomic.value)
atomic.value = 5
assertEquals(5, atomic.value)
assertEquals(5, atomic.getAndSet(6))
assertEquals(6, atomic.value)
assertTrue(atomic.compareAndSet(6, 8))
assertFalse(atomic.compareAndSet(9, 1))
assertEquals(8, atomic.value)
assertEquals(8, atomic.getAndAdd(5))
assertEquals(13, atomic.value)
assertEquals(18, atomic.addAndGet(5))
assertEquals(18, atomic.getAndIncrement())
assertEquals(19, atomic.value)
assertEquals(20, atomic.incrementAndGet())
assertEquals(20, atomic.value)
assertEquals(20, atomic.getAndDecrement())
assertEquals(19, atomic.value)
assertEquals(18, atomic.decrementAndGet())
assertEquals(18, atomic.value)
assertEquals(18, atomic.compareAndExchange(18, 56))
assertEquals(56, atomic.compareAndExchange(18, 56))
assertEquals(56, atomic.compareAndExchange(18, 56))
}
}
class AtomicLongTest {
@Test fun ctor() {
val x = AtomicLong(0)
assertEquals(x.value, 0)
}
@Test fun setter() {
val x = AtomicLong(0)
x.value = 1
assertEquals(x.value, 1)
}
@Test fun addAndGet() {
val x = AtomicLong(1)
val result = x.addAndGet(2L)
assertEquals(result, 1 + 2)
assertEquals(x.value, result)
}
@Test fun compareAndExchange() {
val x = AtomicLong(0)
val successValue = x.compareAndExchange(0, 1)
assertEquals(successValue, 0)
assertEquals(x.value, 1)
val failValue = x.compareAndExchange(0, 2)
assertEquals(failValue, 1)
assertEquals(x.value, 1)
}
@Test fun compareAndSet() {
val x = AtomicLong(0)
val successValue = x.compareAndSet(0, 1)
assertTrue(successValue)
assertEquals(x.value, 1)
val failValue = x.compareAndSet(0, 2)
assertFalse(failValue)
assertEquals(x.value, 1)
}
@Test fun smoke() {
val atomic = AtomicLong(1424920024888900000)
assertEquals(1424920024888900000, atomic.value)
atomic.value = 2424920024888900000
assertEquals(2424920024888900000, atomic.value)
assertEquals(2424920024888900000, atomic.getAndSet(3424920024888900000))
assertEquals(3424920024888900000, atomic.value)
assertTrue(atomic.compareAndSet(3424920024888900000, 4424920024888900000))
assertFalse(atomic.compareAndSet(9, 1))
assertEquals(4424920024888900000, atomic.value)
assertEquals(4424920024888900000, atomic.getAndAdd(100000))
assertEquals(4424920024889000000, atomic.value)
assertEquals(4424920024890000000, atomic.addAndGet(1000000L))
assertEquals(4424920024890000000, atomic.getAndIncrement())
assertEquals(4424920024890000001, atomic.value)
assertEquals(4424920024890000002, atomic.incrementAndGet())
assertEquals(4424920024890000002, atomic.value)
assertEquals(4424920024890000002, atomic.getAndDecrement())
assertEquals(4424920024890000001, atomic.value)
assertEquals(4424920024890000000, atomic.decrementAndGet())
assertEquals(4424920024890000000, atomic.value)
assertEquals(4424920024890000000, atomic.compareAndExchange(4424920024890000000, 5424920024890000000))
assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56))
assertEquals(5424920024890000000, atomic.compareAndExchange(18, 56))
}
}
class AtomicReferenceTest {
@Test fun ctor() {
val x = AtomicReference(Data(1))
assertEquals(x.value, Data(1))
}
@Test fun setter() {
val x = AtomicReference<Data>(Data(1))
x.value = Data(2)
assertEquals(x.value, Data(2))
}
@Test fun compareAndExchange() {
val initial = Data(1)
val new = Data(2)
val x = AtomicReference<Data>(initial)
val successValue = x.compareAndExchange(initial, new)
assertEquals(successValue, initial)
assertEquals(x.value, new)
val failValue = x.compareAndExchange(initial, Data(3))
assertEquals(failValue, new)
assertEquals(x.value, new)
}
@Test fun compareAndSet() {
val initial = Data(1)
val new = Data(2)
val x = AtomicReference<Data>(initial)
val successValue = x.compareAndSet(initial, new)
assertTrue(successValue)
assertEquals(x.value, new)
val failValue = x.compareAndSet(initial, Data(2))
assertFalse(failValue)
assertEquals(x.value, new)
}
@Test
fun smoke() {
val atomic = AtomicReference<List<Data>>(listOf(Data(1), Data(2), Data(3)))
assertEquals(listOf(Data(1), Data(2), Data(3)), atomic.value)
atomic.value = listOf(Data(1), Data(2), Data(1))
assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.value)
assertEquals(listOf(Data(1), Data(2), Data(1)), atomic.getAndSet(listOf(Data(1), Data(1), Data(1))))
assertEquals(listOf(Data(1), Data(1), Data(1)), atomic.value)
var cur = atomic.value
assertTrue(atomic.compareAndSet(cur, listOf(Data(2), Data(2), Data(2))))
assertFalse(atomic.compareAndSet(listOf(Data(1), Data(1), Data(1)), listOf(Data(2), Data(2), Data(2))))
assertEquals(listOf(Data(2), Data(2), Data(2)), atomic.value)
cur = atomic.value
assertEquals(listOf(Data(2), Data(2), Data(2)), atomic.compareAndExchange(cur, listOf(Data(3), Data(3), Data(3))))
assertEquals(listOf(Data(3), Data(3), Data(3)), atomic.compareAndExchange(cur, listOf(Data(4), Data(4), Data(4))))
assertEquals(listOf(Data(3), Data(3), Data(3)), atomic.compareAndExchange(cur, listOf(Data(3), Data(3), Data(3))))
}
}
class AtomicNativePtrTest {
@Test fun smoke() {
val atomic = AtomicNativePtr(NativePtr.NULL)
assertEquals(NativePtr.NULL, atomic.value)
atomic.value = NativePtr.NULL.plus(10L)
assertEquals(10L, atomic.value.toLong())
assertTrue(atomic.compareAndSet(NativePtr.NULL.plus(10L), NativePtr.NULL.plus(20L)))
assertEquals(20L, atomic.value.toLong())
assertFalse(atomic.compareAndSet(NativePtr.NULL.plus(10L), NativePtr.NULL.plus(20L)))
assertEquals(20L, atomic.value.toLong())
assertEquals(NativePtr.NULL.plus(20L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(30L)))
assertEquals(NativePtr.NULL.plus(30L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(40L)))
assertEquals(NativePtr.NULL.plus(30L), atomic.compareAndExchange(NativePtr.NULL.plus(20L), NativePtr.NULL.plus(50L)))
assertEquals(30L, atomic.getAndSet(NativePtr.NULL.plus(55L)).toLong())
assertEquals(55L, atomic.value.toLong())
}
}