summaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPaul Trautrim <paultrautrim@google.com>2019-02-21 17:15:42 +0900
committerPaul Trautrim <paultrautrim@google.com>2019-05-20 17:57:29 +0900
commitbdecb22ce2ef2b6a22c433d70d27bafe7f23e683 (patch)
treea9b2135134fb3ae4f6129e24855f7dff78af026c /tests
parent448072c2e355cc39c9186257d4b688cb202e4fb8 (diff)
downloadgsid-bdecb22ce2ef2b6a22c433d70d27bafe7f23e683.tar.gz
Add end-to-end test for Dynamic System Updates
Bug: 116513434 Test: lunch aosp_cf_x86_phone-userdebug, atest -v DSUEndtoEndTest -- --test-arg \ com.android.tradefed.testtype.HostTest:set-option:system_image_path:/full/path/to/system.img Change-Id: Iac5e28d499908830bd8956a5c2ee0bb39539514d
Diffstat (limited to 'tests')
-rw-r--r--tests/Android.bp54
-rw-r--r--tests/AndroidManifest.xml30
-rw-r--r--tests/DSUEndtoEndTest.java168
-rw-r--r--tests/LockScreenAutomation.java151
-rw-r--r--tests/dsu-test.xml21
5 files changed, 424 insertions, 0 deletions
diff --git a/tests/Android.bp b/tests/Android.bp
new file mode 100644
index 0000000..cb4ae49
--- /dev/null
+++ b/tests/Android.bp
@@ -0,0 +1,54 @@
+//
+// 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.
+//
+
+cc_test {
+ name: "gsi_boot_test",
+ shared_libs: [
+ "libbase",
+ "libcutils",
+ "libhardware",
+ "libhidlbase",
+ "libhidltransport",
+ "libhwbinder",
+ "liblog",
+ "libutils",
+ ],
+ static_libs: [
+ "libext4_utils",
+ "libfstab",
+ "android.hardware.weaver@1.0",
+ ],
+ srcs: [
+ "boot_tests.cpp",
+ ],
+}
+
+java_test_host {
+ name: "DSUEndtoEndTest",
+ srcs: ["DSUEndtoEndTest.java"],
+ libs: ["tradefed"],
+ test_config: "dsu-test.xml",
+ test_suites: ["general-tests"],
+}
+
+android_test {
+ name: "LockScreenAutomation",
+ srcs: ["LockScreenAutomation.java"],
+ libs: ["junit", "android.test.base.stubs"],
+ static_libs: ["androidx.test.uiautomator"],
+ certificate: "platform",
+ manifest: "AndroidManifest.xml"
+}
diff --git a/tests/AndroidManifest.xml b/tests/AndroidManifest.xml
new file mode 100644
index 0000000..19d0c53
--- /dev/null
+++ b/tests/AndroidManifest.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 Google Inc.
+
+ 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="com.google.android.lockscreenautomation"
+ android:sharedUserId="android.uid.system"
+ >
+
+ <uses-sdk android:minSdkVersion="22" android:targetSdkVersion="28"/>
+
+ <application debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation android:name="androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner"
+ android:targetPackage="com.google.android.lockscreenautomation"
+ android:label="Lock Screen Automation"/>
+</manifest>
diff --git a/tests/DSUEndtoEndTest.java b/tests/DSUEndtoEndTest.java
new file mode 100644
index 0000000..a0580aa
--- /dev/null
+++ b/tests/DSUEndtoEndTest.java
@@ -0,0 +1,168 @@
+/*
+ * 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.tests.dsu;
+
+import com.android.tradefed.build.BuildRetrievalError;
+import com.android.tradefed.build.IBuildInfo;
+import com.android.tradefed.build.IDeviceBuildInfo;
+import com.android.tradefed.config.Option;
+import com.android.tradefed.config.Option.Importance;
+import com.android.tradefed.device.DeviceNotAvailableException;
+import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
+import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
+import com.android.tradefed.util.CommandResult;
+import com.android.tradefed.util.ZipUtil2;
+
+import org.apache.commons.compress.archivers.zip.ZipFile;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.Process;
+import java.lang.Runtime;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Test Dynamic System Updates by booting in and out of a supplied system image
+ */
+@RunWith(DeviceJUnit4ClassRunner.class)
+public class DSUEndtoEndTest extends BaseHostJUnit4Test {
+ private static final long kDefaultUserdataSize = 4L * 1024 * 1024 * 1024;
+ private static final String APK = "LockScreenAutomation.apk";
+ private static final String PACKAGE = "com.google.android.lockscreenautomation";
+ private static final String UI_AUTOMATOR_INSTRUMENTATION_RUNNER =
+ "androidx.test.uiautomator.UiAutomatorInstrumentationTestRunner";
+ private static final String CLASS = "LockScreenAutomation";
+ private static final String SIMG2IMG_PATH = "bin/simg2img";
+
+ // Example: atest -v DSUEndtoEndTest -- --test-arg \
+ // com.android.tradefed.testtype.HostTest:set-option:system_image_path:/full/path/to/system.img
+ @Option(name="system_image_path",
+ shortName='s',
+ description="full path to the system image to use. If not specified, attempt " +
+ "to download the image from the test infrastructure",
+ importance=Importance.ALWAYS)
+ private String mSystemImagePath;
+
+ private File mUnsparseSystemImage;
+
+ @After
+ public void teardown() throws Exception {
+ uninstallPackage(PACKAGE);
+ if (mUnsparseSystemImage != null) {
+ mUnsparseSystemImage.delete();
+ }
+ }
+
+ @Test
+ public void testDSU() throws Exception {
+ String simg2imgPath = "simg2img";
+ if (mSystemImagePath == null) {
+ IDeviceBuildInfo deviceBuild = (IDeviceBuildInfo) getBuild();
+ File system = deviceBuild.getDeviceImageFile();
+ Assert.assertNotEquals("Failed to fetch system image. See system_image_path parameter", null, system);
+ mSystemImagePath = system.getAbsolutePath();
+ File otaPackage = deviceBuild.getOtaPackageFile();
+ File simg2img = ZipUtil2.extractFileFromZip(new ZipFile(otaPackage), SIMG2IMG_PATH);
+ simg2imgPath = simg2img.getAbsolutePath();
+ }
+ File gsi = new File(mSystemImagePath);
+ Assert.assertTrue("not a valid file", gsi.isFile());
+ String[] cmd = {simg2imgPath, mSystemImagePath, mSystemImagePath + ".raw"};
+ Process p = Runtime.getRuntime().exec(cmd);
+ p.waitFor();
+ if (p.exitValue() == 0) {
+ mUnsparseSystemImage = new File(mSystemImagePath + ".raw");
+ gsi = mUnsparseSystemImage;
+ }
+
+ boolean wasRoot = getDevice().isAdbRoot();
+ if (!wasRoot)
+ Assert.assertTrue("Test requires root", getDevice().enableAdbRoot());
+
+ expectGsiStatus("normal");
+
+ installPackage(APK);
+ String method = "setPin";
+ String testClass = PACKAGE + "." + CLASS;
+ String testMethod = testClass + "." + method;
+ Assert.assertTrue(testMethod + " failed.",
+ runDeviceTests(UI_AUTOMATOR_INSTRUMENTATION_RUNNER, PACKAGE, testClass, method));
+
+ // Sleep after installing to allow time for gsi_tool to reboot. This prevents a race between
+ // the device rebooting and waitForDeviceAvailable() returning.
+ getDevice().executeShellV2Command("gsi_tool install --userdata-size " + kDefaultUserdataSize +
+ " --gsi-size " + gsi.length() + " && sleep 10000000", gsi, null, 10, TimeUnit.MINUTES, 1);
+ getDevice().waitForDeviceAvailable();
+ getDevice().enableAdbRoot();
+
+ expectGsiStatus("running");
+
+ rebootAndUnlock();
+
+ expectGsiStatus("installed");
+
+ CommandResult result = getDevice().executeShellV2Command("gsi_tool enable");
+ Assert.assertEquals("gsi_tool enable failed", 0, result.getExitCode().longValue());
+
+ getDevice().reboot();
+
+ expectGsiStatus("running");
+
+ getDevice().reboot();
+
+ expectGsiStatus("running");
+
+ getDevice().executeShellV2Command("gsi_tool wipe");
+
+ rebootAndUnlock();
+
+ expectGsiStatus("normal");
+
+ method = "removePin";
+ testClass = PACKAGE + "." + CLASS;
+ testMethod = testClass + "." + method;
+ Assert.assertTrue(testMethod + " failed.",
+ runDeviceTests(UI_AUTOMATOR_INSTRUMENTATION_RUNNER, PACKAGE, testClass, method));
+
+ if (wasRoot) {
+ getDevice().enableAdbRoot();
+ }
+ }
+
+ private void expectGsiStatus(String expected) throws Exception {
+ CommandResult result = getDevice().executeShellV2Command("gsi_tool status");
+ String status = result.getStdout().split("\n", 2)[0].trim();
+ Assert.assertEquals("Device not in expected DSU state", expected, status);
+ }
+
+ private void rebootAndUnlock() throws Exception {
+ getDevice().rebootUntilOnline();
+ getDevice().executeShellV2Command("input keyevent 224"); // KeyEvent.KEYCODE_WAKEUP
+ getDevice().executeShellV2Command("wm dismiss-keyguard");
+ getDevice().executeShellV2Command("input keyevent 7"); // KeyEvent.KEYCODE_0
+ getDevice().executeShellV2Command("input keyevent 7");
+ getDevice().executeShellV2Command("input keyevent 7");
+ getDevice().executeShellV2Command("input keyevent 7");
+ getDevice().executeShellV2Command("input keyevent 66"); // KeyEvent.KEYCODE_ENTER
+ }
+}
+
diff --git a/tests/LockScreenAutomation.java b/tests/LockScreenAutomation.java
new file mode 100644
index 0000000..afefa1c
--- /dev/null
+++ b/tests/LockScreenAutomation.java
@@ -0,0 +1,151 @@
+/*
+ * 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.google.android.lockscreenautomation;
+
+import org.junit.Assert;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.res.Resources;
+import android.provider.Settings;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiAutomatorTestCase;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject2;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiSelector;
+import androidx.test.uiautomator.Until;
+import android.view.KeyEvent;
+
+/**
+ * Methods for configuring lock screen settings
+ */
+public class LockScreenAutomation extends UiAutomatorTestCase {
+
+ private static final String SETTINGS_PACKAGE = "com.android.settings";
+
+ private static final long TIMEOUT = 2000L;
+
+ private Context mContext;
+ private UiDevice mDevice;
+
+ public void setPin() throws Exception {
+ mContext = getInstrumentation().getContext();
+ mDevice = UiDevice.getInstance(getInstrumentation());
+
+ mDevice.wakeUp();
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_MENU);
+ mDevice.waitForIdle(TIMEOUT);
+ launchLockScreenSettings();
+
+ PackageManager pm = mContext.getPackageManager();
+ Resources res = pm.getResourcesForApplication(SETTINGS_PACKAGE);
+
+ int resId = res.getIdentifier("unlock_set_unlock_pin_title", "string", SETTINGS_PACKAGE);
+ findAndClick(By.text(res.getString(resId)));
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressEnter();
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+
+ // Re-enter PIN
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressEnter();
+
+ findAndClick(By.res(SETTINGS_PACKAGE, "redact_sensitive"));
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ findAndClick(By.clazz("android.widget.Button"));
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ }
+
+ public void unlock() throws Exception {
+ mContext = getInstrumentation().getContext();
+ mDevice = UiDevice.getInstance(getInstrumentation());
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_ENTER);
+ }
+
+ public void removePin() throws Exception {
+ mContext = getInstrumentation().getContext();
+ mDevice = UiDevice.getInstance(getInstrumentation());
+
+ mDevice.wakeUp();
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_MENU);
+ mDevice.waitForIdle(TIMEOUT);
+ launchLockScreenSettings();
+
+ PackageManager pm = mContext.getPackageManager();
+ Resources res = pm.getResourcesForApplication(SETTINGS_PACKAGE);
+
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressKeyCode(KeyEvent.KEYCODE_0);
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+ mDevice.pressEnter();
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+
+ int resId = res.getIdentifier("unlock_set_unlock_off_title", "string", SETTINGS_PACKAGE);
+ findAndClick(By.text(res.getString(resId)));
+ mDevice.waitForWindowUpdate(SETTINGS_PACKAGE, 5);
+
+ findAndClick(By.res("android", "button1"));
+ mDevice.waitForIdle(TIMEOUT);
+ }
+
+ private void findAndClick(BySelector selector)
+ {
+ for (int i = 0; i < 3; i++) {
+ mDevice.wait(Until.findObject(selector), TIMEOUT);
+ UiObject2 obj = mDevice.findObject(selector);
+ if (obj != null) {
+ obj.click();
+ return;
+ }
+ }
+ Assert.fail("Could not find and click " + selector);
+ }
+
+ private void launchLockScreenSettings() {
+ final Intent intent = new Intent().setClassName(SETTINGS_PACKAGE, "com.android.settings.password.ChooseLockGeneric");
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
+ mContext.startActivity(intent);
+ mDevice.wait(Until.hasObject(By.pkg(SETTINGS_PACKAGE).depth(0)), TIMEOUT);
+ }
+}
diff --git a/tests/dsu-test.xml b/tests/dsu-test.xml
new file mode 100644
index 0000000..13c5895
--- /dev/null
+++ b/tests/dsu-test.xml
@@ -0,0 +1,21 @@
+<?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 DSU test case">
+ <test class="com.android.tradefed.testtype.HostTest" >
+ <option name="jar" value="DSUEndtoEndTest.jar" />
+ </test>
+</configuration>
+