def Sync(self, retry_count=3): """Perform a adb sync. Blocks until device package manager is responding. Args: retry_count: number of times to retry sync before failing Raises: WaitForResponseTimedOutError if package manager does not respond """ output = self.SendCommand("sync", retry_count=retry_count) if "Read-only file system" in output: logger.SilentLog(output) logger.Log("Remounting read-only filesystem") self.SendCommand("remount") output = self.SendCommand("sync", retry_count=retry_count) if "No space left on device" in output: logger.SilentLog(output) logger.Log("Restarting device runtime") self.SendShellCommand("stop", retry_count=retry_count) output = self.SendCommand("sync", retry_count=retry_count) self.SendShellCommand("start", retry_count=retry_count) logger.SilentLog(output) self.WaitForDevicePm() return output
def _FindUpstreamTests(self, path): """Find tests defined upward from given path. Args: path: the location to start searching. If it points to a java class file or java package dir, the appropriate test suite filters will be set Returns: list of test_suite.AbstractTestSuite found, may be empty """ class_name_arg = None package_name = None # if path is java file, populate class name if self._IsJavaFile(path): class_name_arg = self._GetClassNameFromFile(path) logger.SilentLog('Using java test class %s' % class_name_arg) elif self._IsJavaPackage(path): package_name = self._GetPackageNameFromDir(path) logger.SilentLog('Using java package %s' % package_name) manifest = self._FindUpstreamManifest(path) if manifest: logger.SilentLog('Found AndroidManifest at %s' % manifest.GetAppPath()) build_path = self._MakePathRelativeToBuild(manifest.GetAppPath()) return self._CreateSuitesFromManifest( manifest, build_path, class_name=class_name_arg, java_package_name=package_name)
def CreateTests(self, sub_tests_path=None): """Create tests found in test_path. Will create a single InstrumentationTestSuite based on info found in AndroidManifest.xml found at build_path. Will set additional filters if test_path refers to a java package or java class. """ tests = [] class_name_arg = None java_package_name = None if sub_tests_path: # if path is java file, populate class name if self._IsJavaFile(sub_tests_path): class_name_arg = self._GetClassNameFromFile(sub_tests_path) logger.SilentLog('Using java test class %s' % class_name_arg) elif self._IsJavaPackage(sub_tests_path): java_package_name = self._GetPackageNameFromDir(sub_tests_path) logger.SilentLog('Using java package %s' % java_package_name) try: manifest_parser = android_manifest.AndroidManifest( app_path=self.GetTestsRootPath()) instrs = manifest_parser.GetInstrumentationNames() if not instrs: logger.Log( 'Could not find instrumentation declarations in %s at %s' % (android_manifest.AndroidManifest.FILENAME, self.GetBuildPath())) return tests elif len(instrs) > 1: logger.Log( "Found multiple instrumentation declarations in %s/%s. " "Only using first declared." % (self.GetBuildPath(), android_manifest.AndroidManifest.FILENAME)) instr_name = manifest_parser.GetInstrumentationNames()[0] # escape inner class names instr_name = instr_name.replace('$', '\$') pkg_name = manifest_parser.GetPackageName() if instr_name.find(".") < 0: instr_name = "." + instr_name logger.SilentLog('Found instrumentation %s/%s' % (pkg_name, instr_name)) suite = InstrumentationTestSuite() suite.SetPackageName(pkg_name) suite.SetBuildPath(self.GetBuildPath()) suite.SetRunnerName(instr_name) suite.SetName(pkg_name) suite.SetClassName(class_name_arg) suite.SetJavaPackageFilter(java_package_name) tests.append(suite) return tests except: logger.Log('Could not find or parse %s at %s' % (android_manifest.AndroidManifest.FILENAME, self.GetBuildPath())) return tests
def CreateTests(self, sub_tests_path=None): """Create tests found in test_path. Will create a single InstrumentationTestSuite based on info found in AndroidManifest.xml found at build_path. Will set additional filters if test_path refers to a java package or java class. """ tests = [] class_name_arg = None java_package_name = None if sub_tests_path: # if path is java file, populate class name if self._IsJavaFile(sub_tests_path): class_name_arg = self._GetClassNameFromFile(sub_tests_path) logger.SilentLog('Using java test class %s' % class_name_arg) elif self._IsJavaPackage(sub_tests_path): java_package_name = self._GetPackageNameFromDir(sub_tests_path) logger.SilentLog('Using java package %s' % java_package_name) try: manifest_parser = android_manifest.AndroidManifest( app_path=self.GetTestsRootPath()) instrs = manifest_parser.GetInstrumentationNames() if not instrs: logger.Log( 'Could not find instrumentation declarations in %s at %s' % (android_manifest.AndroidManifest.FILENAME, self.GetBuildPath())) return tests for instr_name in manifest_parser.GetInstrumentationNames(): pkg_name = manifest_parser.GetPackageName() if instr_name.find(".") < 0: instr_name = "." + instr_name logger.SilentLog('Found instrumentation %s/%s' % (pkg_name, instr_name)) suite = InstrumentationTestSuite() suite.SetPackageName(pkg_name) suite.SetBuildPath(self.GetBuildPath()) suite.SetRunnerName(instr_name) suite.SetName(pkg_name) suite.SetClassName(class_name_arg) suite.SetJavaPackageFilter(java_package_name) # this is a bit of a hack, assume if 'com.android.cts' is in # package name, this is a cts test # this logic can be removed altogether when cts tests no longer require # custom build steps if suite.GetPackageName().startswith('com.android.cts'): suite.SetSuite('cts') tests.append(suite) return tests except: logger.Log('Could not find or parse %s at %s' % (android_manifest.AndroidManifest.FILENAME, self.GetBuildPath())) return tests
def RunOnce(cmd, timeout_time=None, return_output=True): start_time = time.time() so = [] pid = [] global _abort_on_error error_occurred = False def Run(): if return_output: output_dest = subprocess.PIPE else: # None means direct to stdout output_dest = None pipe = subprocess.Popen(cmd, executable='/bin/bash', stdout=output_dest, stderr=subprocess.STDOUT, shell=True) pid.append(pipe.pid) try: output = pipe.communicate()[0] if output is not None and len(output) > 0: so.append(output) except OSError, e: logger.SilentLog("failed to retrieve stdout from: %s" % cmd) logger.Log(e) so.append("ERROR") error_occurred = True if pipe.returncode < 0: logger.SilentLog("Error: %s was terminated by signal %d" % (cmd, pipe.returncode)) error_occurred = True
def Run(): global error_occurred if return_output: output_dest = subprocess.PIPE else: # None means direct to stdout output_dest = None if stdin_input: stdin_dest = subprocess.PIPE else: stdin_dest = None pipe = subprocess.Popen(cmd, executable='/bin/bash', stdin=stdin_dest, stdout=output_dest, stderr=subprocess.STDOUT, shell=True) pid.append(pipe.pid) try: output = pipe.communicate(input=stdin_input)[0] if output is not None and len(output) > 0: so.append(output) except OSError, e: logger.SilentLog("failed to retrieve stdout from: %s" % cmd) logger.Log(e) so.append("ERROR") error_occurred = True
def _GetTestFactory(self, android_mk_parser, path, build_path): """Get the test factory for given makefile. If given path is a valid tests build path, will return the TestFactory for creating tests. Args: android_mk_parser: the android mk to evaluate path: the filesystem path of the makefile build_path: filesystem path for the directory to build when running tests, relative to source root. Returns: the TestFactory or None if path is not a valid tests build path """ if android_mk_parser.HasGTest(): return gtest.GTestFactory(path, build_path) elif instrumentation_test.HasInstrumentationTest(path): return instrumentation_test.InstrumentationTestFactory(path, build_path) else: # somewhat unusual, but will continue searching logger.SilentLog('Found makefile at %s, but did not detect any tests.' % path) return None
def Run(): """Does coverage operations based on command line args.""" # TODO: do we want to support combining coverage for a single target try: parser = optparse.OptionParser(usage="usage: %prog --combine-coverage") parser.add_option("-c", "--combine-coverage", dest="combine_coverage", default=False, action="store_true", help="Combine coverage results stored given " "android root path") parser.add_option("-t", "--tidy", dest="tidy", default=False, action="store_true", help="Run tidy on all generated html files") options, args = parser.parse_args() coverage = CoverageGenerator(None) if options.combine_coverage: coverage.CombineCoverage() if options.tidy: coverage.TidyOutput() except errors.AbortError: logger.SilentLog("Exiting due to AbortError")
def CreateTests(self, sub_tests_path=None): """Create tests found in sub_tests_path. Looks for test files matching a pattern, and assumes each one is a separate binary on target. Test files must match one of the following pattern: - test_*.[c|cc|cpp] - *_test.[c|cc|cpp] - *_unittest.[c|cc|cpp] """ if not sub_tests_path: sub_tests_path = self.GetTestRootPath() test_file_list = [] if os.path.isfile(sub_tests_path): self._EvaluateFile(test_file_list, os.path.basename(sub_tests_path)) else: os.path.walk(sub_tests_path, self._CollectTestSources, test_file_list) # TODO: obtain this from makefile instead of hardcoding target_root_path = os.path.join('/data', 'nativetest') test_suites = [] for test_file in test_file_list: logger.SilentLog('Creating gtest suite for file %s' % test_file) suite = GTestSuite() suite.SetBuildPath(self.GetBuildPath()) suite.SetTargetExecPath(os.path.join(target_root_path, test_file)) test_suites.append(suite) return test_suites
def _CreateSuitesFromManifest(self, manifest, build_path, class_name=None, java_package_name=None): """Creates TestSuites from a AndroidManifest. Args: manifest: the AndroidManifest build_path: the build path to use for test class_name: optionally, the class filter for the suite java_package_name: optionally, the java package filter for the suite Returns: the list of tests created """ tests = [] for instr_name in manifest.GetInstrumentationNames(): pkg_name = manifest.GetPackageName() logger.SilentLog('Found instrumentation %s/%s' % (pkg_name, instr_name)) suite = instrumentation_test.InstrumentationTestSuite() suite.SetPackageName(pkg_name) suite.SetBuildPath(build_path) suite.SetRunnerName(instr_name) suite.SetName(pkg_name) suite.SetClassName(class_name) suite.SetJavaPackageFilter(java_package_name) # this is a bit of a hack, assume if 'com.android.cts' is in # package name, this is a cts test # this logic can be removed altogether when cts tests no longer require # custom build steps suite.SetCts(suite.GetPackageName().startswith('com.android.cts')) tests.append(suite) return tests
def _DoFullBuild(self, tests, test_requires_permissions): """If necessary, run a full 'make' command for the tests that need it.""" extra_args_set = Set() for test in tests: if test.IsFullMake() and test.IsGrantedPermissions( ) == test_requires_permissions: if test.GetExtraBuildArgs(): # extra args contains the args to pass to 'make' extra_args_set.add(test.GetExtraBuildArgs()) else: logger.Log( "Warning: test %s needs a full build but does not specify" " extra_build_args" % test.GetName()) # check if there is actually any tests that required a full build if extra_args_set: cmd = ('make -j%s %s' % (self._options.make_jobs, ' '.join(list(extra_args_set)))) logger.Log(cmd) if not self._options.preview: old_dir = os.getcwd() os.chdir(self._root_path) output = run_command.RunCommand(cmd, return_output=True) logger.SilentLog(output) os.chdir(old_dir) self._DoInstall(output, test_requires_permissions)
def RunTests(self): """Main entry method - executes the tests according to command line args.""" try: run_command.SetAbortOnError() self._ProcessOptions() if self._options.only_list_tests: self._DumpTests() return if not self._options.skip_build: self._DoBuild() if self._options.build_install_only: logger.Log( "Skipping test execution (due to --build-install-only flag)" ) return for test_suite in self._GetTestsToRun(): try: test_suite.Run(self._options, self._adb) except errors.WaitForResponseTimedOutError: logger.Log("Timed out waiting for response") except KeyboardInterrupt: logger.Log("Exiting...") except errors.AbortError, error: logger.Log(error.msg) logger.SilentLog("Exiting due to AbortError...")
def RunOnce(cmd, timeout_time=None, return_output=True, stdin_input=None): """Spawns a subprocess to run the given shell command. Args: cmd: shell command to run timeout_time: time in seconds to wait for command to run before aborting. return_output: if True return output of command as string. Otherwise, direct output of command to stdout. stdin_input: data to feed to stdin Returns: output of command Raises: errors.WaitForResponseTimedOutError if command did not complete within timeout_time seconds. errors.AbortError is command returned error code and SetAbortOnError is on. """ start_time = time.time() so = [] global _abort_on_error, error_occurred error_occurred = False if return_output: output_dest = tempfile.TemporaryFile(bufsize=0) else: # None means direct to stdout output_dest = None if stdin_input: stdin_dest = subprocess.PIPE else: stdin_dest = None pipe = subprocess.Popen( cmd, executable='/bin/bash', stdin=stdin_dest, stdout=output_dest, stderr=subprocess.STDOUT, shell=True, close_fds=True, preexec_fn=lambda: signal.signal(signal.SIGPIPE, signal.SIG_DFL)) def Run(): global error_occurred try: pipe.communicate(input=stdin_input) output = None if return_output: output_dest.seek(0) output = output_dest.read() output_dest.close() if output is not None and len(output) > 0: so.append(output) except OSError, e: logger.SilentLog("failed to retrieve stdout from: %s" % cmd) logger.Log(e) so.append("ERROR") error_occurred = True if pipe.returncode: logger.SilentLog("Error: %s returned %d error code" % (cmd, pipe.returncode)) error_occurred = True
def _EvaluateFile(self, test_list, file): (name, ext) = os.path.splitext(file) if ext == ".cc" or ext == ".cpp" or ext == ".c": if re.search("_test$|_test_$|_unittest$|_unittest_$|^test_|Tests$", name): logger.SilentLog("Found native test file %s" % file) test_list.append(name)
def _DoBuild(self): logger.SilentLog("Building tests...") tests = self._GetTestsToRun() # Build and install tests that do not get granted permissions self._DoPermissionAwareBuild(tests, False) # Build and install tests that require granted permissions self._DoPermissionAwareBuild(tests, True)
def _DoBuild(self): logger.SilentLog("Building tests...") tests = self._GetTestsToRun() # turn off dalvik verifier if necessary self._TurnOffVerifier(tests) self._DoFullBuild(tests) target_set = [] extra_args_set = [] for test_suite in tests: self._AddBuildTarget(test_suite, target_set, extra_args_set) if not self._options.preview: self._adb.EnableAdbRoot() else: logger.Log("adb root") rebuild_libcore = False if target_set: if self._options.coverage: coverage.EnableCoverageBuild() # hack to remove core library intermediates # hack is needed because: # 1. EMMA_INSTRUMENT changes what source files to include in libcore # but it does not trigger a rebuild # 2. there's no target (like "clear-intermediates") to remove the files # decently rebuild_libcore = not coverage.TestDeviceCoverageSupport(self._adb) if rebuild_libcore: cmd = "rm -rf %s" % os.path.join( self._root_path, "out/target/common/obj/JAVA_LIBRARIES/core_intermediates/") logger.Log(cmd) run_command.RunCommand(cmd, return_output=False) target_build_string = " ".join(target_set) extra_args_string = " ".join(extra_args_set) # mmm cannot be used from python, so perform a similar operation using # ONE_SHOT_MAKEFILE cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" all_modules %s' % ( target_build_string, self._options.make_jobs, self._root_path, extra_args_string) logger.Log(cmd) if self._options.preview: # in preview mode, just display to the user what command would have been # run logger.Log("adb sync") else: # set timeout for build to 10 minutes, since libcore may need to # be rebuilt run_command.RunCommand(cmd, return_output=False, timeout_time=600) logger.Log("Syncing to device...") self._adb.Sync(runtime_restart=rebuild_libcore)
def FindTests(self, path): """Gets list of Android tests found at given path. Tests are created from info found in Android.mk and AndroidManifest.xml files relative to the given path. Currently supported tests are: - Android application tests run via instrumentation - native C/C++ tests using GTest framework. (note Android.mk must follow expected GTest template) FindTests will first scan sub-folders of path for tests. If none are found, it will scan the file system upwards until a valid test Android.mk is found or the Android build root is reached. Some sample values for path: - a parent directory containing many tests: ie development/samples will return tests for instrumentation's in ApiDemos, ApiDemos/tests, Notepad/tests etc - a java test class file ie ApiDemos/tests/src/../ApiDemosTest.java will return a test for the instrumentation in ApiDemos/tests, with the class name filter set to ApiDemosTest - a java package directory ie ApiDemos/tests/src/com/example/android/apis will return a test for the instrumentation in ApiDemos/tests, with the java package filter set to com.example.android.apis. TODO: add GTest examples Args: path: file system path to search Returns: list of test suites that support operations defined by test_suite.AbstractTestSuite """ if not os.path.exists(path): logger.Log('%s does not exist' % path) return [] realpath = os.path.realpath(path) # ensure path is in ANDROID_BUILD_ROOT self._build_top = os.path.realpath(android_build.GetTop()) if not self._IsPathInBuildTree(realpath): logger.Log('%s is not a sub-directory of build root %s' % (path, self._build_top)) return [] # first, assume path is a parent directory, which specifies to run all # tests within this directory tests = self._FindSubTests(realpath, []) if not tests: logger.SilentLog('No tests found within %s, searching upwards' % path) tests = self._FindUpstreamTests(realpath) return tests
def _DoBuild(self): logger.SilentLog("Building tests...") tests = self._GetTestsToRun() # turn off dalvik verifier if necessary self._TurnOffVerifier(tests) self._DoFullBuild(tests) target_tree = make_tree.MakeTree() extra_args_set = [] for test_suite in tests: self._AddBuildTarget(test_suite, target_tree, extra_args_set) if not self._options.preview: self._adb.EnableAdbRoot() else: logger.Log("adb root") if not target_tree.IsEmpty(): if self._options.coverage: coverage.EnableCoverageBuild() target_tree.AddPath("external/emma") target_list = target_tree.GetPrunedMakeList() target_build_string = " ".join(target_list) extra_args_string = " ".join(extra_args_set) # mmm cannot be used from python, so perform a similar operation using # ONE_SHOT_MAKEFILE cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" GET-INSTALL-PATH all_modules %s' % ( target_build_string, self._options.make_jobs, self._root_path, extra_args_string) logger.Log(cmd) if not self._options.preview: output = run_command.RunCommand(cmd, return_output=True, timeout_time=600) logger.SilentLog(output) self._DoInstall(output)
def Run(): global error_occurred try: pipe.communicate(input=stdin_input) output = None if return_output: output_dest.seek(0) output = output_dest.read() output_dest.close() if output is not None and len(output) > 0: so.append(output) except OSError, e: logger.SilentLog("failed to retrieve stdout from: %s" % cmd) logger.Log(e) so.append("ERROR") error_occurred = True
def __RecursiveGetVariable(self, identifier, visited_variables): variable_value = self.GetVariable(identifier) if not variable_value: return None if variable_value in visited_variables: raise RuntimeError('recursive loop found for makefile variable %s' % variable_value) m = self._RE_VARIABLE_REF.match(variable_value) if m: logger.SilentLog('Found variable ref %s for identifier %s' % (variable_value, identifier)) variable_ref = m.group(1) visited_variables.add(variable_ref) return self.__RecursiveGetVariable(variable_ref, visited_variables) else: return variable_value
def _GetPackageNameFromFile(self, java_file_path): """Gets the java package name associated with given java file path. Args: java_file_path: file system path of java file Returns: the java package name or None """ logger.SilentLog('Looking for java package name in %s' % java_file_path) re_package = re.compile(r'package\s+(.*);') file_handle = open(java_file_path, 'r') for line in file_handle: match = re_package.match(line) if match: return match.group(1) return None
def SendCommand(self, command_string, timeout_time=60, retry_count=3): """Send a command via adb. Args: command_string: adb command to run timeout_time: number of seconds to wait for command to respond before retrying retry_count: number of times to retry command before raising WaitForResponseTimedOutError Returns: string output of command Raises: WaitForResponseTimedOutError if device does not respond to command within time """ adb_cmd = "adb %s %s" % (self._target_arg, command_string) logger.SilentLog("about to run %s" % adb_cmd) return run_command.RunCommand(adb_cmd, timeout_time=timeout_time, retry_count=retry_count)
def _DoBuild(self): logger.SilentLog("Building tests...") target_set = Set() extra_args_set = Set() tests = self._GetTestsToRun() for test_suite in tests: self._AddBuildTarget(test_suite, target_set, extra_args_set) if target_set: if self._options.coverage: coverage.EnableCoverageBuild() # hack to build cts dependencies # TODO: remove this when build dependency support added to runtest or # cts dependencies are removed if self._IsCtsTests(tests): # need to use make since these fail building with ONE_SHOT_MAKEFILE cmd = ('make -j%s CtsTestStubs android.core.tests.runner' % self._options.make_jobs) logger.Log(cmd) if not self._options.preview: old_dir = os.getcwd() os.chdir(self._root_path) run_command.RunCommand(cmd, return_output=False) os.chdir(old_dir) target_build_string = " ".join(list(target_set)) extra_args_string = " ".join(list(extra_args_set)) # mmm cannot be used from python, so perform a similar operation using # ONE_SHOT_MAKEFILE cmd = 'ONE_SHOT_MAKEFILE="%s" make -j%s -C "%s" files %s' % ( target_build_string, self._options.make_jobs, self._root_path, extra_args_string) logger.Log(cmd) if self._options.preview: # in preview mode, just display to the user what command would have been # run logger.Log("adb sync") else: run_command.RunCommand(cmd, return_output=False) logger.Log("Syncing to device...") self._adb.Sync()
def RunTests(self): """Main entry method - executes the tests according to command line args.""" try: run_command.SetAbortOnError() self._ProcessOptions() if self._options.only_list_tests: self._DumpTests() return if not self._options.skip_build: self._DoBuild() for test_suite in self._GetTestsToRun(): test_suite.Run(self._options, self._adb) except KeyboardInterrupt: logger.Log("Exiting...") except errors.AbortError, error: logger.Log(error.msg) logger.SilentLog("Exiting due to AbortError...")
def _CollectTestSources(self, test_list, dirname, files): """For each directory, find tests source file and add them to the list. Test files must match one of the following pattern: - test_*.[cc|cpp] - *_test.[cc|cpp] - *_unittest.[cc|cpp] This method is a callback for os.path.walk. Args: test_list: Where new tests should be inserted. dirname: Current directory. files: List of files in the current directory. """ for f in files: (name, ext) = os.path.splitext(f) if ext == ".cc" or ext == ".cpp" or ext == ".c": if re.search("_test$|_test_$|_unittest$|_unittest_$|^test_", name): logger.SilentLog("Found %s" % f) test_list.append(str(os.path.join(dirname, f)))
def _DoFullBuild(self, tests): """If necessary, run a full 'make' command for the tests that need it.""" extra_args_set = Set() # hack to build cts dependencies # TODO: remove this when cts dependencies are removed is_cts = self._IsCtsTests(tests) if is_cts: # need to use make since these fail building with ONE_SHOT_MAKEFILE extra_args_set.add('CtsTestStubs') extra_args_set.add('android.core.tests.runner') for test in tests: if test.IsFullMake(): if test.GetExtraBuildArgs(): # extra args contains the args to pass to 'make' extra_args_set.add(test.GetExtraBuildArgs()) else: logger.Log( "Warning: test %s needs a full build but does not specify" " extra_build_args" % test.GetName()) # check if there is actually any tests that required a full build if extra_args_set: cmd = ('make -j%s %s' % (self._options.make_jobs, ' '.join(list(extra_args_set)))) logger.Log(cmd) if not self._options.preview: old_dir = os.getcwd() os.chdir(self._root_path) output = run_command.RunCommand(cmd, return_output=True) logger.SilentLog(output) os.chdir(old_dir) self._DoInstall(output) if is_cts: # hack! hardcode install of CtsTestStubs out = android_build.GetTestAppPath() abs_install_path = os.path.join(out, "CtsTestStubs.apk") logger.Log("adb install -r %s" % abs_install_path) logger.Log(self._adb.Install(abs_install_path))
def _DoBuild(self): logger.SilentLog("Building tests...") target_set = Set() for test_suite in self._GetTestsToRun(): self._AddBuildTarget(test_suite.GetBuildPath(), target_set) if target_set: if self._options.coverage: self._coverage_gen.EnableCoverageBuild() self._AddBuildTarget(self._coverage_gen.GetEmmaBuildPath(), target_set) target_build_string = " ".join(list(target_set)) logger.Log("mmm %s" % target_build_string) cmd = 'ONE_SHOT_MAKEFILE="%s" make -C "%s" files' % ( target_build_string, self._root_path) if self._options.preview: # in preview mode, just display to the user what command would have been # run logger.Log("adb sync") else: run_command.RunCommand(cmd, return_output=False) logger.Log("Syncing to device...") self._adb.Sync()
def RunTests(self): """Main entry method - executes the tests according to command line args.""" try: run_command.SetAbortOnError() self._ProcessOptions() if self._options.only_list_tests: self._DumpTests() return if not self._adb.IsDevicePresent(): logger.Log("Error: specified device cannot be found") return if not self._options.skip_build: self._DoBuild() for test_suite in self._GetTestsToRun(): self._RunTest(test_suite) except KeyboardInterrupt: logger.Log("Exiting...") except errors.AbortError: logger.SilentLog("Exiting due to AbortError...") except errors.WaitForResponseTimedOutError: logger.Log("Timed out waiting for response")
error = None if runtime_restart: self.SendShellCommand("setprop ro.test_harness 1", retry_count=retry_count) # manual rest bootcomplete flag self.SendShellCommand("setprop dev.bootcomplete 0", retry_count=retry_count) self.SendShellCommand("stop", retry_count=retry_count) try: output = self.SendCommand("sync", retry_count=retry_count) except errors.AbortError, e: error = e output = e.msg if "Read-only file system" in output: logger.SilentLog(output) logger.Log("Remounting read-only filesystem") self.SendCommand("remount") output = self.SendCommand("sync", retry_count=retry_count) elif "No space left on device" in output: logger.SilentLog(output) logger.Log("Restarting device runtime") self.SendShellCommand("stop", retry_count=retry_count) output = self.SendCommand("sync", retry_count=retry_count) self.SendShellCommand("start", retry_count=retry_count) elif error is not None: # exception occurred that cannot be recovered from raise error logger.SilentLog(output) if runtime_restart: # start runtime and wait till boot complete flag is set
def _ProcessOptions(self): """Processes command-line options.""" # TODO error messages on once-only or mutually-exclusive options. user_test_default = os.path.join(os.environ.get("HOME"), ".android", self._TEST_FILE_NAME) parser = optparse.OptionParser(usage=self._RUNTEST_USAGE) parser.add_option("-l", "--list-tests", dest="only_list_tests", default=False, action="store_true", help="To view the list of tests") parser.add_option("-b", "--skip-build", dest="skip_build", default=False, action="store_true", help="Skip build - just launch") parser.add_option("-j", "--jobs", dest="make_jobs", metavar="X", default=self._DEFAULT_JOBS, help="Number of make jobs to use when building") parser.add_option("-n", "--skip_execute", dest="preview", default=False, action="store_true", help="Do not execute, just preview commands") parser.add_option( "-i", "--build-install-only", dest="build_install_only", default=False, action="store_true", help="Do not execute, build tests and install to device only") parser.add_option("-r", "--raw-mode", dest="raw_mode", default=False, action="store_true", help="Raw mode (for output to other tools)") parser.add_option("-a", "--suite-assign", dest="suite_assign_mode", default=False, action="store_true", help="Suite assignment (for details & usage see " "InstrumentationTestRunner)") parser.add_option("-v", "--verbose", dest="verbose", default=False, action="store_true", help="Increase verbosity of %s" % sys.argv[0]) parser.add_option("-w", "--wait-for-debugger", dest="wait_for_debugger", default=False, action="store_true", help="Wait for debugger before launching tests") parser.add_option("-c", "--test-class", dest="test_class", help="Restrict test to a specific class") parser.add_option("-m", "--test-method", dest="test_method", help="Restrict test to a specific method") parser.add_option("-p", "--test-package", dest="test_package", help="Restrict test to a specific java package") parser.add_option("-z", "--size", dest="test_size", help="Restrict test to a specific test size") parser.add_option( "--annotation", dest="test_annotation", help="Include only those tests tagged with a specific" " annotation") parser.add_option("--not-annotation", dest="test_not_annotation", help="Exclude any tests tagged with a specific" " annotation") parser.add_option("-u", "--user-tests-file", dest="user_tests_file", metavar="FILE", default=user_test_default, help="Alternate source of user test definitions") parser.add_option("-o", "--coverage", dest="coverage", default=False, action="store_true", help="Generate code coverage metrics for test(s)") parser.add_option( "--coverage-target", dest="coverage_target_path", default=None, help="Path to app to collect code coverage target data for.") parser.add_option( "-k", "--skip-permissions", dest="skip_permissions", default=False, action="store_true", help="Do not grant runtime permissions during test package" " installation.") parser.add_option("-x", "--path", dest="test_path", help="Run test(s) at given file system path") parser.add_option("-t", "--all-tests", dest="all_tests", default=False, action="store_true", help="Run all defined tests") parser.add_option( "--continuous", dest="continuous_tests", default=False, action="store_true", help="Run all tests defined as part of the continuous " "test set") parser.add_option( "--timeout", dest="timeout", default=300, help="Set a timeout limit (in sec) for " "running native tests on a device (default: 300 secs)") parser.add_option("--suite", dest="suite", help="Run all tests defined as part of the " "the given test suite") group = optparse.OptionGroup( parser, "Targets", "Use these options to direct tests to a specific " "Android target") group.add_option("-e", "--emulator", dest="emulator", default=False, action="store_true", help="use emulator") group.add_option("-d", "--device", dest="device", default=False, action="store_true", help="use device") group.add_option("-s", "--serial", dest="serial", help="use specific serial") parser.add_option_group(group) self._options, self._test_args = parser.parse_args() if (not self._options.only_list_tests and not self._options.all_tests and not self._options.continuous_tests and not self._options.suite and not self._options.test_path and len(self._test_args) < 1): parser.print_help() logger.SilentLog("at least one test name must be specified") raise errors.AbortError self._adb = adb_interface.AdbInterface() if self._options.emulator: self._adb.SetEmulatorTarget() elif self._options.device: self._adb.SetDeviceTarget() elif self._options.serial is not None: self._adb.SetTargetSerial(self._options.serial) if self._options.verbose: logger.SetVerbose(True) if self._options.coverage_target_path: self._options.coverage = True self._known_tests = self._ReadTests() self._options.host_lib_path = android_build.GetHostLibraryPath() self._options.test_data_path = android_build.GetTestAppPath()