• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.AppCrawlTester;
21 import com.android.csuite.core.TestUtils;
22 import com.android.tradefed.config.Option;
23 import com.android.tradefed.device.DeviceNotAvailableException;
24 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner;
25 import com.android.tradefed.testtype.DeviceJUnit4ClassRunner.TestLogData;
26 import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test;
27 
28 import com.google.common.base.Preconditions;
29 
30 import org.junit.After;
31 import org.junit.Before;
32 import org.junit.Rule;
33 import org.junit.Test;
34 import org.junit.runner.RunWith;
35 
36 import java.io.File;
37 import java.io.IOException;
38 import java.nio.file.Path;
39 import java.util.ArrayList;
40 import java.util.Arrays;
41 import java.util.List;
42 import java.util.stream.Collectors;
43 
44 import javax.annotation.Nullable;
45 
46 /** A test that verifies that a single app can be successfully launched. */
47 @RunWith(DeviceJUnit4ClassRunner.class)
48 public class AppCrawlTest extends BaseHostJUnit4Test {
49     private static final String COLLECT_APP_VERSION = "collect-app-version";
50     private static final String COLLECT_GMS_VERSION = "collect-gms-version";
51     private static final String RECORD_SCREEN = "record-screen";
52 
53     @Rule public TestLogData mLogData = new TestLogData();
54     private boolean mIsLastTestPass;
55     private boolean mIsApkSaved = false;
56 
57     private ApkInstaller mApkInstaller;
58     private AppCrawlTester mCrawler;
59 
60     @Option(name = RECORD_SCREEN, description = "Whether to record screen during test.")
61     private boolean mRecordScreen;
62 
63     @Option(
64             name = COLLECT_APP_VERSION,
65             description =
66                     "Whether to collect package version information and store the information in"
67                             + " test log files.")
68     private boolean mCollectAppVersion;
69 
70     @Option(
71             name = COLLECT_GMS_VERSION,
72             description =
73                     "Whether to collect GMS core version information and store the information in"
74                             + " test log files.")
75     private boolean mCollectGmsVersion;
76 
77     @Option(
78             name = "repack-apk",
79             mandatory = false,
80             description =
81                     "Path to an apk file or a directory containing apk files of a single package "
82                             + "to repack and install in Espresso mode")
83     private File mRepackApk;
84 
85     @Option(
86             name = "install-apk",
87             mandatory = false,
88             description =
89                     "The path to an apk file or a directory of apk files to be installed on the"
90                             + " device. In Ui-automator mode, this includes both the target apk to"
91                             + " install and any dependencies. In Espresso mode this can include"
92                             + " additional libraries or dependencies.")
93     private final List<File> mInstallApkPaths = new ArrayList<>();
94 
95     @Option(
96             name = "install-arg",
97             description =
98                     "Arguments for the 'adb install-multiple' package installation command for"
99                             + " UI-automator mode.")
100     private final List<String> mInstallArgs = new ArrayList<>();
101 
102     @Option(name = "package-name", mandatory = true, description = "Package name of testing app.")
103     private String mPackageName;
104 
105     @Option(
106             name = "crawl-controller-endpoint",
107             mandatory = false,
108             description = "The crawl controller endpoint to target.")
109     private String mCrawlControllerEndpoint;
110 
111     @Option(
112             name = "ui-automator-mode",
113             mandatory = false,
114             description =
115                     "Run the crawler with UIAutomator mode. Apk option is not required in this"
116                             + " mode.")
117     private boolean mUiAutomatorMode = false;
118 
119     @Option(
120             name = "timeout-sec",
121             mandatory = false,
122             description = "The timeout for the crawl test.")
123     private int mTimeoutSec = 60;
124 
125     @Option(
126             name = "robo-script-file",
127             description = "A Roboscript file to be executed by the crawler.")
128     private File mRoboscriptFile;
129 
130     // TODO(b/234512223): add support for contextual roboscript files
131 
132     @Option(
133             name = "crawl-guidance-proto-file",
134             description = "A CrawlGuidance file to be executed by the crawler.")
135     private File mCrawlGuidanceProtoFile;
136 
137     @Option(
138             name = "login-config-dir",
139             description =
140                     "A directory containing Roboscript and CrawlGuidance files with login"
141                         + " credentials that are passed to the crawler. There should be one config"
142                         + " file per package name. If both Roboscript and CrawlGuidance files are"
143                         + " present, only the Roboscript file will be used.")
144     private File mLoginConfigDir;
145 
146     @Option(
147             name = "save-apk-when",
148             description = "When to save apk files to the test result artifacts.")
149     private TestUtils.TakeEffectWhen mSaveApkWhen = TestUtils.TakeEffectWhen.NEVER;
150 
151     @Before
setUp()152     public void setUp() throws ApkInstaller.ApkInstallerException, IOException {
153         mIsLastTestPass = false;
154         mCrawler = AppCrawlTester.newInstance(mPackageName, getTestInformation(), mLogData);
155         if (!mUiAutomatorMode) {
156             setApkForEspressoMode();
157         }
158         mCrawler.setCrawlControllerEndpoint(mCrawlControllerEndpoint);
159         mCrawler.setRecordScreen(mRecordScreen);
160         mCrawler.setCollectGmsVersion(mCollectGmsVersion);
161         mCrawler.setCollectAppVersion(mCollectAppVersion);
162         mCrawler.setUiAutomatorMode(mUiAutomatorMode);
163         mCrawler.setRoboscriptFile(toPathOrNull(mRoboscriptFile));
164         mCrawler.setCrawlGuidanceProtoFile(toPathOrNull(mCrawlGuidanceProtoFile));
165         mCrawler.setLoginConfigDir(toPathOrNull(mLoginConfigDir));
166         mCrawler.setTimeoutSec(mTimeoutSec);
167 
168         mApkInstaller = ApkInstaller.getInstance(getDevice());
169         mApkInstaller.install(
170                 mInstallApkPaths.stream().map(File::toPath).collect(Collectors.toList()),
171                 mInstallArgs);
172     }
173 
174     /** Helper method to fetch the path of optional File variables. */
toPathOrNull(@ullable File f)175     private static Path toPathOrNull(@Nullable File f) {
176         return f == null ? null : f.toPath();
177     }
178 
179     /**
180      * For Espresso mode, checks that a path with the location of the apk to repackage was provided
181      */
setApkForEspressoMode()182     private void setApkForEspressoMode() {
183         Preconditions.checkNotNull(
184                 mRepackApk, "Apk file path is required when not running in UIAutomator mode");
185         // set the root path of the target apk for Espresso mode
186         mCrawler.setApkPath(mRepackApk.toPath());
187     }
188 
189     @Test
testAppCrash()190     public void testAppCrash() throws DeviceNotAvailableException {
191         mCrawler.startAndAssertAppNoCrash();
192         mIsLastTestPass = true;
193     }
194 
195     @After
tearDown()196     public void tearDown() throws DeviceNotAvailableException, ApkInstaller.ApkInstallerException {
197         TestUtils testUtils = TestUtils.getInstance(getTestInformation(), mLogData);
198 
199         if (!mIsApkSaved) {
200             mIsApkSaved =
201                     testUtils.saveApks(
202                                     mSaveApkWhen, mIsLastTestPass, mPackageName, mInstallApkPaths)
203                             && testUtils.saveApks(
204                                     mSaveApkWhen,
205                                     mIsLastTestPass,
206                                     mPackageName,
207                                     Arrays.asList(mRepackApk));
208         }
209 
210         mApkInstaller.uninstallAllInstalledPackages();
211         if (!mUiAutomatorMode) {
212             getDevice().uninstallPackage(mPackageName);
213         }
214 
215         mCrawler.cleanUp();
216     }
217 }
218