diff options
-rw-r--r-- | adb_stress_tests/util.py | 61 | ||||
-rw-r--r-- | build/scripts/slave/recipes/adt/adb.py | 2 | ||||
-rw-r--r-- | console_test_server/app/src/main/java/com/android/devtools/server/services/GeoManagerService.java | 4 | ||||
-rw-r--r-- | emu_test/config/boot_cfg.csv | 3 | ||||
-rw-r--r-- | emu_test/test_avd/launch_avd.py | 160 | ||||
-rw-r--r-- | emu_test/test_console/run_adb_shell.py | 5 | ||||
-rw-r--r-- | emu_test/test_console/testcase_auth.py | 37 | ||||
-rw-r--r-- | emu_test/test_console/testcase_call.py | 4 | ||||
-rw-r--r-- | emu_test/test_console/testcase_geo.py | 4 | ||||
-rw-r--r-- | emu_test/test_console/testcase_orientation.py | 4 | ||||
-rw-r--r-- | emu_test/test_console/testcase_sms.py | 4 | ||||
-rw-r--r-- | emu_test/test_console/uninstall_app.py | 23 | ||||
-rw-r--r-- | emu_test/test_console/utils/util.py | 12 | ||||
-rw-r--r-- | emu_test/utils/emu_testcase.py | 4 | ||||
-rw-r--r-- | emu_test/utils/zip_upload_logs.py | 1 | ||||
-rw-r--r-- | system_image_uitests/app/src/androidTest/java/com/android/devtools/systemimage/uitest/smoke/MapsTest.java | 2 |
16 files changed, 290 insertions, 40 deletions
diff --git a/adb_stress_tests/util.py b/adb_stress_tests/util.py index 73cf6573..abc094c4 100644 --- a/adb_stress_tests/util.py +++ b/adb_stress_tests/util.py @@ -32,23 +32,12 @@ def print_progress(perc, prefix='', sys.stdout.flush() -def test_connected(devices): - """Verify that the expected number of devices/emulators are still connected. - - Args: - devices: Number of expected devices. - - Returns: - A tuple of form (success, connected). - The success member indicates whether the expected number - of devices were found. - The connected member contains a list of device serial numbers - identifying the connected devices. - """ +def get_connected_devices(): + """Returns list of adb device ids that are connected.""" proc = subprocess.Popen('adb devices'.split(), stdout=subprocess.PIPE) output, error = proc.communicate() connected = [] - # verify expected emulators/devices are present + # Collect connected devices. # Note that since Windows includes a carriage return, we # do it in a seperate loop. if platform.system() is not 'Windows': @@ -59,7 +48,25 @@ def test_connected(devices): for emulator_entry in output.split('\r\n')[1:]: if emulator_entry != '': connected.append(emulator_entry.split('\t')[0]) + return connected + +def test_connected(devices): + """Verify that the expected number of devices/emulators are still connected. + + Args: + devices: Number of expected devices. + + Returns: + A tuple of form (success, connected). + The success member indicates whether the expected number + of devices were found. + The connected member contains a list of device serial numbers + identifying the connected devices. + """ + # verify expected emulators/devices are present + # Note that since Windows includes a carriage return, we do it in a seperate loop. + connected = get_connected_devices() success = True if len(connected) != devices: print('\n\nERROR:\nExpected number of connections: ' + @@ -105,6 +112,7 @@ def launcher(test_fn, duration, devices, setup=noop, cleanup=noop, is_print_prog # ThreadPool for running the tests in parallel. # We choose the size to match the number of devices, so that every device can execute in parallel. thread_pool = pool.ThreadPool(processes = devices) + connected_devices = get_connected_devices() try: setup() @@ -122,7 +130,18 @@ def launcher(test_fn, duration, devices, setup=noop, cleanup=noop, is_print_prog connection_success, connected = test_connected(devices) if not connection_success: - return False + failure_time = time.time() - start + for device in connected_devices: + if device not in connected: + filename = os.path.join(log_dir, device, str(iteration) + '.txt') + msg = ("Device failed connection test for interation " + + str(iteration) + + "(at " + str(failure_time) + " seconds)") + spit(filename, msg) + + # if no devices are connected, then end test with failure. + if not connected: + return False # Run one iteration of the test against every device in parallel iteration += 1 @@ -136,8 +155,9 @@ def launcher(test_fn, duration, devices, setup=noop, cleanup=noop, is_print_prog # Capture logcat. logs = thread_pool.map(logcat, connected) for device,log in zip(connected, logs): - filename = os.path.join(log_dir, device, str(iteration) + '.txt') - spit(filename, log) + if log: + filename = os.path.join(log_dir, device, str(iteration) + '.txt') + spit(filename, log) # If we get here, the test completed successfully. if is_print_progress: @@ -192,8 +212,11 @@ def logcat(dut): Returns: String containing the command's output. """ - cmd = ['shell', 'logcat', '-d', '-v', 'threadtime'] - return adb(dut, cmd) + try: + cmd = ['shell', 'logcat', '-d', '-v', 'threadtime'] + return adb(dut, cmd) + except: + return None def spit(filename, text): diff --git a/build/scripts/slave/recipes/adt/adb.py b/build/scripts/slave/recipes/adt/adb.py index 807cb87a..17c28312 100644 --- a/build/scripts/slave/recipes/adt/adb.py +++ b/build/scripts/slave/recipes/adt/adb.py @@ -60,6 +60,8 @@ def RunSteps(api): '--dst', '%s%s/' % (logs_dir, buildername), '--build-dir', build_dir, '--skiplog'] + if api.platform.is_win: + upload_log_args.append('--iswindows') api.python("Zip and Upload Logs", log_util_path, upload_log_args) def GenTests(api): diff --git a/console_test_server/app/src/main/java/com/android/devtools/server/services/GeoManagerService.java b/console_test_server/app/src/main/java/com/android/devtools/server/services/GeoManagerService.java index f78c6469..ebd4ba0c 100644 --- a/console_test_server/app/src/main/java/com/android/devtools/server/services/GeoManagerService.java +++ b/console_test_server/app/src/main/java/com/android/devtools/server/services/GeoManagerService.java @@ -228,9 +228,9 @@ public class GeoManagerService implements Service { Log.d(TAG, "Enabled GPS."); try { - uiDevice.findObject(new UiSelector().text(Constants.YES)). + uiDevice.findObject(new UiSelector().text(Constants.TIP_BUTTON_OK)). clickAndWaitForNewWindow(); - Log.d(TAG, "2.3) Improve location accuracy, " + Constants.YES + " clicked."); + Log.d(TAG, "2.3) Improve location accuracy, " + Constants.TIP_BUTTON_OK + " clicked."); } catch (UiObjectNotFoundException e) { Log.e(TAG, e.getMessage()); } diff --git a/emu_test/config/boot_cfg.csv b/emu_test/config/boot_cfg.csv index 914eb968..593e53d5 100644 --- a/emu_test/config/boot_cfg.csv +++ b/emu_test/config/boot_cfg.csv @@ -82,6 +82,3 @@ API 15,default,armeabi-v7a,Nexus 4,2048,no,public,,,P,P,,,,,,,,, ,,x86,Nexus 4,2048,no,public,,,P,P,,,,,,,,, ,,x86,Nexus 4,2048,no,ics-mr1,P,P,P,P,P,P,P,P,P,P,P,P,P ,google_apis,x86,Nexus 4,2048,no,ics-mr1,P,P,P,P,P,P,P,P,P,P,P,P,P -API 10,default,x86,Nexus 4,2048,no,public,P,P,P,P,,,P,P,P,P,P,P,P -,,x86,Nexus 4,2048,no,gb,P,P,P,P,P,P,P,P,P,P,P,P,P -,google_apis,x86,Nexus 4,2048,no,gb,P,P,P,P,P,P,P,P,P,P,P,P,P diff --git a/emu_test/test_avd/launch_avd.py b/emu_test/test_avd/launch_avd.py new file mode 100644 index 00000000..75aa79c0 --- /dev/null +++ b/emu_test/test_avd/launch_avd.py @@ -0,0 +1,160 @@ +"""AVD Launch test. + +Verify the emulator launched in AVD can be detected. + +usage: launch_avd.py [-h] [-t TIMEOUT_IN_SECONDS] --avd AVD + [--exec EMULATOR_EXEC] +""" + +import argparse +import logging +import multiprocessing.pool +import subprocess +from subprocess import PIPE, STDOUT +import sys +import time +import threading +import unittest + +import util + +log = logging.getLogger('launch_avd') + +def arg_parser(): + """Return argument parser for launch_avd test""" + parser = argparse.ArgumentParser(description='Argument parser for emu test') + + parser.add_argument('-t', '--timeout', type=int, dest='timeout_in_seconds', action='store', + default=600, + help='an integer for timeout in seconds, default is 600') + parser.add_argument('--avd', type=str, dest='avd', action='store', + required=True, + help='run test for given AVD') + parser.add_argument('--exec', type=str, dest='emulator_exec', action='store', + default='emulator', + help='path of emulator executable, default is system emulator') + parser.add_argument('unittest_args', nargs='*') + return parser + +class TimeoutError(Exception): + """Exception raised for timeout + + Attributes: + cmd -- cmd which timed out + timeout -- value of timeout + """ + + def __init__(self, cmd, timeout): + self.cmd = cmd + self.timeout = timeout + +def run_with_timeout(cmd, timeout): + """Run command with specified timeout. + + Args: + cmd - Required : command to run + timeout - Required : timeout (in seconds) + + Returns: + Tuple of form (returncode, output, err), where: + * returncode is the exit code of the command + * output is the stdout output of the command, collected into a string + * err is the stderr output of the command, collected into a string + """ + vars = {'output': "", + 'err': "", + 'process': None} + + def run_cmd(): + vars['process'] = subprocess.Popen(cmd, stdout=PIPE, stderr=PIPE) + (vars['output'], vars['err']) = vars['process'].communicate() + + thread = threading.Thread(target=run_cmd) + thread.start() + + thread.join(timeout) + if thread.is_alive(): + log.debug('cmd %s timeout, force terminate' % ' '.join(cmd)) + try: + vars['process'].terminate() + except Exception as e: + log.error('exception terminating adb getprop process: %r' % e) + thread.join(timeout) + return vars['process'].returncode, vars['output'], vars['err'] + + +def launch_emu(avd, emu_args): + """Launch given avd and return immediately""" + log.debug('call Launching AVD, ...: %s' % str(avd)) + exec_path = emu_args.emulator_exec + launch_cmd = [exec_path, "-avd", str(avd), "-verbose", "-show-kernel"] + + if "emu-master-dev" in exec_path: + launch_cmd += ["-skip-adb-auth"] + + log.info('Launching AVD, cmd: %s' % ' '.join(launch_cmd)) + start_proc = subprocess.Popen(launch_cmd, stdout=PIPE, stderr=STDOUT) + log.info('done Launching AVD, cmd: %s' % ' '.join(launch_cmd)) + + if start_proc.poll(): + raise LaunchError(str(avd)) + log.debug('return Launching AVD, ...: %s' % str(avd)) + return start_proc + + +def launch_emu_and_wait(avd, emu_args): + """Launch given avd and wait for boot completion, return boot time""" + run_with_timeout(["adb", "kill-server"], 20) + run_with_timeout(["adb", "start-server"], 20) + pool = multiprocessing.pool.ThreadPool(processes = 1) + launcher_emu = pool.apply_async(launch_emu, [avd, emu_args]) + start_time = time.time() + completed = "0" + real_time_out = emu_args.timeout_in_seconds; + if 'swiftshader' in str(avd): + real_time_out = real_time_out + emu_args.timeout_in_seconds + if 'arm' in str(avd): + real_time_out = real_time_out + emu_args.timeout_in_seconds; + if 'mips' in str(avd): + real_time_out = real_time_out + emu_args.timeout_in_seconds; + while time.time()-start_time < real_time_out: + cmd = ["adb", "shell", "getprop", "sys.boot_completed"] + try: + (exit_code, output, err) = run_with_timeout(cmd, 10) + except Exception as e: + log.error('exception run_with_timeout adb getprop: %r' % e) + continue + if exit_code is 0: + completed = output.strip() + if completed is "1": + log.info('AVD %s is fully booted' % avd) + break + time.sleep(1) + if completed is not "1": + log.debug('command output - %s %s' % (output,err)) + log.error('AVD %s didn\'t boot up within %s seconds' % (avd,real_time_out)) + raise TimeoutError(avd, real_time_out) + boot_time = time.time() - start_time + log.debug('AVD %s, boot time is %s' % (avd, boot_time)) + emu_proc = launcher_emu.get(10) + if util.get_connected_devices(): + success = True + else: + success = False + emu_proc.terminate() + return success + + +class LaunchAVDTest(unittest.TestCase): + def test_launch_avd(self): + args = arg_parser().parse_args() + avd = args.avd + return launch_emu_and_wait(avd, args) + +if __name__ == '__main__': + console_handler = logging.StreamHandler(sys.stdout) + console_handler.setLevel(logging.DEBUG) + log.addHandler(console_handler) + log.setLevel(logging.DEBUG) + suite = unittest.TestLoader().loadTestsFromTestCase(LaunchAVDTest) + unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/emu_test/test_console/run_adb_shell.py b/emu_test/test_console/run_adb_shell.py index 00d32405..48d562c5 100644 --- a/emu_test/test_console/run_adb_shell.py +++ b/emu_test/test_console/run_adb_shell.py @@ -6,8 +6,7 @@ import time from utils import util -main_apk_package = 'com.android.devtools.server' -launcher_class_name = '%s.Server' % main_apk_package +launcher_class_name = '%s.Server' % util.MAIN_APK_PACKAGE instrumentation_runner = 'android.support.test.runner.AndroidJUnitRunner' num_trials = 1 @@ -21,7 +20,7 @@ while True: '-w', '-e' 'class', launcher_class_name, ('%s.test/%s' - % (main_apk_package, + % (util.MAIN_APK_PACKAGE, instrumentation_runner))]) break except subprocess.CalledProcessError as err: diff --git a/emu_test/test_console/testcase_auth.py b/emu_test/test_console/testcase_auth.py index 72364942..d506f233 100644 --- a/emu_test/test_console/testcase_auth.py +++ b/emu_test/test_console/testcase_auth.py @@ -174,20 +174,31 @@ class AuthTest(testcase_base.BaseConsoleTest): # save auth token value and empty contents of auth token file valid_auth_token = util.get_auth_token() - f = open(util.TOKEN_PATH, 'w') - f.close() - # telnet and verify - self.telnet = util.telnet_emulator() - self._verify_auth_command_by_enter_help_command( - util.REGEX_HELP_DISPLAY_AUTH) - - # reset auth token file - f = open(util.TOKEN_PATH, 'w') - f.write(valid_auth_token) - f.close() - - util.exit_emulator_console(self.telnet) + try: + f = open(util.TOKEN_PATH, 'w') + f.close() + + # telnet and verify + self.telnet = util.telnet_emulator() + self._verify_auth_command_by_enter_help_command( + util.REGEX_HELP_DISPLAY_AUTH) + + # reset auth token file + f = open(util.TOKEN_PATH, 'w') + f.write(valid_auth_token) + f.close() + + util.exit_emulator_console(self.telnet) + except IOError as e: + print 'IOError on auth token file.' + finally: + print ('The failure on resetting auth token file back will affact other ' + 'tests running after this test. Hence, reset it again when ' + 'failure happens.') + f = open(util.TOKEN_PATH, 'w') + f.write(valid_auth_token) + f.close() def test_auth_change_auth_token_file_permissions(self): """Test command for: auth <auth_token>. diff --git a/emu_test/test_console/testcase_call.py b/emu_test/test_console/testcase_call.py index 8c169a1e..71dbc68d 100644 --- a/emu_test/test_console/testcase_call.py +++ b/emu_test/test_console/testcase_call.py @@ -37,6 +37,10 @@ class PhoneCallTest(testcase_base.BaseConsoleTest): def setUpClass(cls): util.run_script_run_adb_shell(TESTCASE_CALL_DIR) + @classmethod + def tearDownClass(cls): + util.unstall_apps(TESTCASE_CALL_DIR) + def _process_request_telephony_service(self, payload): r = requests.post(SERVLET_TELEPHONY, data=json.dumps(payload)) if r.raise_for_status(): diff --git a/emu_test/test_console/testcase_geo.py b/emu_test/test_console/testcase_geo.py index 36aa230b..93029085 100644 --- a/emu_test/test_console/testcase_geo.py +++ b/emu_test/test_console/testcase_geo.py @@ -34,6 +34,10 @@ class GeoTest(testcase_base.BaseConsoleTest): def setUpClass(cls): util.run_script_run_adb_shell(TESTCASE_CALL_DIR) + @classmethod + def tearDownClass(cls): + util.unstall_apps(TESTCASE_CALL_DIR) + def _process_request_geo_service(self, payload): """Processes post request to geo service. diff --git a/emu_test/test_console/testcase_orientation.py b/emu_test/test_console/testcase_orientation.py index a6946273..d372242a 100644 --- a/emu_test/test_console/testcase_orientation.py +++ b/emu_test/test_console/testcase_orientation.py @@ -38,6 +38,10 @@ class OrientationTest(testcase_base.BaseConsoleTest): def setUpClass(cls): util.run_script_run_adb_shell(TESTCASE_CALL_DIR) + @classmethod + def tearDownClass(cls): + util.unstall_apps(TESTCASE_CALL_DIR) + def _process_request_orientation_service(self, payload): """Processes post request to orientation service. diff --git a/emu_test/test_console/testcase_sms.py b/emu_test/test_console/testcase_sms.py index c693f16a..764be972 100644 --- a/emu_test/test_console/testcase_sms.py +++ b/emu_test/test_console/testcase_sms.py @@ -37,6 +37,10 @@ class SmsTest(testcase_base.BaseConsoleTest): def setUpClass(cls): util.run_script_run_adb_shell(TESTCASE_CALL_DIR) + @classmethod + def tearDownClass(cls): + util.unstall_apps(TESTCASE_CALL_DIR) + def _process_request_sms_service(self, payload): """Processes post request to sms service. diff --git a/emu_test/test_console/uninstall_app.py b/emu_test/test_console/uninstall_app.py new file mode 100644 index 00000000..847c1bed --- /dev/null +++ b/emu_test/test_console/uninstall_app.py @@ -0,0 +1,23 @@ +"""This script is to run adb to uninstall apps.""" + +import subprocess +import sys +import time + +from utils import util + +test_apk_package = '%s.test' % util.MAIN_APK_PACKAGE + +num_trials = 1 +while True: + if num_trials is util.ADB_NUM_MAX_TRIALS: + sys.exit(-1) + try: + print ('Run adb shell to uninstall apps, trial num: %s' % str(num_trials)) + subprocess.call(['adb', 'uninstall', util.MAIN_APK_PACKAGE]) + subprocess.call(['adb', 'uninstall', test_apk_package]) + break + except subprocess.CalledProcessError as err: + print 'Subprocess call error: {0}'.format(err) + time.sleep(util.ADB_TRIAL_WAIT_TIME_S) + num_trials += 1 diff --git a/emu_test/test_console/utils/util.py b/emu_test/test_console/utils/util.py index 8899f483..984ee89c 100644 --- a/emu_test/test_console/utils/util.py +++ b/emu_test/test_console/utils/util.py @@ -69,8 +69,10 @@ CMD_EMPTY_AUTH_TOKEN = '%s \n' % AUTH CMD_EXIT = 'exit\n' SCRIPT_TO_INSTALL_APK = 'install_apk.py' SCRIPT_TO_RUN_ADB_SHELL = 'run_adb_shell.py' +SCRIPT_TO_UNINSTALL_APP = 'uninstall_app.py' PYTHON_INTERPRETER = 'python' CMD_ROTATE = 'rotate\n' +MAIN_APK_PACKAGE = 'com.android.devtools.server' def check_read_until(console_output): @@ -304,3 +306,13 @@ def run_script_run_adb_shell(testcase_call_dir): subprocess.call([PYTHON_INTERPRETER, script_install_apk]) subprocess.Popen([PYTHON_INTERPRETER, script_run_adb_shell]) time.sleep(SETUP_WAIT_TIMEOUT_S) + +def unstall_apps(testcase_call_dir): + """Run Python script to uninstall apps. + + Args: + testcase_call_dir: The directory where the test case is called from. + """ + subprocess.Popen([PYTHON_INTERPRETER, + '%s/%s' % (testcase_call_dir, SCRIPT_TO_UNINSTALL_APP)]) + time.sleep(SETUP_WAIT_TIMEOUT_S) diff --git a/emu_test/utils/emu_testcase.py b/emu_test/utils/emu_testcase.py index 60e785c2..21d24ee7 100644 --- a/emu_test/utils/emu_testcase.py +++ b/emu_test/utils/emu_testcase.py @@ -172,7 +172,11 @@ class EmuBaseTestCase(LoggedTestCase): self.m_logger.info('No emulator found, stopping logcat') break if (logcat_proc): + try: logcat_proc.terminate() + except: + # Could not terminate logcat; probably already dead. + pass def readoutput_in_thread(): with open(verbose_log_path, 'a') as verb_output: diff --git a/emu_test/utils/zip_upload_logs.py b/emu_test/utils/zip_upload_logs.py index a807e437..608c37eb 100644 --- a/emu_test/utils/zip_upload_logs.py +++ b/emu_test/utils/zip_upload_logs.py @@ -46,6 +46,7 @@ def zip_and_upload(): # if it is adb stress test log, zip and upload to GCS if 'adb_stress_logs' in args.log_dir: + print 'Running command in directory: %s' % (os.getcwd()) verbose_call(['zip', '-r', args.zip_name, args.log_dir]) adb_stress_gs_dst = 'gs://adb_test_traces/%s/' % builderName verbose_call(['python', gsutil_path, 'cp', args.zip_name, adb_stress_gs_dst]) diff --git a/system_image_uitests/app/src/androidTest/java/com/android/devtools/systemimage/uitest/smoke/MapsTest.java b/system_image_uitests/app/src/androidTest/java/com/android/devtools/systemimage/uitest/smoke/MapsTest.java index b7daf595..433f16f7 100644 --- a/system_image_uitests/app/src/androidTest/java/com/android/devtools/systemimage/uitest/smoke/MapsTest.java +++ b/system_image_uitests/app/src/androidTest/java/com/android/devtools/systemimage/uitest/smoke/MapsTest.java @@ -32,6 +32,7 @@ import com.android.devtools.systemimage.uitest.framework.SystemImageTestFramewor import com.android.devtools.systemimage.uitest.utils.AppLauncher; import org.junit.Assert; +import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; @@ -71,6 +72,7 @@ public class MapsTest { * 2. Navigation overview is displayed. * </pre> */ + @Ignore("bug 36450156 - API 23, 23G does not have maps app") @Test @TestInfo(id = "145493594") public void testMapsApp() throws Exception { |