• 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.core;
18 
19 import com.android.tradefed.config.Option;
20 import com.android.tradefed.invoker.TestInformation;
21 import com.android.tradefed.log.LogUtil.CLog;
22 import com.android.tradefed.targetprep.ITargetPreparer;
23 import com.android.tradefed.targetprep.TargetSetupError;
24 import com.android.tradefed.util.CommandResult;
25 import com.android.tradefed.util.CommandStatus;
26 import com.android.tradefed.util.IRunUtil;
27 import com.android.tradefed.util.RunUtil;
28 
29 import com.google.common.annotations.VisibleForTesting;
30 import com.google.common.io.MoreFiles;
31 
32 import java.io.File;
33 import java.io.IOException;
34 import java.nio.file.Files;
35 import java.nio.file.Path;
36 
37 /** A Tradefed preparer that preparers an app crawler on the host before testing. */
38 public final class AppCrawlTesterHostPreparer implements ITargetPreparer {
39     private static final long COMMAND_TIMEOUT_MILLIS = 4 * 60 * 1000;
40     private static final String SDK_PATH_KEY = "SDK_PATH_KEY";
41     private static final String CRAWLER_BIN_PATH_KEY = "CSUITE_INTERNAL_CRAWLER_BIN_PATH";
42     private static final String CREDENTIAL_PATH_KEY = "CSUITE_INTERNAL_CREDENTIAL_PATH";
43     private static final String IS_READY_KEY = "CSUITE_INTERNAL_IS_READY";
44     @VisibleForTesting static final String SDK_TAR_OPTION = "sdk-tar";
45     @VisibleForTesting static final String CRAWLER_BIN_OPTION = "crawler-bin";
46     @VisibleForTesting static final String CREDENTIAL_JSON_OPTION = "credential-json";
47 
48     @Option(
49             name = SDK_TAR_OPTION,
50             mandatory = true,
51             description = "The path to a tar file that contains the Android SDK.")
52     private File mSdkTar;
53 
54     @Option(
55             name = CRAWLER_BIN_OPTION,
56             mandatory = true,
57             description = "Path to the directory containing the required crawler binary files.")
58     private File mCrawlerBin;
59 
60     @Option(
61             name = CREDENTIAL_JSON_OPTION,
62             mandatory = true,
63             description = "The credential json file to access the crawler server.")
64     private File mCredential;
65 
66     private RunUtilProvider mRunUtilProvider;
67 
AppCrawlTesterHostPreparer()68     public AppCrawlTesterHostPreparer() {
69         this(() -> new RunUtil());
70     }
71 
72     @VisibleForTesting
AppCrawlTesterHostPreparer(RunUtilProvider runUtilProvider)73     AppCrawlTesterHostPreparer(RunUtilProvider runUtilProvider) {
74         mRunUtilProvider = runUtilProvider;
75     }
76 
77     /**
78      * Returns a path that contains Android SDK.
79      *
80      * @param testInfo The test info where the path is stored in.
81      * @return The path to Android SDK; Null if not set.
82      */
getSdkPath(TestInformation testInfo)83     public static Path getSdkPath(TestInformation testInfo) {
84         return getPathFromBuildInfo(testInfo, SDK_PATH_KEY);
85     }
86 
87     /**
88      * Returns a path that contains the crawler binaries.
89      *
90      * @param testInfo The test info where the path is stored in.
91      * @return The path to the crawler binaries folder; Null if not set.
92      */
getCrawlerBinPath(TestInformation testInfo)93     public static Path getCrawlerBinPath(TestInformation testInfo) {
94         return getPathFromBuildInfo(testInfo, CRAWLER_BIN_PATH_KEY);
95     }
96 
97     /**
98      * Returns a path to the credential json file for accessing the Robo crawler server.
99      *
100      * @param testInfo The test info where the path is stored in.
101      * @return The path to the crawler credential json file.
102      */
getCredentialPath(TestInformation testInfo)103     public static Path getCredentialPath(TestInformation testInfo) {
104         return getPathFromBuildInfo(testInfo, CREDENTIAL_PATH_KEY);
105     }
106 
107     /**
108      * Checks whether the preparer has successfully executed.
109      *
110      * @param testInfo The test info .
111      * @return True if the preparer was executed successfully; False otherwise.
112      */
isReady(TestInformation testInfo)113     public static boolean isReady(TestInformation testInfo) {
114         return testInfo.getBuildInfo().getBuildAttributes().get(IS_READY_KEY) != null;
115     }
116 
getPathFromBuildInfo(TestInformation testInfo, String key)117     private static Path getPathFromBuildInfo(TestInformation testInfo, String key) {
118         String path = testInfo.getBuildInfo().getBuildAttributes().get(key);
119         return path == null ? null : Path.of(path);
120     }
121 
122     @VisibleForTesting
setSdkPath(TestInformation testInfo, Path path)123     static void setSdkPath(TestInformation testInfo, Path path) {
124         testInfo.getBuildInfo().addBuildAttribute(SDK_PATH_KEY, path.toString());
125     }
126 
127     @VisibleForTesting
setCrawlerBinPath(TestInformation testInfo, Path path)128     static void setCrawlerBinPath(TestInformation testInfo, Path path) {
129         testInfo.getBuildInfo().addBuildAttribute(CRAWLER_BIN_PATH_KEY, path.toString());
130     }
131 
132     @VisibleForTesting
setCredentialPath(TestInformation testInfo, Path path)133     static void setCredentialPath(TestInformation testInfo, Path path) {
134         testInfo.getBuildInfo().addBuildAttribute(CREDENTIAL_PATH_KEY, path.toString());
135     }
136 
137     @Override
setUp(TestInformation testInfo)138     public void setUp(TestInformation testInfo) throws TargetSetupError {
139         IRunUtil runUtil = mRunUtilProvider.get();
140 
141         Path sdkPath;
142         try {
143             sdkPath = Files.createTempDirectory("android-sdk");
144         } catch (IOException e) {
145             throw new TargetSetupError("Failed to create the output path for android sdk.", e);
146         }
147 
148         String cmd = "tar -xvzf " + mSdkTar.getPath() + " -C " + sdkPath.toString();
149         CLog.i("Decompressing Android SDK to " + sdkPath.toString());
150         CommandResult res = runUtil.runTimedCmd(COMMAND_TIMEOUT_MILLIS, cmd.split(" "));
151         if (!res.getStatus().equals(CommandStatus.SUCCESS)) {
152             throw new TargetSetupError(String.format("Failed to untar android sdk: %s", res));
153         }
154 
155         setSdkPath(testInfo, sdkPath);
156 
157         // Make the crawler binary executable.
158         String chmodCmd =
159                 "chmod 555 " + mCrawlerBin.toPath().resolve("crawl_launcher_deploy.jar").toString();
160         CommandResult chmodRes = runUtil.runTimedCmd(COMMAND_TIMEOUT_MILLIS, chmodCmd.split(" "));
161         if (!chmodRes.getStatus().equals(CommandStatus.SUCCESS)) {
162             throw new TargetSetupError(
163                     String.format("Failed to make crawler binary executable: %s", chmodRes));
164         }
165 
166         setCrawlerBinPath(testInfo, mCrawlerBin.toPath());
167 
168         setCredentialPath(testInfo, mCredential.toPath());
169 
170         testInfo.getBuildInfo().addBuildAttribute(IS_READY_KEY, "true");
171     }
172 
173     @Override
tearDown(TestInformation testInfo, Throwable e)174     public void tearDown(TestInformation testInfo, Throwable e) {
175         try {
176             cleanUp(getSdkPath(testInfo));
177         } catch (IOException ioException) {
178             CLog.e(ioException);
179         }
180     }
181 
cleanUp(Path path)182     private static void cleanUp(Path path) throws IOException {
183         if (path == null || !Files.exists(path)) {
184             return;
185         }
186 
187         MoreFiles.deleteRecursively(path);
188     }
189 
190     @VisibleForTesting
191     interface RunUtilProvider {
get()192         IRunUtil get();
193     }
194 }
195