1 /*
2 * Copyright (C) 2019 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package com.android.testutils
18
19 import android.net.ConnectivityManager.NetworkCallback
20 import android.net.LinkProperties
21 import android.net.LocalNetworkInfo
22 import android.net.Network
23 import android.net.NetworkCapabilities
24 import android.net.NetworkCapabilities.NET_CAPABILITY_VALIDATED
25 import android.util.Log
26 import com.android.net.module.util.ArrayTrackRecord
27 import com.android.testutils.RecorderCallback.CallbackEntry.Available
28 import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
29 import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatusInt
30 import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
31 import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
32 import com.android.testutils.RecorderCallback.CallbackEntry.LocalInfoChanged
33 import com.android.testutils.RecorderCallback.CallbackEntry.Losing
34 import com.android.testutils.RecorderCallback.CallbackEntry.Lost
35 import com.android.testutils.RecorderCallback.CallbackEntry.Reserved
36 import com.android.testutils.RecorderCallback.CallbackEntry.Resumed
37 import com.android.testutils.RecorderCallback.CallbackEntry.Suspended
38 import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
39 import kotlin.reflect.KClass
40 import kotlin.test.assertEquals
41 import kotlin.test.assertNotNull
42 import kotlin.test.fail
43
44 object NULL_NETWORK : Network(-1)
45 object ANY_NETWORK : Network(-2)
anyNetworknull46 fun anyNetwork() = ANY_NETWORK
47
48 private val DEFAULT_TAG = RecorderCallback::class.simpleName
49 ?: fail("Could not determine class name")
50
51 open class RecorderCallback private constructor(
52 private val backingRecord: ArrayTrackRecord<CallbackEntry>,
53 val logTag: String
54 ) : NetworkCallback() {
55 public constructor(logTag: String = DEFAULT_TAG) : this(ArrayTrackRecord(), logTag)
56 protected constructor(src: RecorderCallback?, logTag: String) : this(
57 src?.backingRecord ?: ArrayTrackRecord(),
58 logTag
59 )
60
61 sealed class CallbackEntry {
62 // To get equals(), hashcode(), componentN() etc for free, the child classes of
63 // this class are data classes. But while data classes can inherit from other classes,
64 // they may only have visible members in the constructors, so they couldn't declare
65 // a constructor with a non-val arg to pass to CallbackEntry. Instead, force all
66 // subclasses to implement a `network' property, which can be done in a data class
67 // constructor by specifying override.
68 abstract val network: Network
69
70 data class Reserved private constructor(
71 override val network: Network,
72 val caps: NetworkCapabilities
73 ): CallbackEntry() {
74 constructor(caps: NetworkCapabilities) : this(NULL_NETWORK, caps)
75 }
76 data class Available(override val network: Network) : CallbackEntry()
77 data class CapabilitiesChanged(
78 override val network: Network,
79 val caps: NetworkCapabilities
80 ) : CallbackEntry()
81 data class LinkPropertiesChanged(
82 override val network: Network,
83 val lp: LinkProperties
84 ) : CallbackEntry()
85 data class LocalInfoChanged(
86 override val network: Network,
87 val info: LocalNetworkInfo
88 ) : CallbackEntry()
89 data class Suspended(override val network: Network) : CallbackEntry()
90 data class Resumed(override val network: Network) : CallbackEntry()
91 data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackEntry()
92 data class Lost(override val network: Network) : CallbackEntry()
93 data class Unavailable private constructor(
94 override val network: Network
95 ) : CallbackEntry() {
96 constructor() : this(NULL_NETWORK)
97 }
98 data class BlockedStatus(
99 override val network: Network,
100 val blocked: Boolean
101 ) : CallbackEntry()
102 data class BlockedStatusInt(
103 override val network: Network,
104 val reason: Int
105 ) : CallbackEntry()
106
107 // Convenience constants for expecting a type
108 companion object {
109 @JvmField
110 val RESERVED = Reserved::class
111 @JvmField
112 val AVAILABLE = Available::class
113 @JvmField
114 val NETWORK_CAPS_UPDATED = CapabilitiesChanged::class
115 @JvmField
116 val LINK_PROPERTIES_CHANGED = LinkPropertiesChanged::class
117 @JvmField
118 val LOCAL_INFO_CHANGED = LocalInfoChanged::class
119 @JvmField
120 val SUSPENDED = Suspended::class
121 @JvmField
122 val RESUMED = Resumed::class
123 @JvmField
124 val LOSING = Losing::class
125 @JvmField
126 val LOST = Lost::class
127 @JvmField
128 val UNAVAILABLE = Unavailable::class
129 @JvmField
130 val BLOCKED_STATUS = BlockedStatus::class
131 @JvmField
132 val BLOCKED_STATUS_INT = BlockedStatusInt::class
133 }
134 }
135
136 val history = backingRecord.newReadHead()
137 val mark get() = history.mark
138
139 override fun onReserved(caps: NetworkCapabilities) {
140 Log.d(logTag, "onReserved $caps")
141 history.add(Reserved(caps))
142 }
143
144 override fun onAvailable(network: Network) {
145 Log.d(logTag, "onAvailable $network")
146 history.add(Available(network))
147 }
148
149 // PreCheck is not used in the tests today. For backward compatibility with existing tests that
150 // expect the callbacks not to record this, do not listen to PreCheck here.
151
152 override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
153 Log.d(logTag, "onCapabilitiesChanged $network $caps")
154 history.add(CapabilitiesChanged(network, caps))
155 }
156
157 override fun onLinkPropertiesChanged(network: Network, lp: LinkProperties) {
158 Log.d(logTag, "onLinkPropertiesChanged $network $lp")
159 history.add(LinkPropertiesChanged(network, lp))
160 }
161
162 override fun onLocalNetworkInfoChanged(network: Network, info: LocalNetworkInfo) {
163 Log.d(logTag, "onLocalNetworkInfoChanged $network $info")
164 history.add(LocalInfoChanged(network, info))
165 }
166
167 override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
168 Log.d(logTag, "onBlockedStatusChanged $network $blocked")
169 history.add(BlockedStatus(network, blocked))
170 }
171
172 // Cannot do:
173 // fun onBlockedStatusChanged(network: Network, blocked: Int) {
174 // because on S, that needs to be "override fun", and on R, that cannot be "override fun".
175 override fun onNetworkSuspended(network: Network) {
176 Log.d(logTag, "onNetworkSuspended $network $network")
177 history.add(Suspended(network))
178 }
179
180 override fun onNetworkResumed(network: Network) {
181 Log.d(logTag, "$network onNetworkResumed $network")
182 history.add(Resumed(network))
183 }
184
185 override fun onLosing(network: Network, maxMsToLive: Int) {
186 Log.d(logTag, "onLosing $network $maxMsToLive")
187 history.add(Losing(network, maxMsToLive))
188 }
189
190 override fun onLost(network: Network) {
191 Log.d(logTag, "onLost $network")
192 history.add(Lost(network))
193 }
194
195 override fun onUnavailable() {
196 Log.d(logTag, "onUnavailable")
197 history.add(Unavailable())
198 }
199 }
200
201 private const val DEFAULT_TIMEOUT = 30_000L // ms
202 private const val DEFAULT_NO_CALLBACK_TIMEOUT = 200L // ms
<lambda>null203 private val NOOP = Runnable {}
204
205 /**
206 * See comments on the public constructor below for a description of the arguments.
207 */
208 open class TestableNetworkCallback private constructor(
209 src: TestableNetworkCallback?,
210 val defaultTimeoutMs: Long,
211 val defaultNoCallbackTimeoutMs: Long,
212 val waiterFunc: Runnable,
213 logTag: String
214 ) : RecorderCallback(src, logTag) {
215 /**
216 * Construct a testable network callback.
217 * @param timeoutMs the default timeout for expecting a callback. Default 30 seconds. This
218 * should be long in most cases, because the success case doesn't incur
219 * the wait.
220 * @param noCallbackTimeoutMs the timeout for expecting that no callback is received. Default
221 * 200ms. Because the success case does incur the timeout, this
222 * should be short in most cases, but not so short as to frequently
223 * time out before an incorrect callback is received.
224 * @param waiterFunc a function to use before asserting no callback. For some specific tests,
225 * it is useful to run test-specific code before asserting no callback to
226 * increase the likelihood that a spurious callback is correctly detected.
227 * As an example, a unit test using mock loopers may want to use this to
228 * make sure the loopers are drained before asserting no callback, since
229 * one of them may cause a callback to be called. @see ConnectivityServiceTest
230 * for such an example.
231 */
232 @JvmOverloads
233 constructor(
234 timeoutMs: Long = DEFAULT_TIMEOUT,
235 noCallbackTimeoutMs: Long = DEFAULT_NO_CALLBACK_TIMEOUT,
236 waiterFunc: Runnable = NOOP, // "() -> Unit" would forbid calling with a void func from Java
237 logTag: String = DEFAULT_TAG
238 ) : this(null, timeoutMs, noCallbackTimeoutMs, waiterFunc, logTag)
239
createLinkedCopynull240 fun createLinkedCopy() = TestableNetworkCallback(
241 this,
242 defaultTimeoutMs,
243 defaultNoCallbackTimeoutMs,
244 waiterFunc,
245 logTag
246 )
247
248 // The last available network, or null if any network was lost since the last call to
249 // onAvailable. TODO : fix this by fixing the tests that rely on this behavior
250 val lastAvailableNetwork: Network?
251 get() = when (val it = history.lastOrNull { it is Available || it is Lost }) {
252 is Available -> it.network
253 else -> null
254 }
255
256 /**
257 * Get the next callback or null if timeout.
258 *
259 * With no argument, this method waits out the default timeout. To wait forever, pass
260 * Long.MAX_VALUE.
261 */
262 @JvmOverloads
<lambda>null263 fun poll(timeoutMs: Long = defaultTimeoutMs, predicate: (CallbackEntry) -> Boolean = { true }) =
264 history.poll(timeoutMs, predicate)
265
266 /*****
267 * expect family of methods.
268 * These methods fetch the next callback and assert it matches the conditions : type,
269 * passed predicate. If no callback is received within the timeout, these methods fail.
270 */
271 @JvmOverloads
expectnull272 fun <T : CallbackEntry> expect(
273 type: KClass<T>,
274 network: Network = ANY_NETWORK,
275 timeoutMs: Long = defaultTimeoutMs,
276 errorMsg: String? = null,
277 test: (T) -> Boolean = { true }
<lambda>null278 ) = expect<CallbackEntry>(network, timeoutMs, errorMsg) {
279 if (type.isInstance(it)) {
280 test(it as T) // Cast can't fail since type.isInstance(it) and type: KClass<T>
281 } else {
282 fail("Expected callback ${type.simpleName}, got $it")
283 }
284 } as T
285
286 @JvmOverloads
expectnull287 fun <T : CallbackEntry> expect(
288 type: KClass<T>,
289 network: HasNetwork,
290 timeoutMs: Long = defaultTimeoutMs,
291 errorMsg: String? = null,
292 test: (T) -> Boolean = { true }
293 ) = expect(type, network.network, timeoutMs, errorMsg, test)
294
295 // Java needs an explicit overload to let it omit arguments in the middle, so define these
296 // here. Note that @JvmOverloads give us the versions without the last arguments too, so
297 // there is no need to explicitly define versions without the test predicate.
298 // Without |network|
299 @JvmOverloads
expectnull300 fun <T : CallbackEntry> expect(
301 type: KClass<T>,
302 timeoutMs: Long,
303 errorMsg: String?,
304 test: (T) -> Boolean = { true }
305 ) = expect(type, ANY_NETWORK, timeoutMs, errorMsg, test)
306
307 // Without |timeout|, in Network and HasNetwork versions
308 @JvmOverloads
expectnull309 fun <T : CallbackEntry> expect(
310 type: KClass<T>,
311 network: Network,
312 errorMsg: String?,
313 test: (T) -> Boolean = { true }
314 ) = expect(type, network, defaultTimeoutMs, errorMsg, test)
315
316 @JvmOverloads
expectnull317 fun <T : CallbackEntry> expect(
318 type: KClass<T>,
319 network: HasNetwork,
320 errorMsg: String?,
321 test: (T) -> Boolean = { true }
322 ) = expect(type, network.network, defaultTimeoutMs, errorMsg, test)
323
324 // Without |errorMsg|, in Network and HasNetwork versions
325 @JvmOverloads
expectnull326 fun <T : CallbackEntry> expect(
327 type: KClass<T>,
328 network: Network,
329 timeoutMs: Long,
330 test: (T) -> Boolean
331 ) = expect(type, network, timeoutMs, null, test)
332
333 @JvmOverloads
334 fun <T : CallbackEntry> expect(
335 type: KClass<T>,
336 network: HasNetwork,
337 timeoutMs: Long,
338 test: (T) -> Boolean
339 ) = expect(type, network.network, timeoutMs, null, test)
340
341 // Without |network| or |timeout|
342 @JvmOverloads
343 fun <T : CallbackEntry> expect(
344 type: KClass<T>,
345 errorMsg: String?,
346 test: (T) -> Boolean = { true }
347 ) = expect(type, ANY_NETWORK, defaultTimeoutMs, errorMsg, test)
348
349 // Without |network| or |errorMsg|
350 @JvmOverloads
expectnull351 fun <T : CallbackEntry> expect(
352 type: KClass<T>,
353 timeoutMs: Long,
354 test: (T) -> Boolean = { true }
355 ) = expect(type, ANY_NETWORK, timeoutMs, null, test)
356
357 // Without |timeout| or |errorMsg|, in Network and HasNetwork versions
358 @JvmOverloads
expectnull359 fun <T : CallbackEntry> expect(
360 type: KClass<T>,
361 network: Network,
362 test: (T) -> Boolean
363 ) = expect(type, network, defaultTimeoutMs, null, test)
364
365 @JvmOverloads
366 fun <T : CallbackEntry> expect(
367 type: KClass<T>,
368 network: HasNetwork,
369 test: (T) -> Boolean
370 ) = expect(type, network.network, defaultTimeoutMs, null, test)
371
372 // Without |network| or |timeout| or |errorMsg|
373 @JvmOverloads
374 fun <T : CallbackEntry> expect(
375 type: KClass<T>,
376 test: (T) -> Boolean
377 ) = expect(type, ANY_NETWORK, defaultTimeoutMs, null, test)
378
379 // Kotlin reified versions. Don't call methods above, or the predicate would need to be noinline
380 inline fun <reified T : CallbackEntry> expect(
381 network: Network = ANY_NETWORK,
382 timeoutMs: Long = defaultTimeoutMs,
383 errorMsg: String? = null,
384 test: (T) -> Boolean = { true }
385 ) = (poll(timeoutMs) ?: failWithErrorReason(errorMsg,
386 "Did not receive ${T::class.simpleName} after ${timeoutMs}ms"))
<lambda>null387 .also {
388 if (it !is T) {
389 failWithErrorReason(
390 errorMsg,
391 "Expected callback ${T::class.simpleName}, got $it"
392 )
393 }
394 if (ANY_NETWORK !== network && it.network != network) {
395 failWithErrorReason(errorMsg, "Expected network $network for callback : $it")
396 }
397 if (!test(it)) {
398 failWithErrorReason(errorMsg, "Callback doesn't match predicate : $it")
399 }
400 } as T
401
402 // "Nothing" is the return type to declare a function never returns a value.
failWithErrorReasonnull403 fun failWithErrorReason(errorMsg: String?, errorReason: String): Nothing {
404 val message = if (errorMsg != null) "$errorMsg : $errorReason" else errorReason
405 fail(message)
406 }
407
expectnull408 inline fun <reified T : CallbackEntry> expect(
409 network: HasNetwork,
410 timeoutMs: Long = defaultTimeoutMs,
411 errorMsg: String? = null,
412 test: (T) -> Boolean = { true }
413 ) = expect(network.network, timeoutMs, errorMsg, test)
414
415 /*****
416 * assertNoCallback family of methods.
417 * These methods make sure that no callback that matches the predicate was received.
418 * If no predicate is given, they make sure that no callback at all was received.
419 * These methods run the waiter func given in the constructor if any.
420 */
421 @JvmOverloads
assertNoCallbacknull422 fun assertNoCallback(
423 timeoutMs: Long = defaultNoCallbackTimeoutMs,
424 valid: (CallbackEntry) -> Boolean = { true }
425 ) {
426 waiterFunc.run()
<lambda>null427 history.poll(timeoutMs) { valid(it) }?.let { fail("Expected no callback but got $it") }
428 }
429
assertNoCallbacknull430 fun assertNoCallback(valid: (CallbackEntry) -> Boolean) =
431 assertNoCallback(defaultNoCallbackTimeoutMs, valid)
432
433 /*****
434 * eventuallyExpect family of methods.
435 * These methods make sure a callback that matches the type/predicate is received eventually.
436 * Any callback of the wrong type, or doesn't match the optional predicate, is ignored.
437 * They fail if no callback matching the predicate is received within the timeout.
438 */
439 inline fun <reified T : CallbackEntry> eventuallyExpect(
440 timeoutMs: Long = defaultTimeoutMs,
441 from: Int = mark,
442 crossinline predicate: (T) -> Boolean = { true }
<lambda>null443 ): T = history.poll(timeoutMs, from) { it is T && predicate(it) }.also {
444 assertNotNull(
445 it,
446 "Callback ${T::class} not received within ${timeoutMs}ms. " +
447 "Got ${history.backtrace()}"
448 )
449 } as T
450
451 @JvmOverloads
eventuallyExpectnull452 fun <T : CallbackEntry> eventuallyExpect(
453 type: KClass<T>,
454 timeoutMs: Long = defaultTimeoutMs,
455 predicate: (cb: T) -> Boolean = { true }
<lambda>null456 ) = history.poll(timeoutMs) { type.java.isInstance(it) && predicate(it as T) }.also {
457 assertNotNull(
458 it,
459 "Callback ${type.java} not received within ${timeoutMs}ms. " +
460 "Got ${history.backtrace()}"
461 )
462 } as T
463
eventuallyExpectnull464 fun <T : CallbackEntry> eventuallyExpect(
465 type: KClass<T>,
466 timeoutMs: Long = defaultTimeoutMs,
467 from: Int = mark,
468 predicate: (cb: T) -> Boolean = { true }
<lambda>null469 ) = history.poll(timeoutMs, from) { type.java.isInstance(it) && predicate(it as T) }.also {
470 assertNotNull(
471 it,
472 "Callback ${type.java} not received within ${timeoutMs}ms. " +
473 "Got ${history.backtrace()}"
474 )
475 } as T
476
477 // Expects onAvailable and the callbacks that follow it. These are:
478 // - onSuspended, iff the network was suspended when the callbacks fire.
479 // - onCapabilitiesChanged.
480 // - onLinkPropertiesChanged.
481 // - onBlockedStatusChanged.
482 //
483 // @param network the network to expect the callbacks on.
484 // @param suspended whether to expect a SUSPENDED callback.
485 // @param validated the expected value of the VALIDATED capability in the
486 // onCapabilitiesChanged callback.
487 // @param tmt how long to wait for the callbacks.
488 @JvmOverloads
expectAvailableCallbacksnull489 fun expectAvailableCallbacks(
490 net: Network,
491 suspended: Boolean = false,
492 validated: Boolean? = true,
493 blocked: Boolean = false,
494 upstream: Network? = null,
495 tmt: Long = defaultTimeoutMs
496 ) {
497 expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
498 expect<BlockedStatus>(net, tmt) { it.blocked == blocked }
499 }
500
501 // For backward compatibility, add a method that allows callers to specify a timeout but
502 // no upstream.
expectAvailableCallbacksnull503 fun expectAvailableCallbacks(
504 net: Network,
505 suspended: Boolean = false,
506 validated: Boolean? = true,
507 blocked: Boolean = false,
508 tmt: Long = defaultTimeoutMs
509 ) = expectAvailableCallbacks(net, suspended, validated, blocked, upstream = null, tmt = tmt)
510
511 fun expectAvailableCallbacks(
512 net: Network,
513 suspended: Boolean,
514 validated: Boolean,
515 blockedReason: Int,
516 upstream: Network? = null,
517 tmt: Long
518 ) {
519 expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
520 expect<BlockedStatusInt>(net) { it.reason == blockedReason }
521 }
522
523 // For backward compatibility, add a method that allows callers to specify a timeout but
524 // no upstream.
expectAvailableCallbacksnull525 fun expectAvailableCallbacks(
526 net: Network,
527 suspended: Boolean = false,
528 validated: Boolean = true,
529 blockedReason: Int,
530 tmt: Long = defaultTimeoutMs
531 ) = expectAvailableCallbacks(net, suspended, validated, blockedReason, upstream = null, tmt)
532
533 private fun expectAvailableCallbacksCommon(
534 net: Network,
535 suspended: Boolean,
536 validated: Boolean?,
537 upstream: Network?,
538 tmt: Long
539 ) {
540 expect<Available>(net, tmt)
541 if (suspended) {
542 expect<Suspended>(net, tmt)
543 }
544 val caps = expect<CapabilitiesChanged>(net, tmt) {
545 validated == null || validated == it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
546 }.caps
547 expect<LinkPropertiesChanged>(net, tmt)
548 if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK)) {
549 expect<LocalInfoChanged>(net, tmt) { it.info.upstreamNetwork == upstream }
550 }
551 }
552
553 // Backward compatibility for existing Java code. Use named arguments instead and remove all
554 // these when there is no user left.
expectAvailableAndSuspendedCallbacksnull555 fun expectAvailableAndSuspendedCallbacks(
556 net: Network,
557 validated: Boolean,
558 tmt: Long = defaultTimeoutMs
559 ) = expectAvailableCallbacks(net, suspended = true, validated = validated, tmt = tmt)
560
561 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
562 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
563 // one we just sent.
564 // TODO: this is likely a bug. Fix it and remove this method.
565 fun expectAvailableDoubleValidatedCallbacks(net: Network, tmt: Long = defaultTimeoutMs) {
566 val mark = history.mark
567 expectAvailableCallbacks(net, tmt = tmt)
568 val firstCaps = history.poll(tmt, mark) { it is CapabilitiesChanged }
569 assertEquals(firstCaps, expect<CapabilitiesChanged>(net, tmt))
570 }
571
572 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
573 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
574 // when a network connects and satisfies a callback, and then immediately validates.
expectAvailableThenValidatedCallbacksnull575 fun expectAvailableThenValidatedCallbacks(net: Network, tmt: Long = defaultTimeoutMs) {
576 expectAvailableCallbacks(net, validated = false, tmt = tmt)
577 expectCaps(net, tmt) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
578 }
579
expectAvailableThenValidatedCallbacksnull580 fun expectAvailableThenValidatedCallbacks(
581 net: Network,
582 blockedReason: Int,
583 tmt: Long = defaultTimeoutMs
584 ) {
585 expectAvailableCallbacks(
586 net,
587 validated = false,
588 suspended = false,
589 blockedReason = blockedReason,
590 tmt = tmt
591 )
592 expectCaps(net, tmt) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
593 }
594
595 // Temporary Java compat measure : have MockNetworkAgent implement this so that all existing
596 // calls with networkAgent can be routed through here without moving MockNetworkAgent.
597 // TODO: clean this up, remove this method.
598 interface HasNetwork {
599 val network: Network
600 }
601
602 @JvmOverloads
expectAvailableCallbacksnull603 fun expectAvailableCallbacks(
604 n: HasNetwork,
605 suspended: Boolean,
606 validated: Boolean,
607 blocked: Boolean,
608 upstream: Network? = null,
609 timeoutMs: Long
610 ) = expectAvailableCallbacks(n.network, suspended, validated, blocked, upstream, timeoutMs)
611
612 fun expectAvailableAndSuspendedCallbacks(n: HasNetwork, expectValidated: Boolean) {
613 expectAvailableAndSuspendedCallbacks(n.network, expectValidated)
614 }
615
expectAvailableCallbacksValidatednull616 fun expectAvailableCallbacksValidated(n: HasNetwork) {
617 expectAvailableCallbacks(n.network)
618 }
619
expectAvailableCallbacksValidatedAndBlockednull620 fun expectAvailableCallbacksValidatedAndBlocked(n: HasNetwork) {
621 expectAvailableCallbacks(n.network, blocked = true)
622 }
623
expectAvailableCallbacksUnvalidatednull624 fun expectAvailableCallbacksUnvalidated(n: HasNetwork) {
625 expectAvailableCallbacks(n.network, validated = false)
626 }
627
expectAvailableCallbacksUnvalidatedAndBlockednull628 fun expectAvailableCallbacksUnvalidatedAndBlocked(n: HasNetwork) {
629 expectAvailableCallbacks(n.network, validated = false, blocked = true)
630 }
631
expectAvailableDoubleValidatedCallbacksnull632 fun expectAvailableDoubleValidatedCallbacks(n: HasNetwork) {
633 expectAvailableDoubleValidatedCallbacks(n.network, defaultTimeoutMs)
634 }
635
expectAvailableThenValidatedCallbacksnull636 fun expectAvailableThenValidatedCallbacks(n: HasNetwork) {
637 expectAvailableThenValidatedCallbacks(n.network, defaultTimeoutMs)
638 }
639
640 @JvmOverloads
expectCapsnull641 fun expectCaps(
642 n: HasNetwork,
643 tmt: Long = defaultTimeoutMs,
644 valid: (NetworkCapabilities) -> Boolean = { true }
<lambda>null645 ) = expect<CapabilitiesChanged>(n.network, tmt) { valid(it.caps) }.caps
646
647 @JvmOverloads
expectCapsnull648 fun expectCaps(
649 n: Network,
650 tmt: Long = defaultTimeoutMs,
651 valid: (NetworkCapabilities) -> Boolean
652 ) = expect<CapabilitiesChanged>(n, tmt) { valid(it.caps) }.caps
653
expectCapsnull654 fun expectCaps(
655 n: HasNetwork,
656 valid: (NetworkCapabilities) -> Boolean
657 ) = expect<CapabilitiesChanged>(n.network) { valid(it.caps) }.caps
658
expectCapsnull659 fun expectCaps(
660 tmt: Long,
661 valid: (NetworkCapabilities) -> Boolean
662 ) = expect<CapabilitiesChanged>(ANY_NETWORK, tmt) { valid(it.caps) }.caps
663 }
664