OLD | NEW |
---|---|
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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 file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * This is a helper for run.sh. We try to run all of the Dart code in one | 6 * This is a helper for run.sh. We try to run all of the Dart code in one |
7 * instance of the Dart VM to reduce warm-up time. | 7 * instance of the Dart VM to reduce warm-up time. |
8 */ | 8 */ |
9 library run_impl; | 9 library run_impl; |
10 | 10 |
11 import 'dart:async'; | 11 import 'dart:async'; |
12 import 'dart:io'; | 12 import 'dart:io'; |
13 import 'dart:isolate'; | |
14 import 'dart:math' show min; | |
13 import 'dart:utf' show encodeUtf8; | 15 import 'dart:utf' show encodeUtf8; |
14 import 'dart:isolate'; | |
15 import 'package:unittest/compact_vm_config.dart'; | 16 import 'package:unittest/compact_vm_config.dart'; |
16 import 'package:unittest/unittest.dart'; | 17 import 'package:unittest/unittest.dart'; |
17 import 'package:web_ui/dwc.dart' as dwc; | 18 import 'package:web_ui/dwc.dart' as dwc; |
18 | 19 |
19 import 'analyzer_test.dart' as analyzer_test; | 20 import 'analyzer_test.dart' as analyzer_test; |
20 import 'compiler_test.dart' as compiler_test; | 21 import 'compiler_test.dart' as compiler_test; |
21 import 'emitter_test.dart' as emitter_test; | 22 import 'emitter_test.dart' as emitter_test; |
22 import 'html5_utils_test.dart' as html5_utils_test; | 23 import 'html5_utils_test.dart' as html5_utils_test; |
23 import 'html_cleaner_test.dart' as html_cleaner_test; | 24 import 'html_cleaner_test.dart' as html_cleaner_test; |
24 import 'linked_list_test.dart' as linked_list_test; | 25 import 'linked_list_test.dart' as linked_list_test; |
(...skipping 18 matching lines...) Expand all Loading... | |
43 addGroup('compiler_test.dart', compiler_test.main); | 44 addGroup('compiler_test.dart', compiler_test.main); |
44 addGroup('emitter_test.dart', emitter_test.main); | 45 addGroup('emitter_test.dart', emitter_test.main); |
45 addGroup('html5_utils_test.dart', html5_utils_test.main); | 46 addGroup('html5_utils_test.dart', html5_utils_test.main); |
46 addGroup('html_cleaner_test.dart', html_cleaner_test.main); | 47 addGroup('html_cleaner_test.dart', html_cleaner_test.main); |
47 addGroup('linked_list_test.dart', linked_list_test.main); | 48 addGroup('linked_list_test.dart', linked_list_test.main); |
48 addGroup('observe_test.dart', observe_test.main); | 49 addGroup('observe_test.dart', observe_test.main); |
49 addGroup('path_info_test.dart', path_info_test.main); | 50 addGroup('path_info_test.dart', path_info_test.main); |
50 addGroup('utils_test.dart', utils_test.main); | 51 addGroup('utils_test.dart', utils_test.main); |
51 addGroup('watcher_test.dart', watcher_test.main); | 52 addGroup('watcher_test.dart', watcher_test.main); |
52 | 53 |
53 // TODO(jmesserly): should have listSync for scripting... | 54 var paths = new Directory.fromPath(new Path('data/input')).listSync() |
54 var lister = new Directory.fromPath(new Path('data/input')).list(); | 55 .where((f) => f is File).map((f) => f.name) |
56 .where((p) => p.endsWith('_test.html') && pattern.hasMatch(p)); | |
55 var cwd = new Path(new Directory.current().path); | 57 var cwd = new Path(new Directory.current().path); |
56 var inputDir = cwd.append('data/input'); | 58 for (var path in paths) { |
57 lister.onFile = (path) { | |
58 if (!path.endsWith('_test.html') || !pattern.hasMatch(path)) return; | |
59 var filename = new Path(path).filename; | 59 var filename = new Path(path).filename; |
60 | |
61 test('drt-compile $filename', () { | 60 test('drt-compile $filename', () { |
62 expect(dwc.run(['-o', 'data/output/', path], printTime: false) | 61 expect(dwc.run(['-o', 'data/output/', path], printTime: false) |
63 .then((res) { | 62 .then((res) { |
64 expect(res.messages.length, 0, reason: res.messages.join('\n')); | 63 expect(res.messages.length, 0, reason: res.messages.join('\n')); |
65 }), completes); | 64 }), completes); |
66 }); | 65 }); |
66 } | |
67 | 67 |
68 test('drt-run $filename', () { | 68 test('drt-run', () { |
69 var outDir = cwd.append('data').append('output'); | 69 var outDir = cwd.append('data').append('output'); |
70 var htmlPath = outDir.append(filename).toString(); | 70 var expectedDir = cwd.append('data').append('expected'); |
71 var outputPath = '$htmlPath.txt'; | 71 var filenames = paths.map((p) => new Path(p).filename).toList(); |
72 var errorPath = outDir.append('_errors.$filename.txt').toString(); | 72 var inputPaths = filenames.map((n) => '${outDir.append(n)}').toList(); |
73 var outPaths = inputPaths.map((t) => '$t.txt').toList(); | |
74 var expectedPaths = filenames | |
75 .map((n) => '${expectedDir.append(n)}.txt').toList(); | |
73 | 76 |
74 expect(_runDrt(htmlPath, outputPath, errorPath).then((exitCode) { | 77 expect(Process.run('DumpRenderTree', inputPaths).then((res) { |
Jennifer Messerly
2013/02/21 20:42:37
interesting, so you can just run DRT and give it a
| |
75 if (exitCode == 0) { | 78 expect(res.exitCode, 0, reason: 'DumpRenderTree exit code: $res.exitCode.' |
76 var expectedPath = '$cwd/data/expected/$filename.txt'; | 79 ' Contents of stderr: \n${res.stderr}'); |
77 expect(_diff(expectedPath, outputPath).then((res) { | 80 var outs = res.stdout.split('#EOF\n#EOF\n'); |
78 expect(res, 0, reason: "Test output doesn't match expectation."); | 81 expect(outs.length, outPaths.length + 1); |
79 }), completes); | 82 expect(outs[outs.length - 1], isEmpty); |
80 } else { | |
81 var stderr = new File(errorPath).readAsStringSync(); | |
82 expect(exitCode, 0, reason: | |
83 'DumpRenderTree exited with a non-zero exit code, when running ' | |
84 'on $filename. Contents of stderr: \n$stderr'); | |
85 } | |
86 }), completes); | |
87 }); | |
88 }; | |
89 } | |
90 | 83 |
91 Future<int> _runDrt(htmlPath, String outPath, String errPath) { | 84 // Write out all outputs before we start comparing them. |
92 return Process.run('DumpRenderTree', [htmlPath]).then((res) { | 85 for (int i = 0; i < outs.length - 1; i++) { |
93 var f1 = _writeFile(outPath, res.stdout); | 86 new File(outPaths[i]).writeAsStringSync(outs[i]); |
94 var f2 = _writeFile(errPath, res.stderr); | 87 } |
95 return Future.wait([f1, f2]).then((_) => res.exitCode); | 88 |
89 for (int i = 0; i < outs.length - 1; i++) { | |
90 var expected = new File(expectedPaths[i]).readAsStringSync(); | |
91 expect(expected, new SmartStringMatcher(outs[i]), | |
92 reason: 'unexpected output for ${filenames[i]}'); | |
93 } | |
94 }), completes); | |
96 }); | 95 }); |
97 } | 96 } |
98 | 97 |
99 Future _writeFile(String path, String text) { | 98 // TODO(sigmund): consider moving this matcher to unittest |
100 return new File(path).open(FileMode.WRITE) | 99 class SmartStringMatcher extends BaseMatcher { |
101 .then((file) => file.writeString(text)) | 100 final String _value; |
102 .then((file) => file.close()); | 101 |
102 SmartStringMatcher(this._value); | |
103 | |
104 bool matches(item, MatchState mismatchState) => _value == item; | |
105 | |
106 Description describe(Description description) => | |
107 description.addDescriptionOf(_value); | |
108 | |
109 Description describeMismatch(item, Description mismatchDescription, | |
110 MatchState matchState, bool verbose) { | |
111 if (item is! String) { | |
112 return mismatchDescription.addDescriptionOf(item).add(' not a string'); | |
113 } else { | |
114 var buff = new StringBuffer(); | |
115 buff.write('Strings are not equal.'); | |
116 var escapedItem = _escape(item); | |
117 var escapedValue = _escape(_value); | |
118 int minLength = min(escapedItem.length, escapedValue.length); | |
119 int start; | |
120 for (start = 0; start < minLength; start++) { | |
121 if (escapedValue.codeUnitAt(start) != escapedItem.codeUnitAt(start)) { | |
122 break; | |
123 } | |
124 } | |
125 if (start == minLength) { | |
126 if (escapedValue.length < escapedItem.length) { | |
127 buff.write(' Both strings start the same, but the given value also' | |
128 ' has the following trailing characters: '); | |
129 _writeTrailing(buff, escapedItem, escapedValue.length); | |
130 } else { | |
131 buff.write(' Both strings start the same, but the given value is' | |
132 ' missing the following trailing characters: '); | |
133 _writeTrailing(buff, escapedValue, escapedItem.length); | |
134 } | |
135 } else { | |
136 buff.write('\nExpected: '); | |
137 _writeLeading(buff, escapedValue, start); | |
138 buff.write('[32m'); | |
139 buff.write(escapedValue[start]); | |
140 buff.write('[0m'); | |
141 _writeTrailing(buff, escapedValue, start + 1); | |
142 buff.write('\n But was: '); | |
143 _writeLeading(buff, escapedItem, start); | |
144 buff.write('[31m'); | |
145 buff.write(escapedItem[start]); | |
146 buff.write('[0m'); | |
147 _writeTrailing(buff, escapedItem, start + 1); | |
148 buff.write('[32;1m'); | |
149 buff.write('\n '); | |
150 for (int i = (start > 10 ? 14 : start); i > 0; i--) buff.write(' '); | |
151 buff.write('^ [0m'); | |
152 } | |
153 | |
154 return mismatchDescription.replace(buff.toString()); | |
155 } | |
156 } | |
157 | |
158 static String _escape(String s) => | |
159 s.replaceAll('\n', '\\n').replaceAll('\r', '\\r').replaceAll('\t', '\\t'); | |
160 | |
161 static String _writeLeading(StringBuffer buff, String s, int start) { | |
162 if (start > 10) { | |
163 buff.write('... '); | |
164 buff.write(s.substring(start - 10, start)); | |
165 } else { | |
166 buff.write(s.substring(0, start)); | |
167 } | |
168 } | |
169 | |
170 static String _writeTrailing(StringBuffer buff, String s, int start) { | |
171 if (start + 10 > s.length) { | |
172 buff.write(s.substring(start)); | |
173 } else { | |
174 buff.write(s.substring(start, start + 10)); | |
175 buff.write(' ...'); | |
176 } | |
177 } | |
178 | |
103 } | 179 } |
104 | |
105 Future<int> _diff(expectedPath, outputPath) { | |
106 return Process.run('diff', ['-q', expectedPath, outputPath]) | |
107 .then((res) => res.exitCode); | |
108 } | |
OLD | NEW |