8A top level harness to run all unit-tests in a specific engine build.
11from pathlib
import Path
17import logging.handlers
26from sys
import exit
as sys_exit, platform
as sys_platform
32SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
33BUILDROOT_DIR = os.path.abspath(os.path.join(os.path.realpath(__file__),
'..',
'..',
'..'))
34OUT_DIR = os.path.join(BUILDROOT_DIR,
'out')
35GOLDEN_DIR = os.path.join(BUILDROOT_DIR,
'flutter',
'testing',
'resources')
36FONTS_DIR = os.path.join(BUILDROOT_DIR,
'flutter',
'third_party',
'txt',
'third_party',
'fonts')
37ROBOTO_FONT_PATH = os.path.join(FONTS_DIR,
'Roboto-Regular.ttf')
38FONT_SUBSET_DIR = os.path.join(BUILDROOT_DIR,
'flutter',
'tools',
'font_subset')
42LOG_FILE = os.path.join(OUT_DIR,
'run_tests.log')
43logger = logging.getLogger(__name__)
44console_logger_handler = logging.StreamHandler()
45file_logger_handler = logging.FileHandler(LOG_FILE)
50 logger.info(*args, **kwargs)
56 logger.info(
''.
join([char
for _
in range(80)]))
61 with open(os.path.join(build_dir,
'args.gn'))
as args:
62 if 'is_asan = true' in args.read():
69 cmd: typing.List[str],
70 forbidden_output: typing.List[str] =
None,
71 expect_failure: bool =
False,
72 env: typing.Dict[str, str] =
None,
73 allowed_failure_output: typing.List[str] =
None,
76 if forbidden_output
is None:
78 if allowed_failure_output
is None:
79 allowed_failure_output = []
81 command_string =
' '.
join(cmd)
84 logger.info(
'Running command "%s"', command_string)
86 start_time = time.time()
88 process = subprocess.Popen(
90 stdout=subprocess.PIPE,
91 stderr=subprocess.STDOUT,
93 universal_newlines=
True,
98 for line
in iter(process.stdout.readline,
''):
100 logger.info(line.rstrip())
103 end_time = time.time()
105 if process.returncode != 0
and not expect_failure:
109 'Failed Command:\n\n%s\n\nExit Code: %s\n\nOutput:\n%s', command_string, process.returncode,
115 allowed_failure =
False
116 for allowed_string
in allowed_failure_output:
117 if allowed_string
in output:
118 allowed_failure =
True
120 if not allowed_failure:
121 raise RuntimeError(
'Command "%s" exited with code %s.' % (command_string, process.returncode))
123 for forbidden_string
in forbidden_output:
124 if forbidden_string
in output:
126 'command "%s" contained forbidden string "%s"' % (command_string, forbidden_string)
130 logger.info(
'Command run successfully in %.2f seconds: %s', end_time - start_time, command_string)
134 return sys_platform ==
'darwin'
139 output = subprocess.check_output([
'sysctl',
'machdep.cpu'])
140 text = output.decode(
'utf-8')
141 aarm64 = text.find(
'Apple') >= 0
143 assert text.find(
'GenuineIntel') >= 0
148 return sys_platform.startswith(
'linux')
152 return sys_platform.startswith((
'cygwin',
'win'))
160 if os.path.exists(path):
164 exe_path = path +
'.exe'
165 if os.path.exists(exe_path):
168 bat_path = path +
'.bat'
169 if os.path.exists(bat_path):
172 raise Exception(
'Executable %s does not exist!' % path)
179 'VK_ICD_FILENAMES': os.path.join(build_dir,
'vk_swiftshader_icd.json'),
182 'VK_LAYER_PATH': os.path.join(build_dir,
'vulkan-data'),
183 'VK_INSTANCE_LAYERS':
'VK_LAYER_KHRONOS_validation',
192 'MTL_SHADER_VALIDATION':
'1',
193 'MTL_SHADER_VALIDATION_GLOBAL_MEMORY':
195 'MTL_SHADER_VALIDATION_THREADGROUP_MEMORY':
'1',
196 'MTL_SHADER_VALIDATION_TEXTURE_USAGE':
'1',
200 'METAL_DEBUG_ERROR_MODE':
'0',
201 'METAL_DEVICE_WRAPPER_TYPE':
'1',
207 build_dir, executable_name, flags=None, coverage=False, gtest=False
212 unstripped_exe = os.path.join(build_dir,
'exe.unstripped', executable_name)
214 if is_linux()
and os.path.exists(unstripped_exe)
and not coverage:
217 executable = unstripped_exe
221 coverage_script = os.path.join(BUILDROOT_DIR,
'flutter',
'build',
'generate_coverage.py')
225 '-t', executable,
'-o',
226 os.path.join(build_dir,
'coverage', executable_name),
'-f',
'html'
228 updated_flags = [
'--args=%s' %
' '.
join(flags)]
229 test_command = [coverage_script] + coverage_flags + updated_flags
231 test_command = [executable] + flags
233 gtest_parallel = os.path.join(
234 BUILDROOT_DIR,
'flutter',
'third_party',
'gtest-parallel',
'gtest-parallel'
236 test_command = [
'python3', gtest_parallel] + test_command
247 forbidden_output=None,
248 allowed_failure_output=None,
249 expect_failure=False,
254 if executable_filter
is not None and executable_name
not in executable_filter:
255 logger.info(
'Skipping %s due to filter.', executable_name)
260 if forbidden_output
is None:
261 forbidden_output = []
262 if allowed_failure_output
is None:
263 allowed_failure_output = []
264 if extra_env
is None:
267 unstripped_exe = os.path.join(build_dir,
'exe.unstripped', executable_name)
268 env = os.environ.copy()
270 env[
'LD_LIBRARY_PATH'] = build_dir
271 env[
'VK_DRIVER_FILES'] = os.path.join(build_dir,
'vk_swiftshader_icd.json')
272 if os.path.exists(unstripped_exe):
273 unstripped_vulkan = os.path.join(build_dir,
'lib.unstripped',
'libvulkan.so.1')
274 if os.path.exists(unstripped_vulkan):
275 vulkan_path = unstripped_vulkan
277 vulkan_path = os.path.join(build_dir,
'libvulkan.so.1')
279 os.symlink(vulkan_path, os.path.join(build_dir,
'exe.unstripped',
'libvulkan.so.1'))
280 except OSError
as err:
281 if err.errno == errno.EEXIST:
286 env[
'DYLD_LIBRARY_PATH'] = build_dir
288 env[
'PATH'] = build_dir +
':' + env[
'PATH']
290 logger.info(
'Running %s in %s', executable_name, cwd)
300 env[
'FLUTTER_BUILD_DIRECTORY'] = build_dir
301 for key, value
in extra_env.items():
308 forbidden_output=forbidden_output,
309 expect_failure=expect_failure,
311 allowed_failure_output=allowed_failure_output,
318 luci_test_outputs_path = os.environ.get(
'FLUTTER_TEST_OUTPUTS_DIR')
319 core_path = os.path.join(cwd,
'core')
320 if luci_test_outputs_path
and os.path.exists(core_path)
and os.path.exists(unstripped_exe):
321 dump_path = os.path.join(
322 luci_test_outputs_path,
'%s_%s.txt' % (executable_name, sys_platform)
324 logger.error(
'Writing core dump analysis to %s', dump_path)
326 os.path.join(BUILDROOT_DIR,
'flutter',
'testing',
'analyze_core_dump.sh'),
345 forbidden_output=None,
346 allowed_failure_output=None,
347 expect_failure=False,
380 return ' '.
join(command)
393def run_cc_tests(build_dir, executable_filter, coverage, capture_core_dump):
394 logger.info(
'Running Engine Unit-tests.')
396 if capture_core_dump
and is_linux():
398 resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
400 def make_test(name, flags=None, extra_env=None):
403 if extra_env
is None:
405 return (name, flags, extra_env)
408 make_test(
'client_wrapper_glfw_unittests'),
409 make_test(
'client_wrapper_unittests'),
410 make_test(
'common_cpp_core_unittests'),
411 make_test(
'common_cpp_unittests'),
412 make_test(
'dart_plugin_registrant_unittests'),
413 make_test(
'display_list_rendertests'),
414 make_test(
'display_list_unittests'),
415 make_test(
'embedder_a11y_unittests'),
416 make_test(
'embedder_proctable_unittests'),
417 make_test(
'embedder_unittests'),
418 make_test(
'fml_unittests'),
419 make_test(
'fml_arc_unittests'),
420 make_test(
'no_dart_plugin_registrant_unittests'),
421 make_test(
'runtime_unittests'),
422 make_test(
'testing_unittests'),
423 make_test(
'tonic_unittests'),
425 make_test(
'ui_unittests', flags=repeat_flags + [
'--timeout=90']),
431 make_test(
'android_external_view_embedder_unittests'),
432 make_test(
'jni_unittests'),
433 make_test(
'platform_view_android_delegate_unittests'),
435 make_test(
'shell_unittests'),
441 make_test(
'accessibility_unittests'),
442 make_test(
'client_wrapper_windows_unittests'),
443 make_test(
'flutter_windows_unittests'),
450 make_test(
'accessibility_unittests'),
451 make_test(
'availability_version_check_unittests'),
452 make_test(
'framework_common_unittests'),
453 make_test(
'spring_animation_unittests'),
454 make_test(
'gpu_surface_metal_unittests'),
459 '--golden-dir=%s' % GOLDEN_DIR,
460 '--font-file=%s' % ROBOTO_FONT_PATH,
462 icu_flags = [
'--icu-data-file-path=%s' % os.path.join(build_dir,
'icudtl.dat')]
464 make_test(
'flow_unittests', flags=repeat_flags + [
'--'] + flow_flags),
465 make_test(
'flutter_glfw_unittests'),
466 make_test(
'flutter_linux_unittests', extra_env={
'G_DEBUG':
'fatal-criticals'}),
468 make_test(
'txt_unittests', flags=repeat_flags + [
'--'] + icu_flags),
471 flow_flags = [
'--gtest_filter=-PerformanceOverlayLayer.Gold']
473 make_test(
'flow_unittests', flags=repeat_flags + flow_flags),
476 build_name = os.path.basename(build_dir)
480 for test, flags, extra_env
in unittests:
498 if not os.path.basename(build_dir).startswith(
'host_debug'):
503 'flutter_desktop_darwin_unittests',
510 mac_impeller_unittests_flags = repeat_flags + [
511 '--gtest_filter=-*OpenGLES',
513 '--enable_vulkan_validation',
518 'impeller_unittests',
520 mac_impeller_unittests_flags,
526 allowed_failure_output=[
527 '[MTLCompiler createVertexStageAndLinkPipelineWithFragment:',
528 '[MTLCompiler pipelineStateWithVariant:',
539 'impeller_unittests',
542 '--enable_vulkan_validation',
543 '--enable_playground',
544 '--playground_timeout_ms=4000',
545 '--gtest_filter="*ColorWheel/Vulkan"',
554 'impeller_dart_unittests',
557 '--enable_vulkan_validation',
560 '--gtest_filter=*Metal',
568 logger.info(
'Running Engine Benchmarks.')
570 icu_flags = [
'--icu-data-file-path=%s' % os.path.join(build_dir,
'icudtl.dat')]
593 enable_impeller=False,
594 enable_observatory=False,
604 command_args.append(
'--disable-observatory')
607 command_args += [
'--enable-impeller']
609 command_args += [
'--no-enable-impeller']
612 command_args.insert(0,
'--force-multithreading')
616 return 'multithreaded'
617 return 'single-threaded'
621 return 'impeller swiftshader'
622 return 'skia software'
626 kernel_file_name = os.path.basename(dart_file) +
'.dill'
627 kernel_file_output = os.path.join(build_dir,
'gen', kernel_file_name)
628 error_message =
"%s doesn't exist. Please run the build that populates %s" % (
629 kernel_file_output, build_dir
631 assert os.path.isfile(kernel_file_output), error_message
635 options.apply_args(command_args)
637 dart_file_contents = open(dart_file,
'r')
638 custom_options = re.findall(
'// FlutterTesterOptions=(.*)', dart_file_contents.read())
639 dart_file_contents.close()
640 command_args.extend(custom_options)
644 '--icu-data-file-path=%s' % os.path.join(build_dir,
'icudtl.dat'),
645 '--flutter-assets-dir=%s' % os.path.join(build_dir,
'gen',
'flutter',
'lib',
'ui',
'assets'),
646 '--disable-asset-fonts',
650 tester_name =
'flutter_tester'
652 "Running test '%s' using '%s' (%s, %s)", kernel_file_name, tester_name,
653 options.threading_description(), options.impeller_enabled()
655 forbidden_output = []
if 'unopt' in build_dir
or options.expect_failure
else [
'[ERROR']
661 forbidden_output=forbidden_output,
662 expect_failure=options.expect_failure,
667 """Builds the engine variant and the test dylib containing the XCTests"""
668 tmp_out_dir = os.path.join(OUT_DIR, ios_out_dir)
669 ios_test_lib = os.path.join(tmp_out_dir,
'libios_test_flutter.dylib')
671 message.append(
'gn --ios --unoptimized --runtime-mode=debug --no-lto --simulator')
672 message.append(
'ninja -C %s ios_test_flutter' % ios_out_dir)
673 final_message =
"%s or %s doesn't exist. Please run the following commands: \n%s" % (
674 ios_out_dir, ios_test_lib,
'\n'.
join(message)
676 assert os.path.exists(tmp_out_dir)
and os.path.exists(ios_test_lib), final_message
680 """Checks that the user has a version of Xcode installed"""
681 version_output = subprocess.check_output([
'xcodebuild',
'-version'])
683 version_output = version_output
if isinstance(version_output,
684 str)
else version_output.decode(ENCODING)
685 version_output = version_output.strip()
686 match = re.match(
r'Xcode (\d+)', version_output)
687 message =
'Xcode must be installed to run the iOS embedding unit tests'
688 assert match, message
692 script_path = os.path.dirname(os.path.realpath(__file__))
695 script_path,
'..',
'..',
'third_party',
'java',
'openjdk',
'Contents',
'Home'
697 return os.path.join(script_path,
'..',
'..',
'third_party',
'java',
'openjdk')
705 """Runs the Java JUnit unit tests for the Android embedding"""
706 test_runner_dir = os.path.join(
707 BUILDROOT_DIR,
'flutter',
'shell',
'platform',
'android',
'test_runner'
709 gradle_bin = os.path.join(
710 BUILDROOT_DIR,
'flutter',
'third_party',
'gradle',
'bin',
713 flutter_jar = os.path.join(OUT_DIR, android_variant,
'flutter.jar')
714 android_home = os.path.join(BUILDROOT_DIR,
'flutter',
'third_party',
'android_tools',
'sdk')
715 build_dir = os.path.join(OUT_DIR, android_variant,
'robolectric_tests',
'build')
716 gradle_cache_dir = os.path.join(OUT_DIR, android_variant,
'robolectric_tests',
'.gradle')
718 test_class = executable_filter
if executable_filter
else '*'
721 '-Pflutter_jar=%s' % flutter_jar,
722 '-Pbuild_dir=%s' % build_dir,
724 '--tests=%s' % test_class,
727 '--project-cache-dir=%s' % gradle_cache_dir,
728 '--gradle-user-home=%s' % gradle_cache_dir,
731 env = dict(os.environ, ANDROID_HOME=android_home, JAVA_HOME=
java_home())
732 run_cmd(command, cwd=test_runner_dir, env=env)
736 tests_path = os.path.join(OUT_DIR, android_variant, test_runner_name)
737 remote_path =
'/data/local/tmp'
738 remote_tests_path = os.path.join(remote_path, test_runner_name)
739 run_cmd([adb_path,
'push', tests_path, remote_path], cwd=BUILDROOT_DIR)
742 run_cmd([adb_path,
'shell', remote_tests_path])
744 luci_test_outputs_path = os.environ.get(
'FLUTTER_TEST_OUTPUTS_DIR')
745 if luci_test_outputs_path:
746 print(
'>>>>> Test %s failed. Capturing logcat.' % test_runner_name)
747 logcat_path = os.path.join(luci_test_outputs_path,
'%s_logcat' % test_runner_name)
748 logcat_file = open(logcat_path,
'w')
749 subprocess.run([adb_path,
'logcat',
'-d'], stdout=logcat_file, check=
False)
760 systrace_test = os.path.join(BUILDROOT_DIR,
'flutter',
'testing',
'android_systrace_test.py')
761 scenario_apk = os.path.join(OUT_DIR, android_variant,
'firebase_apks',
'scenario_app.apk')
763 systrace_test,
'--adb-path', adb_path,
'--apk-path', scenario_apk,
'--package-name',
764 'dev.flutter.scenarios',
'--activity-name',
'.PlatformViewsActivity'
769 """Runs Objective-C XCTest unit tests for the iOS embedding"""
771 ios_out_dir = os.path.join(OUT_DIR, ios_variant)
774 new_simulator_name =
'IosUnitTestsSimulator'
784 '%s com.apple.CoreSimulator.SimDeviceType.iPhone-11' % new_simulator_name
786 run_cmd(create_simulator, shell=
True)
789 ios_unit_test_dir = os.path.join(BUILDROOT_DIR,
'flutter',
'testing',
'ios',
'IosUnitTests')
791 with tempfile.TemporaryDirectory(suffix=
'ios_embedding_xcresult')
as result_bundle_temp:
792 result_bundle_path = os.path.join(result_bundle_temp,
'ios_embedding')
800 '-sdk iphonesimulator '
801 '-scheme IosUnitTests '
802 '-resultBundlePath ' + result_bundle_path +
' '
803 '-destination name=' + new_simulator_name +
' '
805 'FLUTTER_ENGINE=' + ios_variant
807 if test_filter
is not None:
808 test_command[0] = test_command[0] +
' -only-testing:%s' % test_filter
810 run_cmd(test_command, cwd=ios_unit_test_dir, shell=
True)
816 luci_test_outputs_path = os.environ.get(
'FLUTTER_TEST_OUTPUTS_DIR')
817 xcresult_bundle = os.path.join(result_bundle_temp,
'ios_embedding.xcresult')
818 if luci_test_outputs_path
and os.path.exists(xcresult_bundle):
819 dump_path = os.path.join(luci_test_outputs_path,
'ios_embedding.xcresult')
821 shutil.make_archive(dump_path,
'zip', root_dir=xcresult_bundle)
837 run_cmd(command, expect_failure=
True)
841 dart_tests_dir = os.path.join(
851 os.path.join(
'dart-sdk',
'bin',
'dart'),
853 flags=[
'pub',
'--suppress-analytics',
'get',
'--offline'],
857 dart_observatory_tests = glob.glob(
'%s/observatory/*_test.dart' % dart_tests_dir)
858 dart_tests = glob.glob(
'%s/*_test.dart' % dart_tests_dir)
860 if 'release' not in build_dir:
861 for dart_test_file
in dart_observatory_tests:
862 if test_filter
is not None and os.path.basename(dart_test_file)
not in test_filter:
863 logger.info(
"Skipping '%s' due to filter.", dart_test_file)
865 logger.info(
"Gathering dart test '%s' with observatory enabled", dart_test_file)
866 for multithreaded
in [
False,
True]:
867 for enable_impeller
in [
False,
True]:
869 build_dir, dart_test_file,
871 multithreaded=multithreaded,
872 enable_impeller=enable_impeller,
873 enable_observatory=
True
877 for dart_test_file
in dart_tests:
878 if test_filter
is not None and os.path.basename(dart_test_file)
not in test_filter:
879 logger.info(
"Skipping '%s' due to filter.", dart_test_file)
881 logger.info(
"Gathering dart test '%s'", dart_test_file)
882 for multithreaded
in [
False,
True]:
883 for enable_impeller
in [
False,
True]:
885 build_dir, dart_test_file,
891 smoke_test = os.path.join(
895 'smoke_test_failure',
898 if test_filter
is not None and os.path.basename(smoke_test)
not in test_filter:
899 logger.info(
"Skipping '%s' due to filter.", smoke_test)
910 dart_tests = glob.glob(
'%s/test/*_test.dart' % package_path)
912 raise Exception(
'No tests found for Dart package at %s' % package_path)
913 for dart_test_file
in dart_tests:
914 opts = [
'--disable-dart-dev', dart_test_file] + extra_opts
916 build_dir, os.path.join(
'dart-sdk',
'bin',
'dart'),
None, flags=opts, cwd=package_path
931 os.path.join(
'flutter',
'ci'),
932 [os.path.join(BUILDROOT_DIR,
'flutter')],
935 os.path.join(
'flutter',
'flutter_frontend_server'),
938 os.path.join(build_dir,
'gen',
'frontend_server_aot.dart.snapshot'),
939 os.path.join(build_dir,
'flutter_patched_sdk')
942 (os.path.join(
'flutter',
'testing',
'litetest'), []),
943 (os.path.join(
'flutter',
'testing',
'pkg_test_demo'), []),
944 (os.path.join(
'flutter',
'testing',
'skia_gold_client'), []),
945 (os.path.join(
'flutter',
'testing',
'scenario_app'), []),
947 os.path.join(
'flutter',
'tools',
'api_check'),
948 [os.path.join(BUILDROOT_DIR,
'flutter')],
950 (os.path.join(
'flutter',
'tools',
'build_bucket_golden_scraper'), []),
951 (os.path.join(
'flutter',
'tools',
'clang_tidy'), []),
953 os.path.join(
'flutter',
'tools',
'const_finder'),
955 os.path.join(build_dir,
'gen',
'frontend_server_aot.dart.snapshot'),
956 os.path.join(build_dir,
'flutter_patched_sdk'),
957 os.path.join(build_dir,
'dart-sdk',
'lib',
'libraries.json'),
960 (os.path.join(
'flutter',
'tools',
'dir_contents_diff'), []),
961 (os.path.join(
'flutter',
'tools',
'engine_tool'), []),
962 (os.path.join(
'flutter',
'tools',
'githooks'), []),
963 (os.path.join(
'flutter',
'tools',
'header_guard_check'), []),
964 (os.path.join(
'flutter',
'tools',
'pkg',
'engine_build_configs'), []),
965 (os.path.join(
'flutter',
'tools',
'pkg',
'engine_repo_tools'), []),
966 (os.path.join(
'flutter',
'tools',
'pkg',
'git_repo_tools'), []),
970 (os.path.join(
'flutter',
'tools',
'path_ops',
'dart'), []),
973 return dart_host_tests
977 test_dir = os.path.join(BUILDROOT_DIR,
'flutter',
'testing',
'benchmark')
978 dart_tests = glob.glob(
'%s/test/*_test.dart' % test_dir)
979 for dart_test_file
in dart_tests:
980 opts = [
'--disable-dart-dev', dart_test_file]
982 build_dir, os.path.join(
'dart-sdk',
'bin',
'dart'),
None, flags=opts, cwd=test_dir
987 queue_handler = logging.handlers.QueueHandler(queue)
988 log = logging.getLogger(__name__)
989 log.setLevel(logging.INFO)
990 queue_handler.setLevel(level)
991 log.addHandler(queue_handler)
1004 max_processes = multiprocessing.cpu_count()
1005 if sys_platform.startswith((
'cygwin',
'win'))
and max_processes > 60:
1008 queue = multiprocessing.Queue()
1009 queue_listener = logging.handlers.QueueListener(
1011 console_logger_handler,
1012 file_logger_handler,
1013 respect_handler_level=
True,
1015 queue_listener.start()
1019 with multiprocessing.Pool(max_processes, worker_init,
1020 [queue, logger.getEffectiveLevel()])
as pool:
1021 async_results = [(t, pool.apply_async(t, ()))
for t
in tasks]
1022 for task, async_result
in async_results:
1025 except Exception
as exn:
1026 failures += [(task, exn)]
1028 queue_listener.stop()
1030 if len(failures) > 0:
1031 logger.error(
'The following commands failed:')
1032 for task, exn
in failures:
1033 logger.error(
'%s\n %s\n\n', str(task), str(exn))
1041 A scoped change in the CWD.
1053 def __exit__(self, exception_type, exception_value, exception_traceback):
1059 Executes the impeller golden image tests from in the `variant` build.
1061 tests_path: str = os.path.join(build_dir, 'impeller_golden_tests')
1062 if not os.path.exists(tests_path):
1064 'Cannot find the "impeller_golden_tests" executable in "%s". You may need to build it.' %
1067 harvester_path: Path =
Path(SCRIPT_DIR).parent.joinpath(
'tools'
1068 ).joinpath(
'golden_tests_harvester')
1070 with tempfile.TemporaryDirectory(prefix=
'impeller_golden')
as temp_dir:
1073 run_cmd([tests_path, f
'--working_dir={temp_dir}'], cwd=build_dir, env=extra_env)
1074 dart_bin = os.path.join(build_dir,
'dart-sdk',
'bin',
'dart')
1075 golden_path = os.path.join(
'testing',
'impeller_golden_tests_output.txt')
1076 script_path = os.path.join(
'tools',
'dir_contents_diff',
'bin',
'dir_contents_diff.dart')
1077 diff_result = subprocess.run(
1078 f
'{dart_bin} --disable-dart-dev {script_path} {golden_path} {temp_dir}',
1081 stdout=subprocess.PIPE,
1082 cwd=os.path.join(BUILDROOT_DIR,
'flutter')
1084 if diff_result.returncode != 0:
1086 print(diff_result.stdout.decode())
1087 raise RuntimeError(
'impeller_golden_tests diff failure')
1089 if not require_skia_gold:
1091 print(
'Skipping any SkiaGoldClient invocation as the --no-skia-gold flag was set.')
1097 if 'GOLDCTL' not in os.environ:
1100 is_luci =
'LUCI_CONTEXT' in os.environ
1104The GOLDCTL environment variable is not set. This is required for Skia Gold tests.
1105See https://github.com/flutter/engine/tree/main/testing/skia_gold_client#configuring-ci
1106for more information.
1112 'Skipping the SkiaGoldClient invocation as the GOLDCTL environment variable is not set.'
1117 bin_path =
Path(
'.').joinpath(
'bin').joinpath(
'golden_tests_harvester.dart')
1118 run_cmd([dart_bin,
'--disable-dart-dev', str(bin_path), temp_dir])
1122 parser = argparse.ArgumentParser(
1124In order to learn the details of running tests in the engine, please consult the
1125Flutter Wiki page on the subject: https://github.com/flutter/flutter/wiki/Testing-the-engine
1140 parser.add_argument(
1144 default=
'host_debug_unopt',
1145 help=
'The engine build variant to run the tests for.'
1147 parser.add_argument(
1151 help=
'A list of test types, default is "all" (equivalent to "%s")' % (
','.
join(all_types))
1153 parser.add_argument(
1154 '--engine-filter', type=str, default=
'', help=
'A list of engine test executables to run.'
1156 parser.add_argument(
1160 help=
'A list of Dart test script base file names to run in '
1161 'flutter_tester (example: "image_filter_test.dart").'
1163 parser.add_argument(
1164 '--dart-host-filter',
1167 help=
'A list of Dart test scripts to run with the Dart CLI.'
1169 parser.add_argument(
1173 help=
'A single Java test class to run (example: "io.flutter.SmokeTest")'
1175 parser.add_argument(
1176 '--android-variant',
1177 dest=
'android_variant',
1179 default=
'android_debug_unopt',
1180 help=
'The engine build variant to run java or android tests for'
1182 parser.add_argument(
1186 default=
'ios_debug_sim_unopt',
1187 help=
'The engine build variant to run objective-c tests for'
1189 parser.add_argument(
1190 '--verbose-dart-snapshot',
1191 dest=
'verbose_dart_snapshot',
1192 action=
'store_true',
1194 help=
'Show extra dart snapshot logging.'
1196 parser.add_argument(
1201 'Filter parameter for which objc tests to run '
1202 '(example: "IosUnitTestsTests/SemanticsObjectTest/testShouldTriggerAnnouncement")'
1205 parser.add_argument(
1207 action=
'store_true',
1209 help=
'Generate coverage reports for each unit test framework run.'
1211 parser.add_argument(
1212 '--engine-capture-core-dump',
1213 dest=
'engine_capture_core_dump',
1214 action=
'store_true',
1216 help=
'Capture core dumps from crashes of engine tests.'
1218 parser.add_argument(
1219 '--use-sanitizer-suppressions',
1220 dest=
'sanitizer_suppressions',
1221 action=
'store_true',
1223 help=
'Provide the sanitizer suppressions lists to the via environment to the tests.'
1225 parser.add_argument(
1230 help=
'Provide the path of adb used for android tests. By default it looks on $PATH.'
1232 parser.add_argument(
1235 action=
'store_true',
1237 help=
'Only emit output when there is an error.'
1239 parser.add_argument(
1243 help=
'The directory that verbose logs will be copied to in --quiet mode.',
1245 parser.add_argument(
1247 dest=
'no_skia_gold',
1248 action=
'store_true',
1250 help=
'Do not compare golden images with Skia Gold.',
1253 args = parser.parse_args()
1255 logger.addHandler(console_logger_handler)
1256 logger.addHandler(file_logger_handler)
1257 logger.setLevel(logging.INFO)
1259 file_logger_handler.setLevel(logging.INFO)
1260 console_logger_handler.setLevel(logging.WARNING)
1262 console_logger_handler.setLevel(logging.INFO)
1264 if args.type ==
'all':
1267 types = args.type.split(
',')
1269 build_dir = os.path.join(OUT_DIR, args.variant)
1270 if args.type !=
'java' and args.type !=
'android':
1271 assert os.path.exists(build_dir),
'Build variant directory %s does not exist!' % build_dir
1273 if args.sanitizer_suppressions:
1275 ),
'The sanitizer suppressions flag is only supported on Linux and Mac.'
1276 file_dir = os.path.dirname(os.path.abspath(__file__))
1278 'env',
'-i',
'bash',
'-c',
1279 'source {}/sanitizer_suppressions.sh >/dev/null && env'.
format(file_dir)
1281 process = subprocess.Popen(command, stdout=subprocess.PIPE)
1282 for line
in process.stdout:
1283 key, _, value = line.decode(
'utf8').strip().partition(
'=')
1284 os.environ[key] = value
1285 process.communicate()
1289 engine_filter = args.engine_filter.split(
',')
if args.engine_filter
else None
1290 if 'engine' in types:
1291 run_cc_tests(build_dir, engine_filter, args.coverage, args.engine_capture_core_dump)
1294 if 'impeller' in types:
1295 build_name = args.variant
1301 'impeller_unittests',
1304 coverage=args.coverage,
1305 extra_env=extra_env,
1312 dart_filter = args.dart_filter.split(
',')
if args.dart_filter
else None
1317 if 'dart-host' in types:
1318 dart_filter = args.dart_host_filter.split(
',')
if args.dart_host_filter
else None
1321 for dart_host_package, extra_opts
in dart_host_packages:
1322 if dart_filter
is None or dart_host_package
in dart_filter:
1326 os.path.join(BUILDROOT_DIR, dart_host_package),
1334 assert not is_windows(),
"Android engine files can't be compiled on Windows."
1335 java_filter = args.java_filter
1336 if ',' in java_filter
or '*' in java_filter:
1338 'Can only filter JUnit4 tests by single entire class name, '
1339 'eg "io.flutter.SmokeTest". Ignoring filter=' + java_filter
1344 if 'android' in types:
1345 assert not is_windows(),
"Android engine files can't be compiled on Windows."
1349 assert is_mac(),
'iOS embedding tests can only be run on macOS.'
1353 if 'benchmarks' in types
and not is_windows():
1357 variants_to_skip = [
'host_release',
'host_profile']
1360 matches = [variant
for variant
in variants_to_skip
if variant
in args.variant]
1361 return len(matches) > 0
1363 if (
'engine' in types
or 'font-subset' in types)
and not should_skip(args.variant):
1364 cmd = [
'python3',
'test.py',
'--variant', args.variant]
1365 if 'arm64' in args.variant:
1366 cmd += [
'--target-cpu',
'arm64']
1367 run_cmd(cmd, cwd=FONT_SUBSET_DIR)
1369 if 'impeller-golden' in types:
1372 if args.quiet
and args.logs_dir:
1373 shutil.copy(LOG_FILE, os.path.join(args.logs_dir,
'run_tests.log'))
1375 return 0
if success
else 1
1378if __name__ ==
'__main__':
static bool should_skip(const char *sink, const char *src, const char *srcOptions, const char *name)
def __init__(self, str new_cwd)
def __exit__(self, exception_type, exception_value, exception_traceback)
def __call__(self, *args)
def __init__(self, build_dir, executable_name, executable_filter, flags=None, cwd=BUILDROOT_DIR, forbidden_output=None, allowed_failure_output=None, expect_failure=False, coverage=False, extra_env=None)
def __init__(self, multithreaded=False, enable_impeller=False, enable_observatory=False, expect_failure=False)
def impeller_enabled(self)
def threading_description(self)
def apply_args(self, command_args)
uint32_t uint32_t * format
def run_android_unittest(test_runner_name, android_variant, adb_path)
def gather_dart_tests(build_dir, test_filter)
def build_engine_executable_command(build_dir, executable_name, flags=None, coverage=False, gtest=False)
def delete_simulator(simulator_name)
def assert_expected_xcode_version()
def metal_validation_env()
def run_engine_tasks_in_parallel(tasks)
def build_dart_host_test_list(build_dir)
def run_impeller_golden_tests(str build_dir, bool require_skia_gold=False)
def gather_dart_package_tests(build_dir, package_path, extra_opts)
def ensure_ios_tests_are_built(ios_out_dir)
def run_java_tests(executable_filter, android_variant='android_debug_unopt')
def run_benchmark_tests(build_dir)
def run_cc_tests(build_dir, executable_filter, coverage, capture_core_dump)
def find_executable_path(path)
def gather_dart_test(build_dir, dart_file, options)
def run_android_tests(android_variant='android_debug_unopt', adb_path=None)
def run_engine_executable(build_dir, executable_name, executable_filter, flags=None, cwd=BUILDROOT_DIR, forbidden_output=None, allowed_failure_output=None, expect_failure=False, coverage=False, extra_env=None, gtest=False)
def worker_init(queue, level)
def run_objc_tests(ios_variant='ios_debug_sim_unopt', test_filter=None)
def print_divider(char='=')
None run_cmd(typing.List[str] cmd, typing.List[str] forbidden_output=None, bool expect_failure=False, typing.Dict[str, str] env=None, typing.List[str] allowed_failure_output=None, **kwargs)
def vulkan_validation_env(build_dir)
def gather_dart_smoke_test(build_dir, test_filter)
def print(*args, **kwargs)
def run_engine_benchmarks(build_dir, executable_filter)
def start_virtual_x(child_build_name, build_dir)
def stop_virtual_x(child_build_name)
static SkString join(const CommandLineFlags::StringArray &)