1 /* 2 * Copyright (C) 2023 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.webview.tests; 18 19 import com.android.tradefed.config.Option; 20 import com.android.tradefed.config.Option.Importance; 21 import com.android.tradefed.invoker.TestInformation; 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.RunUtil; 27 28 import org.junit.Assert; 29 30 import java.io.File; 31 import java.nio.file.Files; 32 import java.nio.file.Paths; 33 import java.util.ArrayList; 34 import java.util.Arrays; 35 import java.util.List; 36 37 import javax.annotation.Nullable; 38 39 public class WebviewInstallerToolPreparer implements ITargetPreparer { 40 private static final long COMMAND_TIMEOUT_MILLIS = 5 * 60 * 1000; 41 private static final String WEBVIEW_INSTALLER_TOOL_PATH = "WEBVIEW_INSTALLER_TOOL_PATH"; 42 private static final String GCLOUD_CLI_PATH = "GCLOUD_CLI_PATH"; 43 44 private File mGcloudCliDir; 45 private RunUtilProvider mRunUtilProvider; 46 47 @Option( 48 name = "gcloud-cli-zip-archive", 49 description = "Path to the google cli zip archive.", 50 importance = Importance.ALWAYS) 51 private File mGcloudCliZipArchive; 52 53 @Option( 54 name = "webview-installer-tool", 55 description = "Path to the webview installer executable.", 56 importance = Importance.ALWAYS) 57 private File mWebviewInstallerTool; 58 WebviewInstallerToolPreparer(RunUtilProvider runUtilProvider)59 public WebviewInstallerToolPreparer(RunUtilProvider runUtilProvider) { 60 mRunUtilProvider = runUtilProvider; 61 } 62 WebviewInstallerToolPreparer()63 public WebviewInstallerToolPreparer() { 64 this(() -> new RunUtil()); 65 } 66 runWebviewInstallerToolCommand( TestInformation testInformation, @Nullable String webviewVersion, @Nullable String releaseChannel, List<String> extraArgs)67 public static CommandResult runWebviewInstallerToolCommand( 68 TestInformation testInformation, 69 @Nullable String webviewVersion, 70 @Nullable String releaseChannel, 71 List<String> extraArgs) { 72 RunUtil runUtil = new RunUtil(); 73 runUtil.setEnvVariable("HOME", getGcloudCliPath(testInformation)); 74 75 List<String> commandLineArgs = 76 new ArrayList<>( 77 Arrays.asList( 78 getWebviewInstallerToolPath(testInformation), 79 "--non-next", 80 "--serial", 81 testInformation.getDevice().getSerialNumber(), 82 "-vvv", 83 "--gsutil", 84 Paths.get( 85 getGcloudCliPath(testInformation), 86 "google-cloud-sdk", 87 "bin", 88 "gsutil") 89 .toFile() 90 .getAbsolutePath())); 91 commandLineArgs.addAll(extraArgs); 92 93 if (webviewVersion != null) { 94 commandLineArgs.addAll(Arrays.asList("--chrome-version", webviewVersion)); 95 } 96 97 if (releaseChannel != null) { 98 commandLineArgs.addAll(Arrays.asList("--channel", releaseChannel)); 99 } 100 101 return runUtil.runTimedCmd( 102 COMMAND_TIMEOUT_MILLIS, 103 System.out, 104 System.out, 105 commandLineArgs.toArray(new String[0])); 106 } 107 setGcloudCliPath(TestInformation testInformation, File gcloudCliDir)108 public static void setGcloudCliPath(TestInformation testInformation, File gcloudCliDir) { 109 testInformation 110 .getBuildInfo() 111 .addBuildAttribute(GCLOUD_CLI_PATH, gcloudCliDir.getAbsolutePath()); 112 } 113 setWebviewInstallerToolPath( TestInformation testInformation, File webviewInstallerTool)114 public static void setWebviewInstallerToolPath( 115 TestInformation testInformation, File webviewInstallerTool) { 116 testInformation 117 .getBuildInfo() 118 .addBuildAttribute( 119 WEBVIEW_INSTALLER_TOOL_PATH, webviewInstallerTool.getAbsolutePath()); 120 } 121 getWebviewInstallerToolPath(TestInformation testInformation)122 public static String getWebviewInstallerToolPath(TestInformation testInformation) { 123 return testInformation.getBuildInfo().getBuildAttributes().get(WEBVIEW_INSTALLER_TOOL_PATH); 124 } 125 getGcloudCliPath(TestInformation testInformation)126 public static String getGcloudCliPath(TestInformation testInformation) { 127 return testInformation.getBuildInfo().getBuildAttributes().get(GCLOUD_CLI_PATH); 128 } 129 130 @Override setUp(TestInformation testInfo)131 public void setUp(TestInformation testInfo) throws TargetSetupError { 132 Assert.assertNotEquals( 133 "Argument --webview-installer-tool must be used.", mWebviewInstallerTool, null); 134 Assert.assertNotEquals( 135 "Argument --gcloud-cli-zip must be used.", mGcloudCliZipArchive, null); 136 try { 137 RunUtil runUtil = mRunUtilProvider.get(); 138 mGcloudCliDir = Files.createTempDirectory(null).toFile(); 139 CommandResult unzipRes = 140 runUtil.runTimedCmd( 141 COMMAND_TIMEOUT_MILLIS, 142 "unzip", 143 mGcloudCliZipArchive.getAbsolutePath(), 144 "-d", 145 mGcloudCliDir.getAbsolutePath()); 146 147 Assert.assertEquals( 148 "Unable to unzip the gcloud cli zip archive", 149 unzipRes.getStatus(), 150 CommandStatus.SUCCESS); 151 152 // The 'gcloud init' command creates configuration files for gsutil and other 153 // applications that use the gcloud sdk in the home directory. We can isolate 154 // the effects of these configuration files to the processes that run the 155 // gcloud and gsutil executables tracked by this class by setting the home 156 // directory for processes that run those executables to a temporary directory 157 // also tracked by this class. 158 runUtil.setEnvVariable("HOME", mGcloudCliDir.getAbsolutePath()); 159 File gcloudBin = 160 mGcloudCliDir 161 .toPath() 162 .resolve(Paths.get("google-cloud-sdk", "bin", "gcloud")) 163 .toFile(); 164 String gcloudInitScript = 165 String.format( 166 "printf \"1\\n1\" | %s init --console-only", 167 gcloudBin.getAbsolutePath()); 168 CommandResult gcloudInitRes = 169 runUtil.runTimedCmd( 170 COMMAND_TIMEOUT_MILLIS, 171 System.out, 172 System.out, 173 "sh", 174 "-c", 175 gcloudInitScript); 176 Assert.assertEquals( 177 "gcloud cli initialization failed", 178 gcloudInitRes.getStatus(), 179 CommandStatus.SUCCESS); 180 181 CommandResult chmodRes = 182 runUtil.runTimedCmd( 183 COMMAND_TIMEOUT_MILLIS, 184 System.out, 185 System.out, 186 "chmod", 187 "755", 188 "-v", 189 mWebviewInstallerTool.getAbsolutePath()); 190 191 Assert.assertEquals( 192 "The 'chmod 755 -v <WebView installer tool>' command failed", 193 chmodRes.getStatus(), 194 CommandStatus.SUCCESS); 195 196 } catch (Exception ex) { 197 throw new TargetSetupError("Caught an exception during setup:\n" + ex); 198 } 199 setGcloudCliPath(testInfo, mGcloudCliDir); 200 setWebviewInstallerToolPath(testInfo, mWebviewInstallerTool); 201 } 202 203 @Override tearDown(TestInformation testInfo, Throwable e)204 public void tearDown(TestInformation testInfo, Throwable e) { 205 // Clean up some files. 206 mRunUtilProvider 207 .get() 208 .runTimedCmd(COMMAND_TIMEOUT_MILLIS, "rm", "-rf", mGcloudCliDir.getAbsolutePath()); 209 } 210 211 interface RunUtilProvider { get()212 RunUtil get(); 213 } 214 } 215