Merge "Add ConnectivityServiceIntegrationTest"
am: 324d724fd7 Change-Id: Ib82c5e5aee9e830a0efe8ea6335933237bb33856
This commit is contained in:
@@ -2165,7 +2165,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
void systemReady() {
|
||||
/**
|
||||
* Called when the system is ready and ConnectivityService can initialize remaining components.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public void systemReady() {
|
||||
mProxyTracker.loadGlobalProxy();
|
||||
registerNetdEventCallback();
|
||||
mTethering.systemReady();
|
||||
|
||||
58
tests/net/integration/AndroidManifest.xml
Normal file
58
tests/net/integration/AndroidManifest.xml
Normal file
@@ -0,0 +1,58 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
-->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.android.server.net.integrationtests">
|
||||
|
||||
<!-- For ConnectivityService registerReceiverAsUser (receiving broadcasts) -->
|
||||
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
|
||||
<!-- PermissionMonitor sets network permissions for each user -->
|
||||
<uses-permission android:name="android.permission.MANAGE_USERS" />
|
||||
<!-- ConnectivityService sends notifications to BatteryStats -->
|
||||
<uses-permission android:name="android.permission.UPDATE_DEVICE_STATS" />
|
||||
<application android:debuggable="true">
|
||||
<uses-library android:name="android.test.runner" />
|
||||
|
||||
<!-- This manifest is merged with the base manifest of the real NetworkStack app.
|
||||
Remove the NetworkStackService from the base (real) manifest, and replace with a test
|
||||
service that responds to the same intent -->
|
||||
<service android:name="com.android.server.NetworkStackService" tools:node="remove"/>
|
||||
<service android:name=".TestNetworkStackService"
|
||||
android:process="com.android.server.net.integrationtests.testnetworkstack">
|
||||
<intent-filter>
|
||||
<action android:name="android.net.INetworkStackConnector.Test"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service android:name=".NetworkStackInstrumentationService"
|
||||
android:process="com.android.server.net.integrationtests.testnetworkstack">
|
||||
<intent-filter>
|
||||
<action android:name=".INetworkStackInstrumentation"/>
|
||||
</intent-filter>
|
||||
</service>
|
||||
<service tools:replace="android:process"
|
||||
android:name="com.android.server.connectivity.ipmemorystore.RegularMaintenanceJobService"
|
||||
android:process="com.android.server.net.integrationtests.testnetworkstack"/>
|
||||
|
||||
</application>
|
||||
|
||||
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||
android:targetPackage="com.android.server.net.integrationtests"
|
||||
android:label="Frameworks Net Integration Tests" />
|
||||
|
||||
</manifest>
|
||||
15
tests/net/integration/res/values/config.xml
Normal file
15
tests/net/integration/res/values/config.xml
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<!--
|
||||
Override configuration for testing. The below settings use the config_ variants, which are
|
||||
normally used by RROs to override the setting with highest priority. -->
|
||||
<integer name="config_captive_portal_dns_probe_timeout">12500</integer>
|
||||
<string name="config_captive_portal_http_url" translatable="false">http://test.android.com</string>
|
||||
<string name="config_captive_portal_https_url" translatable="false">https://secure.test.android.com</string>
|
||||
<string-array name="config_captive_portal_fallback_urls" translatable="false">
|
||||
<item>http://fallback1.android.com</item>
|
||||
<item>http://fallback2.android.com</item>
|
||||
</string-array>
|
||||
<string-array name="config_captive_portal_fallback_probe_specs" translatable="false">
|
||||
</string-array>
|
||||
</resources>
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.net
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import com.android.server.net.integrationtests.TestNetworkStackService
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.Mockito.timeout
|
||||
import org.mockito.Mockito.verify
|
||||
import kotlin.test.fail
|
||||
|
||||
const val TEST_ACTION_SUFFIX = ".Test"
|
||||
|
||||
class TestNetworkStackClient(context: Context) : NetworkStackClient(TestDependencies(context)) {
|
||||
// TODO: consider switching to TrackRecord for more expressive checks
|
||||
private val lastCallbacks = HashMap<Network, INetworkMonitorCallbacks>()
|
||||
|
||||
private class TestDependencies(private val context: Context) : Dependencies {
|
||||
override fun addToServiceManager(service: IBinder) = Unit
|
||||
override fun checkCallerUid() = Unit
|
||||
|
||||
override fun getConnectivityModuleConnector(): ConnectivityModuleConnector {
|
||||
return ConnectivityModuleConnector { _, _, _, inSystemProcess ->
|
||||
getNetworkStackIntent(inSystemProcess)
|
||||
}.also { it.init(context) }
|
||||
}
|
||||
|
||||
private fun getNetworkStackIntent(inSystemProcess: Boolean): Intent? {
|
||||
// Simulate out-of-system-process config: in-process service not found (null intent)
|
||||
if (inSystemProcess) return null
|
||||
val intent = Intent(INetworkStackConnector::class.qualifiedName + TEST_ACTION_SUFFIX)
|
||||
val serviceName = TestNetworkStackService::class.qualifiedName
|
||||
?: fail("TestNetworkStackService name not found")
|
||||
intent.component = ComponentName(context.packageName, serviceName)
|
||||
return intent
|
||||
}
|
||||
}
|
||||
|
||||
// base may be an instance of an inaccessible subclass, so non-spyable.
|
||||
// Use a known open class that delegates to the original instance for all methods except
|
||||
// asBinder. asBinder needs to use its own non-delegated implementation as otherwise it would
|
||||
// return a binder token to a class that is not spied on.
|
||||
open class NetworkMonitorCallbacksWrapper(private val base: INetworkMonitorCallbacks) :
|
||||
INetworkMonitorCallbacks.Stub(), INetworkMonitorCallbacks by base {
|
||||
// asBinder is implemented by both base class and delegate: specify explicitly
|
||||
override fun asBinder(): IBinder {
|
||||
return super.asBinder()
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeNetworkMonitor(network: Network, name: String?, cb: INetworkMonitorCallbacks) {
|
||||
val cbSpy = spy(NetworkMonitorCallbacksWrapper(cb))
|
||||
lastCallbacks[network] = cbSpy
|
||||
super.makeNetworkMonitor(network, name, cbSpy)
|
||||
}
|
||||
|
||||
fun verifyNetworkMonitorCreated(network: Network, timeoutMs: Long) {
|
||||
val cb = lastCallbacks[network]
|
||||
?: fail("NetworkMonitor for network $network not requested")
|
||||
verify(cb, timeout(timeoutMs)).onNetworkMonitorCreated(any())
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.net.integrationtests
|
||||
|
||||
import android.content.ComponentName
|
||||
import android.content.Context
|
||||
import android.content.Context.BIND_AUTO_CREATE
|
||||
import android.content.Context.BIND_IMPORTANT
|
||||
import android.content.Intent
|
||||
import android.content.ServiceConnection
|
||||
import android.net.ConnectivityManager
|
||||
import android.net.IDnsResolver
|
||||
import android.net.INetd
|
||||
import android.net.INetworkPolicyManager
|
||||
import android.net.INetworkStatsService
|
||||
import android.net.LinkProperties
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET
|
||||
import android.net.NetworkCapabilities.TRANSPORT_CELLULAR
|
||||
import android.net.NetworkRequest
|
||||
import android.net.TestNetworkStackClient
|
||||
import android.net.metrics.IpConnectivityLog
|
||||
import android.os.ConditionVariable
|
||||
import android.os.IBinder
|
||||
import android.os.INetworkManagementService
|
||||
import android.testing.TestableContext
|
||||
import android.util.Log
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||
import androidx.test.platform.app.InstrumentationRegistry
|
||||
import com.android.server.ConnectivityService
|
||||
import com.android.server.LocalServices
|
||||
import com.android.server.NetworkAgentWrapper
|
||||
import com.android.server.TestNetIdManager
|
||||
import com.android.server.connectivity.DefaultNetworkMetrics
|
||||
import com.android.server.connectivity.IpConnectivityMetrics
|
||||
import com.android.server.connectivity.MockableSystemProperties
|
||||
import com.android.server.connectivity.ProxyTracker
|
||||
import com.android.server.connectivity.Tethering
|
||||
import com.android.server.net.NetworkPolicyManagerInternal
|
||||
import com.android.testutils.TestableNetworkCallback
|
||||
import org.junit.After
|
||||
import org.junit.Before
|
||||
import org.junit.BeforeClass
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.mockito.Mock
|
||||
import org.mockito.Mockito.any
|
||||
import org.mockito.Mockito.doNothing
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.spy
|
||||
import org.mockito.MockitoAnnotations
|
||||
import org.mockito.Spy
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
const val SERVICE_BIND_TIMEOUT_MS = 5_000L
|
||||
const val TEST_TIMEOUT_MS = 1_000L
|
||||
|
||||
/**
|
||||
* Test that exercises an instrumented version of ConnectivityService against an instrumented
|
||||
* NetworkStack in a different test process.
|
||||
*/
|
||||
@RunWith(AndroidJUnit4::class)
|
||||
class ConnectivityServiceIntegrationTest {
|
||||
// lateinit used here for mocks as they need to be reinitialized between each test and the test
|
||||
// should crash if they are used before being initialized.
|
||||
@Mock
|
||||
private lateinit var netManager: INetworkManagementService
|
||||
@Mock
|
||||
private lateinit var statsService: INetworkStatsService
|
||||
@Mock
|
||||
private lateinit var policyManager: INetworkPolicyManager
|
||||
@Mock
|
||||
private lateinit var log: IpConnectivityLog
|
||||
@Mock
|
||||
private lateinit var netd: INetd
|
||||
@Mock
|
||||
private lateinit var dnsResolver: IDnsResolver
|
||||
@Mock
|
||||
private lateinit var metricsLogger: IpConnectivityMetrics.Logger
|
||||
@Mock
|
||||
private lateinit var defaultMetrics: DefaultNetworkMetrics
|
||||
@Spy
|
||||
private var context = TestableContext(realContext)
|
||||
|
||||
// lateinit for these three classes under test, as they should be reset to a different instance
|
||||
// for every test but should always be initialized before use (or the test should crash).
|
||||
private lateinit var networkStackClient: TestNetworkStackClient
|
||||
private lateinit var service: ConnectivityService
|
||||
private lateinit var cm: ConnectivityManager
|
||||
|
||||
companion object {
|
||||
// lateinit for this binder token, as it must be initialized before any test code is run
|
||||
// and use of it before init should crash the test.
|
||||
private lateinit var nsInstrumentation: INetworkStackInstrumentation
|
||||
private val bindingCondition = ConditionVariable(false)
|
||||
|
||||
private val realContext get() = InstrumentationRegistry.getInstrumentation().context
|
||||
|
||||
private class InstrumentationServiceConnection : ServiceConnection {
|
||||
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
|
||||
Log.i("TestNetworkStack", "Service connected")
|
||||
try {
|
||||
if (service == null) fail("Error binding to NetworkStack instrumentation")
|
||||
if (::nsInstrumentation.isInitialized) fail("Service already connected")
|
||||
nsInstrumentation = INetworkStackInstrumentation.Stub.asInterface(service)
|
||||
} finally {
|
||||
bindingCondition.open()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onServiceDisconnected(name: ComponentName?) = Unit
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
@JvmStatic
|
||||
fun setUpClass() {
|
||||
val intent = Intent(realContext, NetworkStackInstrumentationService::class.java)
|
||||
intent.action = INetworkStackInstrumentation::class.qualifiedName
|
||||
assertTrue(realContext.bindService(intent, InstrumentationServiceConnection(),
|
||||
BIND_AUTO_CREATE or BIND_IMPORTANT),
|
||||
"Error binding to instrumentation service")
|
||||
assertTrue(bindingCondition.block(SERVICE_BIND_TIMEOUT_MS),
|
||||
"Timed out binding to instrumentation service " +
|
||||
"after $SERVICE_BIND_TIMEOUT_MS ms")
|
||||
}
|
||||
}
|
||||
|
||||
@Before
|
||||
fun setUp() {
|
||||
MockitoAnnotations.initMocks(this)
|
||||
doReturn(defaultMetrics).`when`(metricsLogger).defaultNetworkMetrics()
|
||||
doNothing().`when`(context).sendStickyBroadcastAsUser(any(), any(), any())
|
||||
|
||||
networkStackClient = TestNetworkStackClient(realContext)
|
||||
networkStackClient.init()
|
||||
networkStackClient.start()
|
||||
|
||||
LocalServices.removeServiceForTest(NetworkPolicyManagerInternal::class.java)
|
||||
LocalServices.addService(NetworkPolicyManagerInternal::class.java,
|
||||
mock(NetworkPolicyManagerInternal::class.java))
|
||||
|
||||
service = TestConnectivityService(makeDependencies())
|
||||
cm = ConnectivityManager(context, service)
|
||||
context.addMockSystemService(Context.CONNECTIVITY_SERVICE, cm)
|
||||
|
||||
service.systemReady()
|
||||
}
|
||||
|
||||
private inner class TestConnectivityService(deps: Dependencies) : ConnectivityService(
|
||||
context, netManager, statsService, policyManager, dnsResolver, log, netd, deps)
|
||||
|
||||
private fun makeDependencies(): ConnectivityService.Dependencies {
|
||||
val deps = spy(ConnectivityService.Dependencies())
|
||||
doReturn(networkStackClient).`when`(deps).networkStack
|
||||
doReturn(metricsLogger).`when`(deps).metricsLogger
|
||||
doReturn(mock(Tethering::class.java)).`when`(deps).makeTethering(
|
||||
any(), any(), any(), any(), any())
|
||||
doReturn(mock(ProxyTracker::class.java)).`when`(deps).makeProxyTracker(any(), any())
|
||||
doReturn(mock(MockableSystemProperties::class.java)).`when`(deps).systemProperties
|
||||
doReturn(TestNetIdManager()).`when`(deps).makeNetIdManager()
|
||||
return deps
|
||||
}
|
||||
|
||||
@After
|
||||
fun tearDown() {
|
||||
nsInstrumentation.clearAllState()
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testValidation() {
|
||||
val request = NetworkRequest.Builder()
|
||||
.clearCapabilities()
|
||||
.addCapability(NET_CAPABILITY_INTERNET)
|
||||
.build()
|
||||
val testCallback = TestableNetworkCallback()
|
||||
|
||||
cm.registerNetworkCallback(request, testCallback)
|
||||
nsInstrumentation.addHttpResponse(HttpResponse(
|
||||
"http://test.android.com",
|
||||
responseCode = 204, contentLength = 42, redirectUrl = null))
|
||||
nsInstrumentation.addHttpResponse(HttpResponse(
|
||||
"https://secure.test.android.com",
|
||||
responseCode = 204, contentLength = 42, redirectUrl = null))
|
||||
|
||||
val na = NetworkAgentWrapper(TRANSPORT_CELLULAR, LinkProperties(), context)
|
||||
networkStackClient.verifyNetworkMonitorCreated(na.network, TEST_TIMEOUT_MS)
|
||||
|
||||
na.addCapability(NET_CAPABILITY_INTERNET)
|
||||
na.connect()
|
||||
|
||||
testCallback.expectAvailableThenValidatedCallbacks(na.network, TEST_TIMEOUT_MS)
|
||||
assertEquals(2, nsInstrumentation.getRequestUrls().size)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.net.integrationtests
|
||||
|
||||
import android.os.Parcel
|
||||
import android.os.Parcelable
|
||||
|
||||
data class HttpResponse(
|
||||
val requestUrl: String,
|
||||
val responseCode: Int,
|
||||
val contentLength: Long,
|
||||
val redirectUrl: String?
|
||||
) : Parcelable {
|
||||
constructor(p: Parcel): this(p.readString(), p.readInt(), p.readLong(), p.readString())
|
||||
|
||||
override fun writeToParcel(dest: Parcel, flags: Int) {
|
||||
with(dest) {
|
||||
writeString(requestUrl)
|
||||
writeInt(responseCode)
|
||||
writeLong(contentLength)
|
||||
writeString(redirectUrl)
|
||||
}
|
||||
}
|
||||
|
||||
override fun describeContents() = 0
|
||||
companion object CREATOR : Parcelable.Creator<HttpResponse> {
|
||||
override fun createFromParcel(source: Parcel) = HttpResponse(source)
|
||||
override fun newArray(size: Int) = arrayOfNulls<HttpResponse?>(size)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.net.integrationtests
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Intent
|
||||
import java.net.URL
|
||||
import java.util.Collections
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.test.fail
|
||||
|
||||
/**
|
||||
* An instrumentation interface for the NetworkStack that allows controlling behavior to
|
||||
* facilitate integration tests.
|
||||
*/
|
||||
class NetworkStackInstrumentationService : Service() {
|
||||
override fun onBind(intent: Intent) = InstrumentationConnector.asBinder()
|
||||
|
||||
object InstrumentationConnector : INetworkStackInstrumentation.Stub() {
|
||||
private val httpResponses = ConcurrentHashMap<String, ConcurrentLinkedQueue<HttpResponse>>()
|
||||
.run {
|
||||
withDefault { key -> getOrPut(key) { ConcurrentLinkedQueue() } }
|
||||
}
|
||||
private val httpRequestUrls = Collections.synchronizedList(ArrayList<String>())
|
||||
|
||||
/**
|
||||
* Called when an HTTP request is being processed by NetworkMonitor. Returns the response
|
||||
* that should be simulated.
|
||||
*/
|
||||
fun processRequest(url: URL): HttpResponse {
|
||||
val strUrl = url.toString()
|
||||
httpRequestUrls.add(strUrl)
|
||||
return httpResponses[strUrl]?.poll()
|
||||
?: fail("No mocked response for request: $strUrl. " +
|
||||
"Mocked URL keys are: ${httpResponses.keys}")
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all state of this connector. This is intended for use between two tests, so all
|
||||
* state should be reset as if the connector was just created.
|
||||
*/
|
||||
override fun clearAllState() {
|
||||
httpResponses.clear()
|
||||
httpRequestUrls.clear()
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a response to a future HTTP request.
|
||||
*
|
||||
* <p>For any subsequent HTTP/HTTPS query, the first response with a matching URL will be
|
||||
* used to mock the query response.
|
||||
*/
|
||||
override fun addHttpResponse(response: HttpResponse) {
|
||||
httpResponses.getValue(response.requestUrl).add(response)
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ordered list of request URLs that have been sent by NetworkMonitor, and were
|
||||
* answered based on mock responses.
|
||||
*/
|
||||
override fun getRequestUrls(): List<String> {
|
||||
return ArrayList(httpRequestUrls)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.net.integrationtests
|
||||
|
||||
import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.INetworkMonitorCallbacks
|
||||
import android.net.Network
|
||||
import android.net.metrics.IpConnectivityLog
|
||||
import android.net.util.SharedLog
|
||||
import android.os.IBinder
|
||||
import com.android.networkstack.metrics.DataStallStatsUtils
|
||||
import com.android.server.NetworkStackService.NetworkMonitorConnector
|
||||
import com.android.server.NetworkStackService.NetworkStackConnector
|
||||
import com.android.server.connectivity.NetworkMonitor
|
||||
import com.android.server.net.integrationtests.NetworkStackInstrumentationService.InstrumentationConnector
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.mock
|
||||
import org.mockito.Mockito.spy
|
||||
import java.net.HttpURLConnection
|
||||
import java.net.URL
|
||||
import java.net.URLConnection
|
||||
|
||||
private const val TEST_NETID = 42
|
||||
|
||||
/**
|
||||
* Android service that can return an [android.net.INetworkStackConnector] which can be instrumented
|
||||
* through [NetworkStackInstrumentationService].
|
||||
* Useful in tests to create test instrumented NetworkStack components that can receive
|
||||
* instrumentation commands through [NetworkStackInstrumentationService].
|
||||
*/
|
||||
class TestNetworkStackService : Service() {
|
||||
override fun onBind(intent: Intent): IBinder = TestNetworkStackConnector(makeTestContext())
|
||||
|
||||
private fun makeTestContext() = spy(applicationContext).also {
|
||||
doReturn(mock(IBinder::class.java)).`when`(it).getSystemService(Context.NETD_SERVICE)
|
||||
}
|
||||
|
||||
private class TestPermissionChecker : NetworkStackConnector.PermissionChecker() {
|
||||
override fun enforceNetworkStackCallingPermission() = Unit
|
||||
}
|
||||
|
||||
private class NetworkMonitorDeps(private val privateDnsBypassNetwork: Network) :
|
||||
NetworkMonitor.Dependencies() {
|
||||
override fun getPrivateDnsBypassNetwork(network: Network?) = privateDnsBypassNetwork
|
||||
override fun sendNetworkConditionsBroadcast(context: Context, broadcast: Intent) = Unit
|
||||
}
|
||||
|
||||
private inner class TestNetworkStackConnector(context: Context) :
|
||||
NetworkStackConnector(context, TestPermissionChecker()) {
|
||||
|
||||
private val network = Network(TEST_NETID)
|
||||
private val privateDnsBypassNetwork = TestNetwork(TEST_NETID)
|
||||
|
||||
private inner class TestNetwork(netId: Int) : Network(netId) {
|
||||
override fun openConnection(url: URL): URLConnection {
|
||||
val response = InstrumentationConnector.processRequest(url)
|
||||
|
||||
val connection = mock(HttpURLConnection::class.java)
|
||||
doReturn(response.responseCode).`when`(connection).responseCode
|
||||
doReturn(response.contentLength).`when`(connection).contentLengthLong
|
||||
doReturn(response.redirectUrl).`when`(connection).getHeaderField("location")
|
||||
return connection
|
||||
}
|
||||
}
|
||||
|
||||
override fun makeNetworkMonitor(
|
||||
network: Network,
|
||||
name: String?,
|
||||
cb: INetworkMonitorCallbacks
|
||||
) {
|
||||
val nm = NetworkMonitor(this@TestNetworkStackService, cb,
|
||||
this.network,
|
||||
mock(IpConnectivityLog::class.java), mock(SharedLog::class.java),
|
||||
NetworkMonitorDeps(privateDnsBypassNetwork),
|
||||
mock(DataStallStatsUtils::class.java))
|
||||
cb.onNetworkMonitorCreated(NetworkMonitorConnector(nm, TestPermissionChecker()))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user