Bug fixed on waitTimeoutOrNull (was flaky testOuterTimeoutTest)
diff --git a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
index 4e8ada9..afbae4f 100644
--- a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
+++ b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/EventLoop.kt
@@ -154,6 +154,7 @@
         private val block: Runnable
     ) : QueuedTask() {
         override fun invoke() { block.run() }
+        override fun toString(): String = block.toString()
     }
 
     private abstract inner class DelayedTask(
@@ -176,6 +177,8 @@
         }
 
         open fun cancel() {}
+
+        override fun toString(): String = "Delayed[nanos=$nanoTime,seq=$sequence]"
     }
 
     private inner class DelayedResumeTask(
@@ -197,5 +200,6 @@
         private val block: Runnable
     ) : DelayedTask(time, timeUnit) {
         override fun invoke() { block.run() }
+        override fun toString(): String = super.toString() + block.toString()
     }
 }
diff --git a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
index 663e14c..54b29dc 100644
--- a/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
+++ b/kotlinx-coroutines-core/src/main/kotlin/kotlinx/coroutines/experimental/Scheduled.kt
@@ -148,7 +148,8 @@
         try {
             block.startCoroutineUninterceptedOrReturn(completion)
         } catch (e: TimeoutException) {
-            null // replace inner timeout exception with null result
+            // replace inner timeout exception on our coroutine with null result
+            if (e.coroutine == completion) null else throw e
         }
     }
 }
diff --git a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
index 66c79a2..0c50eae 100644
--- a/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
+++ b/kotlinx-coroutines-core/src/test/kotlin/kotlinx/coroutines/experimental/WithTimeoutOrNullTest.kt
@@ -122,26 +122,35 @@
     }
 
     @Test
-    fun testOuterTimeoutTest() {
-        // stress test this particular case 1000 times
-        val nTimes = if (isStressTest) 1000 else 1
-        repeat(nTimes) {
-            runBlocking {
-                var counter = 0
-                val result = withTimeoutOrNull(250) {
+    fun testOuterTimeoutTest() = runBlocking {
+        var counter = 0
+        val result = withTimeoutOrNull(250) {
+            while (true) {
+                val inner = withTimeoutOrNull(100) {
                     while (true) {
-                        val inner = withTimeoutOrNull(100) {
-                            while (true) {
-                                yield()
-                            }
-                        }
-                        assertThat(inner, IsNull())
-                        counter++
+                        yield()
                     }
                 }
-                assertThat(result, IsNull())
-                assertThat(counter, IsEqual(2))
+                assertThat(inner, IsNull())
+                counter++
             }
         }
+        assertThat(result, IsNull())
+        assertThat(counter, IsEqual(2))
+    }
+
+    @Test
+    fun testOuterTimeoutFiredBeforeInner() = runBlocking<Unit> {
+        val result = withTimeoutOrNull(100) {
+            Thread.sleep(200) // wait enough for outer timeout to fire
+            run(NonCancellable) { yield() } // give an event loop a chance to run and process that cancellation
+            withTimeoutOrNull(100) {
+                yield() // will cancel because of outer timeout
+                expectUnreached()
+            }
+            expectUnreached() // should not be reached, because it is outer timeout
+        }
+        // outer timeout results in null
+        assertThat(result, IsNull())
     }
 }
\ No newline at end of file