Stress-testing infrastructure

Tests are run x10 longer with "-DstressTest" JVM option
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
index ca54780..63522a3 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/JobTest.kt
@@ -16,10 +16,10 @@
 
 package kotlinx.coroutines.experimental
 
-import org.junit.Assert.*
+import org.junit.Assert.assertEquals
 import org.junit.Test
 
-class JobTest {
+class JobTest : TestBase() {
     @Test
     fun testState() {
         val job = Job()
@@ -48,7 +48,7 @@
     @Test
     fun testManyHandlers() {
         val job = Job()
-        val n = 100
+        val n = 100 * stressTestMultiplier
         val fireCount = IntArray(n)
         for (i in 0 until n) job.invokeOnCompletion { fireCount[i]++ }
         check(job.isActive)
@@ -66,7 +66,7 @@
     @Test
     fun testUnregisterInHandler() {
         val job = Job()
-        val n = 100
+        val n = 100 * stressTestMultiplier
         val fireCount = IntArray(n)
         for (i in 0 until n) {
             var registration: Job.Registration? = null
@@ -90,7 +90,7 @@
     @Test
     fun testManyHandlersWithUnregister() {
         val job = Job()
-        val n = 100
+        val n = 100 * stressTestMultiplier
         val fireCount = IntArray(n)
         val registrations = Array<Job.Registration>(n) { i -> job.invokeOnCompletion { fireCount[i]++ } }
         check(job.isActive)
@@ -105,7 +105,7 @@
     @Test
     fun testExceptionsInHandler() {
         val job = Job()
-        val n = 100
+        val n = 100 * stressTestMultiplier
         val fireCount = IntArray(n)
         class TestException : Throwable()
         for (i in 0 until n) job.invokeOnCompletion {
@@ -123,7 +123,7 @@
     @Test
     fun testMemoryRelease() {
         val job = Job()
-        val n = 10_000_000
+        val n = 10_000_000 * stressTestMultiplier
         var fireCount = 0
         for (i in 0 until n) job.invokeOnCompletion { fireCount++ }.unregister()
     }
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
index f955982..0454fc3 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/TestBase.kt
@@ -22,6 +22,9 @@
 import java.util.concurrent.atomic.AtomicReference
 
 open class TestBase {
+    val isStressTest = System.getProperty("stressTest") != null
+    val stressTestMultiplier = if (isStressTest) 10 else 1
+
     var actionIndex = AtomicInteger()
     var finished = AtomicBoolean()
     var error = AtomicReference<Throwable>()
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelAtomicCancelStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelAtomicCancelStressTest.kt
index 1363785..da2fd00 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelAtomicCancelStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelAtomicCancelStressTest.kt
@@ -29,14 +29,14 @@
  * Tests cancel atomicity for channel send & receive operations, including their select versions.
  */
 @RunWith(Parameterized::class)
-class ChannelAtomicCancelStressTest(val kind: TestChannelKind) {
+class ChannelAtomicCancelStressTest(val kind: TestChannelKind) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun params(): Collection<Array<Any>> = TestChannelKind.values().map { arrayOf<Any>(it) }
     }
 
-    val TEST_DURATION = 3000L
+    val TEST_DURATION = 3000L * stressTestMultiplier
 
     val channel = kind.create()
     val senderDone = ArrayChannel<Boolean>(1)
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
index 0f5878a..3843497 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/channels/ChannelSendReceiveStressTest.kt
@@ -31,7 +31,7 @@
     val kind: TestChannelKind,
     val nSenders: Int,
     val nReceivers: Int
-) {
+) : TestBase() {
     companion object {
         @Parameterized.Parameters(name = "{0}, nSenders={1}, nReceivers={2}")
         @JvmStatic
@@ -43,8 +43,8 @@
                 }
     }
 
-    val timeLimit = 30_000L // 30 sec
-    val nEvents = 1_000_000
+    val timeLimit = 30_000L * stressTestMultiplier // 30 sec
+    val nEvents = 1_000_000 * stressTestMultiplier
 
     val channel = kind.create()
     val sendersCompleted = AtomicInteger()
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListAtomicStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListAtomicStressTest.kt
index 7c3d676..d3ac3bc 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListAtomicStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListAtomicStressTest.kt
@@ -16,6 +16,7 @@
 
 package kotlinx.coroutines.experimental.internal
 
+import kotlinx.coroutines.experimental.TestBase
 import org.junit.Assert.*
 import org.junit.Test
 import java.util.*
@@ -26,14 +27,15 @@
  * This stress test has 4 threads adding randomly to the list and them immediately undoing
  * this addition by remove, and 4 threads trying to remove nodes from two lists simultaneously (atomically).
  */
-class LockFreeLinkedListAtomicStressTest {
+class LockFreeLinkedListAtomicStressTest : TestBase() {
     data class IntNode(val i: Int) : LockFreeLinkedListNode()
 
+    val TEST_DURATION = 5000L * stressTestMultiplier
+
     val threads = mutableListOf<Thread>()
     val nLists = 4
     val nAdderThreads = 4
     val nRemoverThreads = 4
-    val timeout = 5000L
     val completedAdder = AtomicInteger()
     val completedRemover = AtomicInteger()
 
@@ -45,7 +47,7 @@
 
     @Test
     fun testStress() {
-        val deadline = System.currentTimeMillis() + timeout
+        val deadline = System.currentTimeMillis() + TEST_DURATION
         repeat(nAdderThreads) { threadId ->
             threads += thread(start = false, name = "adder-$threadId") {
                 val rnd = Random()
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListLongStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListLongStressTest.kt
index 5daf1c5..9fc258e 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListLongStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListLongStressTest.kt
@@ -16,6 +16,7 @@
 
 package kotlinx.coroutines.experimental.internal
 
+import kotlinx.coroutines.experimental.TestBase
 import org.junit.Test
 import java.util.*
 import java.util.concurrent.atomic.AtomicInteger
@@ -27,12 +28,12 @@
  * and 6 threads iterating and concurrently removing items. The resulting list that is being
  * stressed is long.
  */
-class LockFreeLinkedListLongStressTest {
+class LockFreeLinkedListLongStressTest : TestBase() {
     data class IntNode(val i: Int) : LockFreeLinkedListNode()
     val list = LockFreeLinkedListHead()
 
     val threads = mutableListOf<Thread>()
-    val nAdded = 10_000_000
+    val nAdded = 10_000_000 * stressTestMultiplier
     val nAddThreads = 4 // must be power of 2 (!!!)
     val nRemoveThreads = 6
     val removeProbability = 0.2
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListShortStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListShortStressTest.kt
index a142117..5a7376f 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListShortStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/internal/LockFreeLinkedListShortStressTest.kt
@@ -16,6 +16,7 @@
 
 package kotlinx.coroutines.experimental.internal
 
+import kotlinx.coroutines.experimental.TestBase
 import org.junit.Assert.*
 import org.junit.Test
 import java.util.*
@@ -27,14 +28,15 @@
  * this addition by remove, and 4 threads removing first node. The resulting list that is being
  * stressed is very short.
  */
-class LockFreeLinkedListShortStressTest {
+class LockFreeLinkedListShortStressTest : TestBase() {
     data class IntNode(val i: Int) : LockFreeLinkedListNode()
     val list = LockFreeLinkedListHead()
 
+    val TEST_DURATION = 5000L * stressTestMultiplier
+
     val threads = mutableListOf<Thread>()
     val nAdderThreads = 6
     val nRemoverThreads = 4
-    val timeout = 5000L
     val completedAdder = AtomicInteger()
     val completedRemover = AtomicInteger()
 
@@ -44,7 +46,7 @@
 
     @Test
     fun testStress() {
-        val deadline = System.currentTimeMillis() + timeout
+        val deadline = System.currentTimeMillis() + TEST_DURATION
         repeat(nAdderThreads) { threadId ->
             threads += thread(start = false, name = "adder-$threadId") {
                 val rnd = Random()
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
index c9cf44c..4f468ef 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectArrayChannelTest.kt
@@ -226,7 +226,7 @@
     @Test
     fun testSelectSendResourceCleanup() = runBlocking<Unit> {
         val channel = ArrayChannel<Int>(1)
-        val n = 10_000_000
+        val n = 10_000_000 * stressTestMultiplier
         expect(1)
         channel.send(-1) // fill the buffer, so all subsequent sends cannot proceed
         repeat(n) { i ->
@@ -241,7 +241,7 @@
     @Test
     fun testSelectReceiveResourceCleanup() = runBlocking<Unit> {
         val channel = ArrayChannel<Int>(1)
-        val n = 10_000_000
+        val n = 10_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
             select {
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
index 0e1f0a2..4124f28 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectMutexTest.kt
@@ -72,7 +72,7 @@
 
     @Test
     fun testSelectCancelledResourceRelease() = runBlocking<Unit> {
-        val n = 1_000
+        val n = 1_000 * stressTestMultiplier
         val mutex = Mutex(true) as MutexImpl // locked
         expect(1)
         repeat(n) { i ->
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
index 5212587..9406ff2 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectPhilosophersStressTest.kt
@@ -21,8 +21,8 @@
 import org.junit.Assert.assertTrue
 import org.junit.Test
 
-class SelectPhilosophersStressTest {
-    val TEST_DURATION = 3000L
+class SelectPhilosophersStressTest : TestBase() {
+    val TEST_DURATION = 3000L * stressTestMultiplier
 
     val n = 10 // number of philosophers
     val forks = Array<Mutex>(n) { Mutex() }
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
index 6dc68c8..c3e4333 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/selects/SelectRendezvousChannelTest.kt
@@ -235,7 +235,7 @@
     @Test
     fun testSelectSendResourceCleanup() = runBlocking<Unit> {
         val channel = RendezvousChannel<Int>()
-        val n = 10_000_000
+        val n = 10_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
             select {
@@ -249,7 +249,7 @@
     @Test
     fun testSelectReceiveResourceCleanup() = runBlocking<Unit> {
         val channel = RendezvousChannel<Int>()
-        val n = 10_000_000
+        val n = 10_000_000 * stressTestMultiplier
         expect(1)
         repeat(n) { i ->
             select {
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
index 0a0fcd5..a04840b 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/sync/MutexTest.kt
@@ -63,7 +63,7 @@
 
     @Test
     fun testStress() = runBlocking<Unit> {
-        val n = 1000
+        val n = 1000 * stressTestMultiplier
         val k = 100
         var shared = 0
         val mutex = Mutex()