Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Functions | Variables
run_tests Namespace Reference

Classes

class  _BundledTestRunner
 
class  DirectoryChange
 
class  EngineExecutableTask
 
class  FlutterTesterOptions
 
class  TestCase
 

Functions

Set[str] resolve_packages (Iterable[Mapping[str, Any]] tests)
 
List[TestCasebuild_test_cases (Iterable[Mapping[str, Any]] tests)
 
_BundledTestRunner _bundled_test_runner_of (str target_id)
 
TestRunner _get_test_runner (argparse.Namespace runner_args, *_)
 
 print (*args, **kwargs)
 
 print_divider (char='=')
 
 is_asan (build_dir)
 
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)
 
 is_mac ()
 
 is_aarm64 ()
 
 is_linux ()
 
 is_windows ()
 
 executable_suffix ()
 
 find_executable_path (path)
 
 vulkan_validation_env (build_dir)
 
 metal_validation_env ()
 
 build_engine_executable_command (build_dir, executable_name, flags=None, coverage=False, gtest=False)
 
 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)
 
 run_cc_tests (build_dir, executable_filter, coverage, capture_core_dump)
 
 run_engine_benchmarks (build_dir, executable_filter)
 
 gather_dart_test (build_dir, dart_file, options)
 
 ensure_ios_tests_are_built (ios_out_dir)
 
 assert_expected_xcode_version ()
 
 java_home ()
 
 java_bin ()
 
 run_java_tests (executable_filter, android_variant='android_debug_unopt')
 
 run_android_unittest (test_runner_name, android_variant, adb_path)
 
 run_android_tests (android_variant='android_debug_unopt', adb_path=None)
 
 run_objc_tests (ios_variant='ios_debug_sim_unopt', test_filter=None)
 
 delete_simulator (simulator_name)
 
 gather_dart_tests (build_dir, test_filter)
 
 gather_dart_smoke_test (build_dir, test_filter)
 
 gather_dart_package_tests (build_dir, package_path, extra_opts)
 
 build_dart_host_test_list (build_dir)
 
 run_benchmark_tests (build_dir)
 
 worker_init (queue, level)
 
 run_engine_tasks_in_parallel (tasks)
 
 run_impeller_golden_tests (str build_dir, bool require_skia_gold=False)
 
 main ()
 

Variables

 VARIANT = sys.argv[1]
 
 OUT_DIR = os.path.join(DIR_SRC_ROOT, 'out', VARIANT)
 
 level
 
 _get_test_runner
 
 SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
 
 BUILDROOT_DIR = os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..', '..'))
 
 GOLDEN_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'resources')
 
 FONTS_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'third_party', 'txt', 'third_party', 'fonts')
 
 ROBOTO_FONT_PATH = os.path.join(FONTS_DIR, 'Roboto-Regular.ttf')
 
 FONT_SUBSET_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'tools', 'font_subset')
 
str ENCODING = 'UTF-8'
 
 LOG_FILE = os.path.join(OUT_DIR, 'run_tests.log')
 
 logger = logging.getLogger(__name__)
 
 console_logger_handler = logging.StreamHandler()
 
 file_logger_handler = logging.FileHandler(LOG_FILE)
 
list shuffle_flags
 
list repeat_flags
 

Detailed Description

A top level harness to run all unit-tests in a specific engine build.

Function Documentation

◆ _bundled_test_runner_of()

_BundledTestRunner run_tests._bundled_test_runner_of ( str  target_id)
protected

Definition at line 124 of file run_tests.py.

124def _bundled_test_runner_of(target_id: str) -> _BundledTestRunner:
125 log_dir = os.environ.get('FLUTTER_LOGS_DIR', '/tmp/log')
126 with open(os.path.join(os.path.dirname(__file__), 'test_suites.yaml'), 'r') as file:
127 tests = yaml.safe_load(file)
128 # TODO(zijiehe-google-com): Run all tests in release build,
129 # https://github.com/flutter/flutter/issues/140179.
130 def variant(test) -> bool:
131 return 'variant' not in test or test['variant'] in VARIANT
132
133 tests = [t for t in tests if variant(t)]
134 return _BundledTestRunner(target_id, resolve_packages(tests), build_test_cases(tests), log_dir)
135
136

◆ _get_test_runner()

TestRunner run_tests._get_test_runner ( argparse.Namespace  runner_args,
_ 
)
protected

Definition at line 137 of file run_tests.py.

137def _get_test_runner(runner_args: argparse.Namespace, *_) -> TestRunner:
138 return _bundled_test_runner_of(runner_args.target_id)
139
140

◆ assert_expected_xcode_version()

run_tests.assert_expected_xcode_version ( )
Checks that the user has a version of Xcode installed

Definition at line 679 of file run_tests.py.

679def assert_expected_xcode_version():
680 """Checks that the user has a version of Xcode installed"""
681 version_output = subprocess.check_output(['xcodebuild', '-version'])
682 # TODO ricardoamador: remove this check when python 2 is deprecated.
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
689
690

◆ build_dart_host_test_list()

run_tests.build_dart_host_test_list (   build_dir)

Definition at line 927 of file run_tests.py.

927def build_dart_host_test_list(build_dir):
928 dart_host_tests = [
929 (
930 os.path.join('flutter', 'ci'),
931 [os.path.join(BUILDROOT_DIR, 'flutter')],
932 ),
933 (
934 os.path.join('flutter', 'flutter_frontend_server'),
935 [
936 build_dir,
937 os.path.join(build_dir, 'gen', 'frontend_server_aot.dart.snapshot'),
938 os.path.join(build_dir, 'flutter_patched_sdk')
939 ],
940 ),
941 (os.path.join('flutter', 'testing', 'litetest'), []),
942 (os.path.join('flutter', 'testing', 'pkg_test_demo'), []),
943 (os.path.join('flutter', 'testing', 'skia_gold_client'), []),
944 (os.path.join('flutter', 'testing', 'scenario_app'), []),
945 (
946 os.path.join('flutter', 'tools', 'api_check'),
947 [os.path.join(BUILDROOT_DIR, 'flutter')],
948 ),
949 (os.path.join('flutter', 'tools', 'build_bucket_golden_scraper'), []),
950 (os.path.join('flutter', 'tools', 'clang_tidy'), []),
951 (
952 os.path.join('flutter', 'tools', 'const_finder'),
953 [
954 os.path.join(build_dir, 'gen', 'frontend_server_aot.dart.snapshot'),
955 os.path.join(build_dir, 'flutter_patched_sdk'),
956 os.path.join(build_dir, 'dart-sdk', 'lib', 'libraries.json'),
957 ],
958 ),
959 (os.path.join('flutter', 'tools', 'dir_contents_diff'), []),
960 (os.path.join('flutter', 'tools', 'engine_tool'), []),
961 (os.path.join('flutter', 'tools', 'githooks'), []),
962 (os.path.join('flutter', 'tools', 'header_guard_check'), []),
963 (os.path.join('flutter', 'tools', 'pkg', 'engine_build_configs'), []),
964 (os.path.join('flutter', 'tools', 'pkg', 'engine_repo_tools'), []),
965 (os.path.join('flutter', 'tools', 'pkg', 'git_repo_tools'), []),
966 ]
967 if not is_asan(build_dir):
968 dart_host_tests += [
969 (os.path.join('flutter', 'tools', 'path_ops', 'dart'), []),
970 ]
971
972 return dart_host_tests
973
974

◆ build_engine_executable_command()

run_tests.build_engine_executable_command (   build_dir,
  executable_name,
  flags = None,
  coverage = False,
  gtest = False 
)

Definition at line 206 of file run_tests.py.

208):
209 if flags is None:
210 flags = []
211
212 unstripped_exe = os.path.join(build_dir, 'exe.unstripped', executable_name)
213 # We cannot run the unstripped binaries directly when coverage is enabled.
214 if is_linux() and os.path.exists(unstripped_exe) and not coverage:
215 # Use unstripped executables in order to get better symbolized crash
216 # stack traces on Linux.
217 executable = unstripped_exe
218 else:
219 executable = find_executable_path(os.path.join(build_dir, executable_name))
220
221 coverage_script = os.path.join(BUILDROOT_DIR, 'flutter', 'build', 'generate_coverage.py')
222
223 if coverage:
224 coverage_flags = [
225 '-t', executable, '-o',
226 os.path.join(build_dir, 'coverage', executable_name), '-f', 'html'
227 ]
228 updated_flags = ['--args=%s' % ' '.join(flags)]
229 test_command = [coverage_script] + coverage_flags + updated_flags
230 else:
231 test_command = [executable] + flags
232 if gtest:
233 gtest_parallel = os.path.join(
234 BUILDROOT_DIR, 'flutter', 'third_party', 'gtest-parallel', 'gtest-parallel'
235 )
236 test_command = ['python3', gtest_parallel] + test_command
237
238 return test_command
239
240

◆ build_test_cases()

List[TestCase] run_tests.build_test_cases ( Iterable[Mapping[str, Any]]  tests)

Definition at line 111 of file run_tests.py.

111def build_test_cases(tests: Iterable[Mapping[str, Any]]) -> List[TestCase]:
112 test_cases = []
113 for test in [t['test_command'] for t in tests]:
114 assert test.startswith('test run ')
115 test = test[len('test run '):]
116 if ' -- ' in test:
117 package, args = test.split(' -- ', 1)
118 test_cases.append(TestCase(package=package, args=args))
119 else:
120 test_cases.append(TestCase(package=test))
121 return test_cases
122
123

◆ delete_simulator()

run_tests.delete_simulator (   simulator_name)

Definition at line 827 of file run_tests.py.

827def delete_simulator(simulator_name):
828 # Will delete all simulators with this name.
829 command = [
830 'xcrun',
831 'simctl',
832 'delete',
833 simulator_name,
834 ]
835 # Let this fail if the simulator was never created.
836 run_cmd(command, expect_failure=True)
837
838

◆ ensure_ios_tests_are_built()

run_tests.ensure_ios_tests_are_built (   ios_out_dir)
Builds the engine variant and the test dylib containing the XCTests

Definition at line 666 of file run_tests.py.

666def ensure_ios_tests_are_built(ios_out_dir):
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')
670 message = []
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)
675 )
676 assert os.path.exists(tmp_out_dir) and os.path.exists(ios_test_lib), final_message
677
678

◆ executable_suffix()

run_tests.executable_suffix ( )

Definition at line 155 of file run_tests.py.

155def executable_suffix():
156 return '.exe' if is_windows() else ''
157
158

◆ find_executable_path()

run_tests.find_executable_path (   path)

Definition at line 159 of file run_tests.py.

159def find_executable_path(path):
160 if os.path.exists(path):
161 return path
162
163 if is_windows():
164 exe_path = path + '.exe'
165 if os.path.exists(exe_path):
166 return exe_path
167
168 bat_path = path + '.bat'
169 if os.path.exists(bat_path):
170 return bat_path
171
172 raise Exception('Executable %s does not exist!' % path)
173
174

◆ gather_dart_package_tests()

run_tests.gather_dart_package_tests (   build_dir,
  package_path,
  extra_opts 
)

Definition at line 908 of file run_tests.py.

908def gather_dart_package_tests(build_dir, package_path, extra_opts):
909 dart_tests = glob.glob('%s/test/*_test.dart' % package_path)
910 if not dart_tests:
911 raise Exception('No tests found for Dart package at %s' % package_path)
912 for dart_test_file in dart_tests:
913 opts = ['--disable-dart-dev', dart_test_file] + extra_opts
914 yield EngineExecutableTask(
915 build_dir, os.path.join('dart-sdk', 'bin', 'dart'), None, flags=opts, cwd=package_path
916 )
917
918
919# Returns a list of Dart packages to test.
920#
921# The first element of each tuple in the returned list is the path to the Dart
922# package to test. It is assumed that the packages follow the convention that
923# tests are named as '*_test.dart', and reside under a directory called 'test'.
924#
925# The second element of each tuple is a list of additional command line
926# arguments to pass to each of the packages tests.

◆ gather_dart_smoke_test()

run_tests.gather_dart_smoke_test (   build_dir,
  test_filter 
)

Definition at line 889 of file run_tests.py.

889def gather_dart_smoke_test(build_dir, test_filter):
890 smoke_test = os.path.join(
891 BUILDROOT_DIR,
892 'flutter',
893 'testing',
894 'smoke_test_failure',
895 'fail_test.dart',
896 )
897 if test_filter is not None and os.path.basename(smoke_test) not in test_filter:
898 logger.info("Skipping '%s' due to filter.", smoke_test)
899 else:
900 yield gather_dart_test(
901 build_dir, smoke_test, FlutterTesterOptions(multithreaded=True, expect_failure=True)
902 )
903 yield gather_dart_test(
904 build_dir, smoke_test, FlutterTesterOptions(multithreaded=False, expect_failure=True)
905 )
906
907

◆ gather_dart_test()

run_tests.gather_dart_test (   build_dir,
  dart_file,
  options 
)

Definition at line 625 of file run_tests.py.

625def gather_dart_test(build_dir, dart_file, options):
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
630 )
631 assert os.path.isfile(kernel_file_output), error_message
632
633 command_args = []
634
635 options.apply_args(command_args)
636
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)
641
642 command_args += [
643 '--use-test-fonts',
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',
647 kernel_file_output,
648 ]
649
650 tester_name = 'flutter_tester'
651 logger.info(
652 "Running test '%s' using '%s' (%s, %s)", kernel_file_name, tester_name,
653 options.threading_description(), options.impeller_enabled()
654 )
655 forbidden_output = [] if 'unopt' in build_dir or options.expect_failure else ['[ERROR']
656 return EngineExecutableTask(
657 build_dir,
658 tester_name,
659 None,
660 command_args,
661 forbidden_output=forbidden_output,
662 expect_failure=options.expect_failure,
663 )
664
665

◆ gather_dart_tests()

run_tests.gather_dart_tests (   build_dir,
  test_filter 
)

Definition at line 839 of file run_tests.py.

839def gather_dart_tests(build_dir, test_filter):
840 dart_tests_dir = os.path.join(
841 BUILDROOT_DIR,
842 'flutter',
843 'testing',
844 'dart',
845 )
846
847 # Now that we have the Sky packages at the hardcoded location, run `dart pub get`.
848 run_engine_executable(
849 build_dir,
850 os.path.join('dart-sdk', 'bin', 'dart'),
851 None,
852 flags=['pub', '--suppress-analytics', 'get', '--offline'],
853 cwd=dart_tests_dir,
854 )
855
856 dart_observatory_tests = glob.glob('%s/observatory/*_test.dart' % dart_tests_dir)
857 dart_tests = glob.glob('%s/*_test.dart' % dart_tests_dir)
858
859 if 'release' not in build_dir:
860 for dart_test_file in dart_observatory_tests:
861 if test_filter is not None and os.path.basename(dart_test_file) not in test_filter:
862 logger.info("Skipping '%s' due to filter.", dart_test_file)
863 else:
864 logger.info("Gathering dart test '%s' with observatory enabled", dart_test_file)
865 for multithreaded in [False, True]:
866 for enable_impeller in [False, True]:
867 yield gather_dart_test(
868 build_dir, dart_test_file,
869 FlutterTesterOptions(
870 multithreaded=multithreaded,
871 enable_impeller=enable_impeller,
872 enable_observatory=True
873 )
874 )
875
876 for dart_test_file in dart_tests:
877 if test_filter is not None and os.path.basename(dart_test_file) not in test_filter:
878 logger.info("Skipping '%s' due to filter.", dart_test_file)
879 else:
880 logger.info("Gathering dart test '%s'", dart_test_file)
881 for multithreaded in [False, True]:
882 for enable_impeller in [False, True]:
883 yield gather_dart_test(
884 build_dir, dart_test_file,
885 FlutterTesterOptions(multithreaded=multithreaded, enable_impeller=enable_impeller)
886 )
887
888

◆ is_aarm64()

run_tests.is_aarm64 ( )

Definition at line 137 of file run_tests.py.

137def is_aarm64():
138 assert is_mac()
139 output = subprocess.check_output(['sysctl', 'machdep.cpu'])
140 text = output.decode('utf-8')
141 aarm64 = text.find('Apple') >= 0
142 if not aarm64:
143 assert text.find('GenuineIntel') >= 0
144 return aarm64
145
146

◆ is_asan()

run_tests.is_asan (   build_dir)

Definition at line 60 of file run_tests.py.

60def is_asan(build_dir):
61 with open(os.path.join(build_dir, 'args.gn')) as args:
62 if 'is_asan = true' in args.read():
63 return True
64
65 return False
66
67

◆ is_linux()

run_tests.is_linux ( )

Definition at line 147 of file run_tests.py.

147def is_linux():
148 return sys_platform.startswith('linux')
149
150

◆ is_mac()

run_tests.is_mac ( )

Definition at line 133 of file run_tests.py.

133def is_mac():
134 return sys_platform == 'darwin'
135
136

◆ is_windows()

run_tests.is_windows ( )

Definition at line 151 of file run_tests.py.

151def is_windows():
152 return sys_platform.startswith(('cygwin', 'win'))
153
154

◆ java_bin()

run_tests.java_bin ( )

Definition at line 700 of file run_tests.py.

700def java_bin():
701 return os.path.join(java_home(), 'bin', 'java.exe' if is_windows() else 'java')
702
703

◆ java_home()

run_tests.java_home ( )

Definition at line 691 of file run_tests.py.

691def java_home():
692 script_path = os.path.dirname(os.path.realpath(__file__))
693 if is_mac():
694 return os.path.join(
695 script_path, '..', '..', 'third_party', 'java', 'openjdk', 'Contents', 'Home'
696 )
697 return os.path.join(script_path, '..', '..', 'third_party', 'java', 'openjdk')
698
699

◆ main()

run_tests.main ( )

Definition at line 1120 of file run_tests.py.

1120def main():
1121 parser = argparse.ArgumentParser(
1122 description="""
1123In order to learn the details of running tests in the engine, please consult the
1124Flutter Wiki page on the subject: https://github.com/flutter/flutter/wiki/Testing-the-engine
1125"""
1126 )
1127 all_types = [
1128 'engine',
1129 'dart',
1130 'dart-host',
1131 'benchmarks',
1132 'java',
1133 'android',
1134 'objc',
1135 'font-subset',
1136 'impeller-golden',
1137 ]
1138
1139 parser.add_argument(
1140 '--variant',
1141 dest='variant',
1142 action='store',
1143 default='host_debug_unopt',
1144 help='The engine build variant to run the tests for.'
1145 )
1146 parser.add_argument(
1147 '--type',
1148 type=str,
1149 default='all',
1150 help='A list of test types, default is "all" (equivalent to "%s")' % (','.join(all_types))
1151 )
1152 parser.add_argument(
1153 '--engine-filter', type=str, default='', help='A list of engine test executables to run.'
1154 )
1155 parser.add_argument(
1156 '--dart-filter',
1157 type=str,
1158 default='',
1159 help='A list of Dart test scripts to run in flutter_tester.'
1160 )
1161 parser.add_argument(
1162 '--dart-host-filter',
1163 type=str,
1164 default='',
1165 help='A list of Dart test scripts to run with the Dart CLI.'
1166 )
1167 parser.add_argument(
1168 '--java-filter',
1169 type=str,
1170 default='',
1171 help='A single Java test class to run (example: "io.flutter.SmokeTest")'
1172 )
1173 parser.add_argument(
1174 '--android-variant',
1175 dest='android_variant',
1176 action='store',
1177 default='android_debug_unopt',
1178 help='The engine build variant to run java or android tests for'
1179 )
1180 parser.add_argument(
1181 '--ios-variant',
1182 dest='ios_variant',
1183 action='store',
1184 default='ios_debug_sim_unopt',
1185 help='The engine build variant to run objective-c tests for'
1186 )
1187 parser.add_argument(
1188 '--verbose-dart-snapshot',
1189 dest='verbose_dart_snapshot',
1190 action='store_true',
1191 default=False,
1192 help='Show extra dart snapshot logging.'
1193 )
1194 parser.add_argument(
1195 '--objc-filter',
1196 type=str,
1197 default=None,
1198 help=(
1199 'Filter parameter for which objc tests to run '
1200 '(example: "IosUnitTestsTests/SemanticsObjectTest/testShouldTriggerAnnouncement")'
1201 )
1202 )
1203 parser.add_argument(
1204 '--coverage',
1205 action='store_true',
1206 default=None,
1207 help='Generate coverage reports for each unit test framework run.'
1208 )
1209 parser.add_argument(
1210 '--engine-capture-core-dump',
1211 dest='engine_capture_core_dump',
1212 action='store_true',
1213 default=False,
1214 help='Capture core dumps from crashes of engine tests.'
1215 )
1216 parser.add_argument(
1217 '--use-sanitizer-suppressions',
1218 dest='sanitizer_suppressions',
1219 action='store_true',
1220 default=False,
1221 help='Provide the sanitizer suppressions lists to the via environment to the tests.'
1222 )
1223 parser.add_argument(
1224 '--adb-path',
1225 dest='adb_path',
1226 action='store',
1227 default=None,
1228 help='Provide the path of adb used for android tests. By default it looks on $PATH.'
1229 )
1230 parser.add_argument(
1231 '--quiet',
1232 dest='quiet',
1233 action='store_true',
1234 default=False,
1235 help='Only emit output when there is an error.'
1236 )
1237 parser.add_argument(
1238 '--logs-dir',
1239 dest='logs_dir',
1240 type=str,
1241 help='The directory that verbose logs will be copied to in --quiet mode.',
1242 )
1243 parser.add_argument(
1244 '--no-skia-gold',
1245 dest='no_skia_gold',
1246 action='store_true',
1247 default=False,
1248 help='Do not compare golden images with Skia Gold.',
1249 )
1250
1251 args = parser.parse_args()
1252
1253 logger.addHandler(console_logger_handler)
1254 logger.addHandler(file_logger_handler)
1255 logger.setLevel(logging.INFO)
1256 if args.quiet:
1257 file_logger_handler.setLevel(logging.INFO)
1258 console_logger_handler.setLevel(logging.WARNING)
1259 else:
1260 console_logger_handler.setLevel(logging.INFO)
1261
1262 if args.type == 'all':
1263 types = all_types
1264 else:
1265 types = args.type.split(',')
1266
1267 build_dir = os.path.join(OUT_DIR, args.variant)
1268 if args.type != 'java' and args.type != 'android':
1269 assert os.path.exists(build_dir), 'Build variant directory %s does not exist!' % build_dir
1270
1271 if args.sanitizer_suppressions:
1272 assert is_linux() or is_mac(
1273 ), 'The sanitizer suppressions flag is only supported on Linux and Mac.'
1274 file_dir = os.path.dirname(os.path.abspath(__file__))
1275 command = [
1276 'env', '-i', 'bash', '-c',
1277 'source {}/sanitizer_suppressions.sh >/dev/null && env'.format(file_dir)
1278 ]
1279 process = subprocess.Popen(command, stdout=subprocess.PIPE)
1280 for line in process.stdout:
1281 key, _, value = line.decode('utf8').strip().partition('=')
1282 os.environ[key] = value
1283 process.communicate() # Avoid pipe deadlock while waiting for termination.
1284
1285 success = True
1286
1287 engine_filter = args.engine_filter.split(',') if args.engine_filter else None
1288 if 'engine' in types:
1289 run_cc_tests(build_dir, engine_filter, args.coverage, args.engine_capture_core_dump)
1290
1291 # Use this type to exclusively run impeller tests.
1292 if 'impeller' in types:
1293 build_name = args.variant
1294 try:
1295 xvfb.start_virtual_x(build_name, build_dir)
1296 extra_env = vulkan_validation_env(build_dir)
1297 run_engine_executable(
1298 build_dir,
1299 'impeller_unittests',
1300 engine_filter,
1301 repeat_flags,
1302 coverage=args.coverage,
1303 extra_env=extra_env,
1304 gtest=True
1305 )
1306 finally:
1307 xvfb.stop_virtual_x(build_name)
1308
1309 if 'dart' in types:
1310 dart_filter = args.dart_filter.split(',') if args.dart_filter else None
1311 tasks = list(gather_dart_smoke_test(build_dir, dart_filter))
1312 tasks += list(gather_dart_tests(build_dir, dart_filter))
1313 success = success and run_engine_tasks_in_parallel(tasks)
1314
1315 if 'dart-host' in types:
1316 dart_filter = args.dart_host_filter.split(',') if args.dart_host_filter else None
1317 dart_host_packages = build_dart_host_test_list(build_dir)
1318 tasks = []
1319 for dart_host_package, extra_opts in dart_host_packages:
1320 if dart_filter is None or dart_host_package in dart_filter:
1321 tasks += list(
1322 gather_dart_package_tests(
1323 build_dir,
1324 os.path.join(BUILDROOT_DIR, dart_host_package),
1325 extra_opts,
1326 )
1327 )
1328
1329 success = success and run_engine_tasks_in_parallel(tasks)
1330
1331 if 'java' in types:
1332 assert not is_windows(), "Android engine files can't be compiled on Windows."
1333 java_filter = args.java_filter
1334 if ',' in java_filter or '*' in java_filter:
1335 logger.wraning(
1336 'Can only filter JUnit4 tests by single entire class name, '
1337 'eg "io.flutter.SmokeTest". Ignoring filter=' + java_filter
1338 )
1339 java_filter = None
1340 run_java_tests(java_filter, args.android_variant)
1341
1342 if 'android' in types:
1343 assert not is_windows(), "Android engine files can't be compiled on Windows."
1344 run_android_tests(args.android_variant, args.adb_path)
1345
1346 if 'objc' in types:
1347 assert is_mac(), 'iOS embedding tests can only be run on macOS.'
1348 run_objc_tests(args.ios_variant, args.objc_filter)
1349
1350 # https://github.com/flutter/flutter/issues/36300
1351 if 'benchmarks' in types and not is_windows():
1352 run_benchmark_tests(build_dir)
1353 run_engine_benchmarks(build_dir, engine_filter)
1354
1355 variants_to_skip = ['host_release', 'host_profile']
1356
1357 def should_skip(variant):
1358 matches = [variant for variant in variants_to_skip if variant in args.variant]
1359 return len(matches) > 0
1360
1361 if ('engine' in types or 'font-subset' in types) and not should_skip(args.variant):
1362 cmd = ['python3', 'test.py', '--variant', args.variant]
1363 if 'arm64' in args.variant:
1364 cmd += ['--target-cpu', 'arm64']
1365 run_cmd(cmd, cwd=FONT_SUBSET_DIR)
1366
1367 if 'impeller-golden' in types:
1368 run_impeller_golden_tests(build_dir, require_skia_gold=not args.no_skia_gold)
1369
1370 if args.quiet and args.logs_dir:
1371 shutil.copy(LOG_FILE, os.path.join(args.logs_dir, 'run_tests.log'))
1372
1373 return 0 if success else 1
1374
1375
static bool should_skip(const char *sink, const char *src, const char *srcOptions, const char *name)
Definition DM.cpp:1142
uint32_t uint32_t * format
Definition main.py:1
start_virtual_x(child_build_name, build_dir)
Definition xvfb.py:27
stop_virtual_x(child_build_name)
Definition xvfb.py:138

◆ metal_validation_env()

run_tests.metal_validation_env ( )

Definition at line 188 of file run_tests.py.

188def metal_validation_env():
189 extra_env = {
190 # pylint: disable=line-too-long
191 # See https://developer.apple.com/documentation/metal/diagnosing_metal_programming_issues_early?language=objc
192 'MTL_SHADER_VALIDATION': '1', # Enables all shader validation tests.
193 'MTL_SHADER_VALIDATION_GLOBAL_MEMORY':
194 '1', # Validates accesses to device and constant memory.
195 'MTL_SHADER_VALIDATION_THREADGROUP_MEMORY': '1', # Validates accesses to threadgroup memory.
196 'MTL_SHADER_VALIDATION_TEXTURE_USAGE': '1', # Validates that texture references are not nil.
197 }
198 if is_aarm64():
199 extra_env.update({
200 'METAL_DEBUG_ERROR_MODE': '0', # Enables metal validation.
201 'METAL_DEVICE_WRAPPER_TYPE': '1', # Enables metal validation.
202 })
203 return extra_env
204
205

◆ print()

run_tests.print ( args,
**  kwargs 
)

Definition at line 49 of file run_tests.py.

49def print(*args, **kwargs): # pylint: disable=redefined-builtin
50 logger.info(*args, **kwargs)
51
52
void print(void *str)
Definition bridge.cpp:126

◆ print_divider()

run_tests.print_divider (   char = '=')

Definition at line 53 of file run_tests.py.

53def print_divider(char='='):
54 logger.info('\n')
55 for _ in range(4):
56 logger.info(''.join([char for _ in range(80)]))
57 logger.info('\n')
58
59

◆ resolve_packages()

Set[str] run_tests.resolve_packages ( Iterable[Mapping[str, Any]]  tests)

Definition at line 82 of file run_tests.py.

82def resolve_packages(tests: Iterable[Mapping[str, Any]]) -> Set[str]:
83 packages = set()
84 for test in tests:
85 if 'package' in test:
86 packages.add(test['package'])
87 else:
88 assert 'packages' in test, \
89 'Expect either one package or a list of packages'
90 packages.update(test['packages'])
91 resolved_packages = set()
92 for package in packages:
93 if package.endswith('-0.far'):
94 # Make a symbolic link to match the name of the package itself without the
95 # '-0.far' suffix.
96 new_package = os.path.join(OUT_DIR, package.replace('-0.far', '.far'))
97 try:
98 # Remove the old one if it exists, usually happen on the devbox, so
99 # ignore the FileNotFoundError.
100 os.remove(new_package)
101 except FileNotFoundError:
102 pass
103 os.symlink(package, new_package)
104 resolved_packages.add(new_package)
105 else:
106 resolved_packages.add(os.path.join(OUT_DIR, package))
107 return resolved_packages
108
109
110# Visible for testing

◆ run_android_tests()

run_tests.run_android_tests (   android_variant = 'android_debug_unopt',
  adb_path = None 
)

Definition at line 752 of file run_tests.py.

752def run_android_tests(android_variant='android_debug_unopt', adb_path=None):
753 if adb_path is None:
754 adb_path = 'adb'
755
756 run_android_unittest('flutter_shell_native_unittests', android_variant, adb_path)
757 run_android_unittest('impeller_toolkit_android_unittests', android_variant, adb_path)
758
759 systrace_test = os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'android_systrace_test.py')
760 scenario_apk = os.path.join(OUT_DIR, android_variant, 'firebase_apks', 'scenario_app.apk')
761 run_cmd([
762 systrace_test, '--adb-path', adb_path, '--apk-path', scenario_apk, '--package-name',
763 'dev.flutter.scenarios', '--activity-name', '.PlatformViewsActivity'
764 ])
765
766

◆ run_android_unittest()

run_tests.run_android_unittest (   test_runner_name,
  android_variant,
  adb_path 
)

Definition at line 734 of file run_tests.py.

734def run_android_unittest(test_runner_name, android_variant, adb_path):
735 tests_path = os.path.join(OUT_DIR, android_variant, test_runner_name)
736 remote_path = '/data/local/tmp'
737 remote_tests_path = os.path.join(remote_path, test_runner_name)
738 run_cmd([adb_path, 'push', tests_path, remote_path], cwd=BUILDROOT_DIR)
739
740 try:
741 run_cmd([adb_path, 'shell', remote_tests_path])
742 except:
743 luci_test_outputs_path = os.environ.get('FLUTTER_TEST_OUTPUTS_DIR')
744 if luci_test_outputs_path:
745 print('>>>>> Test %s failed. Capturing logcat.' % test_runner_name)
746 logcat_path = os.path.join(luci_test_outputs_path, '%s_logcat' % test_runner_name)
747 logcat_file = open(logcat_path, 'w')
748 subprocess.run([adb_path, 'logcat', '-d'], stdout=logcat_file, check=False)
749 raise
750
751

◆ run_benchmark_tests()

run_tests.run_benchmark_tests (   build_dir)

Definition at line 975 of file run_tests.py.

975def run_benchmark_tests(build_dir):
976 test_dir = os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'benchmark')
977 dart_tests = glob.glob('%s/test/*_test.dart' % test_dir)
978 for dart_test_file in dart_tests:
979 opts = ['--disable-dart-dev', dart_test_file]
980 run_engine_executable(
981 build_dir, os.path.join('dart-sdk', 'bin', 'dart'), None, flags=opts, cwd=test_dir
982 )
983
984

◆ run_cc_tests()

run_tests.run_cc_tests (   build_dir,
  executable_filter,
  coverage,
  capture_core_dump 
)

Definition at line 393 of file run_tests.py.

393def run_cc_tests(build_dir, executable_filter, coverage, capture_core_dump):
394 logger.info('Running Engine Unit-tests.')
395
396 if capture_core_dump and is_linux():
397 import resource # pylint: disable=import-outside-toplevel
398 resource.setrlimit(resource.RLIMIT_CORE, (resource.RLIM_INFINITY, resource.RLIM_INFINITY))
399
400 def make_test(name, flags=None, extra_env=None):
401 if flags is None:
402 flags = repeat_flags
403 if extra_env is None:
404 extra_env = {}
405 return (name, flags, extra_env)
406
407 unittests = [
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'),
424 # The image release unit test can take a while on slow machines.
425 make_test('ui_unittests', flags=repeat_flags + ['--timeout=90']),
426 ]
427
428 if not is_windows():
429 unittests += [
430 # https://github.com/google/googletest/issues/2490
431 make_test('android_external_view_embedder_unittests'),
432 make_test('jni_unittests'),
433 make_test('platform_view_android_delegate_unittests'),
434 # https://github.com/flutter/flutter/issues/36295
435 make_test('shell_unittests'),
436 ]
437
438 if is_windows():
439 unittests += [
440 # The accessibility library only supports Mac and Windows.
441 make_test('accessibility_unittests'),
442 make_test('client_wrapper_windows_unittests'),
443 make_test('flutter_windows_unittests'),
444 ]
445
446 # These unit-tests are Objective-C and can only run on Darwin.
447 if is_mac():
448 unittests += [
449 # The accessibility library only supports Mac and Windows.
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'),
455 ]
456
457 if is_linux():
458 flow_flags = [
459 '--golden-dir=%s' % GOLDEN_DIR,
460 '--font-file=%s' % ROBOTO_FONT_PATH,
461 ]
462 icu_flags = ['--icu-data-file-path=%s' % os.path.join(build_dir, 'icudtl.dat')]
463 unittests += [
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'}),
467 # https://github.com/flutter/flutter/issues/36296
468 make_test('txt_unittests', flags=repeat_flags + ['--'] + icu_flags),
469 ]
470 else:
471 flow_flags = ['--gtest_filter=-PerformanceOverlayLayer.Gold']
472 unittests += [
473 make_test('flow_unittests', flags=repeat_flags + flow_flags),
474 ]
475
476 build_name = os.path.basename(build_dir)
477 try:
478 if is_linux():
479 xvfb.start_virtual_x(build_name, build_dir)
480 for test, flags, extra_env in unittests:
481 run_engine_executable(
482 build_dir,
483 test,
484 executable_filter,
485 flags,
486 coverage=coverage,
487 extra_env=extra_env,
488 gtest=True
489 )
490 finally:
491 if is_linux():
492 xvfb.stop_virtual_x(build_name)
493
494 if is_mac():
495 # flutter_desktop_darwin_unittests uses global state that isn't handled
496 # correctly by gtest-parallel.
497 # https://github.com/flutter/flutter/issues/104789
498 if not os.path.basename(build_dir).startswith('host_debug'):
499 # Test is disabled for flaking in debug runs:
500 # https://github.com/flutter/flutter/issues/127441
501 run_engine_executable(
502 build_dir,
503 'flutter_desktop_darwin_unittests',
504 executable_filter,
505 shuffle_flags,
506 coverage=coverage
507 )
508 extra_env = metal_validation_env()
509 extra_env.update(vulkan_validation_env(build_dir))
510 mac_impeller_unittests_flags = repeat_flags + [
511 '--gtest_filter=-*OpenGLES', # These are covered in the golden tests.
512 '--',
513 '--enable_vulkan_validation',
514 ]
515 # Impeller tests are only supported on macOS for now.
516 run_engine_executable(
517 build_dir,
518 'impeller_unittests',
519 executable_filter,
520 mac_impeller_unittests_flags,
521 coverage=coverage,
522 extra_env=extra_env,
523 gtest=True,
524 # TODO(https://github.com/flutter/flutter/issues/123733): Remove this allowlist.
525 # See also https://github.com/flutter/flutter/issues/114872.
526 allowed_failure_output=[
527 '[MTLCompiler createVertexStageAndLinkPipelineWithFragment:',
528 '[MTLCompiler pipelineStateWithVariant:',
529 ]
530 )
531
532 # Run one interactive Vulkan test with validation enabled.
533 #
534 # TODO(matanlurey): https://github.com/flutter/flutter/issues/134852; enable
535 # more of the suite, and ideally we'd like to use Skia gold and take screen
536 # shots as well.
537 run_engine_executable(
538 build_dir,
539 'impeller_unittests',
540 executable_filter,
541 shuffle_flags + [
542 '--enable_vulkan_validation',
543 '--enable_playground',
544 '--playground_timeout_ms=4000',
545 '--gtest_filter="*ColorWheel/Vulkan"',
546 ],
547 coverage=coverage,
548 extra_env=extra_env,
549 )
550
551 # Run the Flutter GPU test suite.
552 run_engine_executable(
553 build_dir,
554 'impeller_dart_unittests',
555 executable_filter,
556 shuffle_flags + [
557 '--enable_vulkan_validation',
558 # TODO(https://github.com/flutter/flutter/issues/145036)
559 # TODO(https://github.com/flutter/flutter/issues/142642)
560 '--gtest_filter=*Metal',
561 ],
562 coverage=coverage,
563 extra_env=extra_env,
564 )
565
566

◆ run_cmd()

None run_tests.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 
)

Definition at line 68 of file run_tests.py.

75) -> None:
76 if forbidden_output is None:
77 forbidden_output = []
78 if allowed_failure_output is None:
79 allowed_failure_output = []
80
81 command_string = ' '.join(cmd)
82
83 print_divider('>')
84 logger.info('Running command "%s"', command_string)
85
86 start_time = time.time()
87
88 process = subprocess.Popen(
89 cmd,
90 stdout=subprocess.PIPE,
91 stderr=subprocess.STDOUT,
92 env=env,
93 universal_newlines=True,
94 **kwargs
95 )
96 output = ''
97
98 for line in iter(process.stdout.readline, ''):
99 output += line
100 logger.info(line.rstrip())
101
102 process.wait()
103 end_time = time.time()
104
105 if process.returncode != 0 and not expect_failure:
106 print_divider('!')
107
108 logger.error(
109 'Failed Command:\n\n%s\n\nExit Code: %s\n\nOutput:\n%s', command_string, process.returncode,
110 output
111 )
112
113 print_divider('!')
114
115 allowed_failure = False
116 for allowed_string in allowed_failure_output:
117 if allowed_string in output:
118 allowed_failure = True
119
120 if not allowed_failure:
121 raise RuntimeError('Command "%s" exited with code %s.' % (command_string, process.returncode))
122
123 for forbidden_string in forbidden_output:
124 if forbidden_string in output:
125 raise RuntimeError(
126 'command "%s" contained forbidden string "%s"' % (command_string, forbidden_string)
127 )
128
129 print_divider('<')
130 logger.info('Command run successfully in %.2f seconds: %s', end_time - start_time, command_string)
131
132

◆ run_engine_benchmarks()

run_tests.run_engine_benchmarks (   build_dir,
  executable_filter 
)

Definition at line 567 of file run_tests.py.

567def run_engine_benchmarks(build_dir, executable_filter):
568 logger.info('Running Engine Benchmarks.')
569
570 icu_flags = ['--icu-data-file-path=%s' % os.path.join(build_dir, 'icudtl.dat')]
571
572 run_engine_executable(build_dir, 'shell_benchmarks', executable_filter, icu_flags)
573
574 run_engine_executable(build_dir, 'fml_benchmarks', executable_filter, icu_flags)
575
576 run_engine_executable(build_dir, 'ui_benchmarks', executable_filter, icu_flags)
577
578 run_engine_executable(build_dir, 'display_list_builder_benchmarks', executable_filter, icu_flags)
579
580 run_engine_executable(build_dir, 'geometry_benchmarks', executable_filter, icu_flags)
581
582 run_engine_executable(build_dir, 'canvas_benchmarks', executable_filter, icu_flags)
583
584 if is_linux():
585 run_engine_executable(build_dir, 'txt_benchmarks', executable_filter, icu_flags)
586
587

◆ run_engine_executable()

run_tests.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 
)

Definition at line 241 of file run_tests.py.

253):
254 if executable_filter is not None and executable_name not in executable_filter:
255 logger.info('Skipping %s due to filter.', executable_name)
256 return
257
258 if flags is None:
259 flags = []
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:
265 extra_env = {}
266
267 unstripped_exe = os.path.join(build_dir, 'exe.unstripped', executable_name)
268 env = os.environ.copy()
269 if is_linux():
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
276 else:
277 vulkan_path = os.path.join(build_dir, 'libvulkan.so.1')
278 try:
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:
282 pass
283 else:
284 raise
285 elif is_mac():
286 env['DYLD_LIBRARY_PATH'] = build_dir
287 else:
288 env['PATH'] = build_dir + ':' + env['PATH']
289
290 logger.info('Running %s in %s', executable_name, cwd)
291
292 test_command = build_engine_executable_command(
293 build_dir,
294 executable_name,
295 flags=flags,
296 coverage=coverage,
297 gtest=gtest,
298 )
299
300 env['FLUTTER_BUILD_DIRECTORY'] = build_dir
301 for key, value in extra_env.items():
302 env[key] = value
303
304 try:
305 run_cmd(
306 test_command,
307 cwd=cwd,
308 forbidden_output=forbidden_output,
309 expect_failure=expect_failure,
310 env=env,
311 allowed_failure_output=allowed_failure_output,
312 )
313 except:
314 # The LUCI environment may provide a variable containing a directory path
315 # for additional output files that will be uploaded to cloud storage.
316 # If the command generated a core dump, then run a script to analyze
317 # the dump and output a report that will be uploaded.
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)
323 )
324 logger.error('Writing core dump analysis to %s', dump_path)
325 subprocess.call([
326 os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'analyze_core_dump.sh'),
327 BUILDROOT_DIR,
328 unstripped_exe,
329 core_path,
330 dump_path,
331 ])
332 os.unlink(core_path)
333 raise
334
335

◆ run_engine_tasks_in_parallel()

run_tests.run_engine_tasks_in_parallel (   tasks)

Definition at line 993 of file run_tests.py.

993def run_engine_tasks_in_parallel(tasks):
994 # Work around a bug in Python.
995 #
996 # The multiprocessing package relies on the win32 WaitForMultipleObjects()
997 # call, which supports waiting on a maximum of MAXIMUM_WAIT_OBJECTS (defined
998 # by Windows to be 64) handles, processes in this case. To avoid hitting
999 # this, we limit ourselves to 60 handles (since there are a couple extra
1000 # processes launched for the queue reader and thread wakeup reader).
1001 #
1002 # See: https://bugs.python.org/issue26903
1003 max_processes = multiprocessing.cpu_count()
1004 if sys_platform.startswith(('cygwin', 'win')) and max_processes > 60:
1005 max_processes = 60
1006
1007 queue = multiprocessing.Queue()
1008 queue_listener = logging.handlers.QueueListener(
1009 queue,
1010 console_logger_handler,
1011 file_logger_handler,
1012 respect_handler_level=True,
1013 )
1014 queue_listener.start()
1015
1016 failures = []
1017 try:
1018 with multiprocessing.Pool(max_processes, worker_init,
1019 [queue, logger.getEffectiveLevel()]) as pool:
1020 async_results = [(t, pool.apply_async(t, ())) for t in tasks]
1021 for task, async_result in async_results:
1022 try:
1023 async_result.get()
1024 except Exception as exn: # pylint: disable=broad-except
1025 failures += [(task, exn)]
1026 finally:
1027 queue_listener.stop()
1028
1029 if len(failures) > 0:
1030 logger.error('The following commands failed:')
1031 for task, exn in failures:
1032 logger.error('%s\n %s\n\n', str(task), str(exn))
1033 return False
1034
1035 return True
1036
1037

◆ run_impeller_golden_tests()

run_tests.run_impeller_golden_tests ( str  build_dir,
bool   require_skia_gold = False 
)
Executes the impeller golden image tests from in the `variant` build.

Definition at line 1056 of file run_tests.py.

1056def run_impeller_golden_tests(build_dir: str, require_skia_gold: bool = False):
1057 """
1058 Executes the impeller golden image tests from in the `variant` build.
1059 """
1060 tests_path: str = os.path.join(build_dir, 'impeller_golden_tests')
1061 if not os.path.exists(tests_path):
1062 raise Exception(
1063 'Cannot find the "impeller_golden_tests" executable in "%s". You may need to build it.' %
1064 (build_dir)
1065 )
1066 harvester_path: Path = Path(SCRIPT_DIR).parent.joinpath('tools'
1067 ).joinpath('golden_tests_harvester')
1068
1069 with tempfile.TemporaryDirectory(prefix='impeller_golden') as temp_dir:
1070 extra_env = metal_validation_env()
1071 extra_env.update(vulkan_validation_env(build_dir))
1072 run_cmd([tests_path, f'--working_dir={temp_dir}'], cwd=build_dir, env=extra_env)
1073 dart_bin = os.path.join(build_dir, 'dart-sdk', 'bin', 'dart')
1074 golden_path = os.path.join('testing', 'impeller_golden_tests_output.txt')
1075 script_path = os.path.join('tools', 'dir_contents_diff', 'bin', 'dir_contents_diff.dart')
1076 diff_result = subprocess.run(
1077 f'{dart_bin} --disable-dart-dev {script_path} {golden_path} {temp_dir}',
1078 check=False,
1079 shell=True,
1080 stdout=subprocess.PIPE,
1081 cwd=os.path.join(BUILDROOT_DIR, 'flutter')
1082 )
1083 if diff_result.returncode != 0:
1084 print_divider('<')
1085 print(diff_result.stdout.decode())
1086 raise RuntimeError('impeller_golden_tests diff failure')
1087
1088 if not require_skia_gold:
1089 print_divider('<')
1090 print('Skipping any SkiaGoldClient invocation as the --no-skia-gold flag was set.')
1091 return
1092
1093 # On release builds and local builds, we typically do not have GOLDCTL set,
1094 # which on other words means that this invoking the SkiaGoldClient would
1095 # throw. Skip this step in those cases and log a notice.
1096 if 'GOLDCTL' not in os.environ:
1097 # On CI, we never want to be running golden tests without Skia Gold.
1098 # See https://github.com/flutter/flutter/issues/147180 as an example.
1099 is_luci = 'LUCI_CONTEXT' in os.environ
1100 if is_luci:
1101 raise RuntimeError(
1102 """
1103The GOLDCTL environment variable is not set. This is required for Skia Gold tests.
1104See https://github.com/flutter/engine/tree/main/testing/skia_gold_client#configuring-ci
1105for more information.
1106"""
1107 )
1108
1109 print_divider('<')
1110 print(
1111 'Skipping the SkiaGoldClient invocation as the GOLDCTL environment variable is not set.'
1112 )
1113 return
1114
1115 with DirectoryChange(harvester_path):
1116 bin_path = Path('.').joinpath('bin').joinpath('golden_tests_harvester.dart')
1117 run_cmd([dart_bin, '--disable-dart-dev', str(bin_path), temp_dir])
1118
1119

◆ run_java_tests()

run_tests.run_java_tests (   executable_filter,
  android_variant = 'android_debug_unopt' 
)
Runs the Java JUnit unit tests for the Android embedding

Definition at line 704 of file run_tests.py.

704def run_java_tests(executable_filter, android_variant='android_debug_unopt'):
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'
708 )
709 gradle_bin = os.path.join(
710 BUILDROOT_DIR, 'third_party', 'gradle', 'bin', 'gradle.bat' if is_windows() else 'gradle'
711 )
712 flutter_jar = os.path.join(OUT_DIR, android_variant, 'flutter.jar')
713 android_home = os.path.join(BUILDROOT_DIR, 'third_party', 'android_tools', 'sdk')
714 build_dir = os.path.join(OUT_DIR, android_variant, 'robolectric_tests', 'build')
715 gradle_cache_dir = os.path.join(OUT_DIR, android_variant, 'robolectric_tests', '.gradle')
716
717 test_class = executable_filter if executable_filter else '*'
718 command = [
719 gradle_bin,
720 '-Pflutter_jar=%s' % flutter_jar,
721 '-Pbuild_dir=%s' % build_dir,
722 'testDebugUnitTest',
723 '--tests=%s' % test_class,
724 '--rerun-tasks',
725 '--no-daemon',
726 '--project-cache-dir=%s' % gradle_cache_dir,
727 '--gradle-user-home=%s' % gradle_cache_dir,
728 ]
729
730 env = dict(os.environ, ANDROID_HOME=android_home, JAVA_HOME=java_home())
731 run_cmd(command, cwd=test_runner_dir, env=env)
732
733

◆ run_objc_tests()

run_tests.run_objc_tests (   ios_variant = 'ios_debug_sim_unopt',
  test_filter = None 
)
Runs Objective-C XCTest unit tests for the iOS embedding

Definition at line 767 of file run_tests.py.

767def run_objc_tests(ios_variant='ios_debug_sim_unopt', test_filter=None):
768 """Runs Objective-C XCTest unit tests for the iOS embedding"""
769 assert_expected_xcode_version()
770 ios_out_dir = os.path.join(OUT_DIR, ios_variant)
771 ensure_ios_tests_are_built(ios_out_dir)
772
773 new_simulator_name = 'IosUnitTestsSimulator'
774
775 # Delete simulators with this name in case any were leaked
776 # from another test run.
777 delete_simulator(new_simulator_name)
778
779 create_simulator = [
780 'xcrun '
781 'simctl '
782 'create '
783 '%s com.apple.CoreSimulator.SimDeviceType.iPhone-11' % new_simulator_name
784 ]
785 run_cmd(create_simulator, shell=True)
786
787 try:
788 ios_unit_test_dir = os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'ios', 'IosUnitTests')
789
790 with tempfile.TemporaryDirectory(suffix='ios_embedding_xcresult') as result_bundle_temp:
791 result_bundle_path = os.path.join(result_bundle_temp, 'ios_embedding')
792
793 # Avoid using xcpretty unless the following can be addressed:
794 # - Make sure all relevant failure output is printed on a failure.
795 # - Make sure that a failing exit code is set for CI.
796 # See https://github.com/flutter/flutter/issues/63742
797 test_command = [
798 'xcodebuild '
799 '-sdk iphonesimulator '
800 '-scheme IosUnitTests '
801 '-resultBundlePath ' + result_bundle_path + ' '
802 '-destination name=' + new_simulator_name + ' '
803 'test '
804 'FLUTTER_ENGINE=' + ios_variant
805 ]
806 if test_filter is not None:
807 test_command[0] = test_command[0] + ' -only-testing:%s' % test_filter
808 try:
809 run_cmd(test_command, cwd=ios_unit_test_dir, shell=True)
810
811 except:
812 # The LUCI environment may provide a variable containing a directory path
813 # for additional output files that will be uploaded to cloud storage.
814 # Upload the xcresult when the tests fail.
815 luci_test_outputs_path = os.environ.get('FLUTTER_TEST_OUTPUTS_DIR')
816 xcresult_bundle = os.path.join(result_bundle_temp, 'ios_embedding.xcresult')
817 if luci_test_outputs_path and os.path.exists(xcresult_bundle):
818 dump_path = os.path.join(luci_test_outputs_path, 'ios_embedding.xcresult')
819 # xcresults contain many little files. Archive the bundle before upload.
820 shutil.make_archive(dump_path, 'zip', root_dir=xcresult_bundle)
821 raise
822
823 finally:
824 delete_simulator(new_simulator_name)
825
826

◆ vulkan_validation_env()

run_tests.vulkan_validation_env (   build_dir)

Definition at line 175 of file run_tests.py.

175def vulkan_validation_env(build_dir):
176 extra_env = {
177 # pylint: disable=line-too-long
178 # Note: built from //third_party/swiftshader
179 'VK_ICD_FILENAMES': os.path.join(build_dir, 'vk_swiftshader_icd.json'),
180 # Note: built from //third_party/vulkan_validation_layers:vulkan_gen_json_files
181 # and //third_party/vulkan_validation_layers.
182 'VK_LAYER_PATH': os.path.join(build_dir, 'vulkan-data'),
183 'VK_INSTANCE_LAYERS': 'VK_LAYER_KHRONOS_validation',
184 }
185 return extra_env
186
187

◆ worker_init()

run_tests.worker_init (   queue,
  level 
)

Definition at line 985 of file run_tests.py.

985def worker_init(queue, level):
986 queue_handler = logging.handlers.QueueHandler(queue)
987 log = logging.getLogger(__name__)
988 log.setLevel(logging.INFO)
989 queue_handler.setLevel(level)
990 log.addHandler(queue_handler)
991
992

Variable Documentation

◆ _get_test_runner

run_tests._get_test_runner
protected

Definition at line 150 of file run_tests.py.

◆ BUILDROOT_DIR

run_tests.BUILDROOT_DIR = os.path.abspath(os.path.join(os.path.realpath(__file__), '..', '..', '..'))

Definition at line 33 of file run_tests.py.

◆ console_logger_handler

run_tests.console_logger_handler = logging.StreamHandler()

Definition at line 44 of file run_tests.py.

◆ ENCODING

str run_tests.ENCODING = 'UTF-8'

Definition at line 40 of file run_tests.py.

◆ file_logger_handler

run_tests.file_logger_handler = logging.FileHandler(LOG_FILE)

Definition at line 45 of file run_tests.py.

◆ FONT_SUBSET_DIR

run_tests.FONT_SUBSET_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'tools', 'font_subset')

Definition at line 38 of file run_tests.py.

◆ FONTS_DIR

run_tests.FONTS_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'third_party', 'txt', 'third_party', 'fonts')

Definition at line 36 of file run_tests.py.

◆ GOLDEN_DIR

run_tests.GOLDEN_DIR = os.path.join(BUILDROOT_DIR, 'flutter', 'testing', 'resources')

Definition at line 35 of file run_tests.py.

◆ level

run_tests.level

Definition at line 142 of file run_tests.py.

◆ LOG_FILE

run_tests.LOG_FILE = os.path.join(OUT_DIR, 'run_tests.log')

Definition at line 42 of file run_tests.py.

◆ logger

run_tests.logger = logging.getLogger(__name__)

Definition at line 43 of file run_tests.py.

◆ OUT_DIR

run_tests.OUT_DIR = os.path.join(DIR_SRC_ROOT, 'out', VARIANT)

Definition at line 48 of file run_tests.py.

◆ repeat_flags

list run_tests.repeat_flags
Initial value:
1= [
2 '--repeat=2',
3]

Definition at line 388 of file run_tests.py.

◆ ROBOTO_FONT_PATH

run_tests.ROBOTO_FONT_PATH = os.path.join(FONTS_DIR, 'Roboto-Regular.ttf')

Definition at line 37 of file run_tests.py.

◆ SCRIPT_DIR

run_tests.SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))

Definition at line 32 of file run_tests.py.

◆ shuffle_flags

list run_tests.shuffle_flags
Initial value:
1= [
2 '--gtest_repeat=2',
3 '--gtest_shuffle',
4]

Definition at line 383 of file run_tests.py.

◆ VARIANT

str run_tests.VARIANT = sys.argv[1]

Definition at line 42 of file run_tests.py.