1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.csuite.tests; 18 19 import com.android.csuite.core.ApkInstaller; 20 import com.android.csuite.core.ApkInstaller.ApkInstallerException; 21 import com.android.csuite.core.DeviceUtils; 22 import com.android.csuite.core.DeviceUtils.DeviceTimestamp; 23 import com.android.csuite.core.DeviceUtils.DeviceUtilsException; 24 import com.android.csuite.core.TestUtils; 25 import com.android.tradefed.config.Option; 26 import com.android.tradefed.device.DeviceNotAvailableException; 27 import com.android.tradefed.log.LogUtil.CLog; 28 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner; 29 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData; 30 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test; 31 import com.android.tradefed.util.RunUtil; 32 33 import com.google.common.annotations.VisibleForTesting; 34 35 import org.junit.After; 36 import org.junit.Assert; 37 import org.junit.Before; 38 import org.junit.Rule; 39 import org.junit.Test; 40 import org.junit.runner.RunWith; 41 42 import java.io.File; 43 import java.io.IOException; 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.stream.Collectors; 47 48 /** A test that verifies that a single app can be successfully launched. */ 49 @RunWith(DeviceJUnit4ClassRunner.class) 50 public class AppLaunchTest extends BaseHostJUnit4Test { 51 @VisibleForTesting static final String SCREENSHOT_AFTER_LAUNCH = "screenshot-after-launch"; 52 @VisibleForTesting static final String COLLECT_APP_VERSION = "collect-app-version"; 53 @VisibleForTesting static final String COLLECT_GMS_VERSION = "collect-gms-version"; 54 @VisibleForTesting static final String RECORD_SCREEN = "record-screen"; 55 @Rule public TestLogData mLogData = new TestLogData(); 56 private ApkInstaller mApkInstaller; 57 private boolean mIsLastTestPass; 58 private boolean mIsApkSaved = false; 59 60 @Option(name = RECORD_SCREEN, description = "Whether to record screen during test.") 61 private boolean mRecordScreen; 62 63 @Option( 64 name = SCREENSHOT_AFTER_LAUNCH, 65 description = "Whether to take a screenshost after a package is launched.") 66 private boolean mScreenshotAfterLaunch; 67 68 @Option( 69 name = COLLECT_APP_VERSION, 70 description = 71 "Whether to collect package version information and store the information in" 72 + " test log files.") 73 private boolean mCollectAppVersion; 74 75 @Option( 76 name = COLLECT_GMS_VERSION, 77 description = 78 "Whether to collect GMS core version information and store the information in" 79 + " test log files.") 80 private boolean mCollectGmsVersion; 81 82 @Option( 83 name = "install-apk", 84 description = 85 "The path to an apk file or a directory of apk files of a singe package to be" 86 + " installed on device. Can be repeated.") 87 private final List<File> mApkPaths = new ArrayList<>(); 88 89 @Option( 90 name = "install-arg", 91 description = "Arguments for the 'adb install-multiple' package installation command.") 92 private final List<String> mInstallArgs = new ArrayList<>(); 93 94 @Option( 95 name = "save-apk-when", 96 description = "When to save apk files to the test result artifacts.") 97 private TestUtils.TakeEffectWhen mSaveApkWhen = TestUtils.TakeEffectWhen.NEVER; 98 99 @Option(name = "package-name", description = "Package name of testing app.") 100 private String mPackageName; 101 102 @Option( 103 name = "app-launch-timeout-ms", 104 description = "Time to wait for app to launch in msecs.") 105 private int mAppLaunchTimeoutMs = 15000; 106 107 @Before setUp()108 public void setUp() throws DeviceNotAvailableException, ApkInstallerException, IOException { 109 Assert.assertNotNull("Package name cannot be null", mPackageName); 110 mIsLastTestPass = false; 111 112 DeviceUtils deviceUtils = DeviceUtils.getInstance(getDevice()); 113 TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData); 114 115 mApkInstaller = ApkInstaller.getInstance(getDevice()); 116 mApkInstaller.install( 117 mApkPaths.stream().map(File::toPath).collect(Collectors.toList()), mInstallArgs); 118 119 if (mCollectGmsVersion) { 120 testUtils.collectGmsVersion(mPackageName); 121 } 122 123 if (mCollectAppVersion) { 124 testUtils.collectAppVersion(mPackageName); 125 } 126 127 deviceUtils.freezeRotation(); 128 } 129 130 @Test testAppCrash()131 public void testAppCrash() throws DeviceNotAvailableException { 132 TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData); 133 134 if (mRecordScreen) { 135 testUtils.collectScreenRecord( 136 () -> { 137 launchPackageAndCheckForCrash(); 138 }, 139 mPackageName); 140 } else { 141 launchPackageAndCheckForCrash(); 142 } 143 mIsLastTestPass = true; 144 } 145 146 @After tearDown()147 public void tearDown() throws DeviceNotAvailableException, ApkInstallerException { 148 DeviceUtils deviceUtils = DeviceUtils.getInstance(getDevice()); 149 TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData); 150 151 if (!mIsApkSaved) { 152 mIsApkSaved = 153 testUtils.saveApks(mSaveApkWhen, mIsLastTestPass, mPackageName, mApkPaths); 154 } 155 156 if (mScreenshotAfterLaunch) { 157 testUtils.collectScreenshot(mPackageName); 158 } 159 160 deviceUtils.stopPackage(mPackageName); 161 deviceUtils.unfreezeRotation(); 162 163 mApkInstaller.uninstallAllInstalledPackages(); 164 } 165 launchPackageAndCheckForCrash()166 private void launchPackageAndCheckForCrash() throws DeviceNotAvailableException { 167 CLog.d("Launching package: %s.", mPackageName); 168 169 DeviceUtils deviceUtils = DeviceUtils.getInstance(getDevice()); 170 TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData); 171 172 try { 173 if (!deviceUtils.isPackageInstalled(mPackageName)) { 174 Assert.fail( 175 "Package " 176 + mPackageName 177 + " is not installed on the device. Aborting the test."); 178 } 179 } catch (DeviceUtilsException e) { 180 Assert.fail("Failed to check the installed package list: " + e.getMessage()); 181 } 182 183 DeviceTimestamp startTime = deviceUtils.currentTimeMillis(); 184 try { 185 deviceUtils.launchPackage(mPackageName); 186 } catch (DeviceUtilsException e) { 187 Assert.fail("Failed to launch package " + mPackageName + ": " + e.getMessage()); 188 } 189 190 CLog.d("Waiting %s milliseconds for the app to launch fully.", mAppLaunchTimeoutMs); 191 RunUtil.getDefault().sleep(mAppLaunchTimeoutMs); 192 193 CLog.d("Completed launching package: %s", mPackageName); 194 195 try { 196 String crashLog = testUtils.getDropboxPackageCrashLog(mPackageName, startTime, true); 197 Assert.assertNull(crashLog, crashLog); 198 } catch (IOException e) { 199 Assert.fail("Error while getting dropbox crash log: " + e); 200 } 201 } 202 } 203