Skip to content

Commit

Permalink
Clean Verfication and AssertionChain
Browse files Browse the repository at this point in the history
  • Loading branch information
bitPogo committed Apr 25, 2022
1 parent 921a3d5 commit 9be81b1
Show file tree
Hide file tree
Showing 6 changed files with 258 additions and 529 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -1258,22 +1258,14 @@ object KMockContract {
/**
*
*/
interface Assert : AssertionInsurance, AssertionContext
internal interface Assert : AssertionInsurance, AssertionContext

/**
* AssertionChain in order to verify over multiple Handles.
* Meant for internal purpose only!
* @author Matthias Geisler
*/
interface AssertionChain {
/**
* Propagates the expected invocation to the Chain and asserts it against the actual values.
* @param expected the expected Invocation.
* @throws AssertionError if the expected value does not match the actual value.
*/
@Throws(AssertionError::class)
fun propagate(expected: Expectation)

/**
* Ensures that all expected or actual values are covered depending on the context.
* @throws AssertionError if the context needs to be exhaustive and not all expected or actual values are covered.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,11 @@

package tech.antibytes.kmock.verification

import co.touchlab.stately.collections.IsoMutableMap
import co.touchlab.stately.collections.sharedMutableMapOf
import kotlinx.atomicfu.atomic
import tech.antibytes.kmock.KMockContract
import tech.antibytes.kmock.KMockContract.Assertions
import tech.antibytes.kmock.KMockContract.Expectation
import tech.antibytes.kmock.KMockContract.Proxy
import tech.antibytes.kmock.KMockContract.Reference
import tech.antibytes.kmock.KMockContract.STRICT_CALL_IDX_NOT_FOUND
import tech.antibytes.kmock.KMockContract.STRICT_CALL_IDX_NOT_MATCH
import tech.antibytes.kmock.KMockContract.CALL_NOT_FOUND
import tech.antibytes.kmock.KMockContract.STRICT_CALL_NOT_MATCH
import tech.antibytes.kmock.KMockContract.STRICT_MISSING_EXPECTATION
Expand All @@ -28,7 +23,6 @@ internal class AssertionChain(
private val assertions: Assertions = Assertions
) : AssertionChain, Assert {
private val invocation = atomic(0)
private val invokedProxies: IsoMutableMap<String, Int> = sharedMutableMapOf()

private fun getProxyIdSet(): Set<String> {
val set: MutableSet<String> = mutableSetOf()
Expand All @@ -48,65 +42,6 @@ internal class AssertionChain(
}
}

private fun assertProxy(
actual: Reference?,
expected: Expectation
) {
when {
actual == null -> throw AssertionError(
CALL_NOT_FOUND.format(expected.proxy.id)
)
actual.proxy !== expected.proxy -> throw AssertionError(
STRICT_CALL_NOT_MATCH.format(expected.proxy.id, actual.proxy.id)
)
}
}

private fun assertInvocation(
actual: Reference,
expected: Expectation
) {
val expectedCallIdxReference = invokedProxies[actual.proxy.id] ?: 0
val expectedCallIdx = expected.callIndices.firstOrNull { call -> call == expectedCallIdxReference }

invokedProxies[actual.proxy.id] = expectedCallIdxReference + 1

when {
expectedCallIdx == null -> {
throw AssertionError(
STRICT_CALL_IDX_NOT_FOUND.format(expectedCallIdxReference + 1, expected.proxy.id)
)
}
expectedCallIdx != actual.callIndex -> throw AssertionError(
STRICT_CALL_IDX_NOT_MATCH.format(
expectedCallIdxReference + 1,
expected.proxy.id,
actual.callIndex + 1
)
)
}
}

@Throws(AssertionError::class)
override fun propagate(expected: Expectation) {
val actual = references.getOrNull(invocation.value)

try {
assertProxy(
actual = actual,
expected = expected
)
assertInvocation(
actual = actual!!,
expected = expected
)
} catch (e: AssertionError) {
throw e
} finally {
invocation.incrementAndGet()
}
}

private fun guardProxy(
expected: Proxy<*, *>
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,10 @@

package tech.antibytes.kmock.verification

import co.touchlab.stately.collections.IsoMutableMap
import co.touchlab.stately.collections.sharedMutableMapOf
import kotlinx.atomicfu.atomic
import kotlinx.atomicfu.update
import tech.antibytes.kmock.KMockContract
import tech.antibytes.kmock.KMockContract.Assertions
import tech.antibytes.kmock.KMockContract.Expectation
import tech.antibytes.kmock.KMockContract.NOT_PART_OF_CHAIN
import tech.antibytes.kmock.KMockContract.Proxy
import tech.antibytes.kmock.KMockContract.Reference
Expand All @@ -25,7 +22,6 @@ internal class VerificationChain(
private val assertions: Assertions = Assertions,
) : AssertionChain, KMockContract.Assert {
private val invocation = atomic(0)
private val invokedProxies: IsoMutableMap<String, Int> = sharedMutableMapOf()

private fun getProxyIdSet(): Set<String> {
val set: MutableSet<String> = mutableSetOf()
Expand All @@ -45,74 +41,6 @@ internal class VerificationChain(
}
}

private fun assertProxy(
expected: Expectation,
actual: Int?
) {
if (actual == null) {
throw AssertionError(
KMockContract.NON_STRICT_CALL_NOT_FOUND.format(expected.proxy.id)
)
}
}

private fun assertInvocation(
expected: Expectation,
expectedCallIdx: Int?,
) {
if (expectedCallIdx == null) {
throw AssertionError(CALL_NOT_FOUND.format(expected.proxy.id))
}
}

private fun findInvocation(
expected: Expectation,
actual: Reference,
): Int? {
val expectedCallIdxReference = invokedProxies[actual.proxy.id] ?: 0
val expectedCallIdx = expected.callIndices.firstOrNull { call -> call >= expectedCallIdxReference }

invokedProxies[actual.proxy.id] = expectedCallIdxReference + 1

return expectedCallIdx
}

@Throws(AssertionError::class)
override fun propagate(expected: Expectation) {
while (invocation.value <= references.size) {
val actualReferenceIdx = findProxy(expected.proxy)

try {
assertProxy(
actual = actualReferenceIdx,
expected = expected,
)
} catch (e: AssertionError) {
throw e
}

val actualInvocation = findInvocation(
expected = expected,
actual = references[actualReferenceIdx!!]
)

try {
assertInvocation(
expected = expected,
expectedCallIdx = actualInvocation,
)
} catch (e: AssertionError) {
throw e
} finally {
invocation.update { actualReferenceIdx + 1 }
}

if (actualInvocation == references[actualReferenceIdx].callIndex) {
break
}
}
}

private fun findProxy(expected: Proxy<*, *>): Int? {
for (idx in invocation.value until references.size) {
if (references[idx].proxy === expected) {
Expand Down
Loading

0 comments on commit 9be81b1

Please sign in to comment.