1 /*
2  * Copyright (C) 2016 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 package android.core.vm.targetprep;
17 
18 import com.android.compatibility.common.tradefed.build.CompatibilityBuildHelper;
19 import com.android.tradefed.build.IBuildInfo;
20 import com.android.tradefed.config.Option;
21 import com.android.tradefed.config.OptionClass;
22 import com.android.tradefed.device.DeviceNotAvailableException;
23 import com.android.tradefed.device.ITestDevice;
24 import com.android.tradefed.log.LogUtil.CLog;
25 import com.android.tradefed.targetprep.BuildError;
26 import com.android.tradefed.targetprep.ITargetCleaner;
27 import com.android.tradefed.targetprep.TargetSetupError;
28 import com.android.tradefed.util.CommandResult;
29 import com.android.tradefed.util.CommandStatus;
30 import com.android.tradefed.util.FileUtil;
31 
32 import java.io.File;
33 import java.io.IOException;
34 import java.util.zip.ZipFile;
35 
36 /**
37  * Configures the device to run VM tests.
38  */
39 @OptionClass(alias="vm-test-preparer")
40 public class VmTestPreparer implements ITargetCleaner {
41 
42     private static final String JAR_FILE = "android.core.vm-tests-tf.jar";
43     private static final String TEMP_DIR = "/data/local/tmp";
44     private static final String VM_TEMP_DIR = TEMP_DIR +"/vm-tests";
45 
46     /**
47      * {@inheritDoc}
48      */
49     @Override
setUp(ITestDevice device, IBuildInfo buildInfo)50     public void setUp(ITestDevice device, IBuildInfo buildInfo)
51             throws TargetSetupError, BuildError, DeviceNotAvailableException {
52         CompatibilityBuildHelper helper = new CompatibilityBuildHelper(buildInfo);
53         if (!installVmPrereqs(device, helper)) {
54             throw new RuntimeException(String.format(
55                     "Failed to install vm-tests prereqs on device %s",
56                     device.getSerialNumber()));
57         }
58     }
59 
60     /**
61      * {@inheritDoc}
62      */
63     @Override
tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)64     public void tearDown(ITestDevice device, IBuildInfo buildInfo, Throwable e)
65             throws DeviceNotAvailableException {
66         cleanupDeviceFiles(device);
67     }
68 
69     /**
70      * Install pre-requisite jars for running vm-tests, creates temp directories for test.
71      *
72      * @param device the {@link ITestDevice}
73      * @param ctsBuild the {@link CompatibilityBuildHelper}
74      * @throws DeviceNotAvailableException
75      * @return true if test jar files are extracted and pushed to device successfully
76      */
installVmPrereqs(ITestDevice device, CompatibilityBuildHelper ctsBuild)77     private boolean installVmPrereqs(ITestDevice device, CompatibilityBuildHelper ctsBuild)
78             throws DeviceNotAvailableException {
79         cleanupDeviceFiles(device);
80         // Creates temp directory recursively. We also need to create the dalvik-cache directory
81         // which is used by the dalvikvm to optimize things. Without the dalvik-cache, there will be
82         // a sigsev thrown by the vm.
83         createRemoteDir(device, VM_TEMP_DIR + "/dalvik-cache" );
84         try {
85             File jarFile = ctsBuild.getTestFile(JAR_FILE);
86             if (!jarFile.exists()) {
87                 CLog.e("Missing jar file %s", jarFile.getPath());
88                 return false;
89             }
90 
91             String jarOnDevice = VM_TEMP_DIR + "/" + JAR_FILE;
92             if (!device.pushFile(jarFile, jarOnDevice)) {
93                 CLog.e("Failed to push vm test jar");
94                 return false;
95             }
96 
97             // TODO: Only extract tests directory, avoid rm.
98             String cmd = "unzip -d " + VM_TEMP_DIR + " " + jarOnDevice
99                     + " && rm -rf " + VM_TEMP_DIR + "/dot*"
100                     + " && mv " + VM_TEMP_DIR + "/tests/* " + VM_TEMP_DIR + "/"
101                     + " && echo Success";
102             CommandResult result = device.executeShellV2Command(cmd);
103             if (result.getStatus() != CommandStatus.SUCCESS) {
104                 CLog.e("Failed to extract and prepare vm tests jar");
105                 return false;
106             }
107         } catch (IOException e) {
108             CLog.e("Failed to extract jar file %s and sync it to device %s.",
109                     JAR_FILE, device.getSerialNumber());
110             return false;
111         }
112         return true;
113     }
114 
115     /**
116      * Removes temporary file directory from device
117      *
118      * @param device
119      * @throws DeviceNotAvailableException
120      */
cleanupDeviceFiles(ITestDevice device)121     private void cleanupDeviceFiles(ITestDevice device) throws DeviceNotAvailableException {
122         if (device.doesFileExist(VM_TEMP_DIR)) {
123             device.executeShellCommand(String.format("rm -r %s", VM_TEMP_DIR));
124         }
125     }
126 
127     /**
128      * Creates the file directory recursively in the device.
129      *
130      * @param device the {@link ITestDevice}
131      * @param remoteFilePath the absolute path.
132      * @throws DeviceNotAvailableException
133      */
createRemoteDir(ITestDevice device, String remoteFilePath)134     private void createRemoteDir(ITestDevice device, String remoteFilePath)
135             throws DeviceNotAvailableException {
136         if (device.doesFileExist(remoteFilePath)) {
137             return;
138         }
139         if (!(device.doesFileExist(TEMP_DIR))) {
140             CLog.e("Error: %s does not exist", TEMP_DIR);
141         }
142         device.executeShellCommand(String.format("mkdir %s", VM_TEMP_DIR));
143         device.executeShellCommand(String.format("mkdir %s", remoteFilePath));
144     }
145 }
146