[atomicfu-K/N] Tests for K/N atomicfu-compiler-plugin
* `nativeTest` task now allows to provide compiler plugins that may be enabled during test compilation * test sets for JVM and K/N backends are equal KT-60800 describes all the issues with native tests that were solved in this commit. Co-authored-by: Dmitriy Dolovov <Dmitriy.Dolovov@jetbrains.com> Merge-request: KT-MR-11401 Merged-by: Maria Sokolova <maria.sokolova@jetbrains.com>
This commit is contained in:
@@ -4284,32 +4284,68 @@
|
||||
<sha256 value="25f20bcfb6e13c6b86ec0ec5183c0feb690d8edc4bce3ad991cf2344944c03fb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu" version="0.21.0">
|
||||
<artifact name="atomicfu-metadata-0.21.0-all.jar">
|
||||
<md5 value="2c143a94ae3341744adc6168e136825f" origin="Generated by Gradle"/>
|
||||
<sha256 value="f31e5b2fd52eb73a0303cffe5c63c8390ca7cf459a02dcf06faa383dd4bb88d3" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-common" version="0.14.4">
|
||||
<artifact name="atomicfu-metadata-0.14.4-all.jar">
|
||||
<md5 value="cf76ac2f212e0cbd2f2b8dc51d69a902" origin="Generated by Gradle"/>
|
||||
<sha256 value="64b6213c123022daf9da8f070c12fe6f865f89a8c086e2c1f9962239f327d008" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-js" version="0.17.1">
|
||||
<artifact name="atomicfu-jsir-0.17.1.klib">
|
||||
<md5 value="2c628c0646001d82beb86b812a27553e" origin="Generated by Gradle"/>
|
||||
<sha256 value="398f7e6a21c450160e44f988563ee09dfd40a2b029688d7ed7883ffb28c5d65b" origin="Generated by Gradle"/>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-js" version="0.21.0">
|
||||
<artifact name="atomicfu-jsir-0.21.0.klib">
|
||||
<md5 value="5a499fda383c643df8168b187eeb208a" origin="Generated by Gradle"/>
|
||||
<sha256 value="f34ac12010dd84d50dd9d04de6cd24c9d5692790cd4231ee4a2ecbc8e7de60cd" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-jvm" version="0.17.1">
|
||||
<artifact name="atomicfu-jvm-0.17.1.jar">
|
||||
<md5 value="7396f6283b01e829a9f290be605b276c" origin="Generated by Gradle"/>
|
||||
<sha256 value="fcd9bfec8d7dd24b0a350455573720dcd731e972903f982d3fef5dcd2b399946" origin="Generated by Gradle"/>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-jvm" version="0.21.0">
|
||||
<artifact name="atomicfu-jvm-0.21.0.jar">
|
||||
<md5 value="aa61ce985451776e884940095b05bf6a" origin="Generated by Gradle"/>
|
||||
<sha256 value="1d2c9337b10c48841c217dd0abb3be5a4250c789a8af89a91d707bed6c65b2fb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-macosx64" version="0.17.1">
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-linuxx64" version="0.21.0">
|
||||
<artifact name="atomicfu-cinterop-interop.klib">
|
||||
<md5 value="64c3271bd490f1e70b1a947265ed421a" origin="Generated by Gradle"/>
|
||||
<sha256 value="1a2842e7f8f52c5bfb92f669162e1fb51d2cda8e98b3caabe4eccf2eb7ba062b" origin="Generated by Gradle"/>
|
||||
<md5 value="0c50c02ac0f860747546f8c06820d8a7" origin="Generated by Gradle"/>
|
||||
<sha256 value="78239c79d67e11a4b8e6205a4ee7d9a946ea6754c768bd7d3a0186838412bc8a" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="atomicfu.klib">
|
||||
<md5 value="59090f29cb19ee6daca530c740b23d74" origin="Generated by Gradle"/>
|
||||
<sha256 value="73117a47d15cca43bbd9edee14db9854f4d35505436b90475aa0467ccff4cf21" origin="Generated by Gradle"/>
|
||||
<md5 value="608e744e6a8eb997c7cb2652aa1b32b3" origin="Generated by Gradle"/>
|
||||
<sha256 value="baa808d6967a9beff770aa595c73f9f9487f076213623386a2e81be498a59381" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-macosarm64" version="0.21.0">
|
||||
<artifact name="atomicfu-cinterop-interop.klib">
|
||||
<md5 value="58d70d0e5dbc661e985ef3e9c6ec6d87" origin="Generated by Gradle"/>
|
||||
<sha256 value="c6f32c6573e1d379ae8a86106808a74e52801d5dfe3e4524e89f79f9946c4677" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="atomicfu.klib">
|
||||
<md5 value="37453e7318cd93283ee14a26ffa4ee49" origin="Generated by Gradle"/>
|
||||
<sha256 value="f9cc52e7fbf91e6cca6d0995e2b4cd23bc25b70a580185e99c0ba2f074bf9dce" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-macosx64" version="0.21.0">
|
||||
<artifact name="atomicfu-cinterop-interop.klib">
|
||||
<md5 value="ca181b6db1fe83c60fcdb84cc389371b" origin="Generated by Gradle"/>
|
||||
<sha256 value="2e7f2563834e6b42bcbc9fdab2aef29174df26ed256630e112be9f5db6aeb9a5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="atomicfu.klib">
|
||||
<md5 value="91edf3cf2a2aadbc25e64453811667df" origin="Generated by Gradle"/>
|
||||
<sha256 value="741bcc8db2e255c7d5c06ebaed62636732af428f3115c62ca716f02231f5e321" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="atomicfu-mingwx64" version="0.21.0">
|
||||
<artifact name="atomicfu-cinterop-interop.klib">
|
||||
<md5 value="bf0bc36e838273c6789beb997bf748bf" origin="Generated by Gradle"/>
|
||||
<sha256 value="7ed242a7bc4b3812822102d5d0253704f3ae7d8455ba56b52ffba6dc38eef69b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="atomicfu.klib">
|
||||
<md5 value="9e46a4533329a42c69c8cd694ebe2954" origin="Generated by Gradle"/>
|
||||
<sha256 value="26e50877925990758b1fc371f5a6c3880325fa241159ded4911c656fcac4480c" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="org.jetbrains.kotlinx" name="binary-compatibility-validator" version="0.13.0">
|
||||
|
||||
+11
-1
@@ -267,6 +267,16 @@ fun main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Atomicfu compiler plugin native tests.
|
||||
testGroup("plugins/atomicfu/atomicfu-compiler/test", "plugins/atomicfu/atomicfu-compiler/testData") {
|
||||
testClass<AbstractNativeBlackBoxTest>(
|
||||
suiteTestClassName = "AtomicfuNativeTestGenerated",
|
||||
annotations = listOf(atomicfuNative(), provider<UseStandardTestCaseGroupProvider>())
|
||||
) {
|
||||
model("nativeBox")
|
||||
}
|
||||
}
|
||||
|
||||
generateTestGroupSuiteWithJUnit5 {
|
||||
testGroup("native/native.tests/tests-gen", "compiler/util-klib-abi/testData") {
|
||||
testClass<AbstractNativeLibraryAbiReaderTest>(
|
||||
@@ -345,4 +355,4 @@ private fun debugger() = annotation(Tag::class.java, "debugger")
|
||||
private fun infrastructure() = annotation(Tag::class.java, "infrastructure")
|
||||
private fun k1libContents() = annotation(Tag::class.java, "k1libContents")
|
||||
private fun k2libContents() = annotation(Tag::class.java, "k2libContents")
|
||||
private fun atomicfu() = annotation(Tag::class.java, "atomicfu")
|
||||
private fun atomicfuNative() = annotation(Tag::class.java, "atomicfu-native")
|
||||
|
||||
+1
@@ -56,6 +56,7 @@ internal class EnforcedProperties(testClass: Class<*>) {
|
||||
internal enum class ClassLevelProperty(shortName: String) {
|
||||
TEST_TARGET("target"),
|
||||
TEST_MODE("mode"),
|
||||
COMPILER_PLUGINS("compilerPlugins"),
|
||||
CUSTOM_KLIBS("customKlibs"),
|
||||
FORCE_STANDALONE("forceStandalone"),
|
||||
COMPILE_ONLY("compileOnly"),
|
||||
|
||||
+10
@@ -190,6 +190,7 @@ private object NativeTestSupport {
|
||||
output += sanitizer
|
||||
output += CacheMode::class to cacheMode
|
||||
output += computeTestMode(enforcedProperties)
|
||||
output += computeCompilerPlugins(enforcedProperties)
|
||||
output += computeCustomKlibs(enforcedProperties)
|
||||
output += computeForcedStandaloneTestKind(enforcedProperties)
|
||||
output += computeForcedNoopTestRunner(enforcedProperties)
|
||||
@@ -277,6 +278,15 @@ private object NativeTestSupport {
|
||||
private fun computeTestMode(enforcedProperties: EnforcedProperties): TestMode =
|
||||
ClassLevelProperty.TEST_MODE.readValue(enforcedProperties, TestMode.values(), default = TestMode.TWO_STAGE_MULTI_MODULE)
|
||||
|
||||
private fun computeCompilerPlugins(enforcedProperties: EnforcedProperties): CompilerPlugins =
|
||||
CompilerPlugins(
|
||||
ClassLevelProperty.COMPILER_PLUGINS.readValue(
|
||||
enforcedProperties,
|
||||
{ it.split(':', ';').mapToSet(::File) },
|
||||
default = emptySet()
|
||||
)
|
||||
)
|
||||
|
||||
private fun computeCustomKlibs(enforcedProperties: EnforcedProperties): CustomKlibs =
|
||||
CustomKlibs(
|
||||
ClassLevelProperty.CUSTOM_KLIBS.readValue(
|
||||
|
||||
+12
@@ -35,6 +35,7 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
|
||||
private val optimizationMode: OptimizationMode,
|
||||
private val compilerOutputInterceptor: CompilerOutputInterceptor,
|
||||
protected val freeCompilerArgs: TestCompilerArgs,
|
||||
protected val compilerPlugins: CompilerPlugins,
|
||||
protected val dependencies: CategorizedDependencies,
|
||||
protected val expectedArtifact: A
|
||||
) : TestCompilation<A>() {
|
||||
@@ -67,6 +68,10 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
|
||||
add(freeCompilerArgs.compilerArgs)
|
||||
}
|
||||
|
||||
private fun ArgsBuilder.applyCompilerPlugins() {
|
||||
add(compilerPlugins.compilerPluginJars) { compilerPluginJar -> "-Xplugin=${compilerPluginJar.path}" }
|
||||
}
|
||||
|
||||
private fun ArgsBuilder.applySources() {
|
||||
addFlattenedTwice(sourceModules, { it.files }) { it.location.path }
|
||||
}
|
||||
@@ -79,6 +84,7 @@ internal abstract class BasicCompilation<A : TestCompilationArtifact>(
|
||||
applySpecificArgs(this)
|
||||
applyDependencies(this)
|
||||
applyFreeArgs()
|
||||
applyCompilerPlugins()
|
||||
applySources()
|
||||
}
|
||||
|
||||
@@ -135,6 +141,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
|
||||
private val allocator: Allocator,
|
||||
private val pipelineType: PipelineType,
|
||||
freeCompilerArgs: TestCompilerArgs,
|
||||
compilerPlugins: CompilerPlugins,
|
||||
override val sourceModules: Collection<TestModule>,
|
||||
dependencies: CategorizedDependencies,
|
||||
expectedArtifact: A
|
||||
@@ -145,6 +152,7 @@ internal abstract class SourceBasedCompilation<A : TestCompilationArtifact>(
|
||||
optimizationMode = optimizationMode,
|
||||
compilerOutputInterceptor = compilerOutputInterceptor,
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = compilerPlugins,
|
||||
dependencies = dependencies,
|
||||
expectedArtifact = expectedArtifact
|
||||
) {
|
||||
@@ -197,6 +205,7 @@ internal class LibraryCompilation(
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
dependencies = CategorizedDependencies(dependencies),
|
||||
expectedArtifact = expectedArtifact
|
||||
@@ -231,6 +240,7 @@ internal class ObjCFrameworkCompilation(
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.getStageDependentPipelineType(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
dependencies = CategorizedDependencies(dependencies),
|
||||
expectedArtifact = expectedArtifact
|
||||
@@ -317,6 +327,7 @@ internal class ExecutableCompilation(
|
||||
allocator = settings.get(),
|
||||
pipelineType = settings.getStageDependentPipelineType(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
sourceModules = sourceModules,
|
||||
dependencies = CategorizedDependencies(dependencies),
|
||||
expectedArtifact = expectedArtifact
|
||||
@@ -409,6 +420,7 @@ internal class StaticCacheCompilation(
|
||||
optimizationMode = settings.get(),
|
||||
compilerOutputInterceptor = settings.get(),
|
||||
freeCompilerArgs = freeCompilerArgs,
|
||||
compilerPlugins = settings.get(),
|
||||
dependencies = CategorizedDependencies(dependencies),
|
||||
expectedArtifact = expectedArtifact
|
||||
) {
|
||||
|
||||
+13
@@ -77,6 +77,19 @@ internal enum class TestMode(private val description: String) {
|
||||
override fun toString() = description
|
||||
}
|
||||
|
||||
/**
|
||||
* Kotlin compiler plugins to be used together with the the Kotlin/Native compiler.
|
||||
*/
|
||||
@JvmInline
|
||||
internal value class CompilerPlugins(val compilerPluginJars: Set<File>) {
|
||||
init {
|
||||
val invalidJars = compilerPluginJars.filterNot { it.isDirectory || (it.isFile && it.extension == "jar") }
|
||||
assertTrue(invalidJars.isEmpty()) {
|
||||
"There are invalid compiler plugin JARs that should be passed for the Kotlin/Native compiler: ${invalidJars.joinToString { "[$it]" }}"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The set of custom (external) klibs that should be passed to the Kotlin/Native compiler.
|
||||
*/
|
||||
|
||||
@@ -41,8 +41,6 @@ val atomicfuNativeKlib by configurations.creating {
|
||||
attribute(KotlinNativeTarget.konanTargetAttribute, nativeTargetName)
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
||||
attribute(KotlinPlatformType.attribute, KotlinPlatformType.native)
|
||||
// todo: don't add platform specific attribute
|
||||
attribute(KotlinNativeTarget.konanTargetAttribute, org.jetbrains.kotlin.konan.target.KonanTarget.MACOS_X64.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,6 +52,8 @@ val atomicfuJsIrRuntimeForTests by configurations.creating {
|
||||
}
|
||||
}
|
||||
|
||||
val atomicfuCompilerPluginForTests by configurations.creating
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
@@ -105,7 +105,7 @@ dependencies {
|
||||
testImplementation(projectTests(":compiler:tests-common"))
|
||||
testImplementation(projectTests(":compiler:tests-common-new"))
|
||||
testImplementation(projectTests(":compiler:test-infrastructure"))
|
||||
testCompileOnly("org.jetbrains.kotlinx:atomicfu:0.17.1") // todo: do not hardcode atomicfu version
|
||||
testCompileOnly("org.jetbrains.kotlinx:atomicfu:0.21.0")
|
||||
|
||||
testApiJUnit5()
|
||||
|
||||
@@ -114,10 +114,32 @@ dependencies {
|
||||
testRuntimeOnly(project(":compiler:backend-common"))
|
||||
testRuntimeOnly(commonDependency("org.fusesource.jansi", "jansi"))
|
||||
|
||||
atomicfuJsClasspath("org.jetbrains.kotlinx:atomicfu-js:0.17.1") { isTransitive = false }
|
||||
atomicfuJsClasspath("org.jetbrains.kotlinx:atomicfu-js:0.21.0") { isTransitive = false }
|
||||
atomicfuJsIrRuntimeForTests(project(":kotlinx-atomicfu-runtime")) { isTransitive = false }
|
||||
atomicfuJvmClasspath("org.jetbrains.kotlinx:atomicfu:0.17.1") { isTransitive = false }
|
||||
atomicfuNativeKlib("org.jetbrains.kotlinx:atomicfu:0.17.1") { isTransitive = false }
|
||||
atomicfuJvmClasspath("org.jetbrains.kotlinx:atomicfu:0.21.0") { isTransitive = false }
|
||||
atomicfuNativeKlib("org.jetbrains.kotlinx:atomicfu:0.21.0") { isTransitive = false }
|
||||
atomicfuCompilerPluginForTests(project(":kotlin-atomicfu-compiler-plugin"))
|
||||
// Implicit dependencies on native artifacts to run native tests on CI
|
||||
implicitDependencies("org.jetbrains.kotlinx:atomicfu-linuxx64:0.21.0") {
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
||||
}
|
||||
}
|
||||
implicitDependencies("org.jetbrains.kotlinx:atomicfu-macosarm64:0.21.0"){
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
||||
}
|
||||
}
|
||||
implicitDependencies("org.jetbrains.kotlinx:atomicfu-macosx64:0.21.0"){
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
||||
}
|
||||
}
|
||||
implicitDependencies("org.jetbrains.kotlinx:atomicfu-mingwx64:0.21.0"){
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
||||
}
|
||||
}
|
||||
|
||||
embedded(project(":kotlinx-atomicfu-runtime")) {
|
||||
attributes {
|
||||
@@ -128,7 +150,7 @@ dependencies {
|
||||
isTransitive = false
|
||||
}
|
||||
|
||||
testImplementation("org.jetbrains.kotlinx:atomicfu:0.17.1")
|
||||
testImplementation("org.jetbrains.kotlinx:atomicfu:0.21.0")
|
||||
|
||||
testRuntimeOnly("org.junit.vintage:junit-vintage-engine:5.9.1")
|
||||
}
|
||||
@@ -146,7 +168,10 @@ testsJar()
|
||||
useD8Plugin()
|
||||
|
||||
projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||
useJUnitPlatform()
|
||||
useJUnitPlatform {
|
||||
// Exclude all tests with the "atomicfu-native" tag. They should be launched by another test task.
|
||||
excludeTags("atomicfu-native")
|
||||
}
|
||||
useJsIrBoxTests(version = version, buildDir = "$buildDir/")
|
||||
|
||||
workingDir = rootDir
|
||||
@@ -154,6 +179,12 @@ projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||
dependsOn(":dist")
|
||||
dependsOn(atomicfuJsIrRuntimeForTests)
|
||||
|
||||
// Depend on the test task that launches Native tests so that it will also run together with tests
|
||||
// for all other targets if K/N is enabled
|
||||
if (kotlinBuildProperties.isKotlinNativeEnabled) {
|
||||
dependsOn(nativeTest)
|
||||
}
|
||||
|
||||
val localAtomicfuJsIrRuntimeForTests: FileCollection = atomicfuJsIrRuntimeForTests
|
||||
val localAtomicfuJsClasspath: FileCollection = atomicfuJsClasspath
|
||||
val localAtomicfuJvmClasspath: FileCollection = atomicfuJvmClasspath
|
||||
@@ -168,10 +199,11 @@ projectTest(jUnitMode = JUnitMode.JUnit5) {
|
||||
publish()
|
||||
standardPublicJars()
|
||||
|
||||
val nativeBoxTest = nativeTest(
|
||||
taskName = "nativeBoxTest",
|
||||
tag = "atomicfu",
|
||||
val nativeTest = nativeTest(
|
||||
taskName = "nativeTest",
|
||||
tag = "atomicfu-native", // Include all tests with the "atomicfu-native" tag.
|
||||
requirePlatformLibs = true,
|
||||
customDependencies = listOf(atomicfuJvmClasspath),
|
||||
customKlibDependencies = listOf(atomicfuNativeKlib)
|
||||
customCompilerDependencies = listOf(atomicfuJvmClasspath),
|
||||
customTestDependencies = listOf(atomicfuNativeKlib),
|
||||
compilerPluginDependencies = listOf(atomicfuCompilerPluginForTests)
|
||||
)
|
||||
|
||||
+276
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* 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 org.jetbrains.kotlin.konan.blackboxtest;
|
||||
|
||||
import com.intellij.testFramework.TestDataPath;
|
||||
import org.jetbrains.kotlin.test.util.KtTestUtil;
|
||||
import org.junit.jupiter.api.Tag;
|
||||
import org.jetbrains.kotlin.konan.blackboxtest.support.group.UseStandardTestCaseGroupProvider;
|
||||
import org.jetbrains.kotlin.test.TestMetadata;
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.GenerateNativeTestsKt}. DO NOT MODIFY MANUALLY */
|
||||
@SuppressWarnings("all")
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class AtomicfuNativeTestGenerated extends AbstractNativeBlackBoxTest {
|
||||
@Test
|
||||
public void testAllFilesPresentInNativeBox() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Atomic_extensions {
|
||||
@Test
|
||||
public void testAllFilesPresentInAtomic_extensions() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ArrayInlineExtensionTest.kt")
|
||||
public void testArrayInlineExtensionTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ArrayInlineExtensionTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ArrayLoopTest.kt")
|
||||
public void testArrayLoopTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ArrayLoopTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ComplexLoopTest.kt")
|
||||
public void testComplexLoopTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ComplexLoopTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ExtensionLoopTest.kt")
|
||||
public void testExtensionLoopTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ExtensionLoopTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ExtensionsTest.kt")
|
||||
public void testExtensionsTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ExtensionsTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InlineExtensionWithTypeParameterTest.kt")
|
||||
public void testInlineExtensionWithTypeParameterTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/InlineExtensionWithTypeParameterTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LambdaTest.kt")
|
||||
public void testLambdaTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/LambdaTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LockFreeIntBitsTest.kt")
|
||||
public void testLockFreeIntBitsTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/LockFreeIntBitsTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LockTest.kt")
|
||||
public void testLockTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/LockTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ParameterizedInlineFunExtensionTest.kt")
|
||||
public void testParameterizedInlineFunExtensionTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomic_extensions/ParameterizedInlineFunExtensionTest.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Atomics_basic {
|
||||
@Test
|
||||
public void testAllFilesPresentInAtomics_basic() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ArithmeticTest.kt")
|
||||
public void testArithmeticTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/ArithmeticTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AtomicArrayTest.kt")
|
||||
public void testAtomicArrayTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/AtomicArrayTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("IndexArrayElementGetterTest.kt")
|
||||
public void testIndexArrayElementGetterTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/IndexArrayElementGetterTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("InitializationOrderTest.kt")
|
||||
public void testInitializationOrderTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/InitializationOrderTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LateinitPropertiesTest.kt")
|
||||
public void testLateinitPropertiesTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/LateinitPropertiesTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LockFreeLongCounterTest.kt")
|
||||
public void testLockFreeLongCounterTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/LockFreeLongCounterTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LockFreeQueueTest.kt")
|
||||
public void testLockFreeQueueTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/LockFreeQueueTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LockFreeStackTest.kt")
|
||||
public void testLockFreeStackTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/LockFreeStackTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("LoopTest.kt")
|
||||
public void testLoopTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/LoopTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("MultiInitTest.kt")
|
||||
public void testMultiInitTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/MultiInitTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ScopeTest.kt")
|
||||
public void testScopeTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/ScopeTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SimpleLockTest.kt")
|
||||
public void testSimpleLockTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/SimpleLockTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("UncheckedCastTest.kt")
|
||||
public void testUncheckedCastTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/atomics_basic/UncheckedCastTest.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/delegated")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Delegated {
|
||||
@Test
|
||||
public void testAllFilesPresentInDelegated() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/delegated"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DelegatedPropertiesTest.kt")
|
||||
public void testDelegatedPropertiesTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/delegated/DelegatedPropertiesTest.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/locks")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Locks {
|
||||
@Test
|
||||
public void testAllFilesPresentInLocks() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/locks"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("ReentrantLockTest.kt")
|
||||
public void testReentrantLockTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/locks/ReentrantLockTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("SynchronizedObjectTest.kt")
|
||||
public void testSynchronizedObjectTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/locks/SynchronizedObjectTest.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/top-level")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Top_level {
|
||||
@Test
|
||||
public void testAllFilesPresentInTop_level() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/top-level"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("FieldInObjectTest.kt")
|
||||
public void testFieldInObjectTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/top-level/FieldInObjectTest.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TopLevelTest.kt")
|
||||
public void testTopLevelTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/top-level/TopLevelTest.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/trace")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@Tag("atomicfu-native")
|
||||
@UseStandardTestCaseGroupProvider()
|
||||
public class Trace {
|
||||
@Test
|
||||
public void testAllFilesPresentInTrace() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/trace"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("TraceTest.kt")
|
||||
public void testTraceTest() throws Exception {
|
||||
runTest("plugins/atomicfu/atomicfu-compiler/testData/nativeBox/trace/TraceTest.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
Vendored
+228
@@ -0,0 +1,228 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class AtomicIntArrayInlineExtensionTest {
|
||||
private val intArr = AtomicIntArray(10)
|
||||
private val a = atomic(0)
|
||||
|
||||
private inline fun casLoop(to: Int): Int {
|
||||
intArr[0].loop { cur ->
|
||||
if (intArr[0].compareAndSet(cur, to)) return intArr[0].value
|
||||
return 777
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun casLoopExpression(to: Int): Int = intArr[3].loop { cur ->
|
||||
if (intArr[3].compareAndSet(cur, to)) return intArr[3].value
|
||||
return 777
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoop(to: Int): Int {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return value
|
||||
return 777
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
|
||||
lazySet(cur + 10)
|
||||
return if (compareAndSet(cur, to)) value else incrementAndGet()
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoopMixedReceivers(first: Int, second: Int, index: Int): Int {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, first)
|
||||
intArr[index].compareAndSet(first, second)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, to)
|
||||
a.extensionLoop(5)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.foo(to: Int): Int {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return 777
|
||||
else return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.bar(delta: Int): Int {
|
||||
return foo(value + delta)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
assertEquals(5, casLoop(5))
|
||||
assertEquals(6, casLoopExpression(6))
|
||||
assertEquals(66, intArr[1].extensionLoop(66))
|
||||
assertEquals(66, intArr[2].extensionLoop(66))
|
||||
assertEquals(77, intArr[1].extensionLoopExpression(777))
|
||||
assertEquals(99, intArr[1].extensionLoopMixedReceivers(88, 99, 1))
|
||||
assertEquals(100, intArr[1].extensionLoopRecursive(100))
|
||||
assertEquals(777, intArr[1].bar(100))
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicLongArrayInlineExtensionTest {
|
||||
private val longArr = AtomicLongArray(10)
|
||||
private val a = atomic(0L)
|
||||
|
||||
private inline fun casLoop(to: Long): Long {
|
||||
longArr[0].loop { cur ->
|
||||
if (longArr[0].compareAndSet(cur, to)) return longArr[0].value
|
||||
return 777L
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun casLoopExpression(to: Long): Long = longArr[3].loop { cur ->
|
||||
if (longArr[3].compareAndSet(cur, to)) return longArr[3].value
|
||||
return 777L
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.extensionLoop(to: Long): Long {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return value
|
||||
return 777L
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.extensionLoopExpression(to: Long): Long = loop { cur ->
|
||||
lazySet(cur + 10L)
|
||||
return if (compareAndSet(cur, to)) value else incrementAndGet()
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.extensionLoopMixedReceivers(first: Long, second: Long, index: Int): Long {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, first)
|
||||
longArr[index].compareAndSet(first, second)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.extensionLoopRecursive(to: Long): Long {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, to)
|
||||
a.extensionLoop(5L)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.foo(to: Long): Long {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return 777L
|
||||
else return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.bar(delta: Long): Long {
|
||||
return foo(value + delta)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
assertEquals(5L, casLoop(5L))
|
||||
assertEquals(6L, casLoopExpression(6L))
|
||||
assertEquals(66L, longArr[1].extensionLoop(66L))
|
||||
assertEquals(66L, longArr[2].extensionLoop(66L))
|
||||
assertEquals(77L, longArr[1].extensionLoopExpression(777L))
|
||||
assertEquals(99L, longArr[1].extensionLoopMixedReceivers(88L, 99L, 1))
|
||||
assertEquals(100L, longArr[1].extensionLoopRecursive(100L))
|
||||
assertEquals(777L, longArr[1].bar(100L))
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicBooleanArrayInlineExtensionTest {
|
||||
private val booleanArr = AtomicBooleanArray(10)
|
||||
|
||||
private inline fun casLoop(to: Boolean): Boolean {
|
||||
booleanArr[0].loop { cur ->
|
||||
if (booleanArr[0].compareAndSet(cur, to)) return booleanArr[0].value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun casLoopExpression(to: Boolean): Boolean = booleanArr[3].loop { cur ->
|
||||
if (booleanArr[3].compareAndSet(cur, to)) return booleanArr[3].value
|
||||
}
|
||||
|
||||
private inline fun AtomicBoolean.extensionLoop(to: Boolean): Boolean {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicBoolean.extensionLoopExpression(to: Boolean): Boolean = loop { cur ->
|
||||
lazySet(false)
|
||||
return if (compareAndSet(cur, to)) value else !value
|
||||
}
|
||||
|
||||
private inline fun AtomicBoolean.extensionLoopMixedReceivers(first: Boolean, second: Boolean, index: Int): Boolean {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, first)
|
||||
booleanArr[index].compareAndSet(first, second)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
assertEquals(true, casLoop(true))
|
||||
assertEquals(true, casLoopExpression(true))
|
||||
assertEquals(true, booleanArr[1].extensionLoop(true))
|
||||
assertEquals(true, booleanArr[1].extensionLoopExpression(true))
|
||||
assertEquals(false, booleanArr[7].extensionLoopMixedReceivers(true, false, 7))
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicRefArrayInlineExtensionTest {
|
||||
private val refArr = atomicArrayOfNulls<String?>(10)
|
||||
private val a = atomic(0L)
|
||||
|
||||
private inline fun casLoop(to: String): String? {
|
||||
refArr[0].loop { cur ->
|
||||
if (refArr[0].compareAndSet(cur, to)) return refArr[0].value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun casLoopExpression(to: String): String? = refArr[3].loop { cur ->
|
||||
if (refArr[3].compareAndSet(cur, to)) return refArr[3].value
|
||||
}
|
||||
|
||||
private inline fun AtomicRef<String?>.extensionLoop(to: String): String? {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return value
|
||||
else "incorrect"
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicRef<String?>.extensionLoopExpression(to: String): String? = loop { cur ->
|
||||
lazySet("aaa")
|
||||
return if (compareAndSet(cur, to)) value else "CAS_failed"
|
||||
}
|
||||
|
||||
private inline fun AtomicRef<String?>.extensionLoopMixedReceivers(first: String, second: String, index: Int): String? {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, first)
|
||||
refArr[index].compareAndSet(first, second)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
assertEquals("aaa", casLoop("aaa"))
|
||||
assertEquals("bbb", casLoopExpression("bbb"))
|
||||
assertEquals("ccc", refArr[1].extensionLoop("ccc"))
|
||||
assertEquals("CAS_failed", refArr[1].extensionLoopExpression("ccc"))
|
||||
assertEquals("bbb", refArr[7].extensionLoopMixedReceivers("aaa", "bbb", 7))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
AtomicIntArrayInlineExtensionTest().test()
|
||||
AtomicLongArrayInlineExtensionTest().test()
|
||||
AtomicBooleanArrayInlineExtensionTest().test()
|
||||
AtomicRefArrayInlineExtensionTest().test()
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class AtomicIntArrayAtomicfuInlineFunctionsTest {
|
||||
private val intArr = AtomicIntArray(10)
|
||||
|
||||
fun testSetArrayElementValueInLoop() {
|
||||
intArr[0].loop { cur ->
|
||||
assertTrue(intArr[0].compareAndSet(cur, 555))
|
||||
assertEquals(555, intArr[0].value)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun action(cur: Int): Int = cur * 1000
|
||||
|
||||
fun testArrayElementUpdate() {
|
||||
intArr[0].lazySet(5)
|
||||
intArr[0].update { cur -> action(cur) }
|
||||
assertEquals(intArr[0].value, 5000)
|
||||
}
|
||||
|
||||
fun testArrayElementGetAndUpdate() {
|
||||
intArr[0].lazySet(5)
|
||||
assertEquals(intArr[0].getAndUpdate{ cur -> action(cur) }, 5)
|
||||
assertEquals(intArr[0].value, 5000)
|
||||
}
|
||||
|
||||
fun testArrayElementUpdateAndGet() {
|
||||
intArr[0].lazySet(5)
|
||||
assertEquals(intArr[0].updateAndGet{ cur -> action(cur) }, 5000)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testSetArrayElementValueInLoop()
|
||||
testArrayElementUpdate()
|
||||
testArrayElementGetAndUpdate()
|
||||
testArrayElementUpdateAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicBooleanArrayAtomicfuInlineFunctionsTest {
|
||||
private val booleanArr = AtomicBooleanArray(10)
|
||||
|
||||
fun testSetArrayElementValueInLoop() {
|
||||
booleanArr[0].loop { cur ->
|
||||
assertTrue(booleanArr[0].compareAndSet(cur, true))
|
||||
assertEquals(true, booleanArr[0].value)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun action(cur: Boolean) = !cur
|
||||
|
||||
fun testArrayElementUpdate() {
|
||||
booleanArr[0].lazySet(true)
|
||||
booleanArr[0].update{ cur -> action(cur) }
|
||||
assertEquals(booleanArr[0].value, false)
|
||||
}
|
||||
|
||||
fun testArrayElementGetAndUpdate() {
|
||||
booleanArr[0].lazySet(true)
|
||||
assertEquals(booleanArr[0].getAndUpdate{ cur -> action(cur) }, true)
|
||||
assertEquals(booleanArr[0].value, false)
|
||||
}
|
||||
|
||||
fun testArrayElementUpdateAndGet() {
|
||||
booleanArr[0].lazySet(true)
|
||||
assertEquals(booleanArr[0].updateAndGet{ cur -> action(cur) }, false)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testSetArrayElementValueInLoop()
|
||||
testArrayElementUpdate()
|
||||
testArrayElementGetAndUpdate()
|
||||
testArrayElementUpdateAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
class AtomicArrayAtomicfuInlineFunctionsTest {
|
||||
private val anyArr = atomicArrayOfNulls<Any?>(5)
|
||||
private val refArr = atomicArrayOfNulls<Box>(5)
|
||||
|
||||
private data class Box(val n: Int)
|
||||
|
||||
fun testSetArrayElementValueInLoop() {
|
||||
anyArr[0].loop { cur ->
|
||||
assertTrue(anyArr[0].compareAndSet(cur, IntArray(5)))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
private fun action(cur: Box?) = cur?.let { Box(cur.n * 10) }
|
||||
|
||||
fun testArrayElementUpdate() {
|
||||
refArr[0].lazySet(Box(5))
|
||||
refArr[0].update { cur -> cur?.let { Box(cur.n * 10) } }
|
||||
assertEquals(refArr[0].value!!.n, 50)
|
||||
}
|
||||
|
||||
fun testArrayElementGetAndUpdate() {
|
||||
refArr[0].lazySet(Box(5))
|
||||
assertEquals(refArr[0].getAndUpdate { cur -> action(cur) }!!.n, 5)
|
||||
assertEquals(refArr[0].value!!.n, 50)
|
||||
}
|
||||
|
||||
fun testArrayElementUpdateAndGet() {
|
||||
refArr[0].lazySet(Box(5))
|
||||
assertEquals(refArr[0].updateAndGet { cur -> action(cur) }!!.n, 50)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testSetArrayElementValueInLoop()
|
||||
testArrayElementUpdate()
|
||||
testArrayElementGetAndUpdate()
|
||||
testArrayElementUpdateAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
AtomicIntArrayAtomicfuInlineFunctionsTest().test()
|
||||
AtomicBooleanArrayAtomicfuInlineFunctionsTest().test()
|
||||
AtomicArrayAtomicfuInlineFunctionsTest().test()
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
private val topLevelA = atomic(0)
|
||||
|
||||
class ComplexLoopTest {
|
||||
private val a = atomic(10)
|
||||
private val long = atomic(6757L)
|
||||
private val b = atomic(11)
|
||||
private val c = atomic(12)
|
||||
private val r = atomic<String>("aaa")
|
||||
private val intArr = AtomicIntArray(10)
|
||||
|
||||
private inline fun AtomicInt.fooInt() {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, 67)) return
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.fooLong() {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, 67L)) return
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun embeddedLoops(to: Int): Int =
|
||||
a.loop { aValue ->
|
||||
if (!a.compareAndSet(aValue, to)) return 666
|
||||
b.loop { bValue ->
|
||||
return if (b.compareAndSet(bValue, to)) a.value + b.value else 777
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionEmbeddedLoops(to: Int): Int =
|
||||
loop { cur1 ->
|
||||
compareAndSet(cur1, to)
|
||||
loop { cur2 ->
|
||||
return cur2
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun embeddedUpdate(to: Int): Int =
|
||||
a.loop { aValue ->
|
||||
a.compareAndSet(aValue, to)
|
||||
return a.updateAndGet { cur -> cur + 100 }
|
||||
}
|
||||
|
||||
private inline fun AtomicRef<String>.extesntionEmbeddedRefUpdate(to: String): String =
|
||||
loop { value ->
|
||||
compareAndSet(value, to)
|
||||
return updateAndGet { cur -> "${cur}AAA" }
|
||||
}
|
||||
|
||||
fun test() {
|
||||
a.fooInt()
|
||||
assertEquals(67, a.value)
|
||||
b.fooInt()
|
||||
assertEquals(67, b.value)
|
||||
c.fooInt()
|
||||
assertEquals(67, c.value)
|
||||
long.fooLong()
|
||||
assertEquals(67L, long.value)
|
||||
assertEquals(24, embeddedLoops(12))
|
||||
assertEquals(77, c.extensionEmbeddedLoops(77))
|
||||
assertEquals(66, intArr[0].extensionEmbeddedLoops(66))
|
||||
assertEquals(166, embeddedUpdate(66))
|
||||
assertEquals("bbbAAA", r.extesntionEmbeddedRefUpdate("bbb"))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testComplexLoopTest() {
|
||||
val testClass = ComplexLoopTest()
|
||||
testClass.test()
|
||||
}
|
||||
Vendored
+92
@@ -0,0 +1,92 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class ExtensionLoopTest {
|
||||
private val a = atomic(0)
|
||||
private val b = atomic(true)
|
||||
private val l = atomic(5000000000)
|
||||
private val r = atomic<A>(A("aaaa"))
|
||||
private val rs = atomic<String>("bbbb")
|
||||
|
||||
class A(val s: String)
|
||||
|
||||
private inline fun casLoop(to: Int): Int {
|
||||
a.loop { cur ->
|
||||
if (a.compareAndSet(cur, to)) return a.value
|
||||
return 777
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun casLoopExpression(to: Int): Int = a.loop { cur ->
|
||||
if (a.compareAndSet(cur, to)) return a.value
|
||||
return 777
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoop(to: Int): Int {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return value
|
||||
return 777
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoopExpression(to: Int): Int = loop { cur ->
|
||||
lazySet(cur + 10)
|
||||
return if (compareAndSet(cur, to)) value + 1 else incrementAndGet()
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionLoopRecursive(to: Int): Int {
|
||||
loop { cur ->
|
||||
compareAndSet(cur, to)
|
||||
extensionLoop(5)
|
||||
return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.foo(to: Int): Int {
|
||||
loop { cur ->
|
||||
if (compareAndSet(cur, to)) return 777
|
||||
else return value
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.bar(delta: Int): Int {
|
||||
return foo(value + delta)
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.extensionEmbeddedLoops(to: Int): Int =
|
||||
loop { cur1 ->
|
||||
compareAndSet(value, to)
|
||||
loop { cur2 ->
|
||||
return cur2
|
||||
}
|
||||
}
|
||||
|
||||
fun testIntExtensionLoops() {
|
||||
assertEquals(5, casLoop(5))
|
||||
assertEquals(45, a.extensionEmbeddedLoops(45))
|
||||
assertEquals(6, casLoopExpression(6))
|
||||
assertEquals(17, a.extensionLoopExpression(777))
|
||||
assertEquals(66, a.extensionLoop(66))
|
||||
assertEquals(5, a.extensionLoopRecursive(100))
|
||||
assertEquals(777, a.bar(100))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private val ref = atomic<String>("aaa")
|
||||
|
||||
private inline fun AtomicRef<String>.topLevelExtensionLoop(to: String): String = loop { cur ->
|
||||
lazySet(cur + to)
|
||||
return value
|
||||
}
|
||||
|
||||
fun testTopLevelExtensionLoop() {
|
||||
assertEquals("aaattt", ref.topLevelExtensionLoop("ttt"))
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testExtensionLoop() {
|
||||
val testClass = ExtensionLoopTest()
|
||||
testClass.testIntExtensionLoops()
|
||||
testTopLevelExtensionLoop()
|
||||
}
|
||||
+114
@@ -0,0 +1,114 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class ExtensionsTest {
|
||||
private val a = atomic(0)
|
||||
private val l = atomic(0L)
|
||||
private val s = atomic<String?>(null)
|
||||
private val b = atomic(true)
|
||||
|
||||
fun testScopedFieldGetters() {
|
||||
check(a.value == 0)
|
||||
val update = 3
|
||||
a.lazySet(update)
|
||||
check(a.compareAndSet(update, 8))
|
||||
a.lazySet(1)
|
||||
check(a.value == 1)
|
||||
check(a.getAndSet(2) == 1)
|
||||
check(a.value == 2)
|
||||
check(a.getAndIncrement() == 2)
|
||||
check(a.value == 3)
|
||||
check(a.getAndDecrement() == 3)
|
||||
check(a.value == 2)
|
||||
check(a.getAndAdd(2) == 2)
|
||||
check(a.value == 4)
|
||||
check(a.addAndGet(3) == 7)
|
||||
check(a.value == 7)
|
||||
check(a.incrementAndGet() == 8)
|
||||
check(a.value == 8)
|
||||
check(a.decrementAndGet() == 7)
|
||||
check(a.value == 7)
|
||||
check(a.compareAndSet(7, 10))
|
||||
}
|
||||
|
||||
private inline fun AtomicInt.intExtensionArithmetic() {
|
||||
value = 0
|
||||
check(value == 0)
|
||||
val update = 3
|
||||
lazySet(update)
|
||||
check(compareAndSet(update, 8))
|
||||
lazySet(1)
|
||||
check(value == 1)
|
||||
check(getAndSet(2) == 1)
|
||||
check(value == 2)
|
||||
check(getAndIncrement() == 2)
|
||||
check(value == 3)
|
||||
check(getAndDecrement() == 3)
|
||||
check(value == 2)
|
||||
check(getAndAdd(2) == 2)
|
||||
check(value == 4)
|
||||
check(addAndGet(3) == 7)
|
||||
check(value == 7)
|
||||
check(incrementAndGet() == 8)
|
||||
check(value == 8)
|
||||
check(decrementAndGet() == 7)
|
||||
check(value == 7)
|
||||
check(compareAndSet(7, 10))
|
||||
check(compareAndSet(value, 55))
|
||||
check(value == 55)
|
||||
}
|
||||
|
||||
private inline fun AtomicLong.longExtensionArithmetic() {
|
||||
value = 2424920024888888848
|
||||
check(value == 2424920024888888848)
|
||||
lazySet(8424920024888888848)
|
||||
check(value == 8424920024888888848)
|
||||
check(getAndSet(8924920024888888848) == 8424920024888888848)
|
||||
check(value == 8924920024888888848)
|
||||
check(incrementAndGet() == 8924920024888888849) // fails
|
||||
check(value == 8924920024888888849)
|
||||
check(getAndDecrement() == 8924920024888888849)
|
||||
check(value == 8924920024888888848)
|
||||
check(getAndAdd(100000000000000000) == 8924920024888888848)
|
||||
check(value == 9024920024888888848)
|
||||
check(addAndGet(-9223372036854775807) == -198452011965886959)
|
||||
check(value == -198452011965886959)
|
||||
check(incrementAndGet() == -198452011965886958)
|
||||
check(value == -198452011965886958)
|
||||
check(decrementAndGet() == -198452011965886959)
|
||||
check(value == -198452011965886959)
|
||||
}
|
||||
|
||||
private inline fun AtomicRef<String?>.refExtension() {
|
||||
value = "aaa"
|
||||
check(value == "aaa")
|
||||
lazySet("bb")
|
||||
check(value == "bb")
|
||||
check(getAndSet("ccc") == "bb")
|
||||
check(value == "ccc")
|
||||
}
|
||||
|
||||
private inline fun AtomicBoolean.booleanExtensionArithmetic() {
|
||||
value = false
|
||||
check(!value)
|
||||
lazySet(true)
|
||||
check(value)
|
||||
check(getAndSet(true))
|
||||
check(compareAndSet(value, false))
|
||||
check(!value)
|
||||
}
|
||||
|
||||
fun testExtension() {
|
||||
a.intExtensionArithmetic()
|
||||
l.longExtensionArithmetic()
|
||||
s.refExtension()
|
||||
b.booleanExtensionArithmetic()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = ExtensionsTest()
|
||||
testClass.testScopedFieldGetters()
|
||||
testClass.testExtension()
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class InlineExtensionWithTypeParameterTest {
|
||||
abstract class Segment<S : Segment<S>>(val id: Int)
|
||||
class SemaphoreSegment(id: Int) : Segment<SemaphoreSegment>(id)
|
||||
|
||||
private inline fun <S : Segment<S>> AtomicRef<S>.foo(
|
||||
id: Int,
|
||||
startFrom: S
|
||||
): Int {
|
||||
lazySet(startFrom)
|
||||
return value.getSegmentId()
|
||||
}
|
||||
|
||||
private inline fun <S : Segment<S>> S.getSegmentId(): Int {
|
||||
var cur: S = this
|
||||
return cur.id
|
||||
}
|
||||
|
||||
private val sref = atomic(SemaphoreSegment(0))
|
||||
|
||||
fun testInlineExtensionWithTypeParameter() {
|
||||
val s = SemaphoreSegment(77)
|
||||
assertEquals(77, sref.foo(0, s))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = InlineExtensionWithTypeParameterTest()
|
||||
testClass.testInlineExtensionWithTypeParameter()
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LambdaTest {
|
||||
private val a = atomic(0)
|
||||
private val rs = atomic<String>("bbbb")
|
||||
|
||||
private inline fun <T> inlineLambda(
|
||||
arg: T,
|
||||
crossinline block: (T) -> Unit
|
||||
) = block(arg)
|
||||
|
||||
fun loopInLambda1(to: Int) = inlineLambda(to) sc@ { arg ->
|
||||
a.loop { value ->
|
||||
a.compareAndSet(value, arg)
|
||||
return@sc
|
||||
}
|
||||
}
|
||||
|
||||
fun loopInLambda2(to: Int) = inlineLambda(to) { arg1 ->
|
||||
inlineLambda(arg1) sc@ { arg2 ->
|
||||
a.loop { value ->
|
||||
a.compareAndSet(value, arg2)
|
||||
return@sc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loopInLambda2Ref(to: String) = inlineLambda(to) { arg1 ->
|
||||
inlineLambda(arg1) sc@ { arg2 ->
|
||||
rs.loop { value ->
|
||||
rs.compareAndSet(value, arg2)
|
||||
return@sc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
loopInLambda1(34)
|
||||
assertEquals(34, a.value)
|
||||
loopInLambda1(77)
|
||||
assertEquals(77, a.value)
|
||||
loopInLambda2Ref("bbb")
|
||||
assertEquals("bbb", rs.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LambdaTest()
|
||||
testClass.test()
|
||||
}
|
||||
Vendored
+57
@@ -0,0 +1,57 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LockFreeIntBitsTest {
|
||||
fun testBasic() {
|
||||
val bs = LockFreeIntBits()
|
||||
assertTrue(!bs[0])
|
||||
assertTrue(bs.bitSet(0))
|
||||
assertTrue(bs[0])
|
||||
assertTrue(!bs.bitSet(0))
|
||||
|
||||
assertTrue(!bs[1])
|
||||
assertTrue(bs.bitSet(1))
|
||||
assertTrue(bs[1])
|
||||
assertTrue(!bs.bitSet(1))
|
||||
assertTrue(!bs.bitSet(0))
|
||||
|
||||
assertTrue(bs[0])
|
||||
assertTrue(bs.bitClear(0))
|
||||
assertTrue(!bs.bitClear(0))
|
||||
|
||||
assertTrue(bs[1])
|
||||
}
|
||||
}
|
||||
|
||||
class LockFreeIntBits {
|
||||
private val bits = atomic(0)
|
||||
|
||||
private fun Int.mask() = 1 shl this
|
||||
|
||||
operator fun get(index: Int): Boolean = bits.value and index.mask() != 0
|
||||
|
||||
// User-defined private inline function
|
||||
private inline fun bitUpdate(check: (Int) -> Boolean, upd: (Int) -> Int): Boolean {
|
||||
bits.update {
|
||||
if (check(it)) return false
|
||||
upd(it)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fun bitSet(index: Int): Boolean {
|
||||
val mask = index.mask()
|
||||
return bitUpdate({ it and mask != 0 }, { it or mask })
|
||||
}
|
||||
|
||||
fun bitClear(index: Int): Boolean {
|
||||
val mask = index.mask()
|
||||
return bitUpdate({ it and mask == 0 }, { it and mask.inv() })
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LockFreeIntBitsTest()
|
||||
testClass.testBasic()
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LockTest {
|
||||
private val inProgressLock = atomic(false)
|
||||
|
||||
fun testLock() {
|
||||
var result = ""
|
||||
if (inProgressLock.tryAcquire()) {
|
||||
result = "OK"
|
||||
}
|
||||
assertEquals("OK", result)
|
||||
}
|
||||
}
|
||||
|
||||
// This function will be removed by transformer
|
||||
@Suppress("NOTHING_TO_INLINE")
|
||||
private inline fun AtomicBoolean.tryAcquire(): Boolean = compareAndSet(false, true)
|
||||
|
||||
// This function is here to test if the Kotlin metadata still consistent after transform
|
||||
// It is used in ReflectionTest, DO NOT REMOVE
|
||||
@Suppress("UNUSED_PARAMETER")
|
||||
fun <AA, BB : Number> String.reflectionTest(mapParam: Map<in AA, BB>): List<BB> = error("no impl")
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LockTest()
|
||||
testClass.testLock()
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class ParameterizedInlineFunExtensionTest {
|
||||
|
||||
private inline fun <S> AtomicRef<S>.foo(res1: S, res2: S, foo: (S) -> S): S {
|
||||
val res = bar(res1, res2)
|
||||
return res
|
||||
}
|
||||
|
||||
private inline fun <S> AtomicRef<S>.bar(res1: S, res2: S): S {
|
||||
return res2
|
||||
}
|
||||
|
||||
private val tail = atomic("aaa")
|
||||
|
||||
fun testClose() {
|
||||
assertEquals("bbb", tail.bar("aaa", "bbb"))
|
||||
val res = tail.foo("bbb", "ccc") { s -> s }
|
||||
assertEquals("ccc", res)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testParameterizedInlineFunExtensionTest() {
|
||||
val testClass = ParameterizedInlineFunExtensionTest()
|
||||
testClass.testClose()
|
||||
}
|
||||
+130
@@ -0,0 +1,130 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class IntArithmetic {
|
||||
private val _x = atomic(0)
|
||||
val x get() = _x.value
|
||||
|
||||
private val local = atomic(0)
|
||||
|
||||
private fun testGetValue() {
|
||||
_x.value = 5
|
||||
assertEquals(5, _x.value)
|
||||
var aValue = _x.value
|
||||
assertEquals(5, aValue)
|
||||
assertEquals(5, x)
|
||||
|
||||
local.value = 555
|
||||
aValue = local.value
|
||||
assertEquals(aValue, local.value)
|
||||
}
|
||||
|
||||
private fun testAtomicCallPlaces() {
|
||||
_x.value = 5
|
||||
_x.compareAndSet(5, 42)
|
||||
val res = _x.compareAndSet(42, 45)
|
||||
assertTrue(res)
|
||||
assertTrue(_x.compareAndSet(45, 77))
|
||||
assertFalse(_x.compareAndSet(95, 77))
|
||||
assertTrue(_x.compareAndSet(77, 88))
|
||||
}
|
||||
|
||||
private fun testInt() {
|
||||
_x.value = 0
|
||||
assertEquals(0, x)
|
||||
val update = 3
|
||||
assertEquals(0, _x.getAndSet(update))
|
||||
assertTrue(_x.compareAndSet(update, 8))
|
||||
_x.lazySet(1)
|
||||
assertEquals(1, x)
|
||||
assertEquals(1, _x.getAndSet(2))
|
||||
assertEquals(2, x)
|
||||
assertEquals(2, _x.getAndIncrement())
|
||||
assertEquals(3, x)
|
||||
assertEquals(3, _x.getAndDecrement())
|
||||
assertEquals(2, x)
|
||||
assertEquals(2, _x.getAndAdd(2))
|
||||
assertEquals(4, x)
|
||||
assertEquals(7, _x.addAndGet(3))
|
||||
assertEquals(7, x)
|
||||
assertEquals(8, _x.incrementAndGet())
|
||||
assertEquals(8, x)
|
||||
assertEquals(7, _x.decrementAndGet())
|
||||
assertEquals(7, x)
|
||||
assertTrue(_x.compareAndSet(7, 10))
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testGetValue()
|
||||
testAtomicCallPlaces()
|
||||
testInt()
|
||||
}
|
||||
}
|
||||
|
||||
class LongArithmetic {
|
||||
private val _x = atomic(4294967296)
|
||||
val x get() = _x.value
|
||||
private val y = atomic(5000000000)
|
||||
private val z = atomic(2424920024888888848)
|
||||
private val max = atomic(9223372036854775807)
|
||||
|
||||
fun testLong() {
|
||||
assertEquals(2424920024888888848, z.value)
|
||||
z.lazySet(8424920024888888848)
|
||||
assertEquals(8424920024888888848, z.value)
|
||||
assertEquals(8424920024888888848, z.getAndSet(8924920024888888848))
|
||||
assertEquals(8924920024888888848, z.value)
|
||||
assertEquals(8924920024888888849, z.incrementAndGet())
|
||||
assertEquals(8924920024888888849, z.value)
|
||||
assertEquals(8924920024888888849, z.getAndDecrement())
|
||||
assertEquals(8924920024888888848, z.value)
|
||||
assertEquals(8924920024888888848, z.getAndAdd(100000000000000000))
|
||||
assertEquals(9024920024888888848, z.value)
|
||||
assertEquals(-198452011965886959, z.addAndGet(-9223372036854775807))
|
||||
assertEquals(-198452011965886959, z.value)
|
||||
assertEquals(-198452011965886958, z.incrementAndGet())
|
||||
assertEquals(-198452011965886958, z.value)
|
||||
assertEquals(-198452011965886959, z.decrementAndGet())
|
||||
assertEquals(-198452011965886959, z.value)
|
||||
}
|
||||
}
|
||||
|
||||
class BooleanArithmetic {
|
||||
private val _x = atomic(false)
|
||||
val x get() = _x.value
|
||||
|
||||
fun testBoolean() {
|
||||
assertEquals(false, _x.value)
|
||||
assertFalse(x)
|
||||
_x.lazySet(true)
|
||||
assertTrue(x)
|
||||
assertTrue(_x.getAndSet(true))
|
||||
assertTrue(_x.compareAndSet(true, false))
|
||||
assertFalse(x)
|
||||
}
|
||||
}
|
||||
|
||||
class ReferenceArithmetic {
|
||||
private val _x = atomic<String?>(null)
|
||||
|
||||
fun testReference() {
|
||||
_x.value = "aaa"
|
||||
assertEquals("aaa", _x.value)
|
||||
_x.lazySet("bb")
|
||||
assertEquals("bb", _x.value)
|
||||
assertEquals("bb", _x.getAndSet("ccc"))
|
||||
assertEquals("ccc", _x.value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun test() {
|
||||
val intClass = IntArithmetic()
|
||||
intClass.test()
|
||||
val longClass = LongArithmetic()
|
||||
longClass.testLong()
|
||||
val booleanClass = BooleanArithmetic()
|
||||
booleanClass.testBoolean()
|
||||
val refClass = ReferenceArithmetic()
|
||||
refClass.testReference()
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class AtomicArrayTest {
|
||||
|
||||
fun testIntArray() {
|
||||
val A = AtomicArrayClass()
|
||||
assertTrue(A.intArr[0].compareAndSet(0, 3))
|
||||
assertEquals(0, A.intArr[1].value)
|
||||
A.intArr[0].lazySet(5)
|
||||
assertEquals(5, A.intArr[0].value + A.intArr[1].value + A.intArr[2].value)
|
||||
assertTrue(A.intArr[0].compareAndSet(5, 10))
|
||||
assertEquals(10, A.intArr[0].getAndDecrement())
|
||||
assertEquals(9, A.intArr[0].value)
|
||||
A.intArr[2].value = 2
|
||||
assertEquals(2, A.intArr[2].value)
|
||||
assertTrue(A.intArr[2].compareAndSet(2, 34))
|
||||
assertEquals(34, A.intArr[2].value)
|
||||
}
|
||||
|
||||
fun testLongArray() {
|
||||
val A = AtomicArrayClass()
|
||||
A.longArr[0].value = 2424920024888888848
|
||||
assertEquals(2424920024888888848, A.longArr[0].value)
|
||||
A.longArr[0].lazySet(8424920024888888848)
|
||||
assertEquals(8424920024888888848, A.longArr[0].value)
|
||||
val ac = A.longArr[0].value
|
||||
A.longArr[3].value = ac
|
||||
assertEquals(8424920024888888848, A.longArr[3].getAndSet(8924920024888888848))
|
||||
assertEquals(8924920024888888848, A.longArr[3].value)
|
||||
val ac1 = A.longArr[3].value
|
||||
A.longArr[4].value = ac1
|
||||
assertEquals(8924920024888888849, A.longArr[4].incrementAndGet())
|
||||
assertEquals(8924920024888888849, A.longArr[4].value)
|
||||
assertEquals(8924920024888888849, A.longArr[4].getAndDecrement())
|
||||
assertEquals(8924920024888888848, A.longArr[4].value)
|
||||
A.longArr[4].value = 8924920024888888848
|
||||
assertEquals(8924920024888888848, A.longArr[4].getAndAdd(100000000000000000))
|
||||
val ac2 = A.longArr[4].value
|
||||
A.longArr[1].value = ac2
|
||||
assertEquals(9024920024888888848, A.longArr[1].value)
|
||||
assertEquals(-198452011965886959, A.longArr[1].addAndGet(-9223372036854775807))
|
||||
assertEquals(-198452011965886959, A.longArr[1].value)
|
||||
assertEquals(-198452011965886958, A.longArr[1].incrementAndGet())
|
||||
assertEquals(-198452011965886958, A.longArr[1].value)
|
||||
assertEquals(-198452011965886959, A.longArr[1].decrementAndGet())
|
||||
assertEquals(-198452011965886959, A.longArr[1].value)
|
||||
}
|
||||
|
||||
fun testBooleanArray() {
|
||||
val A = AtomicArrayClass()
|
||||
assertFalse(A.booleanArr[1].value)
|
||||
assertTrue(A.booleanArr[1].compareAndSet(false, true))
|
||||
A.booleanArr[0].lazySet(true)
|
||||
assertFalse(A.booleanArr[2].getAndSet(true))
|
||||
assertTrue(A.booleanArr[0].value && A.booleanArr[1].value && A.booleanArr[2].value)
|
||||
A.booleanArr[0].value = false
|
||||
assertFalse(A.booleanArr[0].value)
|
||||
}
|
||||
|
||||
fun testRefArray() {
|
||||
val A = AtomicArrayClass()
|
||||
val a2 = ARef(2)
|
||||
val a3 = ARef(3)
|
||||
A.refArr[0].value = a2
|
||||
assertEquals(2, A.refArr[0].value!!.n)
|
||||
assertTrue(A.refArr[0].compareAndSet(a2, a3))
|
||||
assertEquals(3, A.refArr[0].value!!.n)
|
||||
val r0 = A.refArr[0].value
|
||||
A.refArr[3].value = r0
|
||||
assertEquals(3, A.refArr[3].value!!.n)
|
||||
val a = A.a.value
|
||||
assertTrue(A.refArr[3].compareAndSet(a3, a))
|
||||
}
|
||||
|
||||
fun testAnyArray() {
|
||||
val A = AtomicArrayClass()
|
||||
val s1 = "aaa"
|
||||
val s2 = "bbb"
|
||||
A.anyArr[0].value = s1
|
||||
assertEquals("aaa", A.anyArr[0].value)
|
||||
assertTrue(A.anyArr[0].compareAndSet(s1, s2))
|
||||
assertEquals("bbb", A.anyArr[0].value)
|
||||
val r0 = A.anyArr[0].value
|
||||
A.anyArr[3].value = r0
|
||||
assertEquals("bbb", A.anyArr[3].value)
|
||||
}
|
||||
}
|
||||
|
||||
private class AtomicArrayClass {
|
||||
val intArr = AtomicIntArray(10)
|
||||
val longArr = AtomicLongArray(10)
|
||||
val booleanArr = AtomicBooleanArray(10)
|
||||
val refArr = atomicArrayOfNulls<ARef>(10)
|
||||
val anyArr = atomicArrayOfNulls<Any?>(10)
|
||||
internal val a = atomic(ARef(8))
|
||||
}
|
||||
|
||||
data class ARef(val n: Int)
|
||||
|
||||
@Test
|
||||
fun test() {
|
||||
val testClass = AtomicArrayTest()
|
||||
testClass.testIntArray()
|
||||
testClass.testLongArray()
|
||||
testClass.testBooleanArray()
|
||||
testClass.testRefArray()
|
||||
testClass.testAnyArray()
|
||||
}
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class IndexArrayElementGetterTest {
|
||||
private val clazz = AtomicArrayClass()
|
||||
|
||||
fun fib(a: Int): Int = if (a == 0 || a == 1) a else fib(a - 1) + fib(a - 2)
|
||||
|
||||
fun testIndexArrayElementGetting() {
|
||||
clazz.intArr[8].value = 3
|
||||
val i = fib(4)
|
||||
val j = fib(5)
|
||||
assertEquals(3, clazz.intArr[i + j].value)
|
||||
assertEquals(3, clazz.intArr[fib(4) + fib(5)].value)
|
||||
clazz.longArr[3].value = 100
|
||||
assertEquals(100, clazz.longArr[fib(6) - fib(5)].value)
|
||||
assertEquals(100, clazz.longArr[(fib(6) + fib(4)) % 8].value)
|
||||
assertEquals(100, clazz.longArr[(fib(6) + fib(4)) % 8].value)
|
||||
assertEquals(100, clazz.longArr[(fib(4) + fib(5)) % fib(5)].value)
|
||||
}
|
||||
|
||||
private class AtomicArrayClass {
|
||||
val intArr = AtomicIntArray(10)
|
||||
val longArr = AtomicLongArray(10)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = IndexArrayElementGetterTest()
|
||||
testClass.testIndexArrayElementGetting()
|
||||
}
|
||||
Vendored
+33
@@ -0,0 +1,33 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
private class AAA {
|
||||
private val _counter = atomic(5L)
|
||||
val counterValue: Long get() = _counter.value
|
||||
val delegateCounterValue by _counter
|
||||
val lateInitInt: AtomicInt
|
||||
val intArr: AtomicIntArray
|
||||
|
||||
// test ensures that transformation does not change the order of initialization
|
||||
init {
|
||||
lateInitInt = atomic(10)
|
||||
assertTrue(lateInitInt.compareAndSet(10, 100))
|
||||
assertEquals(100, lateInitInt.value)
|
||||
intArr = AtomicIntArray(10)
|
||||
intArr[0].value = 10
|
||||
assertTrue(intArr[0].compareAndSet(10, 100))
|
||||
intArr[1].value = 20
|
||||
}
|
||||
|
||||
init {
|
||||
assertEquals(5L, _counter.value)
|
||||
assertEquals(5L,counterValue)
|
||||
assertEquals(5L, delegateCounterValue)
|
||||
assertEquals(120, intArr[0].value + intArr[1].value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val intClass = AAA()
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlinx.atomicfu.locks.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LateinitPropertiesTest {
|
||||
private val a: AtomicInt
|
||||
private val head: AtomicRef<String>
|
||||
private val dataRef: AtomicRef<Data>
|
||||
private val lateIntArr: AtomicIntArray
|
||||
private val lateRefArr: AtomicArray<String?>
|
||||
|
||||
private class Data(val n: Int)
|
||||
|
||||
init {
|
||||
a = atomic(0)
|
||||
head = atomic("AAA")
|
||||
lateIntArr = AtomicIntArray(55)
|
||||
val data = Data(77)
|
||||
dataRef = atomic(data)
|
||||
val size = 10
|
||||
lateRefArr = atomicArrayOfNulls<String?>(size)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
assertEquals(0, a.value)
|
||||
assertTrue(head.compareAndSet("AAA", "BBB"))
|
||||
assertEquals("BBB", head.value)
|
||||
assertEquals(0, lateIntArr[35].value)
|
||||
assertEquals(77, dataRef.value.n)
|
||||
assertEquals(null, lateRefArr[5].value)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LateinitPropertiesTest()
|
||||
testClass.test()
|
||||
}
|
||||
Vendored
+61
@@ -0,0 +1,61 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LockFreeLongCounterTest {
|
||||
private inline fun testWith(g: LockFreeLongCounter.() -> Long) {
|
||||
val c = LockFreeLongCounter()
|
||||
assertEquals(0L, c.g())
|
||||
assertEquals(1L, c.increment())
|
||||
assertEquals(1L, c.g())
|
||||
assertEquals(2L, c.increment())
|
||||
assertEquals(2L, c.g())
|
||||
}
|
||||
|
||||
fun testBasic() = testWith { get() }
|
||||
|
||||
fun testGetInner() = testWith { getInner() }
|
||||
|
||||
fun testAdd2() {
|
||||
val c = LockFreeLongCounter()
|
||||
c.add2()
|
||||
assertEquals(2L, c.get())
|
||||
c.add2()
|
||||
assertEquals(4L, c.get())
|
||||
}
|
||||
|
||||
fun testSetM2() {
|
||||
val c = LockFreeLongCounter()
|
||||
c.setM2()
|
||||
assertEquals(-2L, c.get())
|
||||
}
|
||||
}
|
||||
|
||||
class LockFreeLongCounter {
|
||||
private val counter = atomic(0L)
|
||||
|
||||
fun get(): Long = counter.value
|
||||
|
||||
fun increment(): Long = counter.incrementAndGet()
|
||||
|
||||
fun add2() = counter.getAndAdd(2)
|
||||
|
||||
fun setM2() {
|
||||
counter.value = -2L // LDC instruction here
|
||||
}
|
||||
|
||||
fun getInner(): Long = Inner().getFromOuter()
|
||||
|
||||
// testing how an inner class can get access to it
|
||||
private inner class Inner {
|
||||
fun getFromOuter(): Long = counter.value
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LockFreeLongCounterTest()
|
||||
testClass.testBasic()
|
||||
testClass.testAdd2()
|
||||
testClass.testSetM2()
|
||||
testClass.testGetInner()
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LockFreeQueueTest {
|
||||
fun testBasic() {
|
||||
val q = LockFreeQueue()
|
||||
assertEquals(-1, q.dequeue())
|
||||
q.enqueue(42)
|
||||
assertEquals(42, q.dequeue())
|
||||
assertEquals(-1, q.dequeue())
|
||||
q.enqueue(1)
|
||||
q.enqueue(2)
|
||||
assertEquals(1, q.dequeue())
|
||||
assertEquals(2, q.dequeue())
|
||||
assertEquals(-1, q.dequeue())
|
||||
}
|
||||
}
|
||||
|
||||
// MS-queue
|
||||
public class LockFreeQueue {
|
||||
private val head = atomic(Node(0))
|
||||
private val tail = atomic(head.value)
|
||||
|
||||
private class Node(val value: Int) {
|
||||
val next = atomic<Node?>(null)
|
||||
}
|
||||
|
||||
public fun enqueue(value: Int) {
|
||||
val node = Node(value)
|
||||
tail.loop { curTail ->
|
||||
val curNext = curTail.next.value
|
||||
if (curNext != null) {
|
||||
tail.compareAndSet(curTail, curNext)
|
||||
return@loop
|
||||
}
|
||||
if (curTail.next.compareAndSet(null, node)) {
|
||||
tail.compareAndSet(curTail, node)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public fun dequeue(): Int {
|
||||
head.loop { curHead ->
|
||||
val next = curHead.next.value ?: return -1
|
||||
if (head.compareAndSet(curHead, next)) return next.value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LockFreeQueueTest()
|
||||
testClass.testBasic()
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LockFreeStackTest {
|
||||
fun testClear() {
|
||||
val s = LockFreeStack<String>()
|
||||
assertTrue(s.isEmpty())
|
||||
s.pushLoop("A")
|
||||
assertTrue(!s.isEmpty())
|
||||
s.clear()
|
||||
assertTrue(s.isEmpty())
|
||||
}
|
||||
|
||||
fun testPushPopLoop() {
|
||||
val s = LockFreeStack<String>()
|
||||
assertTrue(s.isEmpty())
|
||||
s.pushLoop("A")
|
||||
assertTrue(!s.isEmpty())
|
||||
assertEquals("A", s.popLoop())
|
||||
assertTrue(s.isEmpty())
|
||||
}
|
||||
|
||||
fun testPushPopUpdate() {
|
||||
val s = LockFreeStack<String>()
|
||||
assertTrue(s.isEmpty())
|
||||
s.pushUpdate("A")
|
||||
assertTrue(!s.isEmpty())
|
||||
assertEquals("A", s.popUpdate())
|
||||
assertTrue(s.isEmpty())
|
||||
}
|
||||
}
|
||||
|
||||
class LockFreeStack<T> {
|
||||
private val top = atomic<Node<T>?>(null)
|
||||
|
||||
private class Node<T>(val value: T, val next: Node<T>?)
|
||||
|
||||
fun isEmpty() = top.value == null
|
||||
|
||||
fun clear() { top.value = null }
|
||||
|
||||
fun pushLoop(value: T) {
|
||||
top.loop { cur ->
|
||||
val upd = Node(value, cur)
|
||||
if (top.compareAndSet(cur, upd)) return
|
||||
}
|
||||
}
|
||||
|
||||
fun popLoop(): T? {
|
||||
top.loop { cur ->
|
||||
if (cur == null) return null
|
||||
if (top.compareAndSet(cur, cur.next)) return cur.value
|
||||
}
|
||||
}
|
||||
|
||||
fun pushUpdate(value: T) {
|
||||
top.update { cur -> Node(value, cur) }
|
||||
}
|
||||
|
||||
fun popUpdate(): T? =
|
||||
top.getAndUpdate { cur -> cur?.next } ?.value
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LockFreeStackTest()
|
||||
testClass.testClear()
|
||||
testClass.testPushPopLoop()
|
||||
testClass.testPushPopUpdate()
|
||||
}
|
||||
+128
@@ -0,0 +1,128 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class LoopTest {
|
||||
private val a = atomic(0)
|
||||
private val a1 = atomic(1)
|
||||
private val b = atomic(true)
|
||||
private val l = atomic(5000000000L)
|
||||
private val r = atomic<A>(A("aaaa"))
|
||||
private val rs = atomic<String>("bbbb")
|
||||
|
||||
class A(val s: String)
|
||||
|
||||
fun atomicfuIntLoopTest() {
|
||||
a.loop { value ->
|
||||
if (a.compareAndSet(value, 777)) {
|
||||
assertEquals(777, a.value)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun atomicfuBooleanLoopTest() {
|
||||
b.loop { value ->
|
||||
assertTrue(value)
|
||||
if (!b.value) return
|
||||
if (b.compareAndSet(value, false)) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun atomicfuLongLoopTest() {
|
||||
l.loop { cur ->
|
||||
if (l.compareAndSet(5000000003, 9000000000)) {
|
||||
return
|
||||
} else {
|
||||
l.incrementAndGet()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun atomicfuRefLoopTest() {
|
||||
r.loop { cur ->
|
||||
assertEquals("aaaa", cur.s)
|
||||
if (r.compareAndSet(cur, A("bbbb"))) {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun atomicfuLoopTest() {
|
||||
atomicfuIntLoopTest()
|
||||
assertEquals(777, a.value)
|
||||
atomicfuBooleanLoopTest()
|
||||
assertFalse(b.value)
|
||||
atomicfuLongLoopTest()
|
||||
assertEquals(9000000000, l.value)
|
||||
atomicfuRefLoopTest()
|
||||
assertEquals("bbbb", r.value.s)
|
||||
}
|
||||
|
||||
fun atomicfuUpdateTest() {
|
||||
a.value = 0
|
||||
a.update { value ->
|
||||
val newValue = value + 1000
|
||||
if (newValue >= 0) Int.MAX_VALUE else newValue
|
||||
}
|
||||
assertEquals(Int.MAX_VALUE, a.value)
|
||||
b.update { true }
|
||||
assertEquals(true, b.value)
|
||||
assertTrue(b.value)
|
||||
l.value = 0L
|
||||
l.update { cur ->
|
||||
val newValue = cur + 1000
|
||||
if (newValue >= 0L) Long.MAX_VALUE else newValue
|
||||
}
|
||||
assertEquals(Long.MAX_VALUE, l.value)
|
||||
r.lazySet(A("aaaa"))
|
||||
r.update { cur ->
|
||||
A("cccc${cur.s}")
|
||||
}
|
||||
assertEquals("ccccaaaa", r.value.s)
|
||||
}
|
||||
|
||||
fun atomicfuUpdateAndGetTest() {
|
||||
val res1 = a.updateAndGet { value ->
|
||||
if (value >= 0) Int.MAX_VALUE else value
|
||||
}
|
||||
assertEquals(Int.MAX_VALUE, res1)
|
||||
assertEquals(true, b.updateAndGet { true })
|
||||
assertEquals(Long.MAX_VALUE, l.updateAndGet { cur ->
|
||||
if (cur >= 0L) Long.MAX_VALUE else cur
|
||||
})
|
||||
r.lazySet(A("aaaa"))
|
||||
val res3 = r.updateAndGet { cur ->
|
||||
A("cccc${cur.s}")
|
||||
}
|
||||
assertEquals("ccccaaaa", res3.s)
|
||||
}
|
||||
|
||||
fun atomicfuGetAndUpdateTest() {
|
||||
a.getAndUpdate { value ->
|
||||
if (value >= 0) Int.MAX_VALUE else value
|
||||
}
|
||||
assertEquals(Int.MAX_VALUE, a.value)
|
||||
b.getAndUpdate { true }
|
||||
assertTrue(b.value)
|
||||
l.getAndUpdate { cur ->
|
||||
if (cur >= 0L) Long.MAX_VALUE else cur
|
||||
}
|
||||
assertEquals(Long.MAX_VALUE, l.value)
|
||||
r.lazySet(A("aaaa"))
|
||||
r.getAndUpdate { cur ->
|
||||
A("cccc${cur.s}")
|
||||
}
|
||||
assertEquals("ccccaaaa", r.value.s)
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = LoopTest()
|
||||
testClass.atomicfuLoopTest()
|
||||
testClass.atomicfuUpdateTest()
|
||||
testClass.atomicfuUpdateAndGetTest()
|
||||
testClass.atomicfuGetAndUpdateTest()
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class MultiInitTest {
|
||||
fun testBasic() {
|
||||
val t = MultiInit()
|
||||
check(t.incA() == 1)
|
||||
check(t.incA() == 2)
|
||||
check(t.incB() == 1)
|
||||
check(t.incB() == 2)
|
||||
}
|
||||
}
|
||||
|
||||
class MultiInit {
|
||||
private val a = atomic(0)
|
||||
private val b = atomic(0)
|
||||
|
||||
fun incA() = a.incrementAndGet()
|
||||
fun incB() = b.incrementAndGet()
|
||||
|
||||
companion object {
|
||||
fun foo() {} // just to force some clinit in outer file
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = MultiInitTest()
|
||||
testClass.testBasic()
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class AA(val value: Int) {
|
||||
val b = B(value + 1)
|
||||
val c = C(D(E(value + 1)))
|
||||
|
||||
fun updateToB(affected: Any): Boolean {
|
||||
(affected as AtomicState).state.compareAndSet(this, b)
|
||||
return (affected.state.value is B && (affected.state.value as B).value == value + 1)
|
||||
}
|
||||
|
||||
fun manyProperties(affected: Any): Boolean {
|
||||
(affected as AtomicState).state.compareAndSet(this, c.d.e)
|
||||
return (affected.state.value is E && (affected.state.value as E).x == value + 1)
|
||||
}
|
||||
}
|
||||
|
||||
class B (val value: Int)
|
||||
|
||||
class C (val d: D)
|
||||
class D (val e: E)
|
||||
class E (val x: Int)
|
||||
|
||||
|
||||
private class AtomicState(value: Any) {
|
||||
val state = atomic<Any?>(value)
|
||||
}
|
||||
|
||||
class ScopeTest {
|
||||
fun scopeTest() {
|
||||
val a = AA(0)
|
||||
val affected: Any = AtomicState(a)
|
||||
check(a.updateToB(affected))
|
||||
val a1 = AA(0)
|
||||
val affected1: Any = AtomicState(a1)
|
||||
check(a1.manyProperties(affected1))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = ScopeTest()
|
||||
testClass.scopeTest()
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class SimpleLockTest {
|
||||
fun withLock() {
|
||||
val lock = SimpleLock()
|
||||
val result = lock.withLock {
|
||||
"OK"
|
||||
}
|
||||
assertEquals("OK", result)
|
||||
}
|
||||
}
|
||||
|
||||
class SimpleLock {
|
||||
private val _locked = atomic(0)
|
||||
|
||||
fun <T> withLock(block: () -> T): T {
|
||||
// this contrieves construct triggers Kotlin compiler to reuse local variable slot #2 for
|
||||
// the exception in `finally` clause
|
||||
try {
|
||||
_locked.loop { locked ->
|
||||
check(locked == 0)
|
||||
if (!_locked.compareAndSet(0, 1)) return@loop // continue
|
||||
return block()
|
||||
}
|
||||
} finally {
|
||||
_locked.value = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = SimpleLockTest()
|
||||
testClass.withLock()
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
private val topLevelS = atomic<Any>(arrayOf("A", "B"))
|
||||
|
||||
class UncheckedCastTest {
|
||||
private val s = atomic<Any>("AAA")
|
||||
private val bs = atomic<Any?>(null)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun testAtomicValUncheckedCast() {
|
||||
assertEquals((s as AtomicRef<String>).value, "AAA")
|
||||
bs.lazySet(arrayOf(arrayOf(Box(1), Box(2))))
|
||||
assertEquals((bs as AtomicRef<Array<Array<Box>>>).value[0]!![0].b * 10, 10)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun testTopLevelValUnchekedCast() {
|
||||
assertEquals((topLevelS as AtomicRef<Array<String>>).value[1], "B")
|
||||
}
|
||||
|
||||
private data class Box(val b: Int)
|
||||
|
||||
@Suppress("NOTHING_TO_INLINE", "UNCHECKED_CAST")
|
||||
private inline fun <T> AtomicRef<T>.getString(): String =
|
||||
(this as AtomicRef<String>).value
|
||||
|
||||
fun testInlineFunc() {
|
||||
assertEquals("AAA", s.getString())
|
||||
}
|
||||
|
||||
private val a = atomicArrayOfNulls<Any?>(10)
|
||||
|
||||
fun testArrayValueUncheckedCast() {
|
||||
a[0].value = "OK"
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
assertEquals("OK", (a[0] as AtomicRef<String>).value)
|
||||
}
|
||||
|
||||
fun testArrayValueUncheckedCastInlineFunc() {
|
||||
a[0].value = "OK"
|
||||
assertEquals("OK", a[0].getString())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = UncheckedCastTest()
|
||||
testClass.testAtomicValUncheckedCast()
|
||||
testClass.testTopLevelValUnchekedCast()
|
||||
testClass.testArrayValueUncheckedCast()
|
||||
testClass.testArrayValueUncheckedCastInlineFunc()
|
||||
testClass.testInlineFunc()
|
||||
}
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
private val _topLevelInt = atomic(42)
|
||||
var topLevelInt: Int by _topLevelInt
|
||||
|
||||
private var topLevelVolatile by atomic(56)
|
||||
|
||||
class DelegatedProperties {
|
||||
// Delegated properties should be declared in the same scope as the original atomic values
|
||||
private val _a = atomic(42)
|
||||
var a: Int by _a
|
||||
private var privateA: Int by _a
|
||||
|
||||
private val _l = atomic(55555555555)
|
||||
private var l: Long by _l
|
||||
|
||||
private val _b = atomic(false)
|
||||
private var b: Boolean by _b
|
||||
|
||||
private val _ref = atomic(A(B(77)))
|
||||
private var ref: A by _ref
|
||||
|
||||
private var vInt by atomic(77)
|
||||
|
||||
private var vLong by atomic(777777777)
|
||||
|
||||
private var vBoolean by atomic(false)
|
||||
|
||||
private var vRef by atomic(A(B(77)))
|
||||
|
||||
class A (val b: B)
|
||||
class B (val n: Int)
|
||||
|
||||
fun testDelegatedAtomicInt() {
|
||||
assertEquals(42, a)
|
||||
assertEquals(42, privateA)
|
||||
_a.compareAndSet(42, 56)
|
||||
assertEquals(56, a)
|
||||
assertEquals(56, privateA)
|
||||
a = 77
|
||||
_a.compareAndSet(77, 66)
|
||||
privateA = 88
|
||||
_a.compareAndSet(88, 66)
|
||||
assertEquals(66, _a.value)
|
||||
assertEquals(66, a)
|
||||
assertEquals(66, privateA)
|
||||
|
||||
val aValue = a + privateA
|
||||
assertEquals(132, aValue)
|
||||
}
|
||||
|
||||
fun testDelegatedAtomicLong() {
|
||||
assertEquals(55555555555, l)
|
||||
_l.getAndIncrement()
|
||||
assertEquals(55555555556, l)
|
||||
l = 7777777777777
|
||||
assertTrue(_l.compareAndSet(7777777777777, 66666666666))
|
||||
assertEquals(66666666666, _l.value)
|
||||
assertEquals(66666666666, l)
|
||||
}
|
||||
|
||||
fun testDelegatedAtomicBoolean() {
|
||||
assertEquals(false, b)
|
||||
_b.lazySet(true)
|
||||
assertEquals(true, b)
|
||||
b = false
|
||||
assertTrue(_b.compareAndSet(false, true))
|
||||
assertEquals(true, _b.value)
|
||||
assertEquals(true, b)
|
||||
}
|
||||
|
||||
fun testDelegatedAtomicRef() {
|
||||
assertEquals(77, ref.b.n)
|
||||
_ref.lazySet(A(B(66)))
|
||||
assertEquals(66, ref.b.n)
|
||||
assertTrue(_ref.compareAndSet(_ref.value, A(B(56))))
|
||||
assertEquals(56, ref.b.n)
|
||||
ref = A(B(99))
|
||||
assertEquals(99, _ref.value.b.n)
|
||||
}
|
||||
|
||||
fun testVolatileInt() {
|
||||
assertEquals(77, vInt)
|
||||
vInt = 55
|
||||
assertEquals(110, vInt * 2)
|
||||
}
|
||||
|
||||
fun testVolatileLong() {
|
||||
assertEquals(777777777, vLong)
|
||||
vLong = 55
|
||||
assertEquals(55, vLong)
|
||||
}
|
||||
|
||||
fun testVolatileBoolean() {
|
||||
assertEquals(false, vBoolean)
|
||||
vBoolean = true
|
||||
assertEquals(true, vBoolean)
|
||||
}
|
||||
|
||||
fun testVolatileRef() {
|
||||
assertEquals(77, vRef.b.n)
|
||||
vRef = A(B(99))
|
||||
assertEquals(99, vRef.b.n)
|
||||
}
|
||||
|
||||
fun testDelegatedVariablesFlow() {
|
||||
_a.lazySet(55)
|
||||
assertEquals(55, _a.value)
|
||||
assertEquals(55, a)
|
||||
var aValue = a
|
||||
assertEquals(55, aValue)
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testDelegatedAtomicInt()
|
||||
testDelegatedAtomicLong()
|
||||
testDelegatedAtomicBoolean()
|
||||
testDelegatedAtomicRef()
|
||||
testVolatileInt()
|
||||
testVolatileBoolean()
|
||||
testVolatileLong()
|
||||
testVolatileRef()
|
||||
testDelegatedVariablesFlow()
|
||||
}
|
||||
}
|
||||
|
||||
fun testTopLevelDelegatedProperties() {
|
||||
assertEquals(42, topLevelInt)
|
||||
_topLevelInt.compareAndSet(42, 56)
|
||||
assertEquals(56, topLevelInt)
|
||||
topLevelInt = 77
|
||||
_topLevelInt.compareAndSet(77, 66)
|
||||
assertEquals(66, _topLevelInt.value)
|
||||
assertEquals(66, topLevelInt)
|
||||
}
|
||||
|
||||
fun testTopLevelVolatileProperties() {
|
||||
assertEquals(56, topLevelVolatile)
|
||||
topLevelVolatile = 55
|
||||
assertEquals(110, topLevelVolatile * 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = DelegatedProperties()
|
||||
testClass.test()
|
||||
testTopLevelDelegatedProperties()
|
||||
testTopLevelVolatileProperties()
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
import kotlinx.atomicfu.locks.*
|
||||
import kotlin.test.*
|
||||
|
||||
class ReentrantLockFieldTest {
|
||||
private val lock = reentrantLock()
|
||||
private var state = 0
|
||||
|
||||
fun testLock() {
|
||||
lock.withLock {
|
||||
state = 1
|
||||
}
|
||||
assertEquals(1, state)
|
||||
assertTrue(lock.tryLock())
|
||||
lock.unlock()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = ReentrantLockFieldTest()
|
||||
testClass.testLock()
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
import kotlinx.atomicfu.locks.*
|
||||
import kotlin.test.*
|
||||
|
||||
class SynchronizedObjectTest : SynchronizedObject() {
|
||||
|
||||
fun testSync() {
|
||||
val result = synchronized(this) { bar() }
|
||||
assertEquals("OK", result)
|
||||
}
|
||||
|
||||
private fun bar(): String =
|
||||
synchronized(this) {
|
||||
"OK"
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val testClass = SynchronizedObjectTest()
|
||||
testClass.testSync()
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
import kotlin.random.*
|
||||
|
||||
private object Provider {
|
||||
private val port = atomic(Random.nextInt(20, 90) * 100)
|
||||
fun next(): Int = port.incrementAndGet()
|
||||
|
||||
private val _l = atomic(2424920024888888848)
|
||||
fun getL() = _l.incrementAndGet()
|
||||
|
||||
val _ref = atomic<String?>(null)
|
||||
|
||||
val _x = atomic(false)
|
||||
|
||||
val intArr = AtomicIntArray(10)
|
||||
val longArr = AtomicLongArray(10)
|
||||
val refArr = atomicArrayOfNulls<Any?>(5)
|
||||
}
|
||||
|
||||
private object DelegatedProvider {
|
||||
internal val _a = atomic(42)
|
||||
var a: Int by _a
|
||||
|
||||
var vInt by atomic(77)
|
||||
}
|
||||
|
||||
private fun testFieldInObject() {
|
||||
val port = Provider.next()
|
||||
assertEquals(port + 1, Provider.next())
|
||||
|
||||
assertEquals(2424920024888888849, Provider.getL())
|
||||
|
||||
Provider._ref.compareAndSet(null, "abc")
|
||||
assertEquals("abc", Provider._ref.value)
|
||||
|
||||
assertFalse(Provider._x.value)
|
||||
|
||||
Provider.intArr[8].value = 454
|
||||
assertEquals(455, Provider.intArr[8].incrementAndGet())
|
||||
|
||||
Provider.longArr[8].value = 4544096409680468
|
||||
assertEquals(4544096409680470, Provider.longArr[8].addAndGet(2))
|
||||
|
||||
Provider.refArr[1].value = Provider._ref.value
|
||||
assertEquals("abc", Provider.refArr[1].value)
|
||||
}
|
||||
|
||||
private fun testDelegatedPropertiesInObject() {
|
||||
assertEquals(42, DelegatedProvider.a)
|
||||
DelegatedProvider._a.compareAndSet(42, 56)
|
||||
assertEquals(56, DelegatedProvider.a)
|
||||
DelegatedProvider.a = 77
|
||||
DelegatedProvider._a.compareAndSet(77, 66)
|
||||
assertEquals(66, DelegatedProvider._a.value)
|
||||
assertEquals(66, DelegatedProvider.a)
|
||||
|
||||
assertEquals(77, DelegatedProvider.vInt)
|
||||
DelegatedProvider.vInt = 55
|
||||
assertEquals(110, DelegatedProvider.vInt * 2)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
testFieldInObject()
|
||||
testDelegatedPropertiesInObject()
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
private val a = atomic(0)
|
||||
private val b = atomic(2424920024888888848)
|
||||
private val c = atomic(true)
|
||||
private val abcNode = atomic(ANode(BNode(CNode(8))))
|
||||
private val any = atomic<Any?>(null)
|
||||
|
||||
internal val a_internal = atomic(0)
|
||||
internal val b_internal = atomic(2424920024888888848)
|
||||
internal val c_internal = atomic(true)
|
||||
internal val abcNode_internal = atomic(ANode(BNode(CNode(8))))
|
||||
internal val any_internal = atomic<Any?>(null)
|
||||
|
||||
private val intArr = AtomicIntArray(3)
|
||||
private val longArr = AtomicLongArray(5)
|
||||
private val booleanArr = AtomicBooleanArray(4)
|
||||
private val refArr = atomicArrayOfNulls<ANode<BNode<CNode>>>(5)
|
||||
private val anyRefArr = atomicArrayOfNulls<Any>(10)
|
||||
|
||||
private val stringAtomicNullArr = atomicArrayOfNulls<String>(10)
|
||||
|
||||
class TopLevelPrimitiveTest {
|
||||
|
||||
fun testTopLevelInt() {
|
||||
assertEquals(0, a.value)
|
||||
assertEquals(0, a.getAndSet(3))
|
||||
assertTrue(a.compareAndSet(3, 8))
|
||||
a.lazySet(1)
|
||||
assertEquals(1, a.value)
|
||||
assertEquals(1, a.getAndSet(2))
|
||||
assertEquals(2, a.value)
|
||||
assertEquals(2, a.getAndIncrement())
|
||||
assertEquals(3, a.value)
|
||||
assertEquals(3, a.getAndDecrement())
|
||||
assertEquals(2, a.value)
|
||||
assertEquals(2, a.getAndAdd(2))
|
||||
assertEquals(4, a.value)
|
||||
assertEquals(7, a.addAndGet(3))
|
||||
assertEquals(7, a.value)
|
||||
assertEquals(8, a.incrementAndGet())
|
||||
assertEquals(8, a.value)
|
||||
assertEquals(7, a.decrementAndGet())
|
||||
assertEquals(7, a.value)
|
||||
assertTrue(a.compareAndSet(7, 10))
|
||||
}
|
||||
|
||||
fun testTopLevelLong() {
|
||||
assertEquals(2424920024888888848, b.value)
|
||||
b.lazySet(8424920024888888848)
|
||||
assertEquals(8424920024888888848, b.value)
|
||||
assertEquals(8424920024888888848, b.getAndSet(8924920024888888848))
|
||||
assertEquals(8924920024888888848, b.value)
|
||||
assertEquals(8924920024888888849, b.incrementAndGet())
|
||||
assertEquals(8924920024888888849, b.value)
|
||||
assertEquals(8924920024888888849, b.getAndDecrement())
|
||||
assertEquals(8924920024888888848, b.value)
|
||||
assertEquals(8924920024888888848, b.getAndAdd(100000000000000000))
|
||||
assertEquals(9024920024888888848, b.value)
|
||||
assertEquals(-198452011965886959, b.addAndGet(-9223372036854775807))
|
||||
assertEquals(-198452011965886959, b.value)
|
||||
assertEquals(-198452011965886958, b.incrementAndGet())
|
||||
assertEquals(-198452011965886958, b.value)
|
||||
assertEquals(-198452011965886959, b.decrementAndGet())
|
||||
assertEquals(-198452011965886959, b.value)
|
||||
}
|
||||
|
||||
fun testTopLevelBoolean() {
|
||||
assertTrue(c.value)
|
||||
c.lazySet(false)
|
||||
assertFalse(c.value)
|
||||
assertTrue(!c.getAndSet(true))
|
||||
assertTrue(c.compareAndSet(true, false))
|
||||
assertFalse(c.value)
|
||||
}
|
||||
|
||||
fun testTopLevelRef() {
|
||||
assertEquals(8, abcNode.value.b.c.d)
|
||||
val newNode = ANode(BNode(CNode(76)))
|
||||
assertEquals(8, abcNode.getAndSet(newNode).b.c.d)
|
||||
assertEquals(76, abcNode.value.b.c.d)
|
||||
val l = IntArray(4){i -> i}
|
||||
any.lazySet(l)
|
||||
assertEquals(2, (any.value as IntArray)[2])
|
||||
}
|
||||
|
||||
fun testTopLevelArrayOfNulls() {
|
||||
assertEquals(null, stringAtomicNullArr[0].value)
|
||||
assertTrue(stringAtomicNullArr[0].compareAndSet(null, "aa"))
|
||||
stringAtomicNullArr[1].lazySet("aa")
|
||||
assertTrue(stringAtomicNullArr[0].value == stringAtomicNullArr[1].value)
|
||||
}
|
||||
}
|
||||
|
||||
class TopLevelArrayTest {
|
||||
|
||||
fun testIntArray() {
|
||||
assertTrue(intArr[0].compareAndSet(0, 3))
|
||||
assertEquals(0, intArr[1].value)
|
||||
intArr[0].lazySet(5)
|
||||
assertEquals(5, intArr[0].value + intArr[1].value + intArr[2].value)
|
||||
assertTrue(intArr[0].compareAndSet(5, 10))
|
||||
assertEquals(10, intArr[0].getAndDecrement())
|
||||
assertEquals(9, intArr[0].value)
|
||||
intArr[2].value = 2
|
||||
assertEquals(2, intArr[2].value)
|
||||
assertTrue(intArr[2].compareAndSet(2, 34))
|
||||
assertEquals(34, intArr[2].value)
|
||||
}
|
||||
|
||||
fun testLongArray() {
|
||||
longArr[0].value = 2424920024888888848
|
||||
assertEquals(2424920024888888848, longArr[0].value)
|
||||
longArr[0].lazySet(8424920024888888848)
|
||||
assertEquals(8424920024888888848, longArr[0].value)
|
||||
val ac = longArr[0].value
|
||||
longArr[3].value = ac
|
||||
assertEquals(8424920024888888848, longArr[3].getAndSet(8924920024888888848))
|
||||
assertEquals(8924920024888888848, longArr[3].value)
|
||||
val ac1 = longArr[3].value
|
||||
longArr[4].value = ac1
|
||||
assertEquals(8924920024888888849, longArr[4].incrementAndGet())
|
||||
assertEquals(8924920024888888849, longArr[4].value)
|
||||
assertEquals(8924920024888888849, longArr[4].getAndDecrement())
|
||||
assertEquals(8924920024888888848, longArr[4].value)
|
||||
longArr[4].value = 8924920024888888848
|
||||
assertEquals(8924920024888888848, longArr[4].getAndAdd(100000000000000000))
|
||||
val ac2 = longArr[4].value
|
||||
longArr[1].value = ac2
|
||||
assertEquals(9024920024888888848, longArr[1].value)
|
||||
assertEquals(-198452011965886959, longArr[1].addAndGet(-9223372036854775807))
|
||||
assertEquals(-198452011965886959, longArr[1].value)
|
||||
assertEquals(-198452011965886958, longArr[1].incrementAndGet())
|
||||
assertEquals(-198452011965886958, longArr[1].value)
|
||||
assertEquals(-198452011965886959, longArr[1].decrementAndGet())
|
||||
assertEquals(-198452011965886959, longArr[1].value)
|
||||
}
|
||||
|
||||
fun testBooleanArray() {
|
||||
assertFalse(booleanArr[1].value)
|
||||
booleanArr[1].compareAndSet(false, true)
|
||||
booleanArr[0].lazySet(true)
|
||||
assertFalse(booleanArr[2].getAndSet(true))
|
||||
assertTrue(booleanArr[0].value && booleanArr[1].value && booleanArr[2].value)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
fun testRefArray() {
|
||||
val a2 = ANode(BNode(CNode(2)))
|
||||
val a3 = ANode(BNode(CNode(3)))
|
||||
refArr[0].value = a2
|
||||
assertEquals(2, refArr[0].value!!.b.c.d)
|
||||
assertTrue(refArr[0].compareAndSet(a2, a3))
|
||||
assertEquals(3, refArr[0].value!!.b.c.d)
|
||||
val r0 = refArr[0].value
|
||||
refArr[3].value = r0
|
||||
assertEquals(3, refArr[3].value!!.b.c.d)
|
||||
val a = abcNode.value
|
||||
assertTrue(refArr[3].compareAndSet(a3, a))
|
||||
}
|
||||
}
|
||||
|
||||
data class ANode<T>(val b: T)
|
||||
data class BNode<T>(val c: T)
|
||||
data class CNode(val d: Int)
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
val primitiveTest = TopLevelPrimitiveTest()
|
||||
primitiveTest.testTopLevelInt()
|
||||
primitiveTest.testTopLevelLong()
|
||||
primitiveTest.testTopLevelBoolean()
|
||||
primitiveTest.testTopLevelRef()
|
||||
primitiveTest.testTopLevelArrayOfNulls()
|
||||
|
||||
val arrayTest = TopLevelArrayTest()
|
||||
arrayTest.testIntArray()
|
||||
arrayTest.testLongArray()
|
||||
arrayTest.testBooleanArray()
|
||||
arrayTest.testRefArray()
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import kotlinx.atomicfu.*
|
||||
import kotlin.test.*
|
||||
|
||||
class TraceTest {
|
||||
private val defaultTrace = Trace()
|
||||
private val a1 = atomic(5, defaultTrace)
|
||||
|
||||
private val traceWithSize = Trace(30)
|
||||
private val a2 = atomic(1, traceWithSize)
|
||||
|
||||
private val traceWithFormat = Trace(format = TraceFormat { i, text -> "[$i: $text]" })
|
||||
private val a = atomic(0, traceWithFormat)
|
||||
|
||||
private val traceWithSizeAndFormat = Trace(30, TraceFormat { id, text -> "$id: $text"})
|
||||
private val a3 = atomic(2)
|
||||
|
||||
private val shortTrace = Trace(4)
|
||||
private val s = atomic(0, shortTrace.named("s"))
|
||||
|
||||
fun testDefaultTrace() {
|
||||
val oldValue = a1.value
|
||||
defaultTrace { "before CAS value = $oldValue" }
|
||||
val res = a1.compareAndSet(oldValue, oldValue * 10)
|
||||
val newValue = a1.value
|
||||
defaultTrace { "after CAS value = $newValue" }
|
||||
}
|
||||
|
||||
fun testTraceWithSize() {
|
||||
val oldValue = a2.value
|
||||
traceWithSize { "before CAS value = $oldValue" }
|
||||
assertTrue(a2.compareAndSet(oldValue, oldValue * 10))
|
||||
traceWithSize { "after CAS value = ${a2.value}" }
|
||||
traceWithSize { "before getAndDecrement value = ${a2.value}" }
|
||||
a2.getAndDecrement()
|
||||
assertEquals(9, a2.value)
|
||||
traceWithSize { "after getAndDecrement value = ${a2.value}" }
|
||||
}
|
||||
|
||||
fun testTraceWithFormat() {
|
||||
val oldValue = a3.value
|
||||
traceWithFormat { "before CAS value = $oldValue" }
|
||||
assertTrue(a3.compareAndSet(oldValue, oldValue * 10))
|
||||
traceWithFormat { "after CAS value = ${a3.value}" }
|
||||
traceWithFormat { "before getAndDecrement value = ${a3.value}" }
|
||||
a3.getAndDecrement()
|
||||
assertEquals(19, a3.value)
|
||||
traceWithFormat { "after getAndDecrement value = ${a3.value}" }
|
||||
}
|
||||
|
||||
fun testNamedTrace() {
|
||||
s.value = 5
|
||||
shortTrace { "before CAS value = ${s.value}" }
|
||||
s.compareAndSet(5, -2)
|
||||
assertEquals(-2, s.value)
|
||||
shortTrace { "after CAS value = ${s.value}" }
|
||||
}
|
||||
|
||||
private enum class Status { START, END }
|
||||
|
||||
fun testMultipleAppend() {
|
||||
val i = 1
|
||||
traceWithFormat.append(i, Status.START)
|
||||
assertEquals(0, a.value)
|
||||
a.incrementAndGet()
|
||||
traceWithFormat.append(i, a.value, "incAndGet")
|
||||
assertEquals(1, a.value)
|
||||
a.lazySet(10)
|
||||
traceWithFormat.append(i, a.value, "lazySet")
|
||||
assertEquals(10, a.value)
|
||||
traceWithFormat.append(i, Status.END)
|
||||
}
|
||||
|
||||
fun testTraceInBlock() {
|
||||
a1.lazySet(5)
|
||||
if (a1.value == 5) {
|
||||
defaultTrace { "Value checked" }
|
||||
if (a1.compareAndSet(5, 10)) {
|
||||
defaultTrace { "CAS succeeded" }
|
||||
}
|
||||
}
|
||||
assertEquals(10, a1.value)
|
||||
while (true) {
|
||||
if (a1.value == 10) {
|
||||
defaultTrace.append("Value checked", a1.value)
|
||||
a1.value = 15
|
||||
break
|
||||
} else {
|
||||
defaultTrace.append("Wrong value", a1.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun test() {
|
||||
testDefaultTrace()
|
||||
testTraceWithSize()
|
||||
testTraceWithFormat()
|
||||
testNamedTrace()
|
||||
testMultipleAppend()
|
||||
testTraceInBlock()
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun box() {
|
||||
TraceTest().test()
|
||||
}
|
||||
@@ -12,6 +12,7 @@ private enum class TestProperty(shortName: String) {
|
||||
// effect on other Gradle tasks (ex: :kotlin-native:dist) that might be executed along with test task.
|
||||
KOTLIN_NATIVE_HOME("nativeHome"),
|
||||
COMPILER_CLASSPATH("compilerClasspath"),
|
||||
COMPILER_PLUGINS("compilerPlugins"),
|
||||
CUSTOM_KLIBS("customKlibs"),
|
||||
TEST_TARGET("target"),
|
||||
TEST_MODE("mode"),
|
||||
@@ -77,12 +78,23 @@ private class ComputedTestProperties(private val task: Test) {
|
||||
private fun Test.ComputedTestProperties(init: ComputedTestProperties.() -> Unit): ComputedTestProperties =
|
||||
ComputedTestProperties(this).apply { init() }
|
||||
|
||||
/**
|
||||
* @param taskName Name of Gradle task.
|
||||
* @param tag Optional JUnit test tag. See https://junit.org/junit5/docs/current/user-guide/#writing-tests-tagging-and-filtering
|
||||
* @param requirePlatformLibs Where platform KLIBs from the Kotlin/Native distribution are required for running this test.
|
||||
* @param customCompilerDependencies The [Configuration]s that provide additional JARs to be added to the compiler's classpath.
|
||||
* @param customTestDependencies The [Configuration]s that provide KLIBs to be added to Kotlin/Native compiler dependencies list
|
||||
* along with Kotlin/Native stdlib KLIB and Kotlin/Native platform KLIBs (the latter only if [requirePlatformLibs] is `true`).
|
||||
* @param compilerPluginDependencies The [Configuration]s that provide compiler plugins to be enabled for the Kotlin/Native compiler
|
||||
* for the duration of test execution.
|
||||
*/
|
||||
fun Project.nativeTest(
|
||||
taskName: String,
|
||||
tag: String?,
|
||||
requirePlatformLibs: Boolean = false,
|
||||
customDependencies: List<Configuration> = emptyList(),
|
||||
customKlibDependencies: List<Configuration> = emptyList()
|
||||
customCompilerDependencies: List<Configuration> = emptyList(),
|
||||
customTestDependencies: List<Configuration> = emptyList(),
|
||||
compilerPluginDependencies: List<Configuration> = emptyList()
|
||||
) = projectTest(
|
||||
taskName,
|
||||
jUnitMode = JUnitMode.JUnit5,
|
||||
@@ -141,7 +153,7 @@ fun Project.nativeTest(
|
||||
else
|
||||
null
|
||||
|
||||
customDependencies.forEach(::dependsOn)
|
||||
customCompilerDependencies.forEach(::dependsOn)
|
||||
|
||||
lazyClassPath {
|
||||
if (customNativeHome == null) {
|
||||
@@ -151,13 +163,18 @@ fun Project.nativeTest(
|
||||
this += file(customNativeHome).resolve("konan/lib/trove4j.jar")
|
||||
}
|
||||
|
||||
customDependencies.flatMapTo(this) { it.files }
|
||||
customCompilerDependencies.flatMapTo(this) { it.files }
|
||||
}
|
||||
}
|
||||
|
||||
computeLazy(COMPILER_PLUGINS) {
|
||||
compilerPluginDependencies.forEach(::dependsOn)
|
||||
lazyClassPath { compilerPluginDependencies.flatMapTo(this) { it.files } }
|
||||
}
|
||||
|
||||
computeLazy(CUSTOM_KLIBS) {
|
||||
customKlibDependencies.forEach(::dependsOn)
|
||||
lazyClassPath { customKlibDependencies.flatMapTo(this) { it.files } }
|
||||
customTestDependencies.forEach(::dependsOn)
|
||||
lazyClassPath { customTestDependencies.flatMapTo(this) { it.files } }
|
||||
}
|
||||
|
||||
// Pass Gradle properties as JVM properties so test process can read them.
|
||||
|
||||
Reference in New Issue
Block a user