Flutter Engine
The Flutter Engine
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)
 
def print (*args, **kwargs)
 
def print_divider (char='=')
 
def 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)
 
def is_mac ()
 
def is_aarm64 ()
 
def is_linux ()
 
def is_windows ()
 
def executable_suffix ()
 
def find_executable_path (path)
 
def vulkan_validation_env (build_dir)
 
def metal_validation_env ()
 
def build_engine_executable_command (build_dir, executable_name, flags=None, coverage=False, gtest=False)
 
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 run_cc_tests (build_dir, executable_filter, coverage, capture_core_dump)
 
def run_engine_benchmarks (build_dir, executable_filter)
 
def gather_dart_test (build_dir, dart_file, options)
 
def ensure_ios_tests_are_built (ios_out_dir)
 
def assert_expected_xcode_version ()
 
def java_home ()
 
def java_bin ()
 
def run_java_tests (executable_filter, android_variant='android_debug_unopt')
 
def run_android_unittest (test_runner_name, android_variant, adb_path)
 
def run_android_tests (android_variant='android_debug_unopt', adb_path=None)
 
def run_objc_tests (ios_variant='ios_debug_sim_unopt', test_filter=None)
 
def delete_simulator (simulator_name)
 
def gather_dart_tests (build_dir, test_filter)
 
def gather_dart_smoke_test (build_dir, test_filter)
 
def gather_dart_package_tests (build_dir, package_path, extra_opts)
 
def build_dart_host_test_list (build_dir)
 
def run_benchmark_tests (build_dir)
 
def worker_init (queue, level)
 
def run_engine_tasks_in_parallel (tasks)
 
def run_impeller_golden_tests (str build_dir, bool require_skia_gold=False)
 
def main ()
 

Variables

 VARIANT = sys.argv[1]
 
 OUT_DIR = os.path.join(DIR_SRC_ROOT, 'out', VARIANT)
 
 level
 
 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')
 
string 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
 

Function Documentation

◆ assert_expected_xcode_version()

def 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.

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
def assert_expected_xcode_version()
Definition: run_tests.py:679

◆ build_dart_host_test_list()

def run_tests.build_dart_host_test_list (   build_dir)

Definition at line 928 of file run_tests.py.

928def build_dart_host_test_list(build_dir):
929 dart_host_tests = [
930 (
931 os.path.join('flutter', 'ci'),
932 [os.path.join(BUILDROOT_DIR, 'flutter')],
933 ),
934 (
935 os.path.join('flutter', 'flutter_frontend_server'),
936 [
937 build_dir,
938 os.path.join(build_dir, 'gen', 'frontend_server_aot.dart.snapshot'),
939 os.path.join(build_dir, 'flutter_patched_sdk')
940 ],
941 ),
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'), []),
946 (
947 os.path.join('flutter', 'tools', 'api_check'),
948 [os.path.join(BUILDROOT_DIR, 'flutter')],
949 ),
950 (os.path.join('flutter', 'tools', 'build_bucket_golden_scraper'), []),
951 (os.path.join('flutter', 'tools', 'clang_tidy'), []),
952 (
953 os.path.join('flutter', 'tools', 'const_finder'),
954 [
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'),
958 ],
959 ),
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'), []),
967 ]
968 if not is_asan(build_dir):
969 dart_host_tests += [
970 (os.path.join('flutter', 'tools', 'path_ops', 'dart'), []),
971 ]
972
973 return dart_host_tests
974
975
def build_dart_host_test_list(build_dir)
Definition: run_tests.py:928
def is_asan(build_dir)
Definition: run_tests.py:60

◆ build_engine_executable_command()

def 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
def find_executable_path(path)
Definition: run_tests.py:159
def is_linux()
Definition: run_tests.py:147
static SkString join(const CommandLineFlags::StringArray &)
Definition: skpbench.cpp:741

◆ 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
List[TestCase] build_test_cases(Iterable[Mapping[str, Any]] tests)
Definition: run_tests.py:111

◆ delete_simulator()

def run_tests.delete_simulator (   simulator_name)

Definition at line 828 of file run_tests.py.

828def delete_simulator(simulator_name):
829 # Will delete all simulators with this name.
830 command = [
831 'xcrun',
832 'simctl',
833 'delete',
834 simulator_name,
835 ]
836 # Let this fail if the simulator was never created.
837 run_cmd(command, expect_failure=True)
838
839
def delete_simulator(simulator_name)
Definition: run_tests.py:828
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)
Definition: run_tests.py:75

◆ ensure_ios_tests_are_built()

def 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
def ensure_ios_tests_are_built(ios_out_dir)
Definition: run_tests.py:666

◆ executable_suffix()

def run_tests.executable_suffix ( )

Definition at line 155 of file run_tests.py.

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

◆ find_executable_path()

def 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()

def run_tests.gather_dart_package_tests (   build_dir,
  package_path,
  extra_opts 
)

Definition at line 909 of file run_tests.py.

909def gather_dart_package_tests(build_dir, package_path, extra_opts):
910 dart_tests = glob.glob('%s/test/*_test.dart' % package_path)
911 if not dart_tests:
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
915 yield EngineExecutableTask(
916 build_dir, os.path.join('dart-sdk', 'bin', 'dart'), None, flags=opts, cwd=package_path
917 )
918
919
920# Returns a list of Dart packages to test.
921#
922# The first element of each tuple in the returned list is the path to the Dart
923# package to test. It is assumed that the packages follow the convention that
924# tests are named as '*_test.dart', and reside under a directory called 'test'.
925#
926# The second element of each tuple is a list of additional command line
927# arguments to pass to each of the packages tests.
def gather_dart_package_tests(build_dir, package_path, extra_opts)
Definition: run_tests.py:909

◆ gather_dart_smoke_test()

def run_tests.gather_dart_smoke_test (   build_dir,
  test_filter 
)

Definition at line 890 of file run_tests.py.

890def gather_dart_smoke_test(build_dir, test_filter):
891 smoke_test = os.path.join(
892 BUILDROOT_DIR,
893 'flutter',
894 'testing',
895 'smoke_test_failure',
896 'fail_test.dart',
897 )
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)
900 else:
901 yield gather_dart_test(
902 build_dir, smoke_test, FlutterTesterOptions(multithreaded=True, expect_failure=True)
903 )
904 yield gather_dart_test(
905 build_dir, smoke_test, FlutterTesterOptions(multithreaded=False, expect_failure=True)
906 )
907
908
def gather_dart_test(build_dir, dart_file, options)
Definition: run_tests.py:625
def gather_dart_smoke_test(build_dir, test_filter)
Definition: run_tests.py:890

◆ gather_dart_test()

def 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()

def run_tests.gather_dart_tests (   build_dir,
  test_filter 
)

Definition at line 840 of file run_tests.py.

840def gather_dart_tests(build_dir, test_filter):
841 dart_tests_dir = os.path.join(
842 BUILDROOT_DIR,
843 'flutter',
844 'testing',
845 'dart',
846 )
847
848 # Now that we have the Sky packages at the hardcoded location, run `dart pub get`.
850 build_dir,
851 os.path.join('dart-sdk', 'bin', 'dart'),
852 None,
853 flags=['pub', '--suppress-analytics', 'get', '--offline'],
854 cwd=dart_tests_dir,
855 )
856
857 dart_observatory_tests = glob.glob('%s/observatory/*_test.dart' % dart_tests_dir)
858 dart_tests = glob.glob('%s/*_test.dart' % dart_tests_dir)
859
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)
864 else:
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]:
868 yield gather_dart_test(
869 build_dir, dart_test_file,
870 FlutterTesterOptions(
871 multithreaded=multithreaded,
872 enable_impeller=enable_impeller,
873 enable_observatory=True
874 )
875 )
876
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)
880 else:
881 logger.info("Gathering dart test '%s'", dart_test_file)
882 for multithreaded in [False, True]:
883 for enable_impeller in [False, True]:
884 yield gather_dart_test(
885 build_dir, dart_test_file,
886 FlutterTesterOptions(multithreaded=multithreaded, enable_impeller=enable_impeller)
887 )
888
889
def gather_dart_tests(build_dir, test_filter)
Definition: run_tests.py:840
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)
Definition: run_tests.py:253

◆ is_aarm64()

def 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
def is_aarm64()
Definition: run_tests.py:137
def is_mac()
Definition: run_tests.py:133

◆ is_asan()

def 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()

def 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()

def 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()

def 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()

def 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
def java_bin()
Definition: run_tests.py:700
def java_home()
Definition: run_tests.py:691

◆ java_home()

def 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()

def run_tests.main ( )

Definition at line 1121 of file run_tests.py.

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

◆ metal_validation_env()

def run_tests.metal_validation_env ( )

Definition at line 188 of file run_tests.py.

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
def metal_validation_env()
Definition: run_tests.py:188

◆ print()

def 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
def print(*args, **kwargs)
Definition: run_tests.py:49

◆ print_divider()

def 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
def print_divider(char='=')
Definition: run_tests.py:53

◆ 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
DEF_SWITCHES_START aot vmservice shared library Name of the *so containing AOT compiled Dart assets for launching the service isolate vm snapshot The VM snapshot data that will be memory mapped as read only SnapshotAssetPath must be present isolate snapshot The isolate snapshot data that will be memory mapped as read only SnapshotAssetPath must be present cache dir Path to the cache directory This is different from the persistent_cache_path in embedder which is used for Skia shader cache icu native lib Path to the library file that exports the ICU data vm service The hostname IP address on which the Dart VM Service should be served If not set
Definition: switches.h:76
Set[str] resolve_packages(Iterable[Mapping[str, Any]] tests)
Definition: run_tests.py:82

◆ run_android_tests()

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

Definition at line 753 of file run_tests.py.

753def run_android_tests(android_variant='android_debug_unopt', adb_path=None):
754 if adb_path is None:
755 adb_path = 'adb'
756
757 run_android_unittest('flutter_shell_native_unittests', android_variant, adb_path)
758 run_android_unittest('impeller_toolkit_android_unittests', android_variant, adb_path)
759
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')
762 run_cmd([
763 systrace_test, '--adb-path', adb_path, '--apk-path', scenario_apk, '--package-name',
764 'dev.flutter.scenarios', '--activity-name', '.PlatformViewsActivity'
765 ])
766
767
def run_android_unittest(test_runner_name, android_variant, adb_path)
Definition: run_tests.py:735

◆ run_android_unittest()

def run_tests.run_android_unittest (   test_runner_name,
  android_variant,
  adb_path 
)

Definition at line 735 of file run_tests.py.

735def run_android_unittest(test_runner_name, android_variant, adb_path):
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)
740
741 try:
742 run_cmd([adb_path, 'shell', remote_tests_path])
743 except:
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)
750 raise
751
752

◆ run_benchmark_tests()

def run_tests.run_benchmark_tests (   build_dir)

Definition at line 976 of file run_tests.py.

976def run_benchmark_tests(build_dir):
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
983 )
984
985

◆ run_cc_tests()

def 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:
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
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.
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.
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.
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()

def 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()

def 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
def build_engine_executable_command(build_dir, executable_name, flags=None, coverage=False, gtest=False)
Definition: run_tests.py:208

◆ run_engine_tasks_in_parallel()

def run_tests.run_engine_tasks_in_parallel (   tasks)

Definition at line 994 of file run_tests.py.

995 # Work around a bug in Python.
996 #
997 # The multiprocessing package relies on the win32 WaitForMultipleObjects()
998 # call, which supports waiting on a maximum of MAXIMUM_WAIT_OBJECTS (defined
999 # by Windows to be 64) handles, processes in this case. To avoid hitting
1000 # this, we limit ourselves to 60 handles (since there are a couple extra
1001 # processes launched for the queue reader and thread wakeup reader).
1002 #
1003 # See: https://bugs.python.org/issue26903
1004 max_processes = multiprocessing.cpu_count()
1005 if sys_platform.startswith(('cygwin', 'win')) and max_processes > 60:
1006 max_processes = 60
1007
1008 queue = multiprocessing.Queue()
1009 queue_listener = logging.handlers.QueueListener(
1010 queue,
1011 console_logger_handler,
1012 file_logger_handler,
1013 respect_handler_level=True,
1014 )
1015 queue_listener.start()
1016
1017 failures = []
1018 try:
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:
1023 try:
1024 async_result.get()
1025 except Exception as exn: # pylint: disable=broad-except
1026 failures += [(task, exn)]
1027 finally:
1028 queue_listener.stop()
1029
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))
1034 return False
1035
1036 return True
1037
1038

◆ run_impeller_golden_tests()

def 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 1057 of file run_tests.py.

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

◆ run_java_tests()

def 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, 'flutter', 'third_party', 'gradle', 'bin',
711 'gradle.bat' if is_windows() else 'gradle'
712 )
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')
717
718 test_class = executable_filter if executable_filter else '*'
719 command = [
720 gradle_bin,
721 '-Pflutter_jar=%s' % flutter_jar,
722 '-Pbuild_dir=%s' % build_dir,
723 'testDebugUnitTest',
724 '--tests=%s' % test_class,
725 '--rerun-tasks',
726 '--no-daemon',
727 '--project-cache-dir=%s' % gradle_cache_dir,
728 '--gradle-user-home=%s' % gradle_cache_dir,
729 ]
730
731 env = dict(os.environ, ANDROID_HOME=android_home, JAVA_HOME=java_home())
732 run_cmd(command, cwd=test_runner_dir, env=env)
733
734

◆ run_objc_tests()

def 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 768 of file run_tests.py.

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

◆ vulkan_validation_env()

def 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()

def run_tests.worker_init (   queue,
  level 
)

Definition at line 986 of file run_tests.py.

986def worker_init(queue, level):
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)
992
993
def worker_init(queue, level)
Definition: run_tests.py:986

Variable Documentation

◆ 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

string 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

string run_tests.VARIANT = sys.argv[1]

Definition at line 42 of file run_tests.py.