1 /*
2  * Copyright (C) 2014 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.cts.tradefed.testtype;
18 
19 import com.android.cts.tradefed.build.CtsBuildHelper;
20 import com.android.ddmlib.testrunner.TestIdentifier;
21 import com.android.tradefed.build.IBuildInfo;
22 import com.android.tradefed.config.Option;
23 import com.android.tradefed.config.Option.Importance;
24 import com.android.tradefed.device.DeviceNotAvailableException;
25 import com.android.tradefed.device.ITestDevice;
26 import com.android.tradefed.log.LogUtil.CLog;
27 import com.android.tradefed.result.ITestInvocationListener;
28 import com.android.tradefed.testtype.IAbi;
29 import com.android.tradefed.testtype.IBuildReceiver;
30 import com.android.tradefed.testtype.IDeviceTest;
31 import com.android.tradefed.testtype.IRemoteTest;
32 import com.android.tradefed.util.AbiFormatter;
33 import com.android.tradefed.util.ArrayUtil;
34 
35 import junit.framework.Assert;
36 import junit.framework.Test;
37 
38 import java.io.File;
39 import java.io.FileNotFoundException;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.Collection;
43 import java.util.Collections;
44 import java.util.HashSet;
45 import java.util.List;
46 import java.util.Set;
47 import java.util.concurrent.TimeUnit;
48 
49 /**
50  * {@link Test} for running CTS JUnit tests on the device.
51  */
52 public class JUnitDeviceTest implements IDeviceTest, IRemoteTest, IBuildReceiver {
53 
54     private static final String TMP_DIR = "/data/local/tmp/";
55 
56     @Option(name = "junit-device-runtime",
57             description = "The name of the runtime to use on the device",
58             importance = Importance.ALWAYS)
59     private String mRuntimePath = "dalvikvm|#ABI#|";
60 
61     @Option(name = "junit-device-tmpdir", description = "Device path where to store the test jars."
62             , importance = Importance.IF_UNSET)
63     private String mDeviceTestTmpPath = TMP_DIR;
64 
65 
66 
67     // default to no timeout
68     private long mMaxTimeToOutputResponse = 0;
69 
70     private ITestDevice mDevice;
71     private String mRunName;
72     private Collection<TestIdentifier> mTests;
73     private CtsBuildHelper mCtsBuild = null;
74 
75     private List<String> mJarPaths = new ArrayList<String>();
76 
77     private String mRuntimeArgs;
78 
79     private IAbi mAbi;
80 
81     private static final String JUNIT_JAR = "cts-junit.jar";
82 
83     private Set<String> mTestJars = new HashSet<String>(Arrays.asList(JUNIT_JAR));
84 
85     /**
86      * @param abi The ABI to run the test on
87      */
setAbi(IAbi abi)88     public void setAbi(IAbi abi) {
89         mAbi = abi;
90     }
91 
92     @Override
getDevice()93     public ITestDevice getDevice() {
94         return mDevice;
95     }
96 
97     @Override
setDevice(ITestDevice device)98     public void setDevice(ITestDevice device) {
99         mDevice = device;
100     }
101 
addTestJarFileName(String jarFileName)102     public void addTestJarFileName(String jarFileName) {
103         mTestJars.add(jarFileName);
104     }
105 
setRunName(String runName)106     public void setRunName(String runName) {
107         mRunName = runName;
108     }
109 
setTests(Collection<TestIdentifier> tests)110     public void setTests(Collection<TestIdentifier> tests) {
111         mTests = tests;
112     }
113 
getTests()114     public Collection<TestIdentifier> getTests() {
115         return mTests;
116     }
117 
118     @Override
run(ITestInvocationListener listener)119     public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
120         addTestJarFileName(JUNIT_JAR);
121         checkFields();
122         long startTime = System.currentTimeMillis();
123         listener.testRunStarted(mRunName, mTests.size());
124         try {
125             installJars();
126             String jarPath = ArrayUtil.join(":", mJarPaths);
127             for (TestIdentifier testId : mTests) {
128                 SingleJUnitTestResultParser resultParser = new SingleJUnitTestResultParser(
129                         testId, listener);
130                 String cmdLine = String.format("ANDROID_DATA=%s %s -cp %s %s " +
131                         "com.android.cts.junit.SingleJUnitTestRunner %s#%s",
132                         mDeviceTestTmpPath, mRuntimePath, jarPath, mRuntimeArgs,
133                         testId.getClassName(), testId.getTestName());
134                 String cmd = AbiFormatter.formatCmdForAbi(cmdLine, mAbi.getBitness());
135                 CLog.d("Running %s", cmd);
136                 listener.testStarted(testId);
137                 mDevice.executeShellCommand(cmd, resultParser, mMaxTimeToOutputResponse,
138                         TimeUnit.MILLISECONDS, 0);
139             }
140         } finally {
141             listener.testRunEnded(System.currentTimeMillis() - startTime,
142                     Collections.<String, String> emptyMap());
143             // Remove jar files from device
144             removeJars();
145         }
146     }
147 
148     /**
149      * Installs the jar files on the device under test.
150      *
151      * @throws DeviceNotAvailableException
152      */
installJars()153     protected void installJars() throws DeviceNotAvailableException {
154         for (String f : mTestJars) {
155             CLog.d("Installing %s on %s", f, getDevice().getSerialNumber());
156             File jarFile;
157             try {
158                 String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f);
159                 jarFile = mCtsBuild.getTestApp(f);
160                 boolean result = getDevice().pushFile(jarFile, fullJarPath);
161                 Assert.assertTrue(String.format("Failed to push file to %s", fullJarPath), result);
162                 mJarPaths.add(fullJarPath);
163             } catch (FileNotFoundException e) {
164                 Assert.fail(String.format("Could not find file %s", f));
165             }
166         }
167     }
168 
169     /**
170      * Cleans up the jar files from the device under test.
171      *
172      * @throws DeviceNotAvailableException
173      */
removeJars()174     protected void removeJars() throws DeviceNotAvailableException {
175         for (String f : mTestJars) {
176             String fullJarPath = String.format("%s%s", mDeviceTestTmpPath, f);
177             CLog.d("Uninstalling %s on %s", fullJarPath, getDevice().getSerialNumber());
178             getDevice().executeShellCommand(String.format("rm %s", fullJarPath));
179         }
180     }
181 
182     @Override
setBuild(IBuildInfo buildInfo)183     public void setBuild(IBuildInfo buildInfo) {
184         mCtsBuild = CtsBuildHelper.createBuildHelper(buildInfo);
185     }
186 
187     /**
188      * Checks that all mandatory member fields has been set.
189      */
checkFields()190     protected void checkFields() {
191         if (mRunName == null) {
192             throw new IllegalArgumentException("run name has not been set");
193         }
194         if (mDevice == null) {
195             throw new IllegalArgumentException("Device has not been set");
196         }
197         if (mTestJars.isEmpty()) {
198             throw new IllegalArgumentException("No test jar has been set");
199         }
200         if (mTests == null) {
201             throw new IllegalArgumentException("tests has not been set");
202         }
203         if (mCtsBuild == null) {
204             throw new IllegalArgumentException("build has not been set");
205         }
206         for (String f : mTestJars) {
207             try {
208 
209                 mCtsBuild.getTestApp(f);
210             } catch (FileNotFoundException e) {
211                 throw new IllegalArgumentException(String.format(
212                         "Could not find jar %s in CTS build %s", f,
213                         mCtsBuild.getRootDir().getAbsolutePath()));
214             }
215         }
216     }
217 
218     /**
219      * Add runtime arguments to run the tests with.
220      *
221      * @param mRunTimeArgs
222      */
addRunTimeArgs(String mRunTimeArgs)223     public void addRunTimeArgs(String mRunTimeArgs) {
224         mRuntimeArgs = mRunTimeArgs;
225     }
226 }
227