Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(16)

Side by Side Diff: build/android/pylib/local/device/local_device_instrumentation_test_run.py

Issue 2933993002: Add local results details pages.
Patch Set: More doc fixes. Created 3 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 # Copyright 2015 The Chromium Authors. All rights reserved. 1 # Copyright 2015 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 import contextlib 5 import contextlib
6 import hashlib 6 import hashlib
7 import json 7 import json
8 import logging 8 import logging
9 import os 9 import os
10 import posixpath 10 import posixpath
11 import re 11 import re
12 import sys 12 import sys
13 import tempfile
14 import time 13 import time
15 14
16 from devil.android import crash_handler 15 from devil.android import crash_handler
17 from devil.android import device_errors 16 from devil.android import device_errors
18 from devil.android import device_temp_file 17 from devil.android import device_temp_file
19 from devil.android import flag_changer 18 from devil.android import flag_changer
20 from devil.android.sdk import shared_prefs 19 from devil.android.sdk import shared_prefs
20 from devil.android import logcat_monitor
21 from devil.android.tools import system_app 21 from devil.android.tools import system_app
22 from devil.utils import reraiser_thread 22 from devil.utils import reraiser_thread
23 from incremental_install import installer 23 from incremental_install import installer
24 from pylib import valgrind_tools 24 from pylib import valgrind_tools
25 from pylib.android import logdog_logcat_monitor
26 from pylib.base import base_test_result 25 from pylib.base import base_test_result
26 from pylib.base import output_manager
27 from pylib.constants import host_paths 27 from pylib.constants import host_paths
28 from pylib.instrumentation import instrumentation_test_instance 28 from pylib.instrumentation import instrumentation_test_instance
29 from pylib.local.device import local_device_environment 29 from pylib.local.device import local_device_environment
30 from pylib.local.device import local_device_test_run 30 from pylib.local.device import local_device_test_run
31 from pylib.utils import google_storage_helper
32 from pylib.utils import instrumentation_tracing 31 from pylib.utils import instrumentation_tracing
33 from pylib.utils import logdog_helper
34 from pylib.utils import shared_preference_utils 32 from pylib.utils import shared_preference_utils
33
35 from py_trace_event import trace_event 34 from py_trace_event import trace_event
36 from py_trace_event import trace_time 35 from py_trace_event import trace_time
37 from py_utils import contextlib_ext 36 from py_utils import contextlib_ext
38 from py_utils import tempfile_ext 37 from py_utils import tempfile_ext
39 import tombstones 38 import tombstones
40 39
41 with host_paths.SysPath( 40 with host_paths.SysPath(
42 os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'), 0): 41 os.path.join(host_paths.DIR_SOURCE_ROOT, 'third_party'), 0):
43 import jinja2 # pylint: disable=import-error 42 import jinja2 # pylint: disable=import-error
44 import markupsafe # pylint: disable=import-error,unused-import 43 import markupsafe # pylint: disable=import-error,unused-import
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 return False 117 return False
119 118
120 119
121 _CURRENT_FOCUS_CRASH_RE = re.compile( 120 _CURRENT_FOCUS_CRASH_RE = re.compile(
122 r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}') 121 r'\s*mCurrentFocus.*Application (Error|Not Responding): (\S+)}')
123 122
124 123
125 class LocalDeviceInstrumentationTestRun( 124 class LocalDeviceInstrumentationTestRun(
126 local_device_test_run.LocalDeviceTestRun): 125 local_device_test_run.LocalDeviceTestRun):
127 def __init__(self, env, test_instance): 126 def __init__(self, env, test_instance):
128 super(LocalDeviceInstrumentationTestRun, self).__init__(env, test_instance) 127 super(LocalDeviceInstrumentationTestRun, self).__init__(
128 env, test_instance)
129 self._flag_changers = {} 129 self._flag_changers = {}
130 self._ui_capture_dir = dict() 130 self._ui_capture_dir = dict()
131 self._replace_package_contextmanager = None 131 self._replace_package_contextmanager = None
132 132
133 #override 133 #override
134 def TestPackage(self): 134 def TestPackage(self):
135 return self._test_instance.suite 135 return self._test_instance.suite
136 136
137 #override 137 #override
138 def SetUp(self): 138 def SetUp(self):
(...skipping 206 matching lines...) Expand 10 before | Expand all | Expand 10 after
345 coverage_basename = '%s.ec' % ('%s_group' % test[0]['method'] 345 coverage_basename = '%s.ec' % ('%s_group' % test[0]['method']
346 if isinstance(test, list) else test['method']) 346 if isinstance(test, list) else test['method'])
347 extras['coverage'] = 'true' 347 extras['coverage'] = 'true'
348 coverage_directory = os.path.join( 348 coverage_directory = os.path.join(
349 device.GetExternalStoragePath(), 'chrome', 'test', 'coverage') 349 device.GetExternalStoragePath(), 'chrome', 'test', 'coverage')
350 coverage_device_file = os.path.join( 350 coverage_device_file = os.path.join(
351 coverage_directory, coverage_basename) 351 coverage_directory, coverage_basename)
352 extras['coverageFile'] = coverage_device_file 352 extras['coverageFile'] = coverage_device_file
353 # Save screenshot if screenshot dir is specified (save locally) or if 353 # Save screenshot if screenshot dir is specified (save locally) or if
354 # a GS bucket is passed (save in cloud). 354 # a GS bucket is passed (save in cloud).
355 screenshot_device_file = None 355 screenshot_device_file = device_temp_file.DeviceTempFile(
356 if (self._test_instance.screenshot_dir or 356 device.adb, suffix='.png', dir=device.GetExternalStoragePath())
357 self._test_instance.gs_results_bucket): 357 extras[EXTRA_SCREENSHOT_FILE] = screenshot_device_file.name
358 screenshot_device_file = device_temp_file.DeviceTempFile(
359 device.adb, suffix='.png', dir=device.GetExternalStoragePath())
360 extras[EXTRA_SCREENSHOT_FILE] = screenshot_device_file.name
361 358
362 extras[EXTRA_UI_CAPTURE_DIR] = self._ui_capture_dir[device] 359 extras[EXTRA_UI_CAPTURE_DIR] = self._ui_capture_dir[device]
363 360
364 if self._env.trace_output: 361 if self._env.trace_output:
365 trace_device_file = device_temp_file.DeviceTempFile( 362 trace_device_file = device_temp_file.DeviceTempFile(
366 device.adb, suffix='.json', dir=device.GetExternalStoragePath()) 363 device.adb, suffix='.json', dir=device.GetExternalStoragePath())
367 extras[EXTRA_TRACE_FILE] = trace_device_file.name 364 extras[EXTRA_TRACE_FILE] = trace_device_file.name
368 365
369 if isinstance(test, list): 366 if isinstance(test, list):
370 if not self._test_instance.driver_apk: 367 if not self._test_instance.driver_apk:
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
427 self._CreateFlagChangerIfNeeded(device) 424 self._CreateFlagChangerIfNeeded(device)
428 self._flag_changers[str(device)].PushFlags(add=flags_to_add) 425 self._flag_changers[str(device)].PushFlags(add=flags_to_add)
429 426
430 time_ms = lambda: int(time.time() * 1e3) 427 time_ms = lambda: int(time.time() * 1e3)
431 start_ms = time_ms() 428 start_ms = time_ms()
432 429
433 stream_name = 'logcat_%s_%s_%s' % ( 430 stream_name = 'logcat_%s_%s_%s' % (
434 test_name.replace('#', '.'), 431 test_name.replace('#', '.'),
435 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), 432 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()),
436 device.serial) 433 device.serial)
437 logmon = logdog_logcat_monitor.LogdogLogcatMonitor(
438 device.adb, stream_name, filter_specs=LOGCAT_FILTERS)
439 434
440 with contextlib_ext.Optional( 435 with self._env.output_manager.ArchivedTempfile(
jbudorick 2017/08/23 16:16:20 This is fantastic.
mikecase (-- gone --) 2017/08/24 05:29:07 ^.^
441 logmon, self._test_instance.should_save_logcat): 436 stream_name, 'logcat') as logcat_file:
442 with _LogTestEndpoints(device, test_name): 437 with logcat_monitor.LogcatMonitor(
443 with contextlib_ext.Optional( 438 device.adb, filter_specs=LOGCAT_FILTERS,
444 trace_event.trace(test_name), 439 output_file=logcat_file.name) as logmon:
445 self._env.trace_output): 440 with _LogTestEndpoints(device, test_name):
446 output = device.StartInstrumentation( 441 with contextlib_ext.Optional(
447 target, raw=True, extras=extras, timeout=timeout, retries=0) 442 trace_event.trace(test_name),
443 self._env.trace_output):
444 output = device.StartInstrumentation(
445 target, raw=True, extras=extras, timeout=timeout, retries=0)
446 logmon.Close()
jbudorick 2017/08/23 16:16:20 I think this should be closed inside the logcat_fi
mikecase (-- gone --) 2017/08/24 05:29:07 Done
448 447
449 logcat_url = logmon.GetLogcatURL()
450 duration_ms = time_ms() - start_ms 448 duration_ms = time_ms() - start_ms
451 449
452 if self._env.trace_output: 450 if self._env.trace_output:
453 self._SaveTraceData(trace_device_file, device, test['class']) 451 self._SaveTraceData(trace_device_file, device, test['class'])
454 452
455 # TODO(jbudorick): Make instrumentation tests output a JSON so this 453 # TODO(jbudorick): Make instrumentation tests output a JSON so this
456 # doesn't have to parse the output. 454 # doesn't have to parse the output.
457 result_code, result_bundle, statuses = ( 455 result_code, result_bundle, statuses = (
458 self._test_instance.ParseAmInstrumentRawOutput(output)) 456 self._test_instance.ParseAmInstrumentRawOutput(output))
459 results = self._test_instance.GenerateTestResults( 457 results = self._test_instance.GenerateTestResults(
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
496 handle_coverage_data, handle_render_test_data] 494 handle_coverage_data, handle_render_test_data]
497 if self._env.concurrent_adb: 495 if self._env.concurrent_adb:
498 post_test_step_thread_group = reraiser_thread.ReraiserThreadGroup( 496 post_test_step_thread_group = reraiser_thread.ReraiserThreadGroup(
499 reraiser_thread.ReraiserThread(f) for f in post_test_steps) 497 reraiser_thread.ReraiserThread(f) for f in post_test_steps)
500 post_test_step_thread_group.StartAll(will_block=True) 498 post_test_step_thread_group.StartAll(will_block=True)
501 else: 499 else:
502 for step in post_test_steps: 500 for step in post_test_steps:
503 step() 501 step()
504 502
505 for result in results: 503 for result in results:
506 if logcat_url: 504 if logcat_file:
507 result.SetLink('logcat', logcat_url) 505 result.SetLink('logcat', logcat_file.Link())
508 506
509 # Update the result name if the test used flags. 507 # Update the result name if the test used flags.
510 if flags_to_add: 508 if flags_to_add:
511 for r in results: 509 for r in results:
512 if r.GetName() == test_name: 510 if r.GetName() == test_name:
513 r.SetName(test_display_name) 511 r.SetName(test_display_name)
514 512
515 # Add UNKNOWN results for any missing tests. 513 # Add UNKNOWN results for any missing tests.
516 iterable_test = test if isinstance(test, list) else [test] 514 iterable_test = test if isinstance(test, list) else [test]
517 test_names = set(self._GetUniqueTestName(t) for t in iterable_test) 515 test_names = set(self._GetUniqueTestName(t) for t in iterable_test)
518 results_names = set(r.GetName() for r in results) 516 results_names = set(r.GetName() for r in results)
519 results.extend( 517 results.extend(
520 base_test_result.BaseTestResult(u, base_test_result.ResultType.UNKNOWN) 518 base_test_result.BaseTestResult(u, base_test_result.ResultType.UNKNOWN)
521 for u in test_names.difference(results_names)) 519 for u in test_names.difference(results_names))
522 520
523 # Update the result type if we detect a crash. 521 # Update the result type if we detect a crash.
524 if DidPackageCrashOnDevice(self._test_instance.test_package, device): 522 if DidPackageCrashOnDevice(self._test_instance.test_package, device):
525 for r in results: 523 for r in results:
526 if r.GetType() == base_test_result.ResultType.UNKNOWN: 524 if r.GetType() == base_test_result.ResultType.UNKNOWN:
527 r.SetType(base_test_result.ResultType.CRASH) 525 r.SetType(base_test_result.ResultType.CRASH)
528 526
529 # Handle failures by: 527 # Handle failures by:
530 # - optionally taking a screenshot 528 # - optionally taking a screenshot
531 # - logging the raw output at INFO level 529 # - logging the raw output at INFO level
532 # - clearing the application state while persisting permissions 530 # - clearing the application state while persisting permissions
533 if any(r.GetType() not in (base_test_result.ResultType.PASS, 531 if any(r.GetType() not in (base_test_result.ResultType.PASS,
534 base_test_result.ResultType.SKIP) 532 base_test_result.ResultType.SKIP)
535 for r in results): 533 for r in results):
536 with contextlib_ext.Optional( 534 self._SaveScreenshot(device, screenshot_device_file, test_display_name,
537 tempfile_ext.NamedTemporaryDirectory(), 535 results)
538 self._test_instance.screenshot_dir is None and
539 self._test_instance.gs_results_bucket) as screenshot_host_dir:
540 screenshot_host_dir = (
541 self._test_instance.screenshot_dir or screenshot_host_dir)
542 self._SaveScreenshot(device, screenshot_host_dir,
543 screenshot_device_file, test_display_name,
544 results)
545 536
546 logging.info('detected failure in %s. raw output:', test_display_name) 537 logging.info('detected failure in %s. raw output:', test_display_name)
547 for l in output: 538 for l in output:
548 logging.info(' %s', l) 539 logging.info(' %s', l)
549 if (not self._env.skip_clear_data 540 if (not self._env.skip_clear_data
550 and self._test_instance.package_info): 541 and self._test_instance.package_info):
551 permissions = ( 542 permissions = (
552 self._test_instance.apk_under_test.GetPermissions() 543 self._test_instance.apk_under_test.GetPermissions()
553 if self._test_instance.apk_under_test 544 if self._test_instance.apk_under_test
554 else None) 545 else None)
555 device.ClearApplicationState(self._test_instance.package_info.package, 546 device.ClearApplicationState(self._test_instance.package_info.package,
556 permissions=permissions) 547 permissions=permissions)
557 else: 548 else:
558 logging.debug('raw output from %s:', test_display_name) 549 logging.debug('raw output from %s:', test_display_name)
559 for l in output: 550 for l in output:
560 logging.debug(' %s', l) 551 logging.debug(' %s', l)
561 if self._test_instance.store_tombstones: 552 if self._test_instance.store_tombstones:
562 tombstones_url = None 553 tombstones_url = None
563 for result in results: 554 for result in results:
564 if result.GetType() == base_test_result.ResultType.CRASH: 555 if result.GetType() == base_test_result.ResultType.CRASH:
565 if not tombstones_url: 556 if not tombstones_url:
566 resolved_tombstones = tombstones.ResolveTombstones( 557 resolved_tombstones = tombstones.ResolveTombstones(
567 device, 558 device,
568 resolve_all_tombstones=True, 559 resolve_all_tombstones=True,
569 include_stack_symbols=False, 560 include_stack_symbols=False,
570 wipe_tombstones=True, 561 wipe_tombstones=True,
571 tombstone_symbolizer=self._test_instance.symbolizer) 562 tombstone_symbolizer=self._test_instance.symbolizer)
572 stream_name = 'tombstones_%s_%s' % ( 563 tombstone_filename = 'tombstones_%s_%s' % (
573 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()), 564 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()),
574 device.serial) 565 device.serial)
575 tombstones_url = logdog_helper.text( 566 with self._env.output_manager.ArchivedTempfile(
576 stream_name, '\n'.join(resolved_tombstones)) 567 tombstone_filename, 'tombstones') as tombstone_file:
577 result.SetLink('tombstones', tombstones_url) 568 tombstone_file.write('\n'.join(resolved_tombstones))
578 569 result.SetLink('tombstones', tombstone_file.Link())
579 if self._env.concurrent_adb: 570 if self._env.concurrent_adb:
580 post_test_step_thread_group.JoinAll() 571 post_test_step_thread_group.JoinAll()
581 return results, None 572 return results, None
582 573
583 def _GetTestsFromRunner(self): 574 def _GetTestsFromRunner(self):
584 test_apk_path = self._test_instance.test_apk.path 575 test_apk_path = self._test_instance.test_apk.path
585 pickle_path = '%s-runner.pickle' % test_apk_path 576 pickle_path = '%s-runner.pickle' % test_apk_path
586 try: 577 try:
587 return instrumentation_test_instance.GetTestsFromPickle( 578 return instrumentation_test_instance.GetTestsFromPickle(
588 pickle_path, test_apk_path) 579 pickle_path, test_apk_path)
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
680 671
681 with open(trace_host_file, 'r') as host_handle: 672 with open(trace_host_file, 'r') as host_handle:
682 host_contents = host_handle.readline() 673 host_contents = host_handle.readline()
683 674
684 if host_contents: 675 if host_contents:
685 java_trace_json = ',%s' % java_trace_json.lstrip(' [') 676 java_trace_json = ',%s' % java_trace_json.lstrip(' [')
686 677
687 with open(trace_host_file, 'a') as host_handle: 678 with open(trace_host_file, 'a') as host_handle:
688 host_handle.write(java_trace_json) 679 host_handle.write(java_trace_json)
689 680
690 def _SaveScreenshot(self, device, screenshot_host_dir, screenshot_device_file, 681 def _SaveScreenshot(self, device, screenshot_device_file, test_name, results):
691 test_name, results): 682 screenshot_filename = '%s-%s.png' % (
692 if screenshot_host_dir: 683 test_name, time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime()))
693 screenshot_host_file = os.path.join(
694 screenshot_host_dir,
695 '%s-%s.png' % (
696 test_name,
697 time.strftime('%Y%m%dT%H%M%S-UTC', time.gmtime())))
698 if device.FileExists(screenshot_device_file.name): 684 if device.FileExists(screenshot_device_file.name):
699 try: 685 with self._env.output_manager.ArchivedTempfile(
700 device.PullFile(screenshot_device_file.name, screenshot_host_file) 686 screenshot_filename, 'screenshot',
701 finally: 687 output_manager.Datatype.IMAGE) as screenshot_host_file:
702 screenshot_device_file.close() 688 try:
703 689 device.PullFile(screenshot_device_file.name,
704 logging.info( 690 screenshot_host_file.name)
705 'Saved screenshot for %s to %s.', 691 finally:
706 test_name, screenshot_host_file) 692 screenshot_device_file.close()
707 if self._test_instance.gs_results_bucket: 693 for result in results:
708 link = google_storage_helper.upload( 694 result.SetLink('post_test_screenshot', screenshot_host_file.Link())
709 google_storage_helper.unique_name(
710 'screenshot', device=device),
711 screenshot_host_file,
712 bucket=('%s/screenshots' %
713 self._test_instance.gs_results_bucket))
714 for result in results:
715 result.SetLink('post_test_screenshot', link)
716 695
717 def _ProcessRenderTestResults( 696 def _ProcessRenderTestResults(
718 self, device, render_tests_device_output_dir, results): 697 self, device, render_tests_device_output_dir, results):
719 # If GS results bucket is specified, will archive render result images.
720 # If render image dir is specified, will pull the render result image from
721 # the device and leave in the directory.
722 if not (bool(self._test_instance.gs_results_bucket) or
723 bool(self._test_instance.render_results_dir)):
724 return
725 698
726 failure_images_device_dir = posixpath.join( 699 failure_images_device_dir = posixpath.join(
727 render_tests_device_output_dir, 'failures') 700 render_tests_device_output_dir, 'failures')
728 if not device.FileExists(failure_images_device_dir): 701 if not device.FileExists(failure_images_device_dir):
729 return 702 return
730 703
731 diff_images_device_dir = posixpath.join( 704 diff_images_device_dir = posixpath.join(
732 render_tests_device_output_dir, 'diffs') 705 render_tests_device_output_dir, 'diffs')
733 706
734 golden_images_device_dir = posixpath.join( 707 golden_images_device_dir = posixpath.join(
735 render_tests_device_output_dir, 'goldens') 708 render_tests_device_output_dir, 'goldens')
736 709
737 with contextlib_ext.Optional( 710 for failure_filename in device.ListDirectory(failure_images_device_dir):
738 tempfile_ext.NamedTemporaryDirectory(),
739 not bool(self._test_instance.render_results_dir)) as render_temp_dir:
740 render_host_dir = (
741 self._test_instance.render_results_dir or render_temp_dir)
742 711
743 if not os.path.exists(render_host_dir): 712 with self._env.output_manager.ArchivedTempfile(
744 os.makedirs(render_host_dir) 713 'fail_%s' % failure_filename, 'render_tests',
714 output_manager.Datatype.IMAGE) as failure_image_host_file:
715 device.PullFile(
716 posixpath.join(failure_images_device_dir, failure_filename),
717 failure_image_host_file)
718 failure_link = failure_image_host_file.Link()
745 719
746 # Pull all render test results from device. 720 if device.PathExists(
747 device.PullFile(failure_images_device_dir, render_host_dir) 721 posixpath.join(golden_images_device_dir, failure_filename)):
jbudorick 2017/08/23 16:16:20 nit: maybe save this as golden_image_device_file,
mikecase (-- gone --) 2017/08/24 05:29:07 Done
748 722 with self._env.output_manager.ArchivedTempfile(
749 if device.FileExists(diff_images_device_dir): 723 'golden_%s' % failure_filename, 'render_tests',
750 device.PullFile(diff_images_device_dir, render_host_dir) 724 output_manager.Datatype.IMAGE) as golden_image_host_file:
751 else: 725 device.PullFile(
752 logging.error('Diff images not found on device.') 726 posixpath.join(golden_images_device_dir, failure_filename),
753 727 golden_image_host_file)
754 if device.FileExists(golden_images_device_dir): 728 golden_link = golden_image_host_file.Link()
755 device.PullFile(golden_images_device_dir, render_host_dir)
756 else:
757 logging.error('Golden images not found on device.')
758
759 # Upload results to Google Storage.
760 if self._test_instance.gs_results_bucket:
761 self._UploadRenderTestResults(render_host_dir, results)
762
763 def _UploadRenderTestResults(self, render_host_dir, results):
764 render_tests_bucket = (
765 self._test_instance.gs_results_bucket + '/render_tests')
766
767 for failure_filename in os.listdir(
768 os.path.join(render_host_dir, 'failures')):
769 m = RE_RENDER_IMAGE_NAME.match(failure_filename)
770 if not m:
771 logging.warning('Unexpected file in render test failures: %s',
772 failure_filename)
773 continue
774
775 failure_filepath = os.path.join(
776 render_host_dir, 'failures', failure_filename)
777 failure_link = google_storage_helper.upload_content_addressed(
778 failure_filepath, bucket=render_tests_bucket)
779
780 golden_filepath = os.path.join(
781 render_host_dir, 'goldens', failure_filename)
782 if os.path.exists(golden_filepath):
783 golden_link = google_storage_helper.upload_content_addressed(
784 golden_filepath, bucket=render_tests_bucket)
785 else: 729 else:
786 golden_link = '' 730 golden_link = ''
787 731
788 diff_filepath = os.path.join( 732 if device.PathExists(
789 render_host_dir, 'diffs', failure_filename) 733 posixpath.join(diff_images_device_dir, failure_filename)):
jbudorick 2017/08/23 16:16:20 nit: same
mikecase (-- gone --) 2017/08/24 05:29:07 Done
790 if os.path.exists(diff_filepath): 734 with self._env.output_manager.ArchivedTempfile(
791 diff_link = google_storage_helper.upload_content_addressed( 735 'diff_%s' % failure_filename, 'render_tests',
792 diff_filepath, bucket=render_tests_bucket) 736 output_manager.Datatype.IMAGE) as diff_image_host_file:
737 device.PullFile(
738 posixpath.join(diff_images_device_dir, failure_filename),
739 diff_image_host_file)
740 diff_link = diff_image_host_file.Link()
793 else: 741 else:
794 diff_link = '' 742 diff_link = ''
795 743
796 with tempfile.NamedTemporaryFile(suffix='.html') as temp_html: 744 jinja2_env = jinja2.Environment(
797 jinja2_env = jinja2.Environment( 745 loader=jinja2.FileSystemLoader(_JINJA_TEMPLATE_DIR),
798 loader=jinja2.FileSystemLoader(_JINJA_TEMPLATE_DIR), 746 trim_blocks=True)
799 trim_blocks=True) 747 template = jinja2_env.get_template(_JINJA_TEMPLATE_FILENAME)
800 template = jinja2_env.get_template(_JINJA_TEMPLATE_FILENAME) 748 # pylint: disable=no-member
801 # pylint: disable=no-member 749 processed_template_output = template.render(
802 processed_template_output = template.render( 750 test_name=failure_filename,
803 test_name=failure_filename, 751 failure_link=failure_link,
804 failure_link=failure_link, 752 golden_link=golden_link,
805 golden_link=golden_link, 753 diff_link=diff_link)
806 diff_link=diff_link)
807 754
808 temp_html.write(processed_template_output) 755 with self._env.output_manager.ArchivedTempfile(
809 temp_html.flush() 756 '%s.html' % failure_filename, 'render_tests',
810 html_results_link = google_storage_helper.upload_content_addressed( 757 output_manager.Datatype.HTML) as html_results:
811 temp_html.name, 758 html_results.write(processed_template_output)
812 bucket=render_tests_bucket, 759 html_results.flush()
813 content_type='text/html') 760 for result in results:
814 for result in results: 761 result.SetLink(failure_filename, html_results.Link())
815 result.SetLink(failure_filename, html_results_link)
816 762
817 #override 763 #override
818 def _ShouldRetry(self, test, result): 764 def _ShouldRetry(self, test, result):
819 def not_run(res): 765 def not_run(res):
820 if isinstance(res, list): 766 if isinstance(res, list):
821 return any(not_run(r) for r in res) 767 return any(not_run(r) for r in res)
822 return res.GetType() == base_test_result.ResultType.NOTRUN 768 return res.GetType() == base_test_result.ResultType.NOTRUN
823 769
824 if 'RetryOnFailure' in test.get('annotations', {}) or not_run(result): 770 if 'RetryOnFailure' in test.get('annotations', {}) or not_run(result):
825 return True 771 return True
(...skipping 28 matching lines...) Expand all
854 timeout *= cls._GetTimeoutScaleFromAnnotations(annotations) 800 timeout *= cls._GetTimeoutScaleFromAnnotations(annotations)
855 801
856 return timeout 802 return timeout
857 803
858 def _IsRenderTest(test): 804 def _IsRenderTest(test):
859 """Determines if a test or list of tests has a RenderTest amongst them.""" 805 """Determines if a test or list of tests has a RenderTest amongst them."""
860 if not isinstance(test, list): 806 if not isinstance(test, list):
861 test = [test] 807 test = [test]
862 return any([RENDER_TEST_FEATURE_ANNOTATION in t['annotations'].get( 808 return any([RENDER_TEST_FEATURE_ANNOTATION in t['annotations'].get(
863 FEATURE_ANNOTATION, {}).get('value', ()) for t in test]) 809 FEATURE_ANNOTATION, {}).get('value', ()) for t in test])
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698