1111import glob
1212import os
1313import re
14+ import shutil
1415import subprocess
1516import sys
1617import time
@@ -134,12 +135,33 @@ def RunEngineExecutable(build_dir, executable_name, filter, flags=[],
134135 else :
135136 test_command = [ executable ] + flags
136137
137- RunCmd (test_command , cwd = cwd , forbidden_output = forbidden_output , expect_failure = expect_failure , env = env )
138-
139-
140- def RunCCTests (build_dir , filter , coverage ):
138+ try :
139+ RunCmd (test_command , cwd = cwd , forbidden_output = forbidden_output , expect_failure = expect_failure , env = env )
140+ except :
141+ # The LUCI environment may provide a variable containing a directory path
142+ # for additional output files that will be uploaded to cloud storage.
143+ # If the command generated a core dump, then run a script to analyze
144+ # the dump and output a report that will be uploaded.
145+ luci_test_outputs_path = os .environ .get ('FLUTTER_TEST_OUTPUTS_DIR' )
146+ core_path = os .path .join (cwd , 'core' )
147+ if luci_test_outputs_path and os .path .exists (core_path ) and os .path .exists (unstripped_exe ):
148+ dump_path = os .path .join (luci_test_outputs_path , '%s_%s.txt' % (executable_name , sys .platform ))
149+ print 'Writing core dump analysis to %s' % dump_path
150+ subprocess .call ([
151+ os .path .join (buildroot_dir , 'flutter' , 'testing' , 'analyze_core_dump.sh' ),
152+ buildroot_dir , unstripped_exe , core_path , dump_path ,
153+ ])
154+ os .unlink (core_path )
155+ raise
156+
157+
158+ def RunCCTests (build_dir , filter , coverage , capture_core_dump ):
141159 print ("Running Engine Unit-tests." )
142160
161+ if capture_core_dump and IsLinux ():
162+ import resource
163+ resource .setrlimit (resource .RLIMIT_CORE , (resource .RLIM_INFINITY , resource .RLIM_INFINITY ))
164+
143165 # Not all of the engine unit tests are designed to be run more than once.
144166 non_repeatable_shuffle_flags = [
145167 "--gtest_shuffle" ,
@@ -523,6 +545,8 @@ def main():
523545 help = 'Filter parameter for which objc tests to run (example: "IosUnitTestsTests/SemanticsObjectTest/testShouldTriggerAnnouncement")' )
524546 parser .add_argument ('--coverage' , action = 'store_true' , default = None ,
525547 help = 'Generate coverage reports for each unit test framework run.' )
548+ parser .add_argument ('--engine-capture-core-dump' , dest = 'engine_capture_core_dump' , action = 'store_true' ,
549+ default = False , help = 'Capture core dumps from crashes of engine tests.' )
526550
527551 args = parser .parse_args ()
528552
@@ -537,7 +561,7 @@ def main():
537561
538562 engine_filter = args .engine_filter .split (',' ) if args .engine_filter else None
539563 if 'engine' in types :
540- RunCCTests (build_dir , engine_filter , args .coverage )
564+ RunCCTests (build_dir , engine_filter , args .coverage , args . engine_capture_core_dump )
541565
542566 if 'dart' in types :
543567 assert not IsWindows (), "Dart tests can't be run on windows. https://github.com/flutter/flutter/issues/36301."
0 commit comments