[K/N][tests] Migrate various runtime/ tests ^KT-61259

This commit is contained in:
Alexander Shabalin
2024-03-11 22:48:50 +01:00
committed by Space Team
parent 7ad4e58a7a
commit d88092aa94
99 changed files with 2102 additions and 1905 deletions
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2024 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.native.concurrent
import kotlin.native.concurrent.*
import kotlin.test.*
private class A(var x: Int)
@OptIn(FreezingIsDeprecated::class)
class FreezingTest {
@Test
fun freezeIsNoopForObjects() {
val a = A(1)
a.freeze()
a.x = 2
assertEquals(2, a.x)
}
@Test
fun freezeIsNoopForArrays() {
val a = arrayOf(1, 2, 3)
a.freeze()
a[0] = 4
assertContentEquals(arrayOf(4, 2, 3), a)
}
@Test
fun freezeIsNoopForPrimitiveArrays() {
val a = intArrayOf(1, 2, 3)
a.freeze()
a[0] = 4
assertContentEquals(intArrayOf(4, 2, 3), a)
}
}
@@ -0,0 +1,56 @@
/*
* Copyright 2010-2024 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.native.concurrent
import kotlin.native.concurrent.*
import kotlin.test.*
@OptIn(FreezingIsDeprecated::class)
private fun assertContentsEquals(expected: ByteArray, actual: MutableData) {
assertEquals(expected.size, actual.size)
expected.forEachIndexed { index, byte ->
assertEquals(byte, actual.get(index))
}
}
@OptIn(FreezingIsDeprecated::class)
class MutableDataTest {
// See https://youtrack.jetbrains.com/issue/KT-39145
@Test
fun kt39145_1() = withWorker {
execute(TransferMode.SAFE, { "test" }) {
val data = MutableData(1_000)
val bytes = byteArrayOf(0, 10, 20, 30)
data.append(bytes, 0, 4)
assertEquals(4, data.size)
assertContentsEquals(bytes, data)
}.result
}
@Test
fun kt39145_2() = withWorker {
val externalData = MutableData(1_000)
execute(TransferMode.SAFE, { externalData }) {
val bytes = byteArrayOf(0, 10, 20, 30)
it.append(bytes, 0, 4)
assertEquals(4, it.size)
assertContentsEquals(bytes, it)
}.result
}
@Test
fun kt39145_3() {
val mainThreadData = MutableData(1_000)
val bytes = byteArrayOf(0, 10, 20, 30)
mainThreadData.append(bytes, 0, 4)
assertEquals(4, mainThreadData.size)
assertContentsEquals(bytes, mainThreadData)
}
}
@@ -0,0 +1,418 @@
/*
* Copyright 2010-2024 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.
*/
@file:OptIn(FreezingIsDeprecated::class)
package test.native.concurrent
import kotlin.concurrent.AtomicInt
import kotlin.native.concurrent.*
import kotlin.native.concurrent.WorkerBoundReference
import kotlin.test.*
private class C(var a: Int)
private class Wrapper(val ref: WorkerBoundReference<C>)
private val global1: WorkerBoundReference<C> = WorkerBoundReference(C(3))
private val global2: WorkerBoundReference<C> = WorkerBoundReference(C(3))
private val global3: WorkerBoundReference<C> = WorkerBoundReference(C(3).freeze())
private val global4: WorkerBoundReference<C> = WorkerBoundReference(C(3))
private val global5: WorkerBoundReference<C> = WorkerBoundReference(C(3))
private val global6: WorkerBoundReference<C> = WorkerBoundReference(C(3))
private val global7: WorkerBoundReference<C> = WorkerBoundReference(C(3))
class WorkerBoundReference {
@Test
fun global() {
assertEquals(3, global1.value.a)
assertEquals(3, global1.valueOrNull?.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
global1
}
val value = future.result
assertEquals(3, value.value.a)
assertEquals(3, value.valueOrNull?.a)
worker.requestTermination().result
}
@Test
fun globalOnWorker() {
assertEquals(3, global2.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
assertEquals(global2.value, global2.valueOrNull)
global2.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun globalOnWorkerFrozenInitially() {
assertEquals(3, global3.value.a)
assertEquals(3, global3.valueOrNull?.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
global3.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun globalOnWorkerFrozenBeforePassing() {
assertEquals(3, global4.value.a)
global4.value.freeze()
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
global4.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun globalOnWorkerFrozenBeforeAccess() {
val semaphore = AtomicInt(0)
assertEquals(3, global5.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore ->
semaphore.incrementAndGet()
while (semaphore.value < 2) {
}
global5.value.a
}
while (semaphore.value < 1) {
}
global5.value.freeze()
semaphore.incrementAndGet()
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun globalModification() {
val semaphore = AtomicInt(0)
assertEquals(3, global6.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { semaphore }) { semaphore ->
semaphore.incrementAndGet()
while (semaphore.value < 2) {
}
global6
}
while (semaphore.value < 1) {
}
global6.value.a = 4
semaphore.incrementAndGet()
val value = future.result
assertEquals(4, value.value.a)
assertEquals(4, value.valueOrNull?.a)
worker.requestTermination().result
}
@Test
fun globalGetWorker() {
val ownerId = Worker.current.id
assertEquals(ownerId, global7.worker.id)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId ->
assertEquals(ownerId, global7.worker.id)
}
future.result
worker.requestTermination().result
}
@Test
fun local() {
val local = WorkerBoundReference(C(3))
assertEquals(3, local.value.a)
assertEquals(3, local.valueOrNull?.a)
}
@Test
fun localFrozen() {
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(3, local.value.a)
assertEquals(3, local.valueOrNull?.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
local
}
val value = future.result
assertEquals(3, value.value.a)
assertEquals(3, value.valueOrNull?.a)
worker.requestTermination().result
}
@Test
fun localOnWorkerFrozen() {
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(3, local.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
assertEquals(local.value, local.valueOrNull)
local.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun localOnWorkerFrozenInitiallyFrozen() {
val local = WorkerBoundReference(C(3).freeze()).freeze()
assertEquals(3, local.value.a)
assertEquals(3, local.valueOrNull?.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
local.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun localOnWorkerFrozenBeforePassingFrozen() {
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(3, local.value.a)
local.value.freeze()
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
local.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun localOnWorkerFrozenBeforeAccessFrozen() {
val semaphore = AtomicInt(0)
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(3, local.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) ->
semaphore.incrementAndGet()
while (semaphore.value < 2) {
}
local.value.a
}
while (semaphore.value < 1) {
}
local.value.freeze()
semaphore.incrementAndGet()
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun localOnMainThread() {
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
WorkerBoundReference(C(3))
}
assertEquals(3, future.result.value.a)
worker.requestTermination().result
}
@Test
fun localOnMainThreadFrozen() {
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, {}) {
WorkerBoundReference(C(3)).freeze()
}
val value = future.result
assertEquals(3, value.value.a)
assertEquals(value.value, value.valueOrNull)
worker.requestTermination().result
}
@Test
fun localModificationFrozen() {
val semaphore = AtomicInt(0)
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(3, local.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { Pair(local, semaphore) }) { (local, semaphore) ->
semaphore.incrementAndGet()
while (semaphore.value < 2) {
}
local
}
while (semaphore.value < 1) {
}
local.value.a = 4
semaphore.incrementAndGet()
val value = future.result
assertEquals(4, value.value.a)
assertEquals(4, value.valueOrNull?.a)
worker.requestTermination().result
}
@Test
fun localGetWorkerFrozen() {
val local = WorkerBoundReference(C(3)).freeze()
val ownerId = Worker.current.id
assertEquals(ownerId, local.worker.id)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { Pair(local, ownerId) }) { (local, ownerId) ->
assertEquals(ownerId, local.worker.id)
}
future.result
worker.requestTermination().result
}
@Test
fun localForeignGetWorker() {
val worker = Worker.start()
val ownerId = worker.id
val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId ->
val local = WorkerBoundReference(C(3))
assertEquals(ownerId, local.worker.id)
local
}
val value = future.result
assertEquals(ownerId, value.worker.id)
worker.requestTermination().result
}
@Test
fun localForeignGetWorkerFrozen() {
val worker = Worker.start()
val ownerId = worker.id
val future = worker.execute(TransferMode.SAFE, { ownerId }) { ownerId ->
val local = WorkerBoundReference(C(3)).freeze()
assertEquals(ownerId, local.worker.id)
local
}
val value = future.result
assertEquals(ownerId, value.worker.id)
worker.requestTermination().result
}
@Test
fun localWithWrapperFrozen() {
val local = Wrapper(WorkerBoundReference(C(3))).freeze()
assertEquals(3, local.ref.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
local
}
val value = future.result
assertEquals(3, value.ref.value.a)
worker.requestTermination().result
}
@Test
fun localAccessWithWrapperFrozen() {
val local = Wrapper(WorkerBoundReference(C(3))).freeze()
assertEquals(3, local.ref.value.a)
val worker = Worker.start()
val future = worker.execute(TransferMode.SAFE, { local }) { local ->
assertEquals(local.ref.value, local.ref.valueOrNull)
local.ref.value.a
}
val value = future.result
assertEquals(3, value)
worker.requestTermination().result
}
@Test
fun concurrentAccessFrozen() {
val workerCount = 10
val workerUnlocker = AtomicInt(0)
val ref = WorkerBoundReference(C(3)).freeze()
assertEquals(3, ref.value.a)
val workers = Array(workerCount) {
Worker.start()
}
val futures = Array(workers.size) {
workers[it].execute(TransferMode.SAFE, { Pair(ref, workerUnlocker) }) { (ref, workerUnlocker) ->
while (workerUnlocker.value < 1) {
}
ref.value.a
}
}
workerUnlocker.incrementAndGet()
for (future in futures) {
val value = future.result
assertEquals(3, value)
}
for (worker in workers) {
worker.requestTermination().result
}
}
@Test
fun doubleFreeze() {
val ref = WorkerBoundReference(C(3))
val wrapper = Wrapper(ref)
ref.freeze()
ref.freeze()
wrapper.freeze()
}
}