// Copyright (c) 2020, 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. import 'dart:convert'; import 'dart:io'; import 'package:path/path.dart' as path; import 'package:test/test.dart'; final dartCompile = () { final sdkBin = path.dirname(Platform.executable); final dartCmd = path.join(sdkBin, Platform.isWindows ? 'dart.exe' : 'dart'); if (!File(dartCmd).existsSync()) { throw 'Failed to locate `dart` in the SDK'; } return path.canonicalize(dartCmd); }(); class AotSnapshot { final String outputBinary; final String sizesJson; AotSnapshot({required this.outputBinary, required this.sizesJson}); } Future withFlag( Map source, String flag, Future Function(String) f) { return withFlagImpl(source, flag, (info) => f(info.sizesJson)); } Future withFlagImpl( Map source, String? flag, Future Function(AotSnapshot) f) { return withTempDir((dir) async { final snapshot = AotSnapshot( outputBinary: path.join(dir, 'output.exe'), sizesJson: path.join(dir, 'sizes.json'), ); final packages = path.join(dir, '.packages'); final mainDart = path.join(dir, 'main.dart'); // Create test input. for (var file in source.entries) { await File(path.join(dir, file.key)).writeAsString(file.value); } await File(packages).writeAsString(''' { "configVersion": 2, "packages": [ { "name": "input", "rootUri": "./" } ] } '''); await File(mainDart).writeAsString(''' import 'package:input/input.dart' as input; void main(List args) => input.main(args); '''); final extraGenSnapshotOptions = [ '--dwarf-stack-traces', if (flag != null) '$flag=${snapshot.sizesJson}', ]; final args = [ 'compile', 'exe', '-o', snapshot.outputBinary, '--packages=$packages', '--extra-gen-snapshot-options=${extraGenSnapshotOptions.join(',')}', mainDart, ]; // Compile input.dart to native and output instruction sizes. final result = await Process.run(dartCompile, args); expect(result.exitCode, equals(0), reason: ''' Compilation completed with exit code ${result.exitCode}. Command line: $dartCompile ${args.join(' ')} stdout: ${result.stdout} stderr: ${result.stderr} '''); expect(File(snapshot.outputBinary).existsSync(), isTrue, reason: 'Output binary exists'); if (flag != null) { expect(File(snapshot.sizesJson).existsSync(), isTrue, reason: 'Instruction sizes output exists'); } await f(snapshot); }); } final shouldKeepTemporaryDirectories = Platform.environment['KEEP_TEMPORARY_DIRECTORIES']?.isNotEmpty == true; Future withTempDir(Future Function(String dir) f) async { final tempDir = Directory.systemTemp.createTempSync('instruction-sizes-test-'); try { await f(tempDir.path); } finally { if (shouldKeepTemporaryDirectories) { tempDir.deleteSync(recursive: true); } } } Future loadJson(File input) async { return (await input .openRead() .transform(utf8.decoder) .transform(json.decoder) .first)!; }