diff --git a/lection09/app/build.gradle b/lection09/app/build.gradle index bac46e7..486ccce 100644 --- a/lection09/app/build.gradle +++ b/lection09/app/build.gradle @@ -98,6 +98,7 @@ dependencies { testImplementation 'junit:junit:4.+' testImplementation "io.mockk:mockk:1.12.3" + testImplementation 'org.jetbrains.kotlinx:kotlinx-coroutines-test:1.6.1' androidTestImplementation 'androidx.test.ext:junit:1.1.3' androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' diff --git a/lection09/app/src/test/java/company/vk/lection09/CoroutinesExampleUnitTest.kt b/lection09/app/src/test/java/company/vk/lection09/CoroutinesExampleUnitTest.kt new file mode 100644 index 0000000..32214e5 --- /dev/null +++ b/lection09/app/src/test/java/company/vk/lection09/CoroutinesExampleUnitTest.kt @@ -0,0 +1,112 @@ +package company.vk.lection09 + +import kotlinx.coroutines.* +import kotlinx.coroutines.sync.Mutex +import kotlinx.coroutines.sync.withLock +import kotlinx.coroutines.test.runTest +import org.junit.After +import org.junit.Assert +import org.junit.Before +import org.junit.Test +import java.io.ByteArrayOutputStream +import java.io.PrintStream + +interface Counter { + + suspend fun increaseCounterAndPrintAsync() +} + +@ExperimentalCoroutinesApi +class OriginCounter( + private val scope: CoroutineScope +) : Counter { + + private var counter = 0 + + override suspend fun increaseCounterAndPrintAsync() { + scope.launch { + repeat(100) { + launch { + val oldCounter = counter++ + delay(1000L) + println("$oldCounter and ${counter++}") + } + } + }.join() + } +} + +@ExperimentalCoroutinesApi +class MutexCounter( + private val scope: CoroutineScope +) : Counter { + + private val mutex = Mutex() + + private var counter = 0 + + override suspend fun increaseCounterAndPrintAsync() { + scope.launch { + repeat(100) { + launch { + mutex.withLock { + val oldCounter = counter++ + delay(1000L) + println("$oldCounter and ${counter++}") + } + } + } + }.join() + } +} + +@ExperimentalCoroutinesApi +class CoroutinesExampleUnitTest { + + private val printStreamByteArray = ByteArrayOutputStream() + private val mockPrintStream = PrintStream(printStreamByteArray) + private val consolePrintStream = System.out + + @Before + fun before() { + System.setOut(mockPrintStream) + } + + @After + fun after() { + printStreamByteArray.reset() + System.setOut(consolePrintStream) + } + + @Test + fun originalCounterTest() = runTest { + OriginCounter(this) + .increaseCounterAndPrintAsync() + val result = printStreamByteArray.toString() + Assert.assertEquals(expectedForOriginalImpl(), result) + } + + @Test + fun mutexCounterTest() = runTest { + MutexCounter(this) + .increaseCounterAndPrintAsync() + val result = printStreamByteArray.toString() + Assert.assertEquals(expectedForMutexImpl(), result) + } + + private fun expectedForOriginalImpl(): String { + val expected = StringBuilder() + for (i in 0 until 100) { + expected.append("$i and ${i + 100}\n") + } + return expected.toString() + } + + private fun expectedForMutexImpl(): String { + val expected = StringBuilder() + for (i in 0 until 200 step 2) { + expected.append("$i and ${i + 1}\n") + } + return expected.toString() + } +}