Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Side by Side Diff: pkg/fasta/lib/testing/kernel_chain.dart

Issue 2631613003: Add Fasta tests. (Closed)
Patch Set: Address review comments. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/fasta/lib/testing/suite.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE.md file.
4
5 // TODO(ahe): Copied from closure_conversion branch of kernel, remove this file
6 // when closure_conversion is merged with master.
7
8 library kernel.testing.kernel_chain;
9
10 import 'dart:async' show
11 Future;
12
13 import 'dart:io' show
14 Directory,
15 File,
16 IOSink,
17 Platform;
18
19 import 'dart:typed_data' show
20 Uint8List;
21
22 import 'package:kernel/kernel.dart' show
23 Repository,
24 loadProgramFromBinary;
25
26 import 'package:kernel/text/ast_to_text.dart' show
27 Printer;
28
29 import 'package:testing/testing.dart' show
30 Result,
31 StdioProcess,
32 Step;
33
34 import 'package:kernel/ast.dart' show
35 Library,
36 Program;
37
38 import 'package:kernel/verifier.dart' show
39 VerifyingVisitor;
40
41 import 'package:kernel/binary/ast_to_binary.dart' show
42 BinaryPrinter;
43
44 import 'package:kernel/binary/ast_from_binary.dart' show
45 BinaryBuilder;
46
47 import 'package:kernel/binary/loader.dart' show
48 BinaryLoader;
49
50 import 'package:analyzer/src/generated/sdk.dart' show
51 DartSdk;
52
53 import 'package:kernel/analyzer/loader.dart' show
54 DartLoader,
55 DartOptions,
56 createDartSdk;
57
58 import 'package:kernel/target/targets.dart' show
59 Target,
60 TargetFlags,
61 getTarget;
62
63 import 'package:kernel/repository.dart' show
64 Repository;
65
66 import 'package:testing/testing.dart' show
67 Chain,
68 ChainContext,
69 Result,
70 StdioProcess,
71 Step,
72 TestDescription;
73
74 import 'package:kernel/ast.dart' show
75 Program;
76
77 import 'package:package_config/discovery.dart' show
78 loadPackagesFile;
79
80 typedef Future<TestContext> TestContextConstructor(
81 Chain suite, Map<String, String> environment, String sdk, Uri vm,
82 Uri packages, bool strongMode, DartSdk dartSdk, bool updateExpectations);
83
84 Future<bool> fileExists(Uri base, String path) async {
85 return await new File.fromUri(base.resolve(path)).exists();
86 }
87
88 abstract class TestContext extends ChainContext {
89 final Uri vm;
90
91 final Uri packages;
92
93 final DartOptions options;
94
95 final DartSdk dartSdk;
96
97 TestContext(String sdk, this.vm, Uri packages, bool strongMode, this.dartSdk)
98 : packages = packages,
99 options = new DartOptions(strongMode: strongMode, sdk: sdk,
100 packagePath: packages.toFilePath());
101
102 Future<DartLoader> createLoader() async {
103 Repository repository = new Repository();
104 return new DartLoader(repository, options, await loadPackagesFile(packages),
105 ignoreRedirectingFactories: false, dartSdk: dartSdk);
106 }
107
108 static Future<TestContext> create(Chain suite,
109 Map<String, String> environment,
110 TestContextConstructor constructor) async {
111 const String suggestion =
112 "Try checking the value of environment variable 'DART_AOT_SDK', "
113 "it should point to a patched SDK.";
114 String sdk = await getEnvironmentVariable(
115 "DART_AOT_SDK", Environment.directory,
116 "Please define environment variable 'DART_AOT_SDK' to point to a "
117 "patched SDK.",
118 (String n) => "Couldn't locate '$n'. $suggestion");
119 Uri sdkUri = Uri.base.resolve("$sdk/");
120 const String asyncDart = "lib/async/async.dart";
121 if (!await fileExists(sdkUri, asyncDart)) {
122 throw "Couldn't find '$asyncDart' in '$sdk'. $suggestion";
123 }
124 const String asyncSources = "lib/async/async_sources.gypi";
125 if (await fileExists(sdkUri, asyncSources)) {
126 throw "Found '$asyncSources' in '$sdk', so it isn't a patched SDK. "
127 "$suggestion";
128 }
129
130 String vmPath = await getEnvironmentVariable(
131 "DART_AOT_VM", Environment.file,
132 "Please define environment variable 'DART_AOT_VM' to point to a "
133 "Dart VM that reads .dill files.",
134 (String n) => "Couldn't locate '$n'. Please check the value of "
135 "environment variable 'DART_AOT_VM', it should point to a "
136 "Dart VM that reads .dill files.");
137 Uri vm = Uri.base.resolve(vmPath);
138
139 Uri packages = Uri.base.resolve(".packages");
140 bool strongMode = false;
141 bool updateExpectations = environment["updateExpectations"] != "false";
142 return constructor(suite, environment, sdk, vm, packages, strongMode,
143 createDartSdk(sdk, strongMode: strongMode), updateExpectations);
144 }
145 }
146
147 enum Environment {
148 directory,
149 file,
150 }
151
152 Future<String> getEnvironmentVariable(
153 String name, Environment kind, String undefined, notFound(String n)) async {
154 String result = Platform.environment[name];
155 if (result == null) {
156 throw undefined;
157 }
158 switch (kind) {
159 case Environment.directory:
160 if (!await new Directory(result).exists()) throw notFound(result);
161 break;
162
163 case Environment.file:
164 if (!await new File(result).exists()) throw notFound(result);
165 break;
166 }
167 return result;
168 }
169
170 class Kernel extends Step<TestDescription, Program, TestContext> {
171 const Kernel();
172
173 String get name => "kernel";
174
175 Future<Result<Program>> run(
176 TestDescription description, TestContext testContext) async {
177 try {
178 DartLoader loader = await testContext.createLoader();
179 Target target = getTarget(
180 "vm", new TargetFlags(strongMode: testContext.options.strongMode));
181 Program program =
182 loader.loadProgram(description.uri, target: target);
183 for (var error in loader.errors) {
184 return fail(program, "$error");
185 }
186 target.transformProgram(program);
187 return pass(program);
188 } catch (e, s) {
189 return crash(e, s);
190 }
191 }
192 }
193
194
195 class Print extends Step<Program, Program, dynamic> {
196 const Print();
197
198 String get name => "print";
199
200 Future<Result<Program>> run(Program program, _) async {
201 StringBuffer sb = new StringBuffer();
202 for (Library library in program.libraries) {
203 Printer printer = new Printer(sb);
204 if (library.importUri.scheme != "dart" &&
205 library.importUri.scheme != "package") {
206 printer.writeLibraryFile(library);
207 }
208 }
209 print("$sb");
210 return pass(program);
211 }
212 }
213
214 class Verify extends Step<Program, Program, dynamic> {
215 final bool fullCompile;
216
217 const Verify(this.fullCompile);
218
219 String get name => "verify";
220
221 Future<Result<Program>> run(Program program, TestContext testContext) async {
222 try {
223 program.accept(new VerifyingVisitor()..isOutline = !fullCompile);
224 return pass(program);
225 } catch (e, s) {
226 return new Result<Program>(
227 null, testContext.expectationSet["VerificationError"], e, s);
228 }
229 }
230 }
231
232 class MatchExpectation extends Step<Program, Program, dynamic> {
233 final String suffix;
234
235 // TODO(ahe): This is true by default which doesn't match well with the class
236 // name.
237 final bool updateExpectations;
238
239 const MatchExpectation(this.suffix, {this.updateExpectations: true});
240
241 String get name => "match expectations";
242
243 Future<Result<Program>> run(Program program, _) async {
244 Library library = program.libraries.firstWhere(
245 (Library library) => library.importUri.scheme != "dart");
246 Uri uri = library.importUri;
247 StringBuffer buffer = new StringBuffer();
248 new Printer(buffer).writeLibraryFile(library);
249
250 File expectedFile = new File("${uri.toFilePath()}$suffix");
251 if (await expectedFile.exists()) {
252 String expected = await expectedFile.readAsString();
253 if (expected.trim() != "$buffer".trim()) {
254 if (!updateExpectations) {
255 String diff = await runDiff(expectedFile.uri, "$buffer");
256 return fail(null, "$uri doesn't match ${expectedFile.uri}\n$diff");
257 }
258 } else {
259 return pass(program);
260 }
261 }
262 if (updateExpectations) {
263 await openWrite(expectedFile.uri, (IOSink sink) {
264 sink.writeln("$buffer".trim());
265 });
266 return pass(program);
267 } else {
268 return fail(program, """
269 Please create file ${expectedFile.path} with this content:
270 $buffer""");
271 }
272 }
273 }
274
275 class WriteDill extends Step<Program, Uri, dynamic> {
276 const WriteDill();
277
278 String get name => "write .dill";
279
280 Future<Result<Uri>> run(Program program, _) async {
281 Directory tmp = await Directory.systemTemp.createTemp();
282 Uri uri = tmp.uri.resolve("generated.dill");
283 File generated = new File.fromUri(uri);
284 IOSink sink = generated.openWrite();
285 try {
286 new BinaryPrinter(sink).writeProgramFile(program);
287 } catch (e, s) {
288 return fail(uri, e, s);
289 } finally {
290 print("Wrote `${generated.path}`");
291 await sink.close();
292 }
293 return pass(uri);
294 }
295 }
296
297 class ReadDill extends Step<Uri, Uri, dynamic> {
298 const ReadDill();
299
300 String get name => "read .dill";
301
302 Future<Result<Uri>> run(Uri uri, _) async {
303 try {
304 loadProgramFromBinary(uri.toFilePath());
305 } catch (e, s) {
306 return fail(uri, e, s);
307 }
308 return pass(uri);
309 }
310 }
311
312 class Copy extends Step<Program, Program, dynamic> {
313 const Copy();
314
315 String get name => "copy program";
316
317 Future<Result<Program>> run(Program program, _) async {
318 BytesCollector sink = new BytesCollector();
319 new BinaryPrinter(sink).writeProgramFile(program);
320 Uint8List bytes = sink.collect();
321 BinaryLoader loader = new BinaryLoader(new Repository());
322 return pass(new BinaryBuilder(loader, bytes).readProgramFile());
323 }
324 }
325
326 class Run extends Step<Uri, int, TestContext> {
327 const Run();
328
329 String get name => "run";
330
331 bool get isAsync => true;
332
333 bool get isRuntime => true;
334
335 Future<Result<int>> run(Uri uri, TestContext context) async {
336 File generated = new File.fromUri(uri);
337 StdioProcess process;
338 try {
339 process = await StdioProcess.run(
340 context.vm.toFilePath(), [generated.path, "Hello, World!"]);
341 print(process.output);
342 } finally {
343 generated.parent.delete(recursive: true);
344 }
345 return process.toResult();
346 }
347 }
348
349 class BytesCollector implements Sink<List<int>> {
350 final List<List<int>> lists = <List<int>>[];
351
352 int length = 0;
353
354 void add(List<int> data) {
355 lists.add(data);
356 length += data.length;
357 }
358
359 Uint8List collect() {
360 Uint8List result = new Uint8List(length);
361 int offset = 0;
362 for (List<int> list in lists) {
363 result.setRange(offset, offset += list.length, list);
364 }
365 lists.clear();
366 length = 0;
367 return result;
368 }
369
370 void close() {}
371 }
372
373 Future<String> runDiff(Uri expected, String actual) async {
374 // TODO(ahe): Implement this for Windows.
375 StdioProcess process = await StdioProcess.run(
376 "diff", <String>["-u", expected.toFilePath(), "-"], input: actual);
377 return process.output;
378 }
379
380 Future openWrite(Uri uri, f(IOSink sink)) async {
381 IOSink sink = new File.fromUri(uri).openWrite();
382 try {
383 await f(sink);
384 } finally {
385 await sink.close();
386 }
387 print("Wrote $uri");
388 }
OLDNEW
« no previous file with comments | « no previous file | pkg/fasta/lib/testing/suite.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698