1 /*
2  * Copyright (C) 2009 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.hosttest;
18 
19 import java.util.ArrayList;
20 import java.util.List;
21 
22 import junit.framework.Test;
23 import junit.framework.TestResult;
24 import junit.textui.TestRunner;
25 
26 import com.android.ddmlib.AndroidDebugBridge;
27 import com.android.ddmlib.IDevice;
28 import com.android.ddmlib.Log;
29 import com.android.ddmlib.AndroidDebugBridge.IDeviceChangeListener;
30 
31 /**
32  * Command line interface for running DeviceTest tests.
33  *
34  * Extends junit.textui.TestRunner to handle optional -s (device serial) and -p (test data)
35  * arguments, and then pass their values to the instantiated DeviceTests.
36  *
37  * Provided test class must be a DeviceTest.
38  *
39  * @see junit.textui.TestRunner for more information on command line syntax.
40  */
41 public class DeviceTestRunner extends TestRunner {
42 
43     private static final String LOG_TAG = "DeviceTestRunner";
44     private String mDeviceSerial = null;
45     private IDevice mDevice = null;
46     private String mTestDataPath = null;
47 
DeviceTestRunner()48     private DeviceTestRunner() {
49     }
50 
51     /**
52      * Starts the test run.
53      * Extracts out DeviceTestCase specific command line arguments, then passes control to parent
54      * TestRunner.
55      * @param args command line arguments
56      * @return {@link TestResult}
57      */
58     @Override
start(String[] args)59     public TestResult start(String[] args) throws Exception {
60         // holds unprocessed arguments to pass to parent
61         List<String> parentArgs = new ArrayList<String>();
62         for (int i=0; i < args.length; i++) {
63             if (args[i].equals("-s")) {
64                 i++;
65                 mDeviceSerial = extractArg(args, i);
66             } else if (args[i].equals("-p")) {
67                 i++;
68                 mTestDataPath = extractArg(args, i);
69             } else {
70                 // unrecognized arg, must be for parent
71                 parentArgs.add(args[i]);
72             }
73         }
74         DeviceConnector connector = new DeviceConnector();
75         mDevice = connector.connectToDevice(mDeviceSerial);
76         return super.start(parentArgs.toArray(new String[parentArgs.size()]));
77     }
78 
extractArg(String[] args, int index)79     private String extractArg(String[] args, int index) {
80         if (args.length <= index) {
81             printUsage();
82             throw new IllegalArgumentException("Error: not enough arguments");
83         }
84         return args[index];
85     }
86 
87 
88     /**
89      * Main entry point.
90      *
91      * Establishes connection to provided adb device and runs tests
92      *
93      * @param args expects:
94      *     test class to run
95      *     optionally, device serial number. If unspecified, will connect to first device found
96      *     optionally, file system path to test data files
97      */
main(String[] args)98     public static void main(String[] args) {
99         DeviceTestRunner aTestRunner = new DeviceTestRunner();
100         try {
101             TestResult r = aTestRunner.start(args);
102             if (!r.wasSuccessful())
103                 System.exit(FAILURE_EXIT);
104             System.exit(SUCCESS_EXIT);
105         } catch(Exception e) {
106             System.err.println(e.getMessage());
107             System.exit(EXCEPTION_EXIT);
108         }
109     }
110 
printUsage()111     private static void printUsage() {
112         System.out.println("Usage: DeviceTestRunner <test_class> [-s device_serial] " +
113                 "[-p test_data_path]");
114     }
115 
116     /**
117      * Override parent to set DeviceTest data
118      */
119     @Override
doRun(Test test, boolean wait)120     public TestResult doRun(Test test, boolean wait) {
121         if (test instanceof DeviceTest) {
122             DeviceTest deviceTest = (DeviceTest)test;
123             deviceTest.setDevice(mDevice);
124             deviceTest.setTestAppPath(mTestDataPath);
125         } else {
126             Log.w(LOG_TAG, String.format("%s test class is not a DeviceTest.",
127                     test.getClass().getName()));
128         }
129         return super.doRun(test, wait);
130     }
131 
132     /**
133      * Override parent to create DeviceTestSuite wrapper, instead of TestSuite
134      */
135     @SuppressWarnings("unchecked")
136     @Override
runSingleMethod(String testCase, String method, boolean wait)137     protected TestResult runSingleMethod(String testCase, String method, boolean wait)
138     throws Exception {
139         Class testClass = loadSuiteClass(testCase);
140         Test test = DeviceTestSuite.createTest(testClass, method);
141         return doRun(test, wait);
142     }
143 }
144