Structured concurrency implementation:
  * Introducing async, launch, produce, actor and broadcast extensions on CoroutineScope
  * Deprecate top-level coroutine builders
  * Introducing currentScope and coroutineScope for manipulation with CoroutineScope interface
  * Introducing CoroutineScope factories
  * Introducing extension CoroutineScope.isActive

Fixes #410
diff --git a/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
new file mode 100644
index 0000000..22652f2
--- /dev/null
+++ b/common/kotlinx-coroutines-core-common/test/CoroutineScopeTest.kt
@@ -0,0 +1,164 @@
+/*
+ * Copyright 2016-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
+ */
+
+package kotlinx.coroutines.experimental
+
+import kotlin.test.*
+
+class CoroutineScopeTest : TestBase() {
+
+    @Test
+    fun testScope() = runTest {
+        suspend fun callJobScoped() = coroutineScope {
+            expect(2)
+
+            launch {
+                expect(4)
+            }
+
+            launch {
+                expect(5)
+
+                launch {
+                    expect(7)
+                }
+
+                expect(6)
+
+            }
+
+            expect(3)
+            42
+        }
+
+
+        expect(1)
+        val result = callJobScoped()
+        assertEquals(42, result)
+        yield() // Check we're not cancelled
+        finish(8)
+    }
+
+    @Test
+    fun testScopeCancelledFromWithin() = runTest {
+        expect(1)
+        suspend fun callJobScoped() = coroutineScope {
+
+            launch {
+                expect(2)
+                delay(Long.MAX_VALUE)
+            }
+
+            launch {
+                expect(3)
+                throw IllegalArgumentException()
+            }
+        }
+
+        try {
+            callJobScoped()
+            expectUnreached()
+        } catch (e: IllegalArgumentException) {
+            expect(4)
+        }
+
+        yield() // Check we're not cancelled
+        finish(5)
+    }
+
+    @Test
+    fun testScopeBlockThrows() = runTest {
+        expect(1)
+        suspend fun callJobScoped(): Unit = coroutineScope {
+
+            launch {
+                expect(2)
+                delay(Long.MAX_VALUE)
+            }
+
+            yield() // let launch sleep
+            throw NotImplementedError()
+        }
+
+        try {
+            callJobScoped()
+            expectUnreached()
+        } catch (e: NotImplementedError) {
+            expect(3)
+        }
+
+        yield() // Check we're not cancelled
+        finish(4)
+    }
+
+    @Test
+    fun testOuterJobIsCancelled() = runTest {
+
+        suspend fun callJobScoped() = coroutineScope {
+
+            launch {
+                expect(3)
+                try {
+                    delay(Long.MAX_VALUE)
+                } finally {
+                    expect(4)
+                }
+            }
+
+            expect(2)
+            delay(Long.MAX_VALUE)
+            42
+        }
+
+
+        val outerJob = launch(coroutineContext.minusKey(Job)) {
+            expect(1)
+            try {
+                callJobScoped()
+                expectUnreached()
+            } catch (e: JobCancellationException) {
+                expect(5)
+                assertNull(e.cause)
+            }
+        }
+
+        repeat(3) { yield() } // let everything to start properly
+        outerJob.cancel()
+        outerJob.join()
+        finish(6)
+    }
+
+    @Test
+    @Suppress("UNREACHABLE_CODE")
+    fun testDocumentationExample() = runTest {
+        suspend fun loadData() = coroutineScope {
+            expect(1)
+            val data = async {
+                try {
+                    delay(Long.MAX_VALUE)
+                } finally {
+                    expect(3)
+                }
+            }
+
+            yield()
+
+            // UI updater
+            withContext(coroutineContext) {
+                expect(2)
+                throw AssertionError()
+                data.await() // Actually unreached
+                expectUnreached()
+            }
+        }
+
+
+        try {
+            loadData()
+            expectUnreached()
+        } catch (e: AssertionError) {
+            finish(4)
+        }
+    }
+}