Merge "Create new CTS test for tethering" am: b376f283cb am: 235a625d30 am: 84b44168a3

Change-Id: I35cc9b37af6b18df39ba8b4941be59830d71b3f9
This commit is contained in:
Automerger Merge Worker
2019-12-17 15:35:26 +00:00
4 changed files with 327 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
// 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.
android_test {
name: "CtsTetheringTest",
defaults: ["cts_defaults"],
libs: [
"android.test.base.stubs",
],
srcs: [
"src/**/*.java",
],
static_libs: [
"compatibility-device-util-axt",
"ctstestrunner-axt",
"junit",
"junit-params",
],
// Change to system current when TetheringManager move to bootclass path.
platform_apis: true,
// Tag this module as a cts test artifact
test_suites: [
"cts",
"general-tests",
],
}

View File

@@ -0,0 +1,33 @@
<?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"
package="android.tethering.cts">
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
</application>
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
android:targetPackage="android.tethering.cts"
android:label="CTS tests of android.tethering">
<meta-data android:name="listener"
android:value="com.android.cts.runner.CtsTestRunListener" />
</instrumentation>
</manifest>

View File

@@ -0,0 +1,29 @@
<?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.
-->
<configuration description="Config for CTS Tethering test cases">
<option name="test-suite-tag" value="cts" />
<option name="config-descriptor:metadata" key="component" value="networking" />
<option name="config-descriptor:metadata" key="parameter" value="not_instant_app" />
<option name="config-descriptor:metadata" key="parameter" value="not_multi_abi" />
<option name="not-shardable" value="true" />
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
<option name="cleanup-apks" value="true" />
<option name="test-file-name" value="CtsTetheringTest.apk" />
</target_preparer>
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
<option name="package" value="android.tethering.cts" />
</test>
</configuration>

View File

@@ -0,0 +1,222 @@
/*
* 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.tethering.test;
import static org.junit.Assert.fail;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.os.ConditionVariable;
import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class TetheringManagerTest {
private Context mContext;
private ConnectivityManager mCM;
private TetherChangeReceiver mTetherChangeReceiver;
private String[] mTetheredList;
private static final int DEFAULT_TIMEOUT_MS = 60_000;
@Before
public void setUp() throws Exception {
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.adoptShellPermissionIdentity();
mContext = InstrumentationRegistry.getContext();
mCM = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
mTetherChangeReceiver = new TetherChangeReceiver();
final IntentFilter filter = new IntentFilter(
ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
final Intent intent = mContext.registerReceiver(mTetherChangeReceiver, filter);
if (intent != null) mTetherChangeReceiver.onReceive(null, intent);
}
@After
public void tearDown() throws Exception {
mContext.unregisterReceiver(mTetherChangeReceiver);
InstrumentationRegistry.getInstrumentation()
.getUiAutomation()
.dropShellPermissionIdentity();
}
private class TetherChangeReceiver extends BroadcastReceiver {
private class TetherState {
final ArrayList<String> mAvailable;
final ArrayList<String> mActive;
final ArrayList<String> mErrored;
TetherState(Intent intent) {
mAvailable = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_AVAILABLE_TETHER);
mActive = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ACTIVE_TETHER);
mErrored = intent.getStringArrayListExtra(
ConnectivityManager.EXTRA_ERRORED_TETHER);
}
}
@Override
public void onReceive(Context content, Intent intent) {
String action = intent.getAction();
if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
mResult.add(new TetherState(intent));
}
}
public final LinkedBlockingQueue<TetherState> mResult = new LinkedBlockingQueue<>();
// This method expects either an event where one of the interfaces is active, or an event
// where one of the interface is available followed by one where one of the interfaces is
// active.
public void expectActiveTethering(String[] ifaceRegexs) {
TetherState state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS);
if (state == null) fail("Do not receive tethering state change broadcast");
if (isIfaceActive(ifaceRegexs, state)) return;
if (isIfaceAvailable(ifaceRegexs, state)) {
state = pollAndAssertNoError(DEFAULT_TIMEOUT_MS);
if (isIfaceActive(ifaceRegexs, state)) return;
}
fail("Tethering is not actived, available ifaces: " + state.mAvailable.toString()
+ ", active ifaces: " + state.mActive.toString());
}
private TetherState pollAndAssertNoError(final int timeout) {
final TetherState state = pollTetherState(timeout);
assertNoErroredIfaces(state);
return state;
}
private TetherState pollTetherState(final int timeout) {
try {
return mResult.poll(timeout, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
fail("No result after " + timeout + " ms");
return null;
}
}
private boolean isIfaceActive(final String[] ifaceRegexs, final TetherState state) {
return isIfaceMatch(ifaceRegexs, state.mActive);
}
private boolean isIfaceAvailable(final String[] ifaceRegexs, final TetherState state) {
return isIfaceMatch(ifaceRegexs, state.mAvailable);
}
// This method requires a broadcast to have been recorded iff the timeout is non-zero.
public void expectNoActiveTethering(final int timeout) {
final TetherState state = pollAndAssertNoError(timeout);
if (state == null) {
if (timeout != 0) {
fail("Do not receive tethering state change broadcast");
}
return;
}
assertNoActiveIfaces(state);
for (final TetherState ts : mResult) {
assertNoErroredIfaces(ts);
assertNoActiveIfaces(ts);
}
}
private void assertNoErroredIfaces(final TetherState state) {
if (state == null || state.mErrored == null) return;
if (state.mErrored.size() > 0) {
fail("Found failed tethering interfaces: " + state.mErrored.toArray());
}
}
private void assertNoActiveIfaces(final TetherState state) {
if (state.mActive != null && state.mActive.size() > 0) {
fail("Found active tethering interface: " + state.mActive.toArray());
}
}
}
private class OnStartTetheringCallback extends
ConnectivityManager.OnStartTetheringCallback {
@Override
public void onTetheringStarted() {
// Do nothing, TetherChangeReceiver will wait until it receives the broadcast.
}
@Override
public void onTetheringFailed() {
fail("startTethering fail");
}
}
private static boolean isIfaceMatch(final String[] ifaceRegexs,
final ArrayList<String> ifaces) {
if (ifaceRegexs == null) fail("ifaceRegexs should not be null");
if (ifaces == null) return false;
for (String s : ifaces) {
for (String regex : ifaceRegexs) {
if (s.matches(regex)) {
return true;
}
}
}
return false;
}
@Test
public void testStartTetheringWithStateChangeBroadcast() throws Exception {
if (!mCM.isTetheringSupported()) return;
final String[] wifiRegexs = mCM.getTetherableWifiRegexs();
if (wifiRegexs.length == 0) return;
mTetherChangeReceiver.expectNoActiveTethering(0 /** timeout */);
final OnStartTetheringCallback startTetheringCallback = new OnStartTetheringCallback();
mCM.startTethering(ConnectivityManager.TETHERING_WIFI, true, startTetheringCallback);
mTetherChangeReceiver.expectActiveTethering(wifiRegexs);
mCM.stopTethering(ConnectivityManager.TETHERING_WIFI);
mTetherChangeReceiver.expectNoActiveTethering(DEFAULT_TIMEOUT_MS);
}
}