Correctly test for an object being of the correct type

This `as? T` instruction warns that this is an unchecked cast.
It's unchecked in the literal sense : the compiler actually
doesn't check that the var is of that type. Accordingly, this
will only fail if `it` is null, which never happens.

Concretely what that means is that Java code calling this
method like

  expect(AVAILABLE, network)

...will actually pass for *any* callback matching the network,
because the class is not checked.

Thankfully this code is recent and there doesn't seem to be a
lot of tests that got accepted by this bug when they should
have been rejected.

Test: ConnectivityServiceTest, TH
      new test in this patch that fails before but succeeds after
Change-Id: I2e48dae28ff92045f002cfb2798d383c9c19d5ed
This commit is contained in:
Chalard Jean 2023-05-19 18:56:03 +09:00
commit 677b663aaf
2 changed files with 12 additions and 1 deletions

View file

@ -353,6 +353,13 @@ class TestableNetworkCallbackTest {
mCallback.expect<Available>(network = hn)
}
@Test
fun testExpectClass() {
val net = Network(1)
mCallback.onAvailable(net)
assertFails { mCallback.expect(LOST, net) }
}
@Test
fun testPoll() {
assertNull(mCallback.poll(SHORT_TIMEOUT_MS))

View file

@ -236,7 +236,11 @@ open class TestableNetworkCallback private constructor(
errorMsg: String? = null,
test: (T) -> Boolean = { true }
) = expect<CallbackEntry>(network, timeoutMs, errorMsg) {
test(it as? T ?: fail("Expected callback ${type.simpleName}, got $it"))
if (type.isInstance(it)) {
test(it as T) // Cast can't fail since type.isInstance(it) and type: KClass<T>
} else {
fail("Expected callback ${type.simpleName}, got $it")
}
} as T
@JvmOverloads