Initial commit for Settings component test
Test: Tested on local device Bug: 178765084 Change-Id: I3b8f36daa31b0a44e788fe4c84f94d48653ee037
This commit is contained in:
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();
|
||||
}
|
||||
}
|
@@ -1,4 +1,4 @@
|
||||
//############################################################
|
||||
//############################################################
|
||||
// Build SettingsRoboTestStub.apk which includes test-only resources.#
|
||||
//############################################################
|
||||
|
||||
|
Reference in New Issue
Block a user