From b4e2b14622e624058b5eed50e7558e375142af04 Mon Sep 17 00:00:00 2001 From: Lachlan McKee Date: Fri, 5 Aug 2022 16:26:10 +0100 Subject: [PATCH 1/2] Improved SameThreadVerifier error message --- .../mvicore/extension/SameThreadVerifier.kt | 12 ++++-- .../badoo/mvicore/feature/BaseAsyncFeature.kt | 2 +- .../com/badoo/mvicore/feature/BaseFeature.kt | 2 +- .../extension/SameThreadVerifierTest.kt | 39 +++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) create mode 100644 mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt diff --git a/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt b/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt index 78485805..2fda5336 100644 --- a/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt +++ b/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt @@ -1,16 +1,20 @@ package com.badoo.mvicore.extension -class SameThreadVerifier { +class SameThreadVerifier(private val clazz: Class<*>) { companion object { var isEnabled : Boolean = true } - private val originalThread = Thread.currentThread().id + private val originalThread = Thread.currentThread() fun verify() { - if (isEnabled && (Thread.currentThread().id != originalThread)) { - throw AssertionError("Not on same thread as previous verification") + val currentThread = Thread.currentThread() + if (isEnabled && (currentThread.id != originalThread.id)) { + throw AssertionError( + "${clazz.name} was interacted with on the wrong thread. " + + "Expected: '${originalThread.name}', Actual: '${currentThread.name}'" + ) } } diff --git a/mvicore/src/main/java/com/badoo/mvicore/feature/BaseAsyncFeature.kt b/mvicore/src/main/java/com/badoo/mvicore/feature/BaseAsyncFeature.kt index a9ab6a59..89609720 100644 --- a/mvicore/src/main/java/com/badoo/mvicore/feature/BaseAsyncFeature.kt +++ b/mvicore/src/main/java/com/badoo/mvicore/feature/BaseAsyncFeature.kt @@ -33,7 +33,7 @@ open class BaseAsyncFeature { - private val threadVerifier by lazy { SameThreadVerifier() } + private val threadVerifier by lazy { SameThreadVerifier(javaClass) } private val actionSubject = PublishSubject.create().toSerialized() // store last state to make best effort to return it in getState() private val lastState = AtomicReference(initialState) diff --git a/mvicore/src/main/java/com/badoo/mvicore/feature/BaseFeature.kt b/mvicore/src/main/java/com/badoo/mvicore/feature/BaseFeature.kt index f22c3745..9ffb3fbe 100644 --- a/mvicore/src/main/java/com/badoo/mvicore/feature/BaseFeature.kt +++ b/mvicore/src/main/java/com/badoo/mvicore/feature/BaseFeature.kt @@ -46,7 +46,7 @@ open class BaseFeature { - private val threadVerifier = if (featureScheduler == null) SameThreadVerifier() else null + private val threadVerifier = if (featureScheduler == null) SameThreadVerifier(javaClass) else null private val actionSubject = PublishSubject.create().toSerialized() private val stateSubject = BehaviorSubject.createDefault(initialState) private val newsSubject = PublishSubject.create() diff --git a/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt b/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt new file mode 100644 index 00000000..b8961c01 --- /dev/null +++ b/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt @@ -0,0 +1,39 @@ +package com.badoo.mvicore.extension + +import org.junit.Test +import java.util.concurrent.CountDownLatch +import kotlin.concurrent.thread +import kotlin.test.assertEquals +import kotlin.test.assertNotNull + +internal class SameThreadVerifierTest { + @Test + fun `GIVEN same thread WHEN verify THEN expect no exceptions`() { + val threadVerifier = SameThreadVerifier(String::class.java) + threadVerifier.verify() + } + + @Test + fun `GIVEN different thread WHEN verify THEN expect exception`() { + val threadVerifier = SameThreadVerifier(String::class.java) + val testWorkerThreadName = Thread.currentThread().name + + var assertionError: AssertionError? = null + val latch = CountDownLatch(1) + thread(name = "wrong-thread") { + try { + threadVerifier.verify() + } catch (e: AssertionError) { + assertionError = e + } + latch.countDown() + } + latch.await() + + assertNotNull(assertionError) + assertEquals( + "java.lang.String was interacted with on the wrong thread. Expected: '$testWorkerThreadName', Actual: 'wrong-thread'", + assertionError!!.message + ) + } +} \ No newline at end of file From 778a44163159de462e213ee3d9a1cfba151e81b6 Mon Sep 17 00:00:00 2001 From: Lachlan McKee Date: Fri, 5 Aug 2022 17:15:22 +0100 Subject: [PATCH 2/2] Avoid SameThreadVerifier holding onto original thread --- .../badoo/mvicore/extension/SameThreadVerifier.kt | 13 ++++++++++--- .../mvicore/extension/SameThreadVerifierTest.kt | 5 +++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt b/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt index 2fda5336..4540e698 100644 --- a/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt +++ b/mvicore/src/main/java/com/badoo/mvicore/extension/SameThreadVerifier.kt @@ -6,14 +6,21 @@ class SameThreadVerifier(private val clazz: Class<*>) { var isEnabled : Boolean = true } - private val originalThread = Thread.currentThread() + private val originalThreadId: Long + private val originalThreadName: String + + init { + val currentThread = Thread.currentThread() + originalThreadId = currentThread.id + originalThreadName = currentThread.name + } fun verify() { val currentThread = Thread.currentThread() - if (isEnabled && (currentThread.id != originalThread.id)) { + if (isEnabled && (currentThread.id != originalThreadId)) { throw AssertionError( "${clazz.name} was interacted with on the wrong thread. " + - "Expected: '${originalThread.name}', Actual: '${currentThread.name}'" + "Expected: '$originalThreadName', Actual: '${currentThread.name}'" ) } } diff --git a/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt b/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt index b8961c01..91be7a92 100644 --- a/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt +++ b/mvicore/src/test/java/com/badoo/mvicore/extension/SameThreadVerifierTest.kt @@ -2,6 +2,7 @@ package com.badoo.mvicore.extension import org.junit.Test import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit import kotlin.concurrent.thread import kotlin.test.assertEquals import kotlin.test.assertNotNull @@ -28,7 +29,7 @@ internal class SameThreadVerifierTest { } latch.countDown() } - latch.await() + latch.await(1, TimeUnit.SECONDS) assertNotNull(assertionError) assertEquals( @@ -36,4 +37,4 @@ internal class SameThreadVerifierTest { assertionError!!.message ) } -} \ No newline at end of file +}