Merge "Initial commit for Settings component test" into sc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0b1f51445c
23
tests/componenttests/Android.bp
Normal file
23
tests/componenttests/Android.bp
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
//############################################################
|
||||||
|
// Settings Component test target. #
|
||||||
|
//############################################################
|
||||||
|
android_test {
|
||||||
|
name: "SettingsComponentTests",
|
||||||
|
certificate: "platform",
|
||||||
|
privileged: true,
|
||||||
|
srcs: [
|
||||||
|
"src/**/*.java",
|
||||||
|
],
|
||||||
|
|
||||||
|
static_libs: [
|
||||||
|
"truth-prebuilt",
|
||||||
|
"androidx.test.core",
|
||||||
|
"androidx.test.runner",
|
||||||
|
"androidx.test.rules",
|
||||||
|
"androidx.test.ext.junit",
|
||||||
|
],
|
||||||
|
|
||||||
|
test_suites: ["device-tests"],
|
||||||
|
|
||||||
|
instrumentation_for: "Settings",
|
||||||
|
}
|
40
tests/componenttests/AndroidManifest.xml
Normal file
40
tests/componenttests/AndroidManifest.xml
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2016 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:androidprv="http://schemas.android.com/apk/prv/res/android"
|
||||||
|
package="com.android.settings.tests.component">
|
||||||
|
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH" />
|
||||||
|
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
|
||||||
|
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" />
|
||||||
|
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
|
||||||
|
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
|
||||||
|
<uses-permission android:name="android.permission.UPDATE_APP_OPS_STATS" />
|
||||||
|
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||||
|
|
||||||
|
<application/>
|
||||||
|
|
||||||
|
<instrumentation android:name="androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
android:targetPackage="com.android.settings"
|
||||||
|
android:label="Settings Test Cases">
|
||||||
|
</instrumentation>
|
||||||
|
|
||||||
|
</manifest>
|
30
tests/componenttests/AndroidTest.xml
Normal file
30
tests/componenttests/AndroidTest.xml
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Copyright (C) 2017 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="Runs Settings Test Cases.">
|
||||||
|
<option name="test-suite-tag" value="apct" />
|
||||||
|
<option name="test-suite-tag" value="apct-instrumentation" />
|
||||||
|
<target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
|
||||||
|
<option name="cleanup-apks" value="true" />
|
||||||
|
<option name="test-file-name" value="SettingsComponentTests.apk" />
|
||||||
|
</target_preparer>
|
||||||
|
|
||||||
|
<option name="test-tag" value="SettingsComponentTests" />
|
||||||
|
<test class="com.android.tradefed.testtype.AndroidJUnitTest" >
|
||||||
|
<option name="package" value="com.android.settings.tests.component" />
|
||||||
|
<option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
|
||||||
|
<option name="hidden-api-checks" value="false"/>
|
||||||
|
</test>
|
||||||
|
</configuration>
|
3
tests/componenttests/OWNERS
Normal file
3
tests/componenttests/OWNERS
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# People who can approve changes for submission
|
||||||
|
jyhsu@google.com
|
||||||
|
syaoranx@google.com
|
@@ -0,0 +1,143 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.settings.fuelgauge.batterysaver;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static com.google.common.truth.Truth.assert_;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.PowerManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ActivityScenario;
|
||||||
|
import androidx.test.ext.junit.rules.ActivityScenarioRule;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Settings.BatterySaverSettingsActivity;
|
||||||
|
import com.android.settings.testutils.AdbUtils;
|
||||||
|
import com.android.settings.testutils.UiUtils;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class BatterySaverButtonPreferenceControllerComponentTest {
|
||||||
|
private static final String TAG =
|
||||||
|
BatterySaverButtonPreferenceControllerComponentTest.class.getSimpleName();
|
||||||
|
private Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
private PowerManager mManager =
|
||||||
|
(PowerManager) mInstrumentation.getTargetContext().getSystemService(
|
||||||
|
Context.POWER_SERVICE);
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ActivityScenarioRule<BatterySaverSettingsActivity> rule = new ActivityScenarioRule<>(
|
||||||
|
new Intent(
|
||||||
|
Settings.ACTION_BATTERY_SAVER_SETTINGS).setFlags(
|
||||||
|
Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() throws Exception {
|
||||||
|
mInstrumentation.getUiAutomation().executeShellCommand("dumpsys battery unplug");
|
||||||
|
mInstrumentation.getUiAutomation().executeShellCommand("settings get global low_power 0");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_check_battery_saver_button() throws Exception {
|
||||||
|
ActivityScenario scenario = rule.getScenario();
|
||||||
|
scenario.onActivity(activity -> {
|
||||||
|
final Button button = activity.findViewById(R.id.state_on_button);
|
||||||
|
UiUtils.waitUntilCondition(3000, () -> button.isEnabled());
|
||||||
|
button.callOnClick();
|
||||||
|
checkPowerSaverMode(true);
|
||||||
|
|
||||||
|
Button offButton = activity.findViewById(R.id.state_off_button);
|
||||||
|
offButton.callOnClick();
|
||||||
|
checkPowerSaverMode(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
//Ideally, we should be able to also create BatteryTipPreferenceController and verify that
|
||||||
|
//it is showing battery saver on. Unfortunately, that part of code is tightly coupled with
|
||||||
|
//UI, and it's not possible to retrieve that string without reaching very deep into the
|
||||||
|
//codes and become very tightly coupled with any future changes. That is not what component
|
||||||
|
//tests should do, so either we'll need to do this through UI with another ActivityScenario,
|
||||||
|
//or the code needs to be refactored to be less coupled with UI.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_battery_saver_button_changes_when_framework_setting_change() throws Exception {
|
||||||
|
ActivityScenario scenario = rule.getScenario();
|
||||||
|
scenario.onActivity(activity -> {
|
||||||
|
Button buttonOn = activity.findViewById(R.id.state_on_button);
|
||||||
|
Button buttonOff = activity.findViewById(R.id.state_off_button);
|
||||||
|
assertThat(buttonOn.isVisibleToUser()).isEqualTo(true);
|
||||||
|
assertThat(buttonOff.isVisibleToUser()).isEqualTo(false);
|
||||||
|
});
|
||||||
|
|
||||||
|
mManager.setPowerSaveModeEnabled(true);
|
||||||
|
scenario.recreate();
|
||||||
|
scenario.onActivity(activity -> {
|
||||||
|
Button buttonOn = activity.findViewById(R.id.state_on_button);
|
||||||
|
Button buttonOff = activity.findViewById(R.id.state_off_button);
|
||||||
|
assertThat(buttonOn.isVisibleToUser()).isEqualTo(false);
|
||||||
|
assertThat(buttonOff.isVisibleToUser()).isEqualTo(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
mManager.setPowerSaveModeEnabled(false);
|
||||||
|
scenario.recreate();
|
||||||
|
scenario.onActivity(activity -> {
|
||||||
|
Button buttonOn = activity.findViewById(R.id.state_on_button);
|
||||||
|
Button buttonOff = activity.findViewById(R.id.state_off_button);
|
||||||
|
assertThat(buttonOn.isVisibleToUser()).isEqualTo(true);
|
||||||
|
assertThat(buttonOff.isVisibleToUser()).isEqualTo(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
mInstrumentation.getUiAutomation().executeShellCommand("settings get global low_power 0");
|
||||||
|
mInstrumentation.getUiAutomation().executeShellCommand("dumpsys battery reset");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkPowerSaverMode(boolean enabled) {
|
||||||
|
//Check through adb. Note that this needs to be done first, or a wait and poll needs to be
|
||||||
|
//done to the manager.isPowerSaveMode(), because calling isPowerSaveMode immediately after
|
||||||
|
//setting it does not return true. It takes a while for isPowerSaveMode() to return the
|
||||||
|
//up-to-date value.
|
||||||
|
try {
|
||||||
|
assertThat(
|
||||||
|
AdbUtils.checkStringInAdbCommandOutput(TAG, "settings get global low_power",
|
||||||
|
null, enabled ? "1" : "0", 1000)).isTrue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, e.getMessage());
|
||||||
|
assert_().fail();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check through manager
|
||||||
|
assertThat(mManager.isPowerSaveMode() == enabled).isTrue();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.settings.privacy;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
|
||||||
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.SmallTest;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import com.android.settings.testutils.AdbUtils;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@SmallTest
|
||||||
|
public class EnabledContentCapturePreferenceControllerComponentTest {
|
||||||
|
private Instrumentation mInstrumentation;
|
||||||
|
private static final String TAG =
|
||||||
|
EnabledContentCapturePreferenceControllerComponentTest.class.getSimpleName();
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
if (null == mInstrumentation) {
|
||||||
|
mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_uncheck_content_capture() throws Exception {
|
||||||
|
content_capture_checkbox_test_helper(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_check_content_capture() throws Exception {
|
||||||
|
content_capture_checkbox_test_helper(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void content_capture_checkbox_test_helper(boolean check) throws Exception {
|
||||||
|
EnableContentCapturePreferenceController enableContentCapturePreferenceController =
|
||||||
|
new EnableContentCapturePreferenceController(
|
||||||
|
ApplicationProvider.getApplicationContext(),
|
||||||
|
"Test_key");
|
||||||
|
enableContentCapturePreferenceController.setChecked(check);
|
||||||
|
|
||||||
|
//Check through adb command
|
||||||
|
assertThat(AdbUtils.checkStringInAdbCommandOutput(TAG, "dumpsys content_capture",
|
||||||
|
"Users disabled by Settings: ", check ? "{}" : "{0=true}", 1000)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.settings.testutils;
|
||||||
|
|
||||||
|
import android.os.ParcelFileDescriptor;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class AdbUtils {
|
||||||
|
public static boolean checkStringInAdbCommandOutput(String logTag, String command,
|
||||||
|
String prefix, String target, int timeoutInMillis) throws Exception {
|
||||||
|
long start = System.nanoTime();
|
||||||
|
//Sometimes the change do no reflect in adn output immediately, so need a wait and poll here
|
||||||
|
while (System.nanoTime() - start < (timeoutInMillis * 1000000)) {
|
||||||
|
try (ParcelFileDescriptor.AutoCloseInputStream in =
|
||||||
|
new ParcelFileDescriptor.AutoCloseInputStream(
|
||||||
|
InstrumentationRegistry.getInstrumentation()
|
||||||
|
.getUiAutomation()
|
||||||
|
.executeShellCommand(command))) {
|
||||||
|
try (BufferedReader br =
|
||||||
|
new BufferedReader(
|
||||||
|
new InputStreamReader(in, StandardCharsets.UTF_8))) {
|
||||||
|
Optional<String> resultOptional = br.lines().filter(line -> {
|
||||||
|
Log.d(logTag, line);
|
||||||
|
return TextUtils.isEmpty(prefix) || line.contains(prefix);
|
||||||
|
}).findFirst();
|
||||||
|
String result = resultOptional.get();
|
||||||
|
if (result.contains(target)) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.settings.testutils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.graphics.Bitmap;
|
||||||
|
import android.os.Environment;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
|
|
||||||
|
public class CommonUtils {
|
||||||
|
private static final String TAG = CommonUtils.class.getSimpleName();
|
||||||
|
|
||||||
|
public static void takeScreenshot(Activity activity) {
|
||||||
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
|
try {
|
||||||
|
// image naming and path to include sd card appending name you choose for file
|
||||||
|
String mPath =
|
||||||
|
Environment.getExternalStorageDirectory().toString() + "/" + now + ".jpg";
|
||||||
|
Log.d(TAG, "screenshot path is " + mPath);
|
||||||
|
|
||||||
|
// create bitmap screen capture
|
||||||
|
View v1 = activity.getWindow().getDecorView().getRootView();
|
||||||
|
v1.setDrawingCacheEnabled(true);
|
||||||
|
Bitmap bitmap = Bitmap.createBitmap(v1.getDrawingCache());
|
||||||
|
v1.setDrawingCacheEnabled(false);
|
||||||
|
|
||||||
|
File imageFile = new File(mPath);
|
||||||
|
|
||||||
|
FileOutputStream outputStream = new FileOutputStream(imageFile);
|
||||||
|
int quality = 100;
|
||||||
|
bitmap.compress(Bitmap.CompressFormat.JPEG, quality, outputStream);
|
||||||
|
outputStream.flush();
|
||||||
|
outputStream.close();
|
||||||
|
} catch (Throwable e) {
|
||||||
|
// Several error may come out with file handling or DOM
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean connectToURL(URL url) {
|
||||||
|
HttpURLConnection connection = null;
|
||||||
|
try {
|
||||||
|
connection = (HttpsURLConnection) url.openConnection();
|
||||||
|
connection.setRequestMethod("GET");
|
||||||
|
connection.setConnectTimeout(8000);
|
||||||
|
connection.setReadTimeout(8000);
|
||||||
|
connection.connect();
|
||||||
|
if (HttpURLConnection.HTTP_OK == connection.getResponseCode()) {
|
||||||
|
InputStream in = connection.getInputStream();
|
||||||
|
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
|
||||||
|
StringBuilder response = new StringBuilder();
|
||||||
|
String line;
|
||||||
|
while (null != (line = reader.readLine())) {
|
||||||
|
response.append(line);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.d(TAG, e.getMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (null != connection) {
|
||||||
|
connection.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.settings.testutils;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
public static final long ACTIVITY_LAUNCH_WAIT_TIMEOUT = 5000;
|
||||||
|
public static final long VIEW_APPEAR_WAIT_MEDIUM_TIMEOUT = 5000;
|
||||||
|
public static final long WIFI_CONNECT_WAIT_TIMEOUT = 15000;
|
||||||
|
}
|
@@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2020 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.settings.testutils;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
|
||||||
|
import androidx.test.runner.lifecycle.Stage;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public class UiUtils {
|
||||||
|
|
||||||
|
public static void waitUntilCondition(long timeoutInMillis, Supplier<Boolean> condition) {
|
||||||
|
long start = System.nanoTime();
|
||||||
|
while (System.nanoTime() - start < (timeoutInMillis * 1000000)) {
|
||||||
|
try {
|
||||||
|
//Eat NPE from condition because there's a concurrency issue that when calling
|
||||||
|
//findViewById when the view hierarchy is still rendering, it sometimes encounter
|
||||||
|
//null views that may exist few milliseconds before, and causes a NPE.
|
||||||
|
if (condition.get()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean waitForActivitiesInStage(long timeoutInMillis, Stage stage) {
|
||||||
|
final Collection<Activity> activities = new ArrayList<>();
|
||||||
|
waitUntilCondition(Constants.ACTIVITY_LAUNCH_WAIT_TIMEOUT, () -> {
|
||||||
|
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> activities.addAll(
|
||||||
|
ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(
|
||||||
|
Stage.RESUMED)));
|
||||||
|
return activities.size() > 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
return activities.size() > 0;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2021 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.settings.wifi;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import android.app.Instrumentation;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||||
|
import androidx.test.filters.MediumTest;
|
||||||
|
import androidx.test.platform.app.InstrumentationRegistry;
|
||||||
|
import androidx.test.runner.lifecycle.ActivityLifecycleMonitorRegistry;
|
||||||
|
import androidx.test.runner.lifecycle.Stage;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Settings.NetworkProviderSettingsActivity;
|
||||||
|
import com.android.settings.fuelgauge.batterysaver.BatterySaverButtonPreferenceControllerComponentTest;
|
||||||
|
import com.android.settings.network.NetworkProviderSettings;
|
||||||
|
import com.android.settings.testutils.CommonUtils;
|
||||||
|
import com.android.settings.testutils.Constants;
|
||||||
|
import com.android.settings.testutils.UiUtils;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
@MediumTest
|
||||||
|
/*
|
||||||
|
This test is just for demonstration purpose. For component tests, this approach is not recommended.
|
||||||
|
The reason why it is written this way is because the current Settings app wifi codes have tight
|
||||||
|
coupling with UI, so it's not easy to drive from API without binding the test deeply with the code.
|
||||||
|
*/
|
||||||
|
public class WifiSettings2ActivityTest {
|
||||||
|
private static final String TAG =
|
||||||
|
BatterySaverButtonPreferenceControllerComponentTest.class.getSimpleName();
|
||||||
|
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test_connect_to_wifi() throws Exception {
|
||||||
|
//For some reason the ActivityScenario gets null activity here
|
||||||
|
mInstrumentation.getTargetContext().startActivity(
|
||||||
|
new Intent(Settings.ACTION_WIFI_SETTINGS).setFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
|
||||||
|
UiUtils.waitForActivitiesInStage(Constants.ACTIVITY_LAUNCH_WAIT_TIMEOUT, Stage.RESUMED);
|
||||||
|
|
||||||
|
final NetworkProviderSettings[] settings = new NetworkProviderSettings[1];
|
||||||
|
mInstrumentation.runOnMainSync(() -> {
|
||||||
|
NetworkProviderSettingsActivity activity = (NetworkProviderSettingsActivity)
|
||||||
|
ActivityLifecycleMonitorRegistry.getInstance().getActivitiesInStage(
|
||||||
|
Stage.RESUMED).iterator().next();
|
||||||
|
settings[0] =
|
||||||
|
(NetworkProviderSettings) activity.getSupportFragmentManager().getFragments()
|
||||||
|
.get(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
//For some reason this view does not appear immediately after the fragment is resumed.
|
||||||
|
View root = settings[0].getView();
|
||||||
|
UiUtils.waitUntilCondition(Constants.VIEW_APPEAR_WAIT_MEDIUM_TIMEOUT,
|
||||||
|
() -> root.findViewById(R.id.settings_button) != null);
|
||||||
|
View view = root.findViewById(R.id.settings_button);
|
||||||
|
view.callOnClick();
|
||||||
|
|
||||||
|
UiUtils.waitForActivitiesInStage(Constants.ACTIVITY_LAUNCH_WAIT_TIMEOUT, Stage.RESUMED);
|
||||||
|
Button[] button = new Button[1];
|
||||||
|
mInstrumentation.runOnMainSync(() -> {
|
||||||
|
FragmentActivity activity =
|
||||||
|
(FragmentActivity) ActivityLifecycleMonitorRegistry.getInstance()
|
||||||
|
.getActivitiesInStage(Stage.RESUMED).iterator().next();
|
||||||
|
List<Fragment> fragments = activity.getSupportFragmentManager().getFragments();
|
||||||
|
Log.d(TAG, "fragment class is " + fragments.get(0).getClass());
|
||||||
|
button[0] = fragments.get(0).getView().findViewById(R.id.button3);
|
||||||
|
});
|
||||||
|
|
||||||
|
//HttpURLConnection needs to run outside of main thread, so running it in the test thread
|
||||||
|
final URL url = new URL("https://www.google.net/");
|
||||||
|
|
||||||
|
//Make sure the connectivity is available before disconnecting from wifi
|
||||||
|
assertThat(CommonUtils.connectToURL(url)).isTrue();
|
||||||
|
|
||||||
|
//Disconnect from wifi
|
||||||
|
button[0].callOnClick();
|
||||||
|
|
||||||
|
//Make sure the Internet connectivity is gone
|
||||||
|
assertThat(CommonUtils.connectToURL(url)).isFalse();
|
||||||
|
|
||||||
|
//Connect to wifi
|
||||||
|
button[0].callOnClick();
|
||||||
|
ConnectivityManager manager =
|
||||||
|
(ConnectivityManager) mInstrumentation.getTargetContext().getSystemService(
|
||||||
|
Context.CONNECTIVITY_SERVICE);
|
||||||
|
|
||||||
|
//For some reason I can't find a way to tell the time that the internet connectivity is
|
||||||
|
//actually available with the new, non-deprecated ways, so I still need to use this.
|
||||||
|
UiUtils.waitUntilCondition(Constants.WIFI_CONNECT_WAIT_TIMEOUT,
|
||||||
|
() -> manager.getActiveNetworkInfo().isConnected());
|
||||||
|
|
||||||
|
//Make sure the connectivity is back again
|
||||||
|
assertThat(CommonUtils.connectToURL(url)).isTrue();
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user