| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE.md file. | 3 // BSD-style license that can be found in the LICENSE.md file. |
| 4 | 4 |
| 5 library rasta.run_batch; | 5 library rasta.run_batch; |
| 6 | 6 |
| 7 import 'dart:async' show | 7 import 'dart:async' show |
| 8 Future, | 8 Future, |
| 9 Stream; | 9 Stream; |
| 10 | 10 |
| 11 import 'dart:io' show | 11 import 'dart:io' show |
| 12 File, | 12 File, |
| 13 IOSink, | |
| 14 stderr, | 13 stderr, |
| 15 stdin; | 14 stdin; |
| 16 | 15 |
| 17 import 'dart:convert' show | 16 import 'dart:convert' show |
| 18 LineSplitter, | 17 LineSplitter, |
| 19 UTF8; | 18 UTF8; |
| 20 | 19 |
| 21 import 'package:compiler/src/util/uri_extras.dart' show | 20 import 'package:compiler/src/util/uri_extras.dart' show |
| 22 relativize; | 21 relativize; |
| 23 | 22 |
| 24 import 'package:kernel/ast.dart' as ir; | 23 import '../custom_compiler.dart' show |
| 25 | |
| 26 import 'package:kernel/binary/ast_to_binary.dart' show | |
| 27 BinaryPrinter; | |
| 28 | |
| 29 import 'package:rasta/custom_compiler.dart' show | |
| 30 CustomCompiler; | 24 CustomCompiler; |
| 31 | 25 |
| 32 import 'package:rasta/kernel.dart' show | 26 import '../testing.dart' show |
| 33 Kernel; | |
| 34 | |
| 35 import 'package:rasta/testing.dart' show | |
| 36 TestDescription, | 27 TestDescription, |
| 37 listTests; | 28 listTests; |
| 38 | 29 |
| 39 import 'options.dart' show | 30 import 'options.dart' show |
| 40 Options; | 31 Options; |
| 41 | 32 |
| 42 import 'rastask.dart' show | 33 import 'rastask.dart' show |
| 43 Rastask, | 34 Rastask; |
| 44 openWrite; | |
| 45 | 35 |
| 46 // Reads lines of the form '<input> <output>' (space separated) from the | 36 // Reads lines of the form '<input> <output>' (space separated) from the |
| 47 // given stream and generates a test case that compiles each input to the | 37 // given stream and generates a test case that compiles each input to the |
| 48 // corresponding output file. | 38 // corresponding output file. |
| 49 Stream<TestDescription> readTestsFromStream(Stream<List<int>> input) async* { | 39 Stream<TestDescription> readTestsFromStream(Stream<List<int>> input) async* { |
| 50 Stream<String> lines = input | 40 Stream<String> lines = input |
| 51 .transform(UTF8.decoder) | 41 .transform(UTF8.decoder) |
| 52 .transform(new LineSplitter()); | 42 .transform(new LineSplitter()); |
| 53 await for (String line in lines) { | 43 await for (String line in lines) { |
| 54 int splitPoint = line.indexOf(' '); | 44 int splitPoint = line.indexOf(' '); |
| 55 if (splitPoint < 0) { | 45 if (splitPoint < 0) { |
| 56 print("Skipping garbage in input file: $line"); | 46 print("Skipping garbage in input file: $line"); |
| 57 } else { | 47 } else { |
| 58 Uri input = Uri.parse(line.substring(0, splitPoint)); | 48 Uri input = Uri.parse(line.substring(0, splitPoint)); |
| 59 Uri output = Uri.parse(line.substring(splitPoint + 1)); | 49 Uri output = Uri.parse(line.substring(splitPoint + 1)); |
| 60 yield new TestDescription(new File.fromUri(input), output: output); | 50 yield new TestDescription(new File.fromUri(input), output: output); |
| 61 } | 51 } |
| 62 } | 52 } |
| 63 } | 53 } |
| 64 | 54 |
| 65 class RunBatch extends Rastask { | 55 class RunBatch extends Rastask { |
| 66 RunBatch(CustomCompiler compiler, Stopwatch wallClock, Options options) | 56 RunBatch(CustomCompiler compiler, Stopwatch wallClock, Options options) |
| 67 : super(compiler, wallClock, options); | 57 : super(compiler, wallClock, options); |
| 68 | 58 |
| 69 Future<Null> run() async { | 59 Future<Null> run() async { |
| 70 await compiler.setupSdk(); | 60 await setup(); |
| 71 | 61 |
| 72 await compiler.setupPackages(null); | 62 wallClock.reset(); |
| 73 | |
| 74 Kernel kernel = new Kernel(compiler); | |
| 75 await kernel.loadLibrary(Uri.parse("dart:core")); | |
| 76 kernel.processWorkQueue(); | |
| 77 | |
| 78 wallClock.stop(); | |
| 79 print( | |
| 80 "Loading platform libraries took: " | |
| 81 "${(wallClock.elapsedMilliseconds).toStringAsFixed(3)}ms"); | |
| 82 wallClock | |
| 83 ..reset() | |
| 84 ..start(); | |
| 85 | |
| 86 // TODO(ahe): This lists all tests in [testUri] if it is a directory | |
| 87 // and generates Kernel IR for them all. If [testUri] is a file, it | |
| 88 // reads the file as a sequence of lines with pairs of test inputs and | |
| 89 // outputs. However, batch mode should be a server that is controlled | |
| 90 // by test.dart. | |
| 91 | |
| 92 // TODO(ahe): Share more code with RunSingle. | |
| 93 | 63 |
| 94 List<TestDescription> failures = <TestDescription>[]; | 64 List<TestDescription> failures = <TestDescription>[]; |
| 95 | 65 |
| 96 int count = 0; | 66 int count = 0; |
| 97 print("\n"); | 67 print("\n"); |
| 98 | 68 |
| 99 Stream<TestDescription> tests; | 69 Stream<TestDescription> tests; |
| 100 | 70 |
| 101 bool batchFromStdin = (options.input == null); | 71 bool batchFromStdin = (globalOptions.input == null); |
| 102 if (batchFromStdin) { | 72 if (batchFromStdin) { |
| 103 tests = readTestsFromStream(stdin); | 73 tests = readTestsFromStream(stdin); |
| 104 } else { | 74 } else { |
| 105 Uri testUri = compiler.translateUri(null, options.input); | 75 Uri testUri = compiler.translateUri(null, globalOptions.input); |
| 106 File inputFile = new File.fromUri(testUri); | 76 File inputFile = new File.fromUri(testUri); |
| 107 tests = await inputFile.exists() | 77 tests = await inputFile.exists() |
| 108 ? readTestsFromStream(inputFile.openRead()) | 78 ? readTestsFromStream(inputFile.openRead()) |
| 109 : listTests(<Uri>[testUri], pattern: options.pattern); | 79 : listTests(<Uri>[testUri], pattern: globalOptions.pattern); |
| 110 } | 80 } |
| 111 | 81 |
| 112 await for (TestDescription description in tests) { | 82 await for (TestDescription description in tests) { |
| 113 count++; | 83 count++; |
| 114 | 84 |
| 115 int failuresBefore = compiler.elementsWithCompileTimeErrors.length; | 85 int failuresBefore = compiler.elementsWithCompileTimeErrors.length; |
| 86 Uri output = description.output; |
| 87 output ??= description.uri.resolve("${description.uri.path}.bart"); |
| 88 |
| 89 Options options = new Options( |
| 90 description.uri, |
| 91 output, |
| 92 dependenciesFile: null, |
| 93 generateLibrary: globalOptions.generateLibrary, |
| 94 isVerbose: globalOptions.isVerbose || batchFromStdin, |
| 95 isBatch: false, |
| 96 pattern: null); |
| 97 |
| 116 try { | 98 try { |
| 117 Uri output = description.output; | 99 await runOne(options); |
| 118 output ??= description.uri.resolve("${description.uri.path}.bart"); | |
| 119 | |
| 120 Options options = new Options( | |
| 121 description.uri, | |
| 122 output, | |
| 123 generateLibrary: this.options.generateLibrary, | |
| 124 isVerbose: this.options.isVerbose || batchFromStdin); | |
| 125 | |
| 126 ir.Library library = await kernel.loadLibrary(options.input); | |
| 127 if (this.options.generateLibrary) { | |
| 128 kernel.processWorkQueue(targetLibrary: options.input); | |
| 129 } else { | |
| 130 kernel.processWorkQueue(); | |
| 131 } | |
| 132 | |
| 133 if (options.generateLibrary == true) { | |
| 134 await openWrite(options.output, (IOSink sink) { | |
| 135 BinaryPrinter printer = new BinaryPrinter(sink); | |
| 136 printer.writeLibraryFile(library); | |
| 137 }); | |
| 138 } else { | |
| 139 Iterable<ir.Procedure> mainMethods = library.procedures.where( | |
| 140 (ir.Procedure function) => function.name.name == "main"); | |
| 141 | |
| 142 ir.Program program = | |
| 143 new ir.Program(kernel.libraryDependencies(options.input)) | |
| 144 ..mainMethod = mainMethods.single; | |
| 145 | |
| 146 await openWrite(options.output, (IOSink sink) { | |
| 147 BinaryPrinter printer = new BinaryPrinter(sink); | |
| 148 printer.writeProgramFile(program); | |
| 149 }); | |
| 150 } | |
| 151 | |
| 152 int failuresAfter = compiler.elementsWithCompileTimeErrors.length; | |
| 153 if (failuresAfter == failuresBefore) { | |
| 154 if (batchFromStdin) print(">>> TEST OK"); | |
| 155 } else { | |
| 156 if (batchFromStdin) print(">>> TEST FAIL"); | |
| 157 } | |
| 158 | |
| 159 } catch (e, s) { | 100 } catch (e, s) { |
| 160 if (options.isVerbose) { | 101 if (options.isVerbose) { |
| 161 print("${description.uri} failed: $e\n$s\n\n"); | 102 print("${description.uri} failed: $e\n$s\n\n"); |
| 162 } | 103 } |
| 163 failures.add(description); | 104 failures.add(description); |
| 164 if (batchFromStdin) print(">>> TEST CRASH"); | 105 if (batchFromStdin) print(">>> TEST CRASH"); |
| 165 } finally { | |
| 166 stderr.writeln(">>> EOF STDERR"); | |
| 167 } | 106 } |
| 168 | 107 |
| 169 if (!batchFromStdin) { | 108 if (batchFromStdin) { |
| 109 int failuresAfter = compiler.elementsWithCompileTimeErrors.length; |
| 110 if (failuresAfter == failuresBefore) { |
| 111 print(">>> TEST OK"); |
| 112 } else { |
| 113 print(">>> TEST FAIL"); |
| 114 } |
| 115 stderr.writeln(">>> EOF STDERR"); |
| 116 } else { |
| 170 String averageTimeMs = | 117 String averageTimeMs = |
| 171 (wallClock.elapsedMilliseconds / count).toStringAsFixed(3); | 118 (wallClock.elapsedMilliseconds / count).toStringAsFixed(3); |
| 172 String successes = padTo(count - failures.length, 5); | 119 String successes = padTo(count - failures.length, 5); |
| 173 String failuresPadded = padTo(failures.length, 5); | 120 String failuresPadded = padTo(failures.length, 5); |
| 174 print( | 121 print( |
| 175 "\u001b[1A" | 122 "\u001b[1A" |
| 176 "\u001b[2K" | 123 "\u001b[2K" |
| 177 "\u001b[1A" | 124 "\u001b[1A" |
| 178 "\u001b[2K" | 125 "\u001b[2K" |
| 179 "Average time per test: ${averageTimeMs}ms\n" | 126 "Average time per test: ${averageTimeMs}ms\n" |
| (...skipping 20 matching lines...) Expand all Loading... |
| 200 Failures: ${failures.length} | 147 Failures: ${failures.length} |
| 201 Average time per test: ${averageTimeMs}ms | 148 Average time per test: ${averageTimeMs}ms |
| 202 Success rate: ${(100 - failures.length * 100/count).toStringAsFixed(2)}%"""); | 149 Success rate: ${(100 - failures.length * 100/count).toStringAsFixed(2)}%"""); |
| 203 } | 150 } |
| 204 } | 151 } |
| 205 | 152 |
| 206 String padTo(int i, int pad) { | 153 String padTo(int i, int pad) { |
| 207 String result = (" " * pad) + "$i"; | 154 String result = (" " * pad) + "$i"; |
| 208 return result.substring(result.length - pad); | 155 return result.substring(result.length - pad); |
| 209 } | 156 } |
| OLD | NEW |