| // Copyright (c) 2017, 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:io' show Directory, File, Platform; | 
 |  | 
 | import 'package:async_helper/async_helper.dart' show asyncEnd, asyncStart; | 
 | import 'package:front_end/src/base/command_line_options.dart'; | 
 | import 'package:kernel/ast.dart' show Component; | 
 | import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; | 
 | import 'package:kernel/text/ast_to_text.dart' show componentToString; | 
 | import 'package:testing/testing.dart' show StdioProcess; | 
 |  | 
 | Future main() async { | 
 |   asyncStart(); | 
 |   Uri sourceCompiler = | 
 |       Uri.base.resolve("pkg/front_end/tool/_fasta/compile.dart"); | 
 |   Uri outline = Uri.base.resolve("pkg/front_end/tool/_fasta/outline.dart"); | 
 |   Directory tmp = await Directory.systemTemp.createTemp("fasta_bootstrap"); | 
 |   Uri compiledOnceOutput = tmp.uri.resolve("fasta1.dill"); | 
 |   Uri compiledTwiceOutput = tmp.uri.resolve("fasta2.dill"); | 
 |   Uri outlineOutput = tmp.uri.resolve("outline.dill"); | 
 |   try { | 
 |     await runCompiler(sourceCompiler, sourceCompiler, compiledOnceOutput); | 
 |     await runCompiler(compiledOnceOutput, sourceCompiler, compiledTwiceOutput); | 
 |     await compare(compiledOnceOutput, compiledTwiceOutput); | 
 |     await runCompiler(compiledTwiceOutput, outline, outlineOutput); | 
 |     try { | 
 |       // Test that compare actually works by comparing the compiled component | 
 |       // to the outline component (which are different, but similar). | 
 |       await compare(compiledOnceOutput, outlineOutput, silent: true); | 
 |       throw "Expected an error."; | 
 |     } on ComparisonFailed { | 
 |       // Expected. | 
 |     } | 
 |   } finally { | 
 |     await tmp.delete(recursive: true); | 
 |   } | 
 |   asyncEnd(); | 
 | } | 
 |  | 
 | Future runCompiler(Uri compiler, Uri input, Uri output) async { | 
 |   Uri dartVm = Uri.base.resolveUri(new Uri.file(Platform.resolvedExecutable)); | 
 |   String executable = dartVm.toFilePath(); | 
 |   List<String> arguments = <String>[ | 
 |     "-Dbenchmark=true", | 
 |     compiler.toFilePath(), | 
 |     "${Flags.compileSdk}=sdk/", | 
 |     "${Flags.output}=${output.toFilePath()}", | 
 |     Flags.verify, | 
 |     input.toFilePath(), | 
 |     "-Dbenchmark=true", | 
 |   ]; | 
 |   print('Running: $executable ${arguments.join(' ')}'); | 
 |   Stopwatch stopwatch = new Stopwatch()..start(); | 
 |   StdioProcess result = await StdioProcess.run(executable, arguments, | 
 |       suppressOutput: false, timeout: const Duration(minutes: 2)); | 
 |   print("Run finished with exit code ${result.exitCode}" | 
 |       " in ${stopwatch.elapsed}"); | 
 |   if (result.exitCode != 0) { | 
 |     throw "Compilation failed:\n${result.output}"; | 
 |   } | 
 | } | 
 |  | 
 | Future compare(Uri a, Uri b, {bool silent = false}) async { | 
 |   List<int> bytesA = await new File.fromUri(a).readAsBytes(); | 
 |   List<int> bytesB = await new File.fromUri(b).readAsBytes(); | 
 |   if (bytesA.length == bytesB.length) { | 
 |     bool same = true; | 
 |     for (int i = 0; i < bytesA.length; i++) { | 
 |       if (bytesA[i] != bytesB[i]) { | 
 |         same = false; | 
 |         break; | 
 |       } | 
 |     } | 
 |     if (same) return; | 
 |   } | 
 |   if (!silent) { | 
 |     print("$a is different from $b"); | 
 |   } | 
 |   Component componentA = new Component(); | 
 |   Component componentB = new Component(); | 
 |   new BinaryBuilder(bytesA, filename: a.toFilePath()).readComponent(componentA); | 
 |   new BinaryBuilder(bytesB, filename: b.toFilePath()).readComponent(componentB); | 
 |   RegExp splitLines = new RegExp('^', multiLine: true); | 
 |   List<String> linesA = componentToString(componentA).split(splitLines); | 
 |   List<String> linesB = componentToString(componentB).split(splitLines); | 
 |   for (int i = 0; i < linesA.length && i < linesB.length; i++) { | 
 |     String lineA = linesA[i].trimRight(); | 
 |     String lineB = linesB[i].trimRight(); | 
 |     if (lineA != lineB) { | 
 |       String diffHunk = "${i}c$i\n>$lineA\n---\n<$lineB"; | 
 |       if (!silent) { | 
 |         print(diffHunk); | 
 |       } | 
 |     } | 
 |   } | 
 |   throw new ComparisonFailed(a, b); | 
 | } | 
 |  | 
 | class ComparisonFailed { | 
 |   final Uri a; | 
 |   final Uri b; | 
 |  | 
 |   ComparisonFailed(this.a, this.b); | 
 |  | 
 |   @override | 
 |   String toString() => "Error: $a is different from $b"; | 
 | } |