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.Resumed
36 import com.android.testutils.RecorderCallback.CallbackEntry.Suspended
37 import com.android.testutils.RecorderCallback.CallbackEntry.Unavailable
38 import kotlin.reflect.KClass
39 import kotlin.test.assertEquals
40 import kotlin.test.assertNotNull
41 import kotlin.test.fail
42
43 object NULL_NETWORK : Network(-1)
44 object ANY_NETWORK : Network(-2)
anyNetworknull45 fun anyNetwork() = ANY_NETWORK
46
47 private val DEFAULT_TAG = RecorderCallback::class.simpleName
48 ?: fail("Could not determine class name")
49
50 open class RecorderCallback private constructor(
51 private val backingRecord: ArrayTrackRecord<CallbackEntry>,
52 val logTag: String
53 ) : NetworkCallback() {
54 public constructor(logTag: String = DEFAULT_TAG) : this(ArrayTrackRecord(), logTag)
55 protected constructor(src: RecorderCallback?, logTag: String) : this(
56 src?.backingRecord ?: ArrayTrackRecord(),
57 logTag
58 )
59
60 sealed class CallbackEntry {
61 // To get equals(), hashcode(), componentN() etc for free, the child classes of
62 // this class are data classes. But while data classes can inherit from other classes,
63 // they may only have visible members in the constructors, so they couldn't declare
64 // a constructor with a non-val arg to pass to CallbackEntry. Instead, force all
65 // subclasses to implement a `network' property, which can be done in a data class
66 // constructor by specifying override.
67 abstract val network: Network
68
69 data class Available(override val network: Network) : CallbackEntry()
70 data class CapabilitiesChanged(
71 override val network: Network,
72 val caps: NetworkCapabilities
73 ) : CallbackEntry()
74 data class LinkPropertiesChanged(
75 override val network: Network,
76 val lp: LinkProperties
77 ) : CallbackEntry()
78 data class LocalInfoChanged(
79 override val network: Network,
80 val info: LocalNetworkInfo
81 ) : CallbackEntry()
82 data class Suspended(override val network: Network) : CallbackEntry()
83 data class Resumed(override val network: Network) : CallbackEntry()
84 data class Losing(override val network: Network, val maxMsToLive: Int) : CallbackEntry()
85 data class Lost(override val network: Network) : CallbackEntry()
86 data class Unavailable private constructor(
87 override val network: Network
88 ) : CallbackEntry() {
89 constructor() : this(NULL_NETWORK)
90 }
91 data class BlockedStatus(
92 override val network: Network,
93 val blocked: Boolean
94 ) : CallbackEntry()
95 data class BlockedStatusInt(
96 override val network: Network,
97 val reason: Int
98 ) : CallbackEntry()
99
100 // Convenience constants for expecting a type
101 companion object {
102 @JvmField
103 val AVAILABLE = Available::class
104 @JvmField
105 val NETWORK_CAPS_UPDATED = CapabilitiesChanged::class
106 @JvmField
107 val LINK_PROPERTIES_CHANGED = LinkPropertiesChanged::class
108 @JvmField
109 val LOCAL_INFO_CHANGED = LocalInfoChanged::class
110 @JvmField
111 val SUSPENDED = Suspended::class
112 @JvmField
113 val RESUMED = Resumed::class
114 @JvmField
115 val LOSING = Losing::class
116 @JvmField
117 val LOST = Lost::class
118 @JvmField
119 val UNAVAILABLE = Unavailable::class
120 @JvmField
121 val BLOCKED_STATUS = BlockedStatus::class
122 @JvmField
123 val BLOCKED_STATUS_INT = BlockedStatusInt::class
124 }
125 }
126
127 val history = backingRecord.newReadHead()
128 val mark get() = history.mark
129
130 override fun onAvailable(network: Network) {
131 Log.d(logTag, "onAvailable $network")
132 history.add(Available(network))
133 }
134
135 // PreCheck is not used in the tests today. For backward compatibility with existing tests that
136 // expect the callbacks not to record this, do not listen to PreCheck here.
137
138 override fun onCapabilitiesChanged(network: Network, caps: NetworkCapabilities) {
139 Log.d(logTag, "onCapabilitiesChanged $network $caps")
140 history.add(CapabilitiesChanged(network, caps))
141 }
142
143 override fun onLinkPropertiesChanged(network: Network, lp: LinkProperties) {
144 Log.d(logTag, "onLinkPropertiesChanged $network $lp")
145 history.add(LinkPropertiesChanged(network, lp))
146 }
147
148 override fun onLocalNetworkInfoChanged(network: Network, info: LocalNetworkInfo) {
149 Log.d(logTag, "onLocalNetworkInfoChanged $network $info")
150 history.add(LocalInfoChanged(network, info))
151 }
152
153 override fun onBlockedStatusChanged(network: Network, blocked: Boolean) {
154 Log.d(logTag, "onBlockedStatusChanged $network $blocked")
155 history.add(BlockedStatus(network, blocked))
156 }
157
158 // Cannot do:
159 // fun onBlockedStatusChanged(network: Network, blocked: Int) {
160 // because on S, that needs to be "override fun", and on R, that cannot be "override fun".
161 override fun onNetworkSuspended(network: Network) {
162 Log.d(logTag, "onNetworkSuspended $network $network")
163 history.add(Suspended(network))
164 }
165
166 override fun onNetworkResumed(network: Network) {
167 Log.d(logTag, "$network onNetworkResumed $network")
168 history.add(Resumed(network))
169 }
170
171 override fun onLosing(network: Network, maxMsToLive: Int) {
172 Log.d(logTag, "onLosing $network $maxMsToLive")
173 history.add(Losing(network, maxMsToLive))
174 }
175
176 override fun onLost(network: Network) {
177 Log.d(logTag, "onLost $network")
178 history.add(Lost(network))
179 }
180
181 override fun onUnavailable() {
182 Log.d(logTag, "onUnavailable")
183 history.add(Unavailable())
184 }
185 }
186
187 private const val DEFAULT_TIMEOUT = 30_000L // ms
188 private const val DEFAULT_NO_CALLBACK_TIMEOUT = 200L // ms
<lambda>null189 private val NOOP = Runnable {}
190
191 /**
192 * See comments on the public constructor below for a description of the arguments.
193 */
194 open class TestableNetworkCallback private constructor(
195 src: TestableNetworkCallback?,
196 val defaultTimeoutMs: Long,
197 val defaultNoCallbackTimeoutMs: Long,
198 val waiterFunc: Runnable,
199 logTag: String
200 ) : RecorderCallback(src, logTag) {
201 /**
202 * Construct a testable network callback.
203 * @param timeoutMs the default timeout for expecting a callback. Default 30 seconds. This
204 * should be long in most cases, because the success case doesn't incur
205 * the wait.
206 * @param noCallbackTimeoutMs the timeout for expecting that no callback is received. Default
207 * 200ms. Because the success case does incur the timeout, this
208 * should be short in most cases, but not so short as to frequently
209 * time out before an incorrect callback is received.
210 * @param waiterFunc a function to use before asserting no callback. For some specific tests,
211 * it is useful to run test-specific code before asserting no callback to
212 * increase the likelihood that a spurious callback is correctly detected.
213 * As an example, a unit test using mock loopers may want to use this to
214 * make sure the loopers are drained before asserting no callback, since
215 * one of them may cause a callback to be called. @see ConnectivityServiceTest
216 * for such an example.
217 */
218 @JvmOverloads
219 constructor(
220 timeoutMs: Long = DEFAULT_TIMEOUT,
221 noCallbackTimeoutMs: Long = DEFAULT_NO_CALLBACK_TIMEOUT,
222 waiterFunc: Runnable = NOOP, // "() -> Unit" would forbid calling with a void func from Java
223 logTag: String = DEFAULT_TAG
224 ) : this(null, timeoutMs, noCallbackTimeoutMs, waiterFunc, logTag)
225
createLinkedCopynull226 fun createLinkedCopy() = TestableNetworkCallback(
227 this,
228 defaultTimeoutMs,
229 defaultNoCallbackTimeoutMs,
230 waiterFunc,
231 logTag
232 )
233
234 // The last available network, or null if any network was lost since the last call to
235 // onAvailable. TODO : fix this by fixing the tests that rely on this behavior
236 val lastAvailableNetwork: Network?
237 get() = when (val it = history.lastOrNull { it is Available || it is Lost }) {
238 is Available -> it.network
239 else -> null
240 }
241
242 /**
243 * Get the next callback or null if timeout.
244 *
245 * With no argument, this method waits out the default timeout. To wait forever, pass
246 * Long.MAX_VALUE.
247 */
248 @JvmOverloads
<lambda>null249 fun poll(timeoutMs: Long = defaultTimeoutMs, predicate: (CallbackEntry) -> Boolean = { true }) =
250 history.poll(timeoutMs, predicate)
251
252 /*****
253 * expect family of methods.
254 * These methods fetch the next callback and assert it matches the conditions : type,
255 * passed predicate. If no callback is received within the timeout, these methods fail.
256 */
257 @JvmOverloads
expectnull258 fun <T : CallbackEntry> expect(
259 type: KClass<T>,
260 network: Network = ANY_NETWORK,
261 timeoutMs: Long = defaultTimeoutMs,
262 errorMsg: String? = null,
263 test: (T) -> Boolean = { true }
<lambda>null264 ) = expect<CallbackEntry>(network, timeoutMs, errorMsg) {
265 if (type.isInstance(it)) {
266 test(it as T) // Cast can't fail since type.isInstance(it) and type: KClass<T>
267 } else {
268 fail("Expected callback ${type.simpleName}, got $it")
269 }
270 } as T
271
272 @JvmOverloads
expectnull273 fun <T : CallbackEntry> expect(
274 type: KClass<T>,
275 network: HasNetwork,
276 timeoutMs: Long = defaultTimeoutMs,
277 errorMsg: String? = null,
278 test: (T) -> Boolean = { true }
279 ) = expect(type, network.network, timeoutMs, errorMsg, test)
280
281 // Java needs an explicit overload to let it omit arguments in the middle, so define these
282 // here. Note that @JvmOverloads give us the versions without the last arguments too, so
283 // there is no need to explicitly define versions without the test predicate.
284 // Without |network|
285 @JvmOverloads
expectnull286 fun <T : CallbackEntry> expect(
287 type: KClass<T>,
288 timeoutMs: Long,
289 errorMsg: String?,
290 test: (T) -> Boolean = { true }
291 ) = expect(type, ANY_NETWORK, timeoutMs, errorMsg, test)
292
293 // Without |timeout|, in Network and HasNetwork versions
294 @JvmOverloads
expectnull295 fun <T : CallbackEntry> expect(
296 type: KClass<T>,
297 network: Network,
298 errorMsg: String?,
299 test: (T) -> Boolean = { true }
300 ) = expect(type, network, defaultTimeoutMs, errorMsg, test)
301
302 @JvmOverloads
expectnull303 fun <T : CallbackEntry> expect(
304 type: KClass<T>,
305 network: HasNetwork,
306 errorMsg: String?,
307 test: (T) -> Boolean = { true }
308 ) = expect(type, network.network, defaultTimeoutMs, errorMsg, test)
309
310 // Without |errorMsg|, in Network and HasNetwork versions
311 @JvmOverloads
expectnull312 fun <T : CallbackEntry> expect(
313 type: KClass<T>,
314 network: Network,
315 timeoutMs: Long,
316 test: (T) -> Boolean
317 ) = expect(type, network, timeoutMs, null, test)
318
319 @JvmOverloads
320 fun <T : CallbackEntry> expect(
321 type: KClass<T>,
322 network: HasNetwork,
323 timeoutMs: Long,
324 test: (T) -> Boolean
325 ) = expect(type, network.network, timeoutMs, null, test)
326
327 // Without |network| or |timeout|
328 @JvmOverloads
329 fun <T : CallbackEntry> expect(
330 type: KClass<T>,
331 errorMsg: String?,
332 test: (T) -> Boolean = { true }
333 ) = expect(type, ANY_NETWORK, defaultTimeoutMs, errorMsg, test)
334
335 // Without |network| or |errorMsg|
336 @JvmOverloads
expectnull337 fun <T : CallbackEntry> expect(
338 type: KClass<T>,
339 timeoutMs: Long,
340 test: (T) -> Boolean = { true }
341 ) = expect(type, ANY_NETWORK, timeoutMs, null, test)
342
343 // Without |timeout| or |errorMsg|, in Network and HasNetwork versions
344 @JvmOverloads
expectnull345 fun <T : CallbackEntry> expect(
346 type: KClass<T>,
347 network: Network,
348 test: (T) -> Boolean
349 ) = expect(type, network, defaultTimeoutMs, null, test)
350
351 @JvmOverloads
352 fun <T : CallbackEntry> expect(
353 type: KClass<T>,
354 network: HasNetwork,
355 test: (T) -> Boolean
356 ) = expect(type, network.network, defaultTimeoutMs, null, test)
357
358 // Without |network| or |timeout| or |errorMsg|
359 @JvmOverloads
360 fun <T : CallbackEntry> expect(
361 type: KClass<T>,
362 test: (T) -> Boolean
363 ) = expect(type, ANY_NETWORK, defaultTimeoutMs, null, test)
364
365 // Kotlin reified versions. Don't call methods above, or the predicate would need to be noinline
366 inline fun <reified T : CallbackEntry> expect(
367 network: Network = ANY_NETWORK,
368 timeoutMs: Long = defaultTimeoutMs,
369 errorMsg: String? = null,
370 test: (T) -> Boolean = { true }
371 ) = (poll(timeoutMs) ?: failWithErrorReason(errorMsg,
372 "Did not receive ${T::class.simpleName} after ${timeoutMs}ms"))
<lambda>null373 .also {
374 if (it !is T) {
375 failWithErrorReason(
376 errorMsg,
377 "Expected callback ${T::class.simpleName}, got $it"
378 )
379 }
380 if (ANY_NETWORK !== network && it.network != network) {
381 failWithErrorReason(errorMsg, "Expected network $network for callback : $it")
382 }
383 if (!test(it)) {
384 failWithErrorReason(errorMsg, "Callback doesn't match predicate : $it")
385 }
386 } as T
387
388 // "Nothing" is the return type to declare a function never returns a value.
failWithErrorReasonnull389 fun failWithErrorReason(errorMsg: String?, errorReason: String): Nothing {
390 val message = if (errorMsg != null) "$errorMsg : $errorReason" else errorReason
391 fail(message)
392 }
393
expectnull394 inline fun <reified T : CallbackEntry> expect(
395 network: HasNetwork,
396 timeoutMs: Long = defaultTimeoutMs,
397 errorMsg: String? = null,
398 test: (T) -> Boolean = { true }
399 ) = expect(network.network, timeoutMs, errorMsg, test)
400
401 /*****
402 * assertNoCallback family of methods.
403 * These methods make sure that no callback that matches the predicate was received.
404 * If no predicate is given, they make sure that no callback at all was received.
405 * These methods run the waiter func given in the constructor if any.
406 */
407 @JvmOverloads
assertNoCallbacknull408 fun assertNoCallback(
409 timeoutMs: Long = defaultNoCallbackTimeoutMs,
410 valid: (CallbackEntry) -> Boolean = { true }
411 ) {
412 waiterFunc.run()
<lambda>null413 history.poll(timeoutMs) { valid(it) }?.let { fail("Expected no callback but got $it") }
414 }
415
assertNoCallbacknull416 fun assertNoCallback(valid: (CallbackEntry) -> Boolean) =
417 assertNoCallback(defaultNoCallbackTimeoutMs, valid)
418
419 /*****
420 * eventuallyExpect family of methods.
421 * These methods make sure a callback that matches the type/predicate is received eventually.
422 * Any callback of the wrong type, or doesn't match the optional predicate, is ignored.
423 * They fail if no callback matching the predicate is received within the timeout.
424 */
425 inline fun <reified T : CallbackEntry> eventuallyExpect(
426 timeoutMs: Long = defaultTimeoutMs,
427 from: Int = mark,
428 crossinline predicate: (T) -> Boolean = { true }
<lambda>null429 ): T = history.poll(timeoutMs, from) { it is T && predicate(it) }.also {
430 assertNotNull(
431 it,
432 "Callback ${T::class} not received within ${timeoutMs}ms. " +
433 "Got ${history.backtrace()}"
434 )
435 } as T
436
437 @JvmOverloads
eventuallyExpectnull438 fun <T : CallbackEntry> eventuallyExpect(
439 type: KClass<T>,
440 timeoutMs: Long = defaultTimeoutMs,
441 predicate: (cb: T) -> Boolean = { true }
<lambda>null442 ) = history.poll(timeoutMs) { type.java.isInstance(it) && predicate(it as T) }.also {
443 assertNotNull(
444 it,
445 "Callback ${type.java} not received within ${timeoutMs}ms. " +
446 "Got ${history.backtrace()}"
447 )
448 } as T
449
eventuallyExpectnull450 fun <T : CallbackEntry> eventuallyExpect(
451 type: KClass<T>,
452 timeoutMs: Long = defaultTimeoutMs,
453 from: Int = mark,
454 predicate: (cb: T) -> Boolean = { true }
<lambda>null455 ) = history.poll(timeoutMs, from) { type.java.isInstance(it) && predicate(it as T) }.also {
456 assertNotNull(
457 it,
458 "Callback ${type.java} not received within ${timeoutMs}ms. " +
459 "Got ${history.backtrace()}"
460 )
461 } as T
462
463 // Expects onAvailable and the callbacks that follow it. These are:
464 // - onSuspended, iff the network was suspended when the callbacks fire.
465 // - onCapabilitiesChanged.
466 // - onLinkPropertiesChanged.
467 // - onBlockedStatusChanged.
468 //
469 // @param network the network to expect the callbacks on.
470 // @param suspended whether to expect a SUSPENDED callback.
471 // @param validated the expected value of the VALIDATED capability in the
472 // onCapabilitiesChanged callback.
473 // @param tmt how long to wait for the callbacks.
474 @JvmOverloads
expectAvailableCallbacksnull475 fun expectAvailableCallbacks(
476 net: Network,
477 suspended: Boolean = false,
478 validated: Boolean? = true,
479 blocked: Boolean = false,
480 upstream: Network? = null,
481 tmt: Long = defaultTimeoutMs
482 ) {
483 expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
484 expect<BlockedStatus>(net, tmt) { it.blocked == blocked }
485 }
486
487 // For backward compatibility, add a method that allows callers to specify a timeout but
488 // no upstream.
expectAvailableCallbacksnull489 fun expectAvailableCallbacks(
490 net: Network,
491 suspended: Boolean = false,
492 validated: Boolean? = true,
493 blocked: Boolean = false,
494 tmt: Long = defaultTimeoutMs
495 ) = expectAvailableCallbacks(net, suspended, validated, blocked, upstream = null, tmt = tmt)
496
497 fun expectAvailableCallbacks(
498 net: Network,
499 suspended: Boolean,
500 validated: Boolean,
501 blockedReason: Int,
502 upstream: Network? = null,
503 tmt: Long
504 ) {
505 expectAvailableCallbacksCommon(net, suspended, validated, upstream, tmt)
506 expect<BlockedStatusInt>(net) { it.reason == blockedReason }
507 }
508
509 // For backward compatibility, add a method that allows callers to specify a timeout but
510 // no upstream.
expectAvailableCallbacksnull511 fun expectAvailableCallbacks(
512 net: Network,
513 suspended: Boolean = false,
514 validated: Boolean = true,
515 blockedReason: Int,
516 tmt: Long = defaultTimeoutMs
517 ) = expectAvailableCallbacks(net, suspended, validated, blockedReason, upstream = null, tmt)
518
519 private fun expectAvailableCallbacksCommon(
520 net: Network,
521 suspended: Boolean,
522 validated: Boolean?,
523 upstream: Network?,
524 tmt: Long
525 ) {
526 expect<Available>(net, tmt)
527 if (suspended) {
528 expect<Suspended>(net, tmt)
529 }
530 val caps = expect<CapabilitiesChanged>(net, tmt) {
531 validated == null || validated == it.caps.hasCapability(NET_CAPABILITY_VALIDATED)
532 }.caps
533 expect<LinkPropertiesChanged>(net, tmt)
534 if (caps.hasCapability(NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK)) {
535 expect<LocalInfoChanged>(net, tmt) { it.info.upstreamNetwork == upstream }
536 }
537 }
538
539 // Backward compatibility for existing Java code. Use named arguments instead and remove all
540 // these when there is no user left.
expectAvailableAndSuspendedCallbacksnull541 fun expectAvailableAndSuspendedCallbacks(
542 net: Network,
543 validated: Boolean,
544 tmt: Long = defaultTimeoutMs
545 ) = expectAvailableCallbacks(net, suspended = true, validated = validated, tmt = tmt)
546
547 // Expects the available callbacks (where the onCapabilitiesChanged must contain the
548 // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
549 // one we just sent.
550 // TODO: this is likely a bug. Fix it and remove this method.
551 fun expectAvailableDoubleValidatedCallbacks(net: Network, tmt: Long = defaultTimeoutMs) {
552 val mark = history.mark
553 expectAvailableCallbacks(net, tmt = tmt)
554 val firstCaps = history.poll(tmt, mark) { it is CapabilitiesChanged }
555 assertEquals(firstCaps, expect<CapabilitiesChanged>(net, tmt))
556 }
557
558 // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
559 // then expects another onCapabilitiesChanged that has the validated bit set. This is used
560 // when a network connects and satisfies a callback, and then immediately validates.
expectAvailableThenValidatedCallbacksnull561 fun expectAvailableThenValidatedCallbacks(net: Network, tmt: Long = defaultTimeoutMs) {
562 expectAvailableCallbacks(net, validated = false, tmt = tmt)
563 expectCaps(net, tmt) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
564 }
565
expectAvailableThenValidatedCallbacksnull566 fun expectAvailableThenValidatedCallbacks(
567 net: Network,
568 blockedReason: Int,
569 tmt: Long = defaultTimeoutMs
570 ) {
571 expectAvailableCallbacks(
572 net,
573 validated = false,
574 suspended = false,
575 blockedReason = blockedReason,
576 tmt = tmt
577 )
578 expectCaps(net, tmt) { it.hasCapability(NET_CAPABILITY_VALIDATED) }
579 }
580
581 // Temporary Java compat measure : have MockNetworkAgent implement this so that all existing
582 // calls with networkAgent can be routed through here without moving MockNetworkAgent.
583 // TODO: clean this up, remove this method.
584 interface HasNetwork {
585 val network: Network
586 }
587
588 @JvmOverloads
expectAvailableCallbacksnull589 fun expectAvailableCallbacks(
590 n: HasNetwork,
591 suspended: Boolean,
592 validated: Boolean,
593 blocked: Boolean,
594 upstream: Network? = null,
595 timeoutMs: Long
596 ) = expectAvailableCallbacks(n.network, suspended, validated, blocked, upstream, timeoutMs)
597
598 fun expectAvailableAndSuspendedCallbacks(n: HasNetwork, expectValidated: Boolean) {
599 expectAvailableAndSuspendedCallbacks(n.network, expectValidated)
600 }
601
expectAvailableCallbacksValidatednull602 fun expectAvailableCallbacksValidated(n: HasNetwork) {
603 expectAvailableCallbacks(n.network)
604 }
605
expectAvailableCallbacksValidatedAndBlockednull606 fun expectAvailableCallbacksValidatedAndBlocked(n: HasNetwork) {
607 expectAvailableCallbacks(n.network, blocked = true)
608 }
609
expectAvailableCallbacksUnvalidatednull610 fun expectAvailableCallbacksUnvalidated(n: HasNetwork) {
611 expectAvailableCallbacks(n.network, validated = false)
612 }
613
expectAvailableCallbacksUnvalidatedAndBlockednull614 fun expectAvailableCallbacksUnvalidatedAndBlocked(n: HasNetwork) {
615 expectAvailableCallbacks(n.network, validated = false, blocked = true)
616 }
617
expectAvailableDoubleValidatedCallbacksnull618 fun expectAvailableDoubleValidatedCallbacks(n: HasNetwork) {
619 expectAvailableDoubleValidatedCallbacks(n.network, defaultTimeoutMs)
620 }
621
expectAvailableThenValidatedCallbacksnull622 fun expectAvailableThenValidatedCallbacks(n: HasNetwork) {
623 expectAvailableThenValidatedCallbacks(n.network, defaultTimeoutMs)
624 }
625
626 @JvmOverloads
expectCapsnull627 fun expectCaps(
628 n: HasNetwork,
629 tmt: Long = defaultTimeoutMs,
630 valid: (NetworkCapabilities) -> Boolean = { true }
<lambda>null631 ) = expect<CapabilitiesChanged>(n.network, tmt) { valid(it.caps) }.caps
632
633 @JvmOverloads
expectCapsnull634 fun expectCaps(
635 n: Network,
636 tmt: Long = defaultTimeoutMs,
637 valid: (NetworkCapabilities) -> Boolean
638 ) = expect<CapabilitiesChanged>(n, tmt) { valid(it.caps) }.caps
639
expectCapsnull640 fun expectCaps(
641 n: HasNetwork,
642 valid: (NetworkCapabilities) -> Boolean
643 ) = expect<CapabilitiesChanged>(n.network) { valid(it.caps) }.caps
644
expectCapsnull645 fun expectCaps(
646 tmt: Long,
647 valid: (NetworkCapabilities) -> Boolean
648 ) = expect<CapabilitiesChanged>(ANY_NETWORK, tmt) { valid(it.caps) }.caps
649 }
650