def SetUp(self): available_devices = device_utils.DeviceUtils.HealthyDevices( self._blacklist, enable_device_files_cache=self._enable_device_cache) if not available_devices: raise device_errors.NoDevicesError if self._device_serial: self._devices = [d for d in available_devices if d.adb.GetDeviceSerial() == self._device_serial] if not self._devices: raise device_errors.DeviceUnreachableError( 'Could not find device %r' % self._device_serial) else: self._devices = available_devices if self._enable_device_cache: for d in self._devices: cache_path = _DeviceCachePath(d) if os.path.exists(cache_path): logging.info('Using device cache: %s', cache_path) with open(cache_path) as f: d.LoadCacheData(f.read()) os.unlink(cache_path) if self._logcat_output_dir: for d in self._devices: logcat_file = os.path.join( self._logcat_output_dir, '%s_%s' % (d.adb.GetDeviceSerial(), datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S'))) monitor = logcat_monitor.LogcatMonitor( d.adb, clear=True, output_file=logcat_file) self._logcat_monitors.append(monitor) monitor.Start()
def _ArchiveLogcat(self, device, test): if isinstance(test, str): desc = test else: desc = hash(tuple(test)) stream_name = 'logcat_%s_%s_%s' % ( desc, time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) logcat_file = None logmon = None try: with self._env.output_manager.ArchivedTempfile( stream_name, 'logcat') as logcat_file: with logcat_monitor.LogcatMonitor( device.adb, filter_specs=local_device_environment.LOGCAT_FILTERS, output_file=logcat_file.name, check_error=False) as logmon: with contextlib_ext.Optional(trace_event.trace(str(test)), self._env.trace_output): yield logcat_file finally: if logmon: logmon.Close() if logcat_file and logcat_file.Link(): logging.info('Logcat saved to %s', logcat_file.Link())
def _ArchiveLogcat(self, device, test_name): stream_name = 'logcat_%s_%s_%s' % ( test_name.replace('#', '.'), time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) logcat_file = None logmon = None try: with self._env.output_manager.ArchivedTempfile( stream_name, 'logcat') as logcat_file: with logcat_monitor.LogcatMonitor( device.adb, filter_specs=local_device_environment.LOGCAT_FILTERS, output_file=logcat_file.name, transform_func=self._test_instance.MaybeDeobfuscateLines, check_error=False) as logmon: with _LogTestEndpoints(device, test_name): with contextlib_ext.Optional( trace_event.trace(test_name), self._env.trace_output): yield logcat_file finally: if logmon: logmon.Close() if logcat_file and logcat_file.Link(): logging.info('Logcat saved to %s', logcat_file.Link())
def SetUpProcess(cls): """Prepares the test device""" super(WebViewCrxSmokeTests, cls).SetUpProcess() assert cls._finder_options.crx_file, '--crx-file is required' assert cls._finder_options.component_name, '--component-name is required' cls.SetBrowserOptions(cls._finder_options) webview_package_name = cls._finder_options.webview_package_name if not webview_package_name: webview_provider_apk = (cls._browser_to_create .settings.GetApkName(cls._device)) webview_apk_path = util.FindLatestApkOnHost( cls._finder_options.chrome_root, webview_provider_apk) webview_package_name = apk_helper.GetPackageName(webview_apk_path) cls._device_components_dir = ('/data/data/%s/app_webview/components' % webview_package_name) logcat_output_dir = ( os.path.dirname(cls._typ_runner.args.write_full_results_to or '') or os.getcwd()) # Set up a logcat monitor cls._logcat_monitor = logcat_monitor.LogcatMonitor( cls._device.adb, output_file=os.path.join(logcat_output_dir, '%s_logcat.txt' % cls.Name()), filter_specs=_LOGCAT_FILTERS) cls._logcat_monitor.Start() cls._MaybeClearOutComponentsDir() component_id = _COMPONENT_NAME_TO_DATA.get( cls._finder_options.component_name).component_id with zipfile.ZipFile(cls._finder_options.crx_file) as crx_archive, \ NamedTemporaryDirectory() as tmp_dir, \ crx_archive.open('manifest.json') as manifest: crx_device_dir = posixpath.join( cls._device_components_dir, 'cps', component_id, '1_%s' % json.loads(manifest.read())['version']) try: # Create directory on the test device for the CRX files logger.info('Creating directory %r on device' % crx_device_dir) output = cls._device.RunShellCommand( ['mkdir', '-p', crx_device_dir]) logger.debug('Recieved the following output from adb: %s' % output) except Exception as e: logger.exception('Exception %r was raised' % str(e)) raise # Move CRX files to the device directory crx_archive.extractall(tmp_dir) cls._MoveNewCrxToDevice(tmp_dir, crx_device_dir) # Start the browser after the device is in a clean state and the CRX # files are loaded onto the device cls.StartBrowser()
def SetUp(self): device_arg = 'default' if self._target_devices_file: device_arg = device_list.GetPersistentDeviceList( self._target_devices_file) if not device_arg: logging.warning('No target devices specified. Falling back to ' 'running on all available devices.') device_arg = 'default' else: logging.info('Read device list %s from target devices file.', str(device_arg)) elif self._device_serial: device_arg = self._device_serial self._devices = device_utils.DeviceUtils.HealthyDevices( self._blacklist, enable_device_files_cache=self._enable_device_cache, default_retries=self._max_tries - 1, device_arg=device_arg) if not self._devices: raise device_errors.NoDevicesError if self._enable_device_cache: for d in self._devices: cache_path = _DeviceCachePath(d) if os.path.exists(cache_path): logging.info('Using device cache: %s', cache_path) with open(cache_path) as f: d.LoadCacheData(f.read()) # Delete cached file so that any exceptions cause it to be cleared. os.unlink(cache_path) if self._logcat_output_file: self._logcat_output_dir = tempfile.mkdtemp() if self._logcat_output_dir: for d in self._devices: logcat_file = os.path.join( self._logcat_output_dir, '%s_%s' % (d.adb.GetDeviceSerial(), datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S'))) monitor = logcat_monitor.LogcatMonitor(d.adb, clear=True, output_file=logcat_file) self._logcat_monitors.append(monitor) monitor.Start()
def prepare_device(d): if self._enable_device_cache: cache_path = _DeviceCachePath(d) if os.path.exists(cache_path): logging.info('Using device cache: %s', cache_path) with open(cache_path) as f: d.LoadCacheData(f.read()) # Delete cached file so that any exceptions cause it to be cleared. os.unlink(cache_path) if self._logcat_output_dir: logcat_file = os.path.join( self._logcat_output_dir, '%s_%s' % (d.adb.GetDeviceSerial(), datetime.datetime.utcnow().strftime('%Y%m%dT%H%M%S'))) monitor = logcat_monitor.LogcatMonitor( d.adb, clear=True, output_file=logcat_file) self._logcat_monitors.append(monitor) monitor.Start()
def testWaitFor_buffering(self): # Simulate an adb log stream which does not complete until the test tells it # to. This checks that the log matcher can receive individual lines from the # log reader thread even if adb is not producing enough output to fill an # entire file io buffer. finished_lock = threading.Lock() finished_lock.acquire() def LogGenerator(): for line in type(self)._TEST_THREADTIME_LOGCAT_DATA: yield line finished_lock.acquire() test_adb = adb_wrapper.AdbWrapper('0123456789abcdef') test_adb.Logcat = mock.Mock(return_value=LogGenerator()) test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False) test_log.Start() actual_match = test_log.WaitFor(r'.*last line.*', None) finished_lock.release() self.assertTrue(actual_match) test_log.Stop() test_log.Close()
def _CreateTestLog(raw_logcat=None): test_adb = adb_wrapper.AdbWrapper('0123456789abcdef') test_adb.Logcat = mock.Mock(return_value=(l for l in raw_logcat)) test_log = logcat_monitor.LogcatMonitor(test_adb, clear=False) return test_log
def _RunTest(self, device, test): extras = {} # Provide package name under test for apk_under_test. if self._test_instance.apk_under_test: package_name = self._test_instance.apk_under_test.GetPackageName() extras[_EXTRA_PACKAGE_UNDER_TEST] = package_name flags_to_add = [] test_timeout_scale = None if self._test_instance.coverage_directory: coverage_basename = '%s.exec' % ( '%s_%s_group' % (test[0]['class'], test[0]['method']) if isinstance( test, list) else '%s_%s' % (test['class'], test['method'])) extras['coverage'] = 'true' coverage_directory = os.path.join(device.GetExternalStoragePath(), 'chrome', 'test', 'coverage') if not device.PathExists(coverage_directory): device.RunShellCommand(['mkdir', '-p', coverage_directory], check_return=True) coverage_device_file = os.path.join(coverage_directory, coverage_basename) extras['coverageFile'] = coverage_device_file # Save screenshot if screenshot dir is specified (save locally) or if # a GS bucket is passed (save in cloud). screenshot_device_file = device_temp_file.DeviceTempFile( device.adb, suffix='.png', dir=device.GetExternalStoragePath()) extras[EXTRA_SCREENSHOT_FILE] = screenshot_device_file.name # Set up the screenshot directory. This needs to be done for each test so # that we only get screenshots created by that test. It has to be on # external storage since the default location doesn't allow file creation # from the instrumentation test app on Android L and M. ui_capture_dir = device_temp_file.NamedDeviceTemporaryDirectory( device.adb, dir=device.GetExternalStoragePath()) extras[EXTRA_UI_CAPTURE_DIR] = ui_capture_dir.name if self._env.trace_output: trace_device_file = device_temp_file.DeviceTempFile( device.adb, suffix='.json', dir=device.GetExternalStoragePath()) extras[EXTRA_TRACE_FILE] = trace_device_file.name if isinstance(test, list): if not self._test_instance.driver_apk: raise Exception('driver_apk does not exist. ' 'Please build it and try again.') if any(t.get('is_junit4') for t in test): raise Exception('driver apk does not support JUnit4 tests') def name_and_timeout(t): n = instrumentation_test_instance.GetTestName(t) i = self._GetTimeoutFromAnnotations(t['annotations'], n) return (n, i) test_names, timeouts = zip(*(name_and_timeout(t) for t in test)) test_name = ','.join(test_names) test_display_name = test_name target = '%s/%s' % (self._test_instance.driver_package, self._test_instance.driver_name) extras.update( self._test_instance.GetDriverEnvironmentVars( test_list=test_names)) timeout = sum(timeouts) else: test_name = instrumentation_test_instance.GetTestName(test) test_display_name = self._GetUniqueTestName(test) if test['is_junit4']: target = '%s/%s' % (self._test_instance.test_package, self._test_instance.junit4_runner_class) else: target = '%s/%s' % (self._test_instance.test_package, self._test_instance.junit3_runner_class) extras['class'] = test_name if 'flags' in test and test['flags']: flags_to_add.extend(test['flags']) timeout = self._GetTimeoutFromAnnotations(test['annotations'], test_display_name) test_timeout_scale = self._GetTimeoutScaleFromAnnotations( test['annotations']) if test_timeout_scale and test_timeout_scale != 1: valgrind_tools.SetChromeTimeoutScale( device, test_timeout_scale * self._test_instance.timeout_scale) if self._test_instance.wait_for_java_debugger: timeout = None logging.info('preparing to run %s: %s', test_display_name, test) render_tests_device_output_dir = None if _IsRenderTest(test): # TODO(mikecase): Add DeviceTempDirectory class and use that instead. render_tests_device_output_dir = posixpath.join( device.GetExternalStoragePath(), 'render_test_output_dir') flags_to_add.append('--render-test-output-dir=%s' % render_tests_device_output_dir) if flags_to_add: self._CreateFlagChangerIfNeeded(device) self._flag_changers[str(device)].PushFlags(add=flags_to_add) time_ms = lambda: int(time.time() * 1e3) start_ms = time_ms() stream_name = 'logcat_%s_%s_%s' % (test_name.replace( '#', '.'), time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) with ui_capture_dir: with self._env.output_manager.ArchivedTempfile( stream_name, 'logcat') as logcat_file: try: with logcat_monitor.LogcatMonitor( device.adb, filter_specs=local_device_environment. LOGCAT_FILTERS, output_file=logcat_file.name, transform_func=self._test_instance. MaybeDeobfuscateLines, check_error=False) as logmon: with _LogTestEndpoints(device, test_name): with contextlib_ext.Optional( trace_event.trace(test_name), self._env.trace_output): output = device.StartInstrumentation( target, raw=True, extras=extras, timeout=timeout, retries=0) finally: logmon.Close() if logcat_file.Link(): logging.info('Logcat saved to %s', logcat_file.Link()) duration_ms = time_ms() - start_ms with contextlib_ext.Optional(trace_event.trace('ProcessResults'), self._env.trace_output): output = self._test_instance.MaybeDeobfuscateLines(output) # TODO(jbudorick): Make instrumentation tests output a JSON so this # doesn't have to parse the output. result_code, result_bundle, statuses = ( self._test_instance.ParseAmInstrumentRawOutput(output)) results = self._test_instance.GenerateTestResults( result_code, result_bundle, statuses, start_ms, duration_ms, device.product_cpu_abi, self._test_instance.symbolizer) if self._env.trace_output: self._SaveTraceData(trace_device_file, device, test['class']) def restore_flags(): if flags_to_add: self._flag_changers[str(device)].Restore() def restore_timeout_scale(): if test_timeout_scale: valgrind_tools.SetChromeTimeoutScale( device, self._test_instance.timeout_scale) def handle_coverage_data(): if self._test_instance.coverage_directory: try: if not os.path.exists( self._test_instance.coverage_directory): os.makedirs(self._test_instance.coverage_directory) device.PullFile(coverage_device_file, self._test_instance.coverage_directory) device.RemovePath(coverage_device_file, True) except (OSError, base_error.BaseError) as e: logging.warning( 'Failed to handle coverage data after tests: %s', e) def handle_render_test_data(): if _IsRenderTest(test): # Render tests do not cause test failure by default. So we have to # check to see if any failure images were generated even if the test # does not fail. try: self._ProcessRenderTestResults( device, render_tests_device_output_dir, results) finally: device.RemovePath(render_tests_device_output_dir, recursive=True, force=True) def pull_ui_screen_captures(): screenshots = [] for filename in device.ListDirectory(ui_capture_dir.name): if filename.endswith('.json'): screenshots.append(pull_ui_screenshot(filename)) if screenshots: json_archive_name = 'ui_capture_%s_%s.json' % ( test_name.replace('#', '.'), time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime())) with self._env.output_manager.ArchivedTempfile( json_archive_name, 'ui_capture', output_manager.Datatype.JSON) as json_archive: json.dump(screenshots, json_archive) for result in results: result.SetLink('ui screenshot', json_archive.Link()) def pull_ui_screenshot(filename): source_dir = ui_capture_dir.name json_path = posixpath.join(source_dir, filename) json_data = json.loads(device.ReadFile(json_path)) image_file_path = posixpath.join(source_dir, json_data['location']) with self._env.output_manager.ArchivedTempfile( json_data['location'], 'ui_capture', output_manager.Datatype.PNG) as image_archive: device.PullFile(image_file_path, image_archive.name) json_data['image_link'] = image_archive.Link() return json_data # While constructing the TestResult objects, we can parallelize several # steps that involve ADB. These steps should NOT depend on any info in # the results! Things such as whether the test CRASHED have not yet been # determined. post_test_steps = [ restore_flags, restore_timeout_scale, handle_coverage_data, handle_render_test_data, pull_ui_screen_captures ] if self._env.concurrent_adb: post_test_step_thread_group = reraiser_thread.ReraiserThreadGroup( reraiser_thread.ReraiserThread(f) for f in post_test_steps) post_test_step_thread_group.StartAll(will_block=True) else: for step in post_test_steps: step() for result in results: if logcat_file: result.SetLink('logcat', logcat_file.Link()) # Update the result name if the test used flags. if flags_to_add: for r in results: if r.GetName() == test_name: r.SetName(test_display_name) # Add UNKNOWN results for any missing tests. iterable_test = test if isinstance(test, list) else [test] test_names = set(self._GetUniqueTestName(t) for t in iterable_test) results_names = set(r.GetName() for r in results) results.extend( base_test_result.BaseTestResult( u, base_test_result.ResultType.UNKNOWN) for u in test_names.difference(results_names)) # Update the result type if we detect a crash. try: if DidPackageCrashOnDevice(self._test_instance.test_package, device): for r in results: if r.GetType() == base_test_result.ResultType.UNKNOWN: r.SetType(base_test_result.ResultType.CRASH) except device_errors.CommandTimeoutError: logging.warning( 'timed out when detecting/dismissing error dialogs') # Attach screenshot to the test to help with debugging the dialog boxes. self._SaveScreenshot(device, screenshot_device_file, test_display_name, results, 'dialog_box_screenshot') # Handle failures by: # - optionally taking a screenshot # - logging the raw output at INFO level # - clearing the application state while persisting permissions if any(r.GetType() not in (base_test_result.ResultType.PASS, base_test_result.ResultType.SKIP) for r in results): self._SaveScreenshot(device, screenshot_device_file, test_display_name, results, 'post_test_screenshot') logging.info('detected failure in %s. raw output:', test_display_name) for l in output: logging.info(' %s', l) if (not self._env.skip_clear_data and self._test_instance.package_info): permissions = ( self._test_instance.apk_under_test.GetPermissions() if self._test_instance.apk_under_test else None) device.ClearApplicationState( self._test_instance.package_info.package, permissions=permissions) else: logging.debug('raw output from %s:', test_display_name) for l in output: logging.debug(' %s', l) if self._test_instance.store_tombstones: tombstones_url = None for result in results: if result.GetType() == base_test_result.ResultType.CRASH: if not tombstones_url: resolved_tombstones = tombstones.ResolveTombstones( device, resolve_all_tombstones=True, include_stack_symbols=False, wipe_tombstones=True, tombstone_symbolizer=self._test_instance.symbolizer ) tombstone_filename = 'tombstones_%s_%s' % ( time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) with self._env.output_manager.ArchivedTempfile( tombstone_filename, 'tombstones') as tombstone_file: tombstone_file.write( '\n'.join(resolved_tombstones)) result.SetLink('tombstones', tombstone_file.Link()) if self._env.concurrent_adb: post_test_step_thread_group.JoinAll() return results, None
def _RunTest(self, device, test): # Run the test. timeout = (self._test_instance.shard_timeout * self.GetTool(device).GetTimeoutScale()) if self._test_instance.wait_for_java_debugger: timeout = None if self._test_instance.store_tombstones: tombstones.ClearAllTombstones(device) test_perf_output_filename = next(self._test_perf_output_filenames) with device_temp_file.DeviceTempFile( adb=device.adb, dir=self._delegate.ResultsDirectory(device), suffix='.xml') as device_tmp_results_file: with contextlib_ext.Optional( device_temp_file.NamedDeviceTemporaryDirectory( adb=device.adb, dir='/sdcard/'), self._test_instance. gs_test_artifacts_bucket) as test_artifacts_dir: with (contextlib_ext.Optional( device_temp_file.DeviceTempFile( adb=device.adb, dir=self._delegate.ResultsDirectory(device)), test_perf_output_filename) ) as isolated_script_test_perf_output: flags = list(self._test_instance.flags) if self._test_instance.enable_xml_result_parsing: flags.append('--gtest_output=xml:%s' % device_tmp_results_file.name) if self._test_instance.gs_test_artifacts_bucket: flags.append('--test_artifacts_dir=%s' % test_artifacts_dir.name) if test_perf_output_filename: flags.append('--isolated_script_test_perf_output=%s' % isolated_script_test_perf_output.name) logging.info('flags:') for f in flags: logging.info(' %s', f) stream_name = 'logcat_%s_%s_%s' % ( hash(tuple(test)), time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), device.serial) with self._env.output_manager.ArchivedTempfile( stream_name, 'logcat') as logcat_file: with logcat_monitor.LogcatMonitor( device.adb, filter_specs=local_device_environment. LOGCAT_FILTERS, output_file=logcat_file.name, check_error=False) as logmon: with contextlib_ext.Optional( trace_event.trace(str(test)), self._env.trace_output): output = self._delegate.Run( test, device, flags=' '.join(flags), timeout=timeout, retries=0) logmon.Close() if logcat_file.Link(): logging.info('Logcat saved to %s', logcat_file.Link()) if self._test_instance.enable_xml_result_parsing: try: gtest_xml = device.ReadFile( device_tmp_results_file.name, as_root=True) except device_errors.CommandFailedError as e: logging.warning( 'Failed to pull gtest results XML file %s: %s', device_tmp_results_file.name, str(e)) gtest_xml = None if test_perf_output_filename: try: device.PullFile( isolated_script_test_perf_output.name, test_perf_output_filename) except device_errors.CommandFailedError as e: logging.warning( 'Failed to pull chartjson results %s: %s', isolated_script_test_perf_output.name, str(e)) test_artifacts_url = self._UploadTestArtifacts( device, test_artifacts_dir) for s in self._servers[str(device)]: s.Reset() if self._test_instance.app_files: self._delegate.PullAppFiles(device, self._test_instance.app_files, self._test_instance.app_file_dir) if not self._env.skip_clear_data: self._delegate.Clear(device) for l in output: logging.info(l) # Parse the output. # TODO(jbudorick): Transition test scripts away from parsing stdout. if self._test_instance.enable_xml_result_parsing: results = gtest_test_instance.ParseGTestXML(gtest_xml) else: results = gtest_test_instance.ParseGTestOutput( output, self._test_instance.symbolizer, device.product_cpu_abi) tombstones_url = None for r in results: if logcat_file: r.SetLink('logcat', logcat_file.Link()) if self._test_instance.gs_test_artifacts_bucket: r.SetLink('test_artifacts', test_artifacts_url) if r.GetType() == base_test_result.ResultType.CRASH: self._crashes.add(r.GetName()) if self._test_instance.store_tombstones: if not tombstones_url: resolved_tombstones = tombstones.ResolveTombstones( device, resolve_all_tombstones=True, include_stack_symbols=False, wipe_tombstones=True) stream_name = 'tombstones_%s_%s' % (time.strftime( '%Y%m%dT%H%M%S', time.localtime()), device.serial) tombstones_url = logdog_helper.text( stream_name, '\n'.join(resolved_tombstones)) r.SetLink('tombstones', tombstones_url) tests_stripped_disabled_prefix = set() for t in test: tests_stripped_disabled_prefix.add( gtest_test_instance.TestNameWithoutDisabledPrefix(t)) not_run_tests = tests_stripped_disabled_prefix.difference( set(r.GetName() for r in results)) return results, list(not_run_tests) if results else None
def main(args): TEST_CASES.update({ p.product_name(): p for p in [ChromeFinchTestCase, WebViewFinchTestCase, WebLayerFinchTestCase] }) parser = argparse.ArgumentParser(prog='run_finch_smoke_tests_android.py') parser.add_argument( '--test-case', choices=TEST_CASES.keys(), # TODO(rmhasan): Remove default values after # adding arguments to test suites. Also make # this argument required. default='webview', help='Name of test case') parser.add_argument('--finch-seed-path', default=TEST_SEED_PATH, type=os.path.realpath, help='Path to the finch seed') parser.add_argument('--browser-apk', '--webview-shell-apk', '--weblayer-shell-apk', help='Path to the browser apk', type=os.path.realpath, required=True) parser.add_argument('--webview-provider-apk', type=os.path.realpath, help='Path to the WebView provider apk') parser.add_argument('--browser-activity-name', action='store', help='Browser activity name') parser.add_argument('--write-full-results-to', '--isolated-script-test-output', action='store', type=os.path.realpath, default=os.path.join(os.getcwd(), 'output.json'), help='Path to output directory') add_emulator_args(parser) script_common.AddDeviceArguments(parser) script_common.AddEnvironmentArguments(parser) logging_common.AddLoggingArguments(parser) options, _ = parser.parse_known_args(args) devil_chromium.Initialize(adb_path=options.adb_path) logging_common.InitializeLogging(options) with get_device(options) as device, \ TEST_CASES[options.test_case](device, options) as test_case, \ test_case.install_apks(): device.EnableRoot() log_mon = logcat_monitor.LogcatMonitor( device.adb, output_file=os.path.join( os.path.dirname(options.write_full_results_to), '%s_finch_smoke_tests_logcat.txt' % test_case.product_name()), filter_specs=_LOGCAT_FILTERS) log_mon.Start() device.RunShellCommand( ['pm', 'clear', get_package_name(options.browser_apk)], check_return=True) tests_pass = False with_seed_res = TestResult.Fail without_seed_res = TestResult.Fail if test_case.run_tests('without finch seed') != 0: test_case.install_seed() tests_pass = test_case.run_tests('with finch seed') without_seed_res = TestResult.Pass if tests_pass: with_seed_res = TestResult.Pass log_mon.Stop() json_results = get_json_results(with_seed_res, without_seed_res) with open(options.write_full_results_to, 'w') as json_out: json_out.write(json.dumps(json_results, indent=4)) # Return zero exit code if tests pass return not tests_pass