| // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file |
| // for details. All rights reserved. Use of this source code is governed by a |
| // BSD-style license that can be found in the LICENSE file. |
| |
| // This test ensures that --trace-precompiler runs without issue and prints |
| // valid JSON for reasons to retain objects. |
| |
| // OtherResources=use_dwarf_stack_traces_flag_program.dart |
| |
| import "dart:convert"; |
| import "dart:io"; |
| |
| import 'package:expect/expect.dart'; |
| import 'package:path/path.dart' as path; |
| |
| import 'use_flag_test_helper.dart'; |
| |
| main(List<String> args) async { |
| if (!isAOTRuntime) { |
| return; // Running in JIT: AOT binaries not available. |
| } |
| |
| if (Platform.isAndroid) { |
| return; // SDK tree and dart_bootstrap not available on the test device. |
| } |
| |
| // These are the tools we need to be available to run on a given platform: |
| if (!await testExecutable(genSnapshot)) { |
| throw "Cannot run test as $genSnapshot not available"; |
| } |
| if (!await testExecutable(aotRuntime)) { |
| throw "Cannot run test as $aotRuntime not available"; |
| } |
| if (!File(platformDill).existsSync()) { |
| throw "Cannot run test as $platformDill does not exist"; |
| } |
| |
| await withTempDir('trace-precompiler-flag-test', (String tempDir) async { |
| final cwDir = path.dirname(Platform.script.toFilePath()); |
| // We can just reuse the program for the use_dwarf_stack_traces test. |
| final script = path.join(cwDir, 'use_dwarf_stack_traces_flag_program.dart'); |
| final scriptDill = path.join(tempDir, 'flag_program.dill'); |
| |
| // Compile script to Kernel IR. |
| await run(genKernel, <String>[ |
| '--aot', |
| '--platform=$platformDill', |
| '-o', |
| scriptDill, |
| script, |
| ]); |
| |
| // Run the AOT compiler with every enabled/disabled combination of the |
| // following flags that affect object retention: |
| final retentionFlags = [ |
| 'retain-function-objects', |
| 'dwarf-stack-traces-mode' |
| ]; |
| |
| for (var i = 0; i < 1 << retentionFlags.length; i++) { |
| final flags = <String>[]; |
| for (var j = 0; j < retentionFlags.length; j++) { |
| final buffer = StringBuffer('--'); |
| if ((i & (1 << j)) == 0) { |
| buffer.write('no-'); |
| } |
| buffer.write(retentionFlags[j]); |
| flags.add(buffer.toString()); |
| } |
| await testTracePrecompiler(tempDir, scriptDill, flags); |
| } |
| }); |
| } |
| |
| Future<void> testTracePrecompiler( |
| String tempDir, String scriptDill, List<String> flags) async { |
| final reasonsFile = path.join(tempDir, 'reasons.json'); |
| final snapshot = path.join(tempDir, 'snapshot.so'); |
| final result = await run(genSnapshot, <String>[ |
| ...flags, |
| '--write-retained-reasons-to=$reasonsFile', |
| '--snapshot-kind=app-aot-elf', |
| '--elf=$snapshot', |
| scriptDill, |
| ]); |
| |
| final stream = Stream.fromFuture(File(reasonsFile).readAsString()); |
| final decisionsJson = await json.decoder.bind(stream).first; |
| Expect.isTrue(decisionsJson is List, 'not a list of decisions'); |
| Expect.isTrue((decisionsJson as List).every((o) => o is Map), |
| 'not a list of decision objects'); |
| final decisions = (decisionsJson as List).map((o) => o as Map); |
| for (final m in decisions) { |
| Expect.isTrue(m.containsKey("name"), 'no name field in decision'); |
| Expect.isTrue(m["name"] is String, 'name field is not a string'); |
| Expect.isTrue(m.containsKey("type"), 'no type field in decision'); |
| Expect.isTrue(m["type"] is String, 'type field is not a string'); |
| Expect.isTrue(m.containsKey("retained"), 'no retained field in decision'); |
| Expect.isTrue(m["retained"] is bool, 'retained field is not a boolean'); |
| if (m["retained"] as bool) { |
| Expect.isTrue(m.containsKey("reasons"), 'no reasons field in decision'); |
| Expect.isTrue(m["reasons"] is List, 'reasons field is not a list'); |
| final reasons = m["reasons"] as List; |
| Expect.isFalse(reasons.isEmpty, 'reasons list should not be empty'); |
| for (final o in reasons) { |
| Expect.isTrue(o is String, 'reason is not a string'); |
| } |
| } |
| } |
| } |