Skip to content

Commit

Permalink
Add a lincheck test for remove in the segment list algorithm (Kotli…
Browse files Browse the repository at this point in the history
  • Loading branch information
ndkoval committed Apr 28, 2020
1 parent cd5ab49 commit 515e86a
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 4 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ junit_version=4.12
atomicfu_version=0.14.2
knit_version=0.1.3
html_version=0.6.8
lincheck_version=2.6
lincheck_version=2.7.1
dokka_version=0.9.16-rdev-2-mpp-hacks
byte_buddy_version=1.10.9
reactor_vesion=3.2.5.RELEASE
Expand Down
24 changes: 21 additions & 3 deletions kotlinx-coroutines-core/jvm/test/internal/SegmentBasedQueue.kt
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,24 @@ internal class SegmentBasedQueue<T> {
}

fun checkHeadPrevIsCleaned() {
check(head.value.prev === null)
check(head.value.prev === null) { "head.prev is not null"}
}

fun checkAllSegmentsAreNotLogicallyRemoved() {
var prev: OneElementSegment<T>? = null
var cur = head.value
while (true) {
check(!cur.logicallyRemoved || cur.isTail) {
"This queue contains removed segments, memory leak detected"
}
check(cur.prev === prev) {
"Two neighbour segments are incorrectly linked: S.next.prev != S"
}
prev = cur
cur = cur.next ?: return
}
}

}

private fun <T> createSegment(id: Long, prev: OneElementSegment<T>?) = OneElementSegment(id, prev, 0)
Expand All @@ -98,9 +114,11 @@ internal class OneElementSegment<T>(id: Long, prev: OneElementSegment<T>?, point

override val maxSlots get() = 1

val logicallyRemoved get() = element.value === BROKEN

fun removeSegment() {
element.value = BROKEN
onSlotCleaned()
val old = element.getAndSet(BROKEN)
if (old !== BROKEN) onSlotCleaned()
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/

@file:Suppress("unused")

package kotlinx.coroutines.linearizability

import kotlinx.coroutines.*
import kotlinx.coroutines.internal.*
import org.jetbrains.kotlinx.lincheck.annotations.*
import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.paramgen.*
import org.jetbrains.kotlinx.lincheck.verifier.*
import org.junit.*


class SegmentListRemoveLCStressTest : VerifierState() {
private val q = SegmentBasedQueue<Int>()
private val segments: Array<OneElementSegment<Int>>

init {
segments = (0..5).map { q.enqueue(it)!! }.toTypedArray()
q.enqueue(6)
}

@Operation
fun removeSegment(@Param(gen = IntGen::class, conf = "1:5") index: Int) {
segments[index].removeSegment()
}

override fun extractState() = segments.map { it.logicallyRemoved }

@Validate
fun checkAllRemoved() {
q.checkHeadPrevIsCleaned()
q.checkAllSegmentsAreNotLogicallyRemoved()
}

@Test
fun test() = LCStressOptionsDefault()
.actorsBefore(0)
.actorsAfter(0)
.check(this::class)
}

0 comments on commit 515e86a

Please sign in to comment.