OLD | NEW |
| (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 library test.kernel.closures.suite; | |
6 | |
7 import 'dart:async' show Future; | |
8 | |
9 import 'dart:io' show Directory, File, IOSink; | |
10 | |
11 import 'dart:typed_data' show Uint8List; | |
12 | |
13 import 'package:kernel/kernel.dart' show loadProgramFromBinary; | |
14 | |
15 import 'package:kernel/text/ast_to_text.dart' show Printer; | |
16 | |
17 import 'package:testing/testing.dart' | |
18 show ChainContext, Result, StdioProcess, Step; | |
19 | |
20 import 'package:kernel/ast.dart' show Library, Program; | |
21 | |
22 import 'package:kernel/verifier.dart' show verifyProgram; | |
23 | |
24 import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter; | |
25 | |
26 import 'package:kernel/binary/ast_from_binary.dart' show BinaryBuilder; | |
27 | |
28 Future<bool> fileExists(Uri base, String path) async { | |
29 return await new File.fromUri(base.resolve(path)).exists(); | |
30 } | |
31 | |
32 class Print extends Step<Program, Program, ChainContext> { | |
33 const Print(); | |
34 | |
35 String get name => "print"; | |
36 | |
37 Future<Result<Program>> run(Program program, _) async { | |
38 StringBuffer sb = new StringBuffer(); | |
39 for (Library library in program.libraries) { | |
40 Printer printer = new Printer(sb); | |
41 if (library.importUri.scheme != "dart") { | |
42 printer.writeLibraryFile(library); | |
43 } | |
44 } | |
45 print("$sb"); | |
46 return pass(program); | |
47 } | |
48 } | |
49 | |
50 class SanityCheck extends Step<Program, Program, ChainContext> { | |
51 const SanityCheck(); | |
52 | |
53 String get name => "sanity check"; | |
54 | |
55 Future<Result<Program>> run(Program program, _) async { | |
56 try { | |
57 verifyProgram(program); | |
58 return pass(program); | |
59 } catch (e, s) { | |
60 return crash(e, s); | |
61 } | |
62 } | |
63 } | |
64 | |
65 class MatchExpectation extends Step<Program, Program, ChainContext> { | |
66 final String suffix; | |
67 | |
68 final bool updateExpectations; | |
69 | |
70 const MatchExpectation(this.suffix, {this.updateExpectations: true}); | |
71 | |
72 String get name => "match expectations"; | |
73 | |
74 Future<Result<Program>> run(Program program, _) async { | |
75 Library library = program.libraries | |
76 .firstWhere((Library library) => library.importUri.scheme != "dart"); | |
77 Uri uri = library.importUri; | |
78 StringBuffer buffer = new StringBuffer(); | |
79 new Printer(buffer).writeLibraryFile(library); | |
80 | |
81 File expectedFile = new File("${uri.toFilePath()}$suffix"); | |
82 if (await expectedFile.exists()) { | |
83 String expected = await expectedFile.readAsString(); | |
84 if (expected.trim() != "$buffer".trim()) { | |
85 if (!updateExpectations) { | |
86 String diff = await runDiff(expectedFile.uri, "$buffer"); | |
87 return fail(null, "$uri doesn't match ${expectedFile.uri}\n$diff"); | |
88 } | |
89 } else { | |
90 return pass(program); | |
91 } | |
92 } | |
93 if (updateExpectations) { | |
94 await openWrite(expectedFile.uri, (IOSink sink) { | |
95 sink.writeln("$buffer".trim()); | |
96 }); | |
97 return pass(program); | |
98 } else { | |
99 return fail( | |
100 program, | |
101 """ | |
102 Please create file ${expectedFile.path} with this content: | |
103 $buffer"""); | |
104 } | |
105 } | |
106 } | |
107 | |
108 class WriteDill extends Step<Program, Uri, ChainContext> { | |
109 const WriteDill(); | |
110 | |
111 String get name => "write .dill"; | |
112 | |
113 Future<Result<Uri>> run(Program program, _) async { | |
114 Directory tmp = await Directory.systemTemp.createTemp(); | |
115 Uri uri = tmp.uri.resolve("generated.dill"); | |
116 File generated = new File.fromUri(uri); | |
117 IOSink sink = generated.openWrite(); | |
118 try { | |
119 new BinaryPrinter(sink).writeProgramFile(program); | |
120 program.unbindCanonicalNames(); | |
121 } catch (e, s) { | |
122 return fail(uri, e, s); | |
123 } finally { | |
124 print("Wrote `${generated.path}`"); | |
125 await sink.close(); | |
126 } | |
127 return pass(uri); | |
128 } | |
129 } | |
130 | |
131 class ReadDill extends Step<Uri, Uri, ChainContext> { | |
132 const ReadDill(); | |
133 | |
134 String get name => "read .dill"; | |
135 | |
136 Future<Result<Uri>> run(Uri uri, _) async { | |
137 try { | |
138 loadProgramFromBinary(uri.toFilePath()); | |
139 } catch (e, s) { | |
140 return fail(uri, e, s); | |
141 } | |
142 return pass(uri); | |
143 } | |
144 } | |
145 | |
146 class Copy extends Step<Program, Program, ChainContext> { | |
147 const Copy(); | |
148 | |
149 String get name => "copy program"; | |
150 | |
151 Future<Result<Program>> run(Program program, _) async { | |
152 BytesCollector sink = new BytesCollector(); | |
153 new BinaryPrinter(sink).writeProgramFile(program); | |
154 program.unbindCanonicalNames(); | |
155 Uint8List bytes = sink.collect(); | |
156 var newProgram = new Program(); | |
157 new BinaryBuilder(bytes).readProgram(newProgram); | |
158 newProgram.unbindCanonicalNames(); | |
159 return pass(newProgram); | |
160 } | |
161 } | |
162 | |
163 class BytesCollector implements Sink<List<int>> { | |
164 final List<List<int>> lists = <List<int>>[]; | |
165 | |
166 int length = 0; | |
167 | |
168 void add(List<int> data) { | |
169 lists.add(data); | |
170 length += data.length; | |
171 } | |
172 | |
173 Uint8List collect() { | |
174 Uint8List result = new Uint8List(length); | |
175 int offset = 0; | |
176 for (List<int> list in lists) { | |
177 result.setRange(offset, offset += list.length, list); | |
178 } | |
179 lists.clear(); | |
180 length = 0; | |
181 return result; | |
182 } | |
183 | |
184 void close() {} | |
185 } | |
186 | |
187 Future<String> runDiff(Uri expected, String actual) async { | |
188 StdioProcess process = await StdioProcess | |
189 .run("diff", <String>["-u", expected.toFilePath(), "-"], input: actual); | |
190 return process.output; | |
191 } | |
192 | |
193 Future openWrite(Uri uri, f(IOSink sink)) async { | |
194 IOSink sink = new File.fromUri(uri).openWrite(); | |
195 try { | |
196 await f(sink); | |
197 } finally { | |
198 await sink.close(); | |
199 } | |
200 print("Wrote $uri"); | |
201 } | |
OLD | NEW |