• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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