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

Side by Side Diff: tests/standalone/packages_file_test.dart

Issue 2770063002: Revert "Format all multitests" (Closed)
Patch Set: Created 3 years, 9 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 | « tests/standalone/io/platform_resolved_executable_test.dart ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import "dart:async"; 5 import "dart:async";
6 import "dart:io"; 6 import "dart:io";
7 import "dart:convert" show JSON; 7 import "dart:convert" show JSON;
8 import "package:path/path.dart" as p; 8 import "package:path/path.dart" as p;
9 import "package:async_helper/async_helper.dart"; 9 import "package:async_helper/async_helper.dart";
10 10
11 /// Root directory of generated files. 11 /// Root directory of generated files.
12 /// Path contains trailing slash. 12 /// Path contains trailing slash.
13 /// Each configuration gets its own sub-directory. 13 /// Each configuration gets its own sub-directory.
14 Directory fileRoot; 14 Directory fileRoot;
15
16 /// Shared HTTP server serving the files in [httpFiles]. 15 /// Shared HTTP server serving the files in [httpFiles].
17 /// Each configuration gets its own "sub-dir" entry in `httpFiles`. 16 /// Each configuration gets its own "sub-dir" entry in `httpFiles`.
18 HttpServer httpServer; 17 HttpServer httpServer;
19
20 /// Directory structure served by HTTP server. 18 /// Directory structure served by HTTP server.
21 Map<String, dynamic> httpFiles = {}; 19 Map<String, dynamic> httpFiles = {};
22
23 /// List of configurations. 20 /// List of configurations.
24 List<Configuration> configurations = []; 21 List<Configuration> configurations = [];
25
26 /// Collection of failing tests and their failure messages. 22 /// Collection of failing tests and their failure messages.
27 /// 23 ///
28 /// Each test may fail in more than one way. 24 /// Each test may fail in more than one way.
29 var failingTests = <String, List<String>>{}; 25 var failingTests = <String, List<String>>{};
30 26
31 main() async { 27 main() async {
32 asyncStart(); 28 asyncStart();
33 await setUp(); 29 await setUp();
34 30
35 await runTests(); // //# 01: ok 31 await runTests(); // //# 01: ok
36 await runTests([spawn]); // //# 02: ok 32 await runTests([spawn]); // //# 02: ok
37 await runTests([spawn, spawn]); // //# 03: ok 33 await runTests([spawn, spawn]); // //# 03: ok
38 await runTests([spawnUriInherit]); // //# 04: ok 34 await runTests([spawnUriInherit]); // //# 04: ok
39 await runTests([spawnUriInherit, spawn]); // //# 05: ok 35 await runTests([spawnUriInherit, spawn]); // //# 05: ok
40 await runTests([spawn, spawnUriInherit]); // //# 06: ok 36 await runTests([spawn, spawnUriInherit]); // //# 06: ok
41 37
42 // Test that spawning a new VM with file paths instead of URIs as arguments 38 // Test that spawning a new VM with file paths instead of URIs as arguments
43 // gives the same URIs in the internal values. 39 // gives the same URIs in the internal values.
44 await runTests([asPath]); // //# 07: ok 40 await runTests([asPath]); // //# 07: ok
45 41
46 // Test that spawnUri can reproduce the behavior of VM command line parameters 42 // Test that spawnUri can reproduce the behavior of VM command line parameters
47 // exactly. 43 // exactly.
48 // (Don't run all configuration combinations in the same test, so 44 // (Don't run all configuration combinations in the same test, so
49 // unroll the configurations into multiple groups and run each group 45 // unroll the configurations into multiple groups and run each group
50 // as its own multitest. 46 // as its own multitest.
51 { 47 {
52 var groupCount = 8; 48 var groupCount = 8;
53 var groups = new List.generate(8, (_) => []); 49 var groups = new List.generate(8, (_)=>[]);
54 for (int i = 0; i < configurations.length; i++) { 50 for (int i = 0; i < configurations.length; i++) {
55 groups[i % groupCount].add(configurations[i]); 51 groups[i % groupCount].add(configurations[i]);
56 } 52 }
57 var group = -1; 53 var group = -1;
58 group = 0; // //# 10: ok 54 group = 0; // //# 10: ok
59 group = 1; // //# 11: ok 55 group = 1; // //# 11: ok
60 group = 2; // //# 12: ok 56 group = 2; // //# 12: ok
61 group = 3; // //# 13: ok 57 group = 3; // //# 13: ok
62 group = 4; // //# 14: ok 58 group = 4; // //# 14: ok
63 group = 5; // //# 15: ok 59 group = 5; // //# 15: ok
64 group = 6; // //# 16: ok 60 group = 6; // //# 16: ok
65 group = 7; // //# 17: ok 61 group = 7; // //# 17: ok
66 if (group >= 0) { 62 if (group >= 0) {
67 for (var other in groups[group]) { 63 for (var other in groups[group]) {
68 await runTests([spawnUriOther(other)]); 64 await runTests([spawnUriOther(other)]);
69 } 65 }
70 } 66 }
71 } 67 }
72 68
69
73 await tearDown(); 70 await tearDown();
74 71
75 if (failingTests.isNotEmpty) { 72 if (failingTests.isNotEmpty) {
76 print("Errors found in tests:"); 73 print("Errors found in tests:");
77 failingTests.forEach((test, actual) { 74 failingTests.forEach((test, actual) {
78 print("$test:\n ${actual.join("\n ")}"); 75 print("$test:\n ${actual.join("\n ")}");
79 }); 76 });
80 exit(255); 77 exit(255);
81 } 78 }
82 79
83 asyncEnd(); 80 asyncEnd();
84 } 81 }
85 82
86 /// Test running the test of the configuration through [Isolate.spawn]. 83 /// Test running the test of the configuration through [Isolate.spawn].
87 /// 84 ///
88 /// This should not change the expected results compared to running it 85 /// This should not change the expected results compared to running it
89 /// directly. 86 /// directly.
90 Configuration spawn(Configuration conf) { 87 Configuration spawn(Configuration conf) {
91 return conf.update( 88 return conf.update(
92 description: conf.description + "/spawn", 89 description: conf.description + "/spawn",
93 main: "spawnMain", 90 main: "spawnMain",
94 newArgs: [conf.mainType], 91 newArgs: [conf.mainType],
95 expect: null); 92 expect: null
93 );
96 } 94 }
97 95
98 /// Tests running a spawnUri on top of the configuration before testing. 96 /// Tests running a spawnUri on top of the configuration before testing.
99 /// 97 ///
100 /// The `spawnUri` call has no explicit root or config parameter, and 98 /// The `spawnUri` call has no explicit root or config parameter, and
101 /// shouldn't search for one, so it implicitly inherits the current isolate's 99 /// shouldn't search for one, so it implicitly inherits the current isolate's
102 /// actual root or configuration. 100 /// actual root or configuration.
103 Configuration spawnUriInherit(Configuration conf) { 101 Configuration spawnUriInherit(Configuration conf) {
104 if (conf.expect["iroot"] == null && 102 if (conf.expect["iroot"] == null &&
105 conf.expect["iconf"] == null && 103 conf.expect["iconf"] == null &&
106 conf.expect["pconf"] != null) { 104 conf.expect["pconf"] != null) {
107 // This means that the specified configuration file didn't exist. 105 // This means that the specified configuration file didn't exist.
108 // spawning a new URI to "inherit" that will actually do an automatic 106 // spawning a new URI to "inherit" that will actually do an automatic
109 // package resolution search with results that are unpredictable. 107 // package resolution search with results that are unpredictable.
110 // That behavior will be tested in a setting where we have more control over 108 // That behavior will be tested in a setting where we have more control over
111 // the files around the spawned URI. 109 // the files around the spawned URI.
112 return null; 110 return null;
113 } 111 }
114 return conf.update( 112 return conf.update(
115 description: conf.description + "/spawnUri-inherit", 113 description: conf.description + "/spawnUri-inherit",
116 main: "spawnUriMain", 114 main: "spawnUriMain",
117 // encode null parameters as "-". Windows fails if using empty string. 115 // encode null parameters as "-". Windows fails if using empty string.
118 newArgs: [ 116 newArgs: [conf.mainFile, "-", "-", "false"],
119 conf.mainFile, 117 expect: {
120 "-", 118 "proot": conf.expect["iroot"],
121 "-", 119 "pconf": conf.expect["iconf"],
122 "false" 120 }
123 ], 121 );
124 expect: {
125 "proot": conf.expect["iroot"],
126 "pconf": conf.expect["iconf"],
127 });
128 } 122 }
129 123
130 /// Tests running a spawnUri with an explicit configuration different 124 /// Tests running a spawnUri with an explicit configuration different
131 /// from the original configuration. 125 /// from the original configuration.
132 /// 126 ///
133 /// Duplicates the explicit parameters as arguments to the spawned isolate. 127 /// Duplicates the explicit parameters as arguments to the spawned isolate.
134 ConfigurationTransformer spawnUriOther(Configuration other) { 128 ConfigurationTransformer spawnUriOther(Configuration other) {
135 return (Configuration conf) { 129 return (Configuration conf) {
136 bool search = (other.config == null) && (other.root == null); 130 bool search = (other.config == null) && (other.root == null);
137 return conf.update( 131 return conf.update(
138 description: "${conf.description} -spawnUri-> ${other.description}", 132 description: "${conf.description} -spawnUri-> ${other.description}",
139 main: "spawnUriMain", 133 main: "spawnUriMain",
140 newArgs: [ 134 newArgs: [other.mainFile,
141 other.mainFile, 135 other.config ?? "-", other.root ?? "-", "$search"],
142 other.config ?? "-", 136 expect: other.expect
143 other.root ?? "-", 137 );
144 "$search"
145 ],
146 expect: other.expect);
147 }; 138 };
148 } 139 }
149 140
141
150 /// Convert command line parameters to file paths. 142 /// Convert command line parameters to file paths.
151 /// 143 ///
152 /// This only works on the command line, not with `spawnUri`. 144 /// This only works on the command line, not with `spawnUri`.
153 Configuration asPath(Configuration conf) { 145 Configuration asPath(Configuration conf) {
154 bool change = false; 146 bool change = false;
155 147
156 String toPath(String string) { 148 String toPath(String string) {
157 if (string == null) return null; 149 if (string == null) return null;
158 if (string.startsWith("file:")) { 150 if (string.startsWith("file:")) {
159 change = true; 151 change = true;
160 return new File.fromUri(Uri.parse(string)).path; 152 return new File.fromUri(Uri.parse(string)).path;
161 } 153 }
162 return string; 154 return string;
163 } 155 }
164 156
165 var mainFile = toPath(conf.mainFile); 157 var mainFile = toPath(conf.mainFile);
166 var root = toPath(conf.root); 158 var root = toPath(conf.root);
167 var config = toPath(conf.config); 159 var config = toPath(conf.config);
168 if (!change) return null; 160 if (!change) return null;
169 return conf.update( 161 return conf.update(description: conf.description + "/as path",
170 description: conf.description + "/as path", 162 mainFile: mainFile, root: root, config: config);
171 mainFile: mainFile,
172 root: root,
173 config: config);
174 } 163 }
175 164
176 /// -------------------------------------------------------------- 165 /// --------------------------------------------------------------
177 166
167
178 Future setUp() async { 168 Future setUp() async {
179 fileRoot = createTempDir(); 169 fileRoot = createTempDir();
180 // print("FILES: $fileRoot"); 170 // print("FILES: $fileRoot");
181 httpServer = await startServer(httpFiles); 171 httpServer = await startServer(httpFiles);
182 // print("HTTPS: ${httpServer.address.address}:${httpServer.port}"); 172 // print("HTTPS: ${httpServer.address.address}:${httpServer.port}");
183 createConfigurations(); 173 createConfigurations();
184 } 174 }
185 175
186 Future tearDown() async { 176 Future tearDown() async {
187 fileRoot.deleteSync(recursive: true); 177 fileRoot.deleteSync(recursive: true);
188 await httpServer.close(); 178 await httpServer.close();
189 } 179 }
190 180
191 typedef Configuration ConfigurationTransformer(Configuration conf); 181 typedef Configuration ConfigurationTransformer(Configuration conf);
192 182
193 Future runTests([List<ConfigurationTransformer> transformations]) async { 183 Future runTests([List<ConfigurationTransformer> transformations]) async {
194 outer: 184 outer: for (var config in configurations) {
195 for (var config in configurations) {
196 if (transformations != null) { 185 if (transformations != null) {
197 for (int i = transformations.length - 1; i >= 0; i--) { 186 for (int i = transformations.length - 1; i >= 0; i--) {
198 config = transformations[i](config); 187 config = transformations[i](config);
199 if (config == null) { 188 if (config == null) {
200 continue outer; // Can be used to skip some tests. 189 continue outer; // Can be used to skip some tests.
201 } 190 }
202 } 191 }
203 } 192 }
204 await testConfiguration(config); 193 await testConfiguration(config);
205 } 194 }
206 } 195 }
207 196
208 // Creates a combination of configurations for running the Dart VM. 197 // Creates a combination of configurations for running the Dart VM.
209 // 198 //
210 // The combinations covers most configurations of implicit and explicit 199 // The combinations covers most configurations of implicit and explicit
211 // package configurations over both file: and http: file sources. 200 // package configurations over both file: and http: file sources.
212 // It also specifies the expected values of the following for a VM 201 // It also specifies the expected values of the following for a VM
213 // run in that configuration. 202 // run in that configuration.
214 // 203 //
215 // * `Process.packageRoot` 204 // * `Process.packageRoot`
216 // * `Process.packageConfig` 205 // * `Process.packageConfig`
217 // * `Isolate.packageRoot` 206 // * `Isolate.packageRoot`
218 // * `Isolate.packageRoot` 207 // * `Isolate.packageRoot`
219 // * `Isolate.resolvePackageUri` of various inputs. 208 // * `Isolate.resolvePackageUri` of various inputs.
220 // * A variable defined in a library loaded using a `package:` URI. 209 // * A variable defined in a library loaded using a `package:` URI.
221 // 210 //
222 // The configurations all have URIs as `root`, `config` and `mainFile` strings, 211 // The configurations all have URIs as `root`, `config` and `mainFile` strings,
223 // have empty argument lists and `mainFile` points to the `main.dart` file. 212 // have empty argument lists and `mainFile` points to the `main.dart` file.
224 void createConfigurations() { 213 void createConfigurations() {
225 add(String description, String mainDir, 214 add(String description, String mainDir, {String root, String config,
226 {String root, String config, Map file, Map http, Map expect}) { 215 Map file, Map http, Map expect}) {
227 var id = freshName("conf"); 216 var id = freshName("conf");
228 217
229 file ??= {}; 218 file ??= {};
230 http ??= {}; 219 http ??= {};
231 220
232 // Fix-up paths. 221 // Fix-up paths.
233 String fileUri = fileRoot.uri.resolve("$id/").toString(); 222 String fileUri = fileRoot.uri.resolve("$id/").toString();
234 String httpUri = 223 String httpUri =
235 "http://${httpServer.address.address}:${httpServer.port}/$id/"; 224 "http://${httpServer.address.address}:${httpServer.port}/$id/";
236 225
(...skipping 18 matching lines...) Expand all
255 } 244 }
256 245
257 if (!mainDir.endsWith("/")) mainDir += "/"; 246 if (!mainDir.endsWith("/")) mainDir += "/";
258 // Insert main files into the main-dir map. 247 // Insert main files into the main-dir map.
259 Map mainDirMap; 248 Map mainDirMap;
260 { 249 {
261 if (mainDir.startsWith("%file/")) { 250 if (mainDir.startsWith("%file/")) {
262 mainDirMap = file; 251 mainDirMap = file;
263 } else { 252 } else {
264 mainDirMap = http; 253 mainDirMap = http;
254
265 } 255 }
266 var parts = mainDir.split('/'); 256 var parts = mainDir.split('/');
267 for (int i = 1; i < parts.length - 1; i++) { 257 for (int i = 1; i < parts.length - 1; i++) {
268 var dirName = parts[i]; 258 var dirName = parts[i];
269 mainDirMap = mainDirMap[dirName] ?? (mainDirMap[dirName] = {}); 259 mainDirMap = mainDirMap[dirName] ?? (mainDirMap[dirName] = {});
270 } 260 }
271 } 261 }
272 262
273 mainDirMap["main"] = testMain; 263 mainDirMap["main"] = testMain;
274 mainDirMap["spawnMain"] = spawnMain.replaceAll("%mainDir/", mainDir); 264 mainDirMap["spawnMain"] = spawnMain.replaceAll("%mainDir/", mainDir);
275 mainDirMap["spawnUriMain"] = spawnUriMain; 265 mainDirMap["spawnUriMain"] = spawnUriMain;
276 266
277 mainDir = fixPath(mainDir); 267 mainDir = fixPath(mainDir);
278 root = fixPath(root); 268 root = fixPath(root);
279 config = fixPath(config); 269 config = fixPath(config);
280 fixPaths(file); 270 fixPaths(file);
281 fixPaths(http); 271 fixPaths(http);
282 // These expectations are default. If not overridden the value will be 272 // These expectations are default. If not overridden the value will be
283 // expected to be null. That is, you can't avoid testing the actual 273 // expected to be null. That is, you can't avoid testing the actual
284 // value of these, you can only change what value to expect. 274 // value of these, you can only change what value to expect.
285 // For values not included here (commented out), the result is not tested 275 // For values not included here (commented out), the result is not tested
286 // unless a value (maybe null) is provided. 276 // unless a value (maybe null) is provided.
287 fixPaths(expect); 277 fixPaths(expect);
288 278
289 expect = { 279 expect = {
290 "pconf": null, 280 "pconf": null,
291 "proot": null, 281 "proot": null,
292 "iconf": null, 282 "iconf": null,
293 "iroot": null, 283 "iroot": null,
294 "foo": null, 284 "foo": null,
295 "foo/": null, 285 "foo/": null,
296 "foo/bar": null, 286 "foo/bar": null,
297 "foo.x": "qux", 287 "foo.x": "qux",
298 "bar/bar": null, 288 "bar/bar": null,
299 "relative": "relative/path", 289 "relative": "relative/path",
300 "nonpkg": "http://example.org/file" 290 "nonpkg": "http://example.org/file"
301 }..addAll(expect ?? const {}); 291 }..addAll(expect ?? const {});
302 292
303 // Add http files to the http server. 293 // Add http files to the http server.
304 if (http.isNotEmpty) { 294 if (http.isNotEmpty) {
305 httpFiles[id] = http; 295 httpFiles[id] = http;
306 } 296 }
307 // Add file files to the file system. 297 // Add file files to the file system.
308 if (file.isNotEmpty) { 298 if (file.isNotEmpty) {
309 createFiles(fileRoot, id, file); 299 createFiles(fileRoot, id, file);
310 } 300 }
311 301
312 configurations.add(new Configuration( 302 configurations.add(new Configuration(
313 description: description, 303 description: description,
314 root: root, 304 root: root,
315 config: config, 305 config: config,
316 mainFile: mainDir + "main.dart", 306 mainFile: mainDir + "main.dart",
317 args: const [], 307 args: const [],
318 expect: expect)); 308 expect: expect));
319 } 309 }
320 310
321 // The `test` function can generate file or http resources. 311 // The `test` function can generate file or http resources.
322 // It replaces "%file/" with URI of the root directory of generated files and 312 // It replaces "%file/" with URI of the root directory of generated files and
323 // "%http/" with the URI of the HTTP server's root in appropriate contexts 313 // "%http/" with the URI of the HTTP server's root in appropriate contexts
324 // (all file contents and parameters). 314 // (all file contents and parameters).
325 315
326 // Tests that only use one scheme to access files. 316 // Tests that only use one scheme to access files.
327 for (var scheme in ["file", "http"]) { 317 for (var scheme in ["file", "http"]) {
318
328 /// Run a test in the current scheme. 319 /// Run a test in the current scheme.
329 /// 320 ///
330 /// The files are served either through HTTP or in a local directory. 321 /// The files are served either through HTTP or in a local directory.
331 /// Use "%$scheme/" to refer to the root of the served files. 322 /// Use "%$scheme/" to refer to the root of the served files.
332 addScheme(description, main, {expect, files, args, root, config}) { 323 addScheme(description, main, {expect, files, args, root, config}) {
333 add("$scheme/$description", main, 324 add("$scheme/$description", main, expect: expect,
334 expect: expect, 325 root: root, config: config,
335 root: root, 326 file: (scheme == "file") ? files : null,
336 config: config, 327 http: (scheme == "http") ? files : null);
337 file: (scheme == "file") ? files : null,
338 http: (scheme == "http") ? files : null);
339 } 328 }
340 329
341 { 330 {
342 // No parameters, no .packages files or packages/ dir. 331 // No parameters, no .packages files or packages/ dir.
343 // A "file:" source realizes there is no configuration and can't resolve 332 // A "file:" source realizes there is no configuration and can't resolve
344 // any packages, but a "http:" source assumes a "packages/" directory. 333 // any packages, but a "http:" source assumes a "packages/" directory.
345 addScheme("no resolution", "%$scheme/", 334 addScheme("no resolution",
346 files: {}, 335 "%$scheme/",
347 expect: (scheme == "file") 336 files: {},
348 ? {"foo.x": null} 337 expect: (scheme == "file") ? {
349 : { 338 "foo.x": null
350 "iroot": "%http/packages/", 339 } : {
351 "foo": "%http/packages/foo", 340 "iroot": "%http/packages/",
352 "foo/": "%http/packages/foo/", 341 "foo": "%http/packages/foo",
353 "foo/bar": "%http/packages/foo/bar", 342 "foo/": "%http/packages/foo/",
354 "foo.x": null, 343 "foo/bar": "%http/packages/foo/bar",
355 "bar/bar": "%http/packages/bar/bar", 344 "foo.x": null,
356 }); 345 "bar/bar": "%http/packages/bar/bar",
346 });
357 } 347 }
358 348
359 { 349 {
360 // No parameters, no .packages files, 350 // No parameters, no .packages files,
361 // packages/ dir exists and is detected. 351 // packages/ dir exists and is detected.
362 var files = {"packages": fooPackage}; 352 var files = {"packages": fooPackage};
363 addScheme("implicit packages dir", "%$scheme/", files: files, expect: { 353 addScheme("implicit packages dir","%$scheme/",
364 "iroot": "%$scheme/packages/", 354 files: files,
365 "foo": "%$scheme/packages/foo", 355 expect: {
366 "foo/": "%$scheme/packages/foo/", 356 "iroot": "%$scheme/packages/",
367 "foo/bar": "%$scheme/packages/foo/bar", 357 "foo": "%$scheme/packages/foo",
368 "bar/bar": "%$scheme/packages/bar/bar", 358 "foo/": "%$scheme/packages/foo/",
369 }); 359 "foo/bar": "%$scheme/packages/foo/bar",
360 "bar/bar": "%$scheme/packages/bar/bar",
361 });
370 } 362 }
371 363
372 { 364 {
373 // No parameters, no .packages files in current dir, but one in parent, 365 // No parameters, no .packages files in current dir, but one in parent,
374 // packages/ dir exists and is used. 366 // packages/ dir exists and is used.
375 // 367 //
376 // Should not detect the .packages file in parent directory. 368 // Should not detect the .packages file in parent directory.
377 // That file is empty, so if it is used, the system cannot resolve "foo". 369 // That file is empty, so if it is used, the system cannot resolve "foo".
378 var files = { 370 var files = {"sub": {"packages": fooPackage},
379 "sub": {"packages": fooPackage}, 371 ".packages": ""};
380 ".packages": "" 372 addScheme("implicit packages dir overrides parent .packages",
381 }; 373 "%$scheme/sub/",
382 addScheme( 374 files: files,
383 "implicit packages dir overrides parent .packages", "%$scheme/sub/", 375 expect: {
384 files: files, 376 "iroot": "%$scheme/sub/packages/",
385 expect: { 377 "foo": "%$scheme/sub/packages/foo",
386 "iroot": "%$scheme/sub/packages/", 378 "foo/": "%$scheme/sub/packages/foo/",
387 "foo": "%$scheme/sub/packages/foo", 379 "foo/bar": "%$scheme/sub/packages/foo/bar",
388 "foo/": "%$scheme/sub/packages/foo/", 380 // "foo.x": "qux", // Blocked by issue http://dartbug.com/26482
389 "foo/bar": "%$scheme/sub/packages/foo/bar", 381 "bar/bar": "%$scheme/sub/packages/bar/bar",
390 // "foo.x": "qux", // Blocked by issue http://dartbug.com/26482 382 });
391 "bar/bar": "%$scheme/sub/packages/bar/bar",
392 });
393 } 383 }
394 384
395 { 385 {
396 // No parameters, a .packages file next to entry is found and used. 386 // No parameters, a .packages file next to entry is found and used.
397 // A packages/ directory is ignored. 387 // A packages/ directory is ignored.
398 var files = { 388 var files = {".packages": "foo:pkgs/foo/",
399 ".packages": "foo:pkgs/foo/", 389 "packages": {},
400 "packages": {}, 390 "pkgs": fooPackage};
401 "pkgs": fooPackage 391 addScheme("implicit .packages file", "%$scheme/",
402 }; 392 files: files,
403 addScheme("implicit .packages file", "%$scheme/", files: files, expect: { 393 expect: {
404 "iconf": "%$scheme/.packages", 394 "iconf": "%$scheme/.packages",
405 "foo/": "%$scheme/pkgs/foo/", 395 "foo/": "%$scheme/pkgs/foo/",
406 "foo/bar": "%$scheme/pkgs/foo/bar", 396 "foo/bar": "%$scheme/pkgs/foo/bar",
407 }); 397 });
408 } 398 }
409 399
410 { 400 {
411 // No parameters, a .packages file in parent dir, no packages/ dir. 401 // No parameters, a .packages file in parent dir, no packages/ dir.
412 // With a file: URI, find the .packages file. 402 // With a file: URI, find the .packages file.
413 // WIth a http: URI, assume a packages/ dir. 403 // WIth a http: URI, assume a packages/ dir.
414 var files = {"sub": {}, ".packages": "foo:pkgs/foo/", "pkgs": fooPackage}; 404 var files = {"sub": {},
405 ".packages": "foo:pkgs/foo/",
406 "pkgs": fooPackage};
415 addScheme(".packages file in parent", "%$scheme/sub/", 407 addScheme(".packages file in parent", "%$scheme/sub/",
416 files: files, 408 files: files,
417 expect: (scheme == "file") 409 expect: (scheme == "file") ? {
418 ? { 410 "iconf": "%file/.packages",
419 "iconf": "%file/.packages", 411 "foo/": "%file/pkgs/foo/",
420 "foo/": "%file/pkgs/foo/", 412 "foo/bar": "%file/pkgs/foo/bar",
421 "foo/bar": "%file/pkgs/foo/bar", 413 } : {
422 } 414 "iroot": "%http/sub/packages/",
423 : { 415 "foo": "%http/sub/packages/foo",
424 "iroot": "%http/sub/packages/", 416 "foo/": "%http/sub/packages/foo/",
425 "foo": "%http/sub/packages/foo", 417 "foo/bar": "%http/sub/packages/foo/bar",
426 "foo/": "%http/sub/packages/foo/", 418 "foo.x": null,
427 "foo/bar": "%http/sub/packages/foo/bar", 419 "bar/bar": "%http/sub/packages/bar/bar",
428 "foo.x": null, 420 });
429 "bar/bar": "%http/sub/packages/bar/bar",
430 });
431 } 421 }
432 422
433 { 423 {
434 // Specified package root that doesn't exist. 424 // Specified package root that doesn't exist.
435 // Ignores existing .packages file and packages/ dir. 425 // Ignores existing .packages file and packages/ dir.
436 addScheme("explicit root not there", "%$scheme/", 426 addScheme("explicit root not there",
437 files: { 427 "%$scheme/",
438 "packages": fooPackage, 428 files: {"packages": fooPackage,
439 ".packages": "foo:%$scheme/packages/" 429 ".packages": "foo:%$scheme/packages/"},
440 }, 430 root: "%$scheme/notthere/",
441 root: "%$scheme/notthere/", 431 expect: {
442 expect: { 432 "proot": "%$scheme/notthere/",
443 "proot": "%$scheme/notthere/", 433 "iroot": "%$scheme/notthere/",
444 "iroot": "%$scheme/notthere/", 434 "foo": "%$scheme/notthere/foo",
445 "foo": "%$scheme/notthere/foo", 435 "foo/": "%$scheme/notthere/foo/",
446 "foo/": "%$scheme/notthere/foo/", 436 "foo/bar": "%$scheme/notthere/foo/bar",
447 "foo/bar": "%$scheme/notthere/foo/bar", 437 "foo.x": null,
448 "foo.x": null, 438 "bar/bar": "%$scheme/notthere/bar/bar",
449 "bar/bar": "%$scheme/notthere/bar/bar", 439 });
450 });
451 } 440 }
452 441
453 { 442 {
454 // Specified package config that doesn't exist. 443 // Specified package config that doesn't exist.
455 // Ignores existing .packages file and packages/ dir. 444 // Ignores existing .packages file and packages/ dir.
456 addScheme("explicit config not there", "%$scheme/", 445 addScheme("explicit config not there",
457 files: {".packages": "foo:packages/foo/", "packages": fooPackage}, 446 "%$scheme/",
458 config: "%$scheme/.notthere", 447 files: {".packages": "foo:packages/foo/",
459 expect: { 448 "packages": fooPackage},
460 "pconf": "%$scheme/.notthere", 449 config: "%$scheme/.notthere",
461 "iconf": null, // <- Only there if actually loaded (unspecified). 450 expect: {
462 "foo/": null, 451 "pconf": "%$scheme/.notthere",
463 "foo/bar": null, 452 "iconf": null, // <- Only there if actually loaded (unspecified).
464 "foo.x": null, 453 "foo/": null,
465 }); 454 "foo/bar": null,
455 "foo.x": null,
456 });
466 } 457 }
467 458
468 { 459 {
469 // Specified package root with no trailing slash. 460 // Specified package root with no trailing slash.
470 // The Platform.packageRoot and Isolate.packageRoot has a trailing slash. 461 // The Platform.packageRoot and Isolate.packageRoot has a trailing slash.
471 var files = { 462 var files = {".packages": "foo:packages/foo/",
472 ".packages": "foo:packages/foo/", 463 "packages": {},
473 "packages": {}, 464 "pkgs": fooPackage};
474 "pkgs": fooPackage
475 };
476 addScheme("explicit package root, no slash", "%$scheme/", 465 addScheme("explicit package root, no slash", "%$scheme/",
477 files: files, 466 files: files,
478 root: "%$scheme/pkgs", 467 root: "%$scheme/pkgs",
479 expect: { 468 expect: {
480 "proot": "%$scheme/pkgs/", 469 "proot": "%$scheme/pkgs/",
481 "iroot": "%$scheme/pkgs/", 470 "iroot": "%$scheme/pkgs/",
482 "foo": "%$scheme/pkgs/foo", 471 "foo": "%$scheme/pkgs/foo",
483 "foo/": "%$scheme/pkgs/foo/", 472 "foo/": "%$scheme/pkgs/foo/",
484 "foo/bar": "%$scheme/pkgs/foo/bar", 473 "foo/bar": "%$scheme/pkgs/foo/bar",
485 "bar/bar": "%$scheme/pkgs/bar/bar", 474 "bar/bar": "%$scheme/pkgs/bar/bar",
486 }); 475 });
487 } 476 }
488 477
489 { 478 {
490 // Specified package root with trailing slash. 479 // Specified package root with trailing slash.
491 var files = { 480 var files = {".packages": "foo:packages/foo/",
492 ".packages": "foo:packages/foo/", 481 "packages": {},
493 "packages": {}, 482 "pkgs": fooPackage};
494 "pkgs": fooPackage
495 };
496 addScheme("explicit package root, slash", "%$scheme/", 483 addScheme("explicit package root, slash", "%$scheme/",
497 files: files, 484 files: files,
498 root: "%$scheme/pkgs", 485 root: "%$scheme/pkgs",
499 expect: { 486 expect: {
500 "proot": "%$scheme/pkgs/", 487 "proot": "%$scheme/pkgs/",
501 "iroot": "%$scheme/pkgs/", 488 "iroot": "%$scheme/pkgs/",
502 "foo": "%$scheme/pkgs/foo", 489 "foo": "%$scheme/pkgs/foo",
503 "foo/": "%$scheme/pkgs/foo/", 490 "foo/": "%$scheme/pkgs/foo/",
504 "foo/bar": "%$scheme/pkgs/foo/bar", 491 "foo/bar": "%$scheme/pkgs/foo/bar",
505 "bar/bar": "%$scheme/pkgs/bar/bar", 492 "bar/bar": "%$scheme/pkgs/bar/bar",
506 }); 493 });
507 } 494 }
508 495
509 { 496 {
510 // Specified package config. 497 // Specified package config.
511 var files = { 498 var files = {".packages": "foo:packages/foo/",
512 ".packages": "foo:packages/foo/", 499 "packages": {},
513 "packages": {}, 500 ".pkgs": "foo:pkgs/foo/",
514 ".pkgs": "foo:pkgs/foo/", 501 "pkgs": fooPackage};
515 "pkgs": fooPackage
516 };
517 addScheme("explicit package config file", "%$scheme/", 502 addScheme("explicit package config file", "%$scheme/",
518 files: files, 503 files: files,
519 config: "%$scheme/.pkgs", 504 config: "%$scheme/.pkgs",
520 expect: { 505 expect: {
521 "pconf": "%$scheme/.pkgs", 506 "pconf": "%$scheme/.pkgs",
522 "iconf": "%$scheme/.pkgs", 507 "iconf": "%$scheme/.pkgs",
523 "foo/": "%$scheme/pkgs/foo/", 508 "foo/": "%$scheme/pkgs/foo/",
524 "foo/bar": "%$scheme/pkgs/foo/bar", 509 "foo/bar": "%$scheme/pkgs/foo/bar",
525 }); 510 });
526 } 511 }
527 512
528 { 513 {
529 // Specified package config as data: URI. 514 // Specified package config as data: URI.
530 // The package config can be specified as a data: URI. 515 // The package config can be specified as a data: URI.
531 // (In that case, relative URI references in the config file won't work). 516 // (In that case, relative URI references in the config file won't work).
532 var files = { 517 var files = {".packages": "foo:packages/foo/",
533 ".packages": "foo:packages/foo/", 518 "packages": {},
534 "packages": {}, 519 "pkgs": fooPackage};
535 "pkgs": fooPackage
536 };
537 var dataUri = "data:,foo:%$scheme/pkgs/foo/\n"; 520 var dataUri = "data:,foo:%$scheme/pkgs/foo/\n";
538 addScheme("explicit data: config file", "%$scheme/", 521 addScheme("explicit data: config file", "%$scheme/",
539 files: files, 522 files: files,
540 config: dataUri, 523 config: dataUri,
541 expect: { 524 expect: {
542 "pconf": dataUri, 525 "pconf": dataUri,
543 "iconf": dataUri, 526 "iconf": dataUri,
544 "foo/": "%$scheme/pkgs/foo/", 527 "foo/": "%$scheme/pkgs/foo/",
545 "foo/bar": "%$scheme/pkgs/foo/bar", 528 "foo/bar": "%$scheme/pkgs/foo/bar",
546 }); 529 });
547 } 530 }
548 } 531 }
549 532
550 // Tests where there are files on both http: and file: sources. 533 // Tests where there are files on both http: and file: sources.
551 534
552 for (var entryScheme in const ["file", "http"]) { 535 for (var entryScheme in const ["file", "http"]) {
553 for (var pkgScheme in const ["file", "http"]) { 536 for (var pkgScheme in const ["file", "http"]) {
554 // Package root. 537 // Package root.
555 if (entryScheme != pkgScheme) { 538 if (entryScheme != pkgScheme) {
556 // Package dir and entry point on different schemes. 539 // Package dir and entry point on different schemes.
557 var files = {}; 540 var files = {};
558 var https = {}; 541 var https = {};
559 (entryScheme == "file" ? files : https)["main"] = testMain; 542 (entryScheme == "file" ? files : https)["main"] = testMain;
560 (pkgScheme == "file" ? files : https)["pkgs"] = fooPackage; 543 (pkgScheme == "file" ? files : https)["pkgs"] = fooPackage;
561 add("$pkgScheme pkg/$entryScheme main", "%$entryScheme/", 544 add("$pkgScheme pkg/$entryScheme main", "%$entryScheme/",
562 file: files, 545 file: files, http: https,
563 http: https, 546 root: "%$pkgScheme/pkgs/",
564 root: "%$pkgScheme/pkgs/", 547 expect: {
565 expect: { 548 "proot": "%$pkgScheme/pkgs/",
566 "proot": "%$pkgScheme/pkgs/", 549 "iroot": "%$pkgScheme/pkgs/",
567 "iroot": "%$pkgScheme/pkgs/", 550 "foo": "%$pkgScheme/pkgs/foo",
568 "foo": "%$pkgScheme/pkgs/foo", 551 "foo/": "%$pkgScheme/pkgs/foo/",
569 "foo/": "%$pkgScheme/pkgs/foo/", 552 "foo/bar": "%$pkgScheme/pkgs/foo/bar",
570 "foo/bar": "%$pkgScheme/pkgs/foo/bar", 553 "bar/bar": "%$pkgScheme/pkgs/bar/bar",
571 "bar/bar": "%$pkgScheme/pkgs/bar/bar", 554 "foo.x": "qux",
572 "foo.x": "qux", 555 });
573 });
574 } 556 }
575 // Package config. The configuration file may also be on either source. 557 // Package config. The configuration file may also be on either source.
576 for (var configScheme in const ["file", "http"]) { 558 for (var configScheme in const ["file", "http"]) {
577 // Don't do the boring stuff! 559 // Don't do the boring stuff!
578 if (entryScheme == configScheme && entryScheme == pkgScheme) continue; 560 if (entryScheme == configScheme && entryScheme == pkgScheme) continue;
579 // Package config, packages and entry point not all on same scheme. 561 // Package config, packages and entry point not all on same scheme.
580 var files = {}; 562 var files = {};
581 var https = {}; 563 var https = {};
582 (entryScheme == "file" ? files : https)["main"] = testMain; 564 (entryScheme == "file" ? files : https)["main"] = testMain;
583 (configScheme == "file" ? files : https)[".pkgs"] = 565 (configScheme == "file" ? files : https)[".pkgs"] =
584 "foo:%$pkgScheme/pkgs/foo/\n"; 566 "foo:%$pkgScheme/pkgs/foo/\n";
585 (pkgScheme == "file" ? files : https)["pkgs"] = fooPackage; 567 (pkgScheme == "file" ? files : https)["pkgs"] = fooPackage;
586 add("$pkgScheme pkg/$configScheme config/$entryScheme main", 568 add("$pkgScheme pkg/$configScheme config/$entryScheme main",
587 "%$entryScheme/", 569 "%$entryScheme/",
588 file: files, 570 file: files, http: https,
589 http: https, 571 config: "%$configScheme/.pkgs",
590 config: "%$configScheme/.pkgs", 572 expect: {
591 expect: { 573 "pconf": "%$configScheme/.pkgs",
592 "pconf": "%$configScheme/.pkgs", 574 "iconf": "%$configScheme/.pkgs",
593 "iconf": "%$configScheme/.pkgs", 575 "foo/": "%$pkgScheme/pkgs/foo/",
594 "foo/": "%$pkgScheme/pkgs/foo/", 576 "foo/bar": "%$pkgScheme/pkgs/foo/bar",
595 "foo/bar": "%$pkgScheme/pkgs/foo/bar", 577 "foo.x": "qux",
596 "foo.x": "qux", 578 });
597 });
598 } 579 }
599 } 580 }
600 } 581 }
601 } 582 }
602 583
584
603 // --------------------------------------------------------- 585 // ---------------------------------------------------------
604 // Helper functionality. 586 // Helper functionality.
605 587
606 var fileHttpRegexp = new RegExp(r"%(?:file|http)/"); 588 var fileHttpRegexp = new RegExp(r"%(?:file|http)/");
607 589
608 // Executes a test in a configuration. 590 // Executes a test in a configuration.
609 // 591 //
610 // The test must specify which main file to use 592 // The test must specify which main file to use
611 // (`main`, `spawnMain` or `spawnUriMain`) 593 // (`main`, `spawnMain` or `spawnUriMain`)
612 // and any arguments which will be used by `spawnMain` and `spawnUriMain`. 594 // and any arguments which will be used by `spawnMain` and `spawnUriMain`.
613 // 595 //
614 // The [expect] map may be used to override the expectations of the 596 // The [expect] map may be used to override the expectations of the
615 // configuration on a value-by-value basis. Passing, e.g., `{"pconf": null}` 597 // configuration on a value-by-value basis. Passing, e.g., `{"pconf": null}`
616 // will override only the `pconf` (`Platform.packageConfig`) expectation. 598 // will override only the `pconf` (`Platform.packageConfig`) expectation.
617 Future testConfiguration(Configuration conf) async { 599 Future testConfiguration(Configuration conf) async {
618 print("-- ${conf.description}"); 600 print("-- ${conf.description}");
619 var description = conf.description; 601 var description = conf.description;
620 try { 602 try {
621 var output = await execDart(conf.mainFile, 603 var output = await execDart(conf.mainFile,
622 root: conf.root, config: conf.config, scriptArgs: conf.args); 604 root: conf.root,
605 config: conf.config,
606 scriptArgs: conf.args);
623 match(JSON.decode(output), conf.expect, description, output); 607 match(JSON.decode(output), conf.expect, description, output);
624 } catch (e, s) { 608 } catch (e, s) {
625 // Unexpected error calling execDart or parsing the result. 609 // Unexpected error calling execDart or parsing the result.
626 // Report it and continue. 610 // Report it and continue.
627 print("ERROR running $description: $e\n$s"); 611 print("ERROR running $description: $e\n$s");
628 failingTests.putIfAbsent(description, () => []).add("$e"); 612 failingTests.putIfAbsent(description, () => []).add("$e");
629 } 613 }
630 } 614 }
631 615
616
632 /// Test that the output of running testMain matches the expectations. 617 /// Test that the output of running testMain matches the expectations.
633 /// 618 ///
634 /// The output is a string which is parse as a JSON literal. 619 /// The output is a string which is parse as a JSON literal.
635 /// The resulting map is always mapping strings to strings, or possibly `null`. 620 /// The resulting map is always mapping strings to strings, or possibly `null`.
636 /// The expectations can have non-string values other than null, 621 /// The expectations can have non-string values other than null,
637 /// they are `toString`'ed before being compared (so the caller can use a URI 622 /// they are `toString`'ed before being compared (so the caller can use a URI
638 /// or a File/Directory directly as an expectation). 623 /// or a File/Directory directly as an expectation).
639 void match(Map actuals, Map expectations, String desc, String actualJson) { 624 void match(Map actuals, Map expectations, String desc, String actualJson) {
640 for (var key in expectations.keys) { 625 for (var key in expectations.keys) {
641 var expectation = expectations[key]?.toString(); 626 var expectation = expectations[key]?.toString();
642 var actual = actuals[key]; 627 var actual = actuals[key];
643 if (expectation != actual) { 628 if (expectation != actual) {
644 print("ERROR: $desc: $key: Expected: <$expectation> Found: <$actual>"); 629 print("ERROR: $desc: $key: Expected: <$expectation> Found: <$actual>");
645 failingTests 630 failingTests.putIfAbsent(desc, ()=>[]).add(
646 .putIfAbsent(desc, () => []) 631 "$key: $expectation != $actual");
647 .add("$key: $expectation != $actual");
648 } 632 }
649 } 633 }
650 } 634 }
651 635
652 const String improt = "import"; // Avoid multitest import rewriting. 636 const String improt = "import"; // Avoid multitest import rewriting.
653 637
654 /// Script that prints the current state and the result of resolving 638 /// Script that prints the current state and the result of resolving
655 /// a few package URIs. This script will be invoked in different settings, 639 /// a few package URIs. This script will be invoked in different settings,
656 /// and the result will be parsed and compared to the expectations. 640 /// and the result will be parsed and compared to the expectations.
657 const String testMain = """ 641 const String testMain = """
658 $improt "dart:convert" show JSON; 642 $improt "dart:convert" show JSON;
659 $improt "dart:io" show Platform, Directory; 643 $improt "dart:io" show Platform, Directory;
660 $improt "dart:isolate" show Isolate; 644 $improt "dart:isolate" show Isolate;
661 $improt "package:foo/foo.dart" deferred as foo; 645 $improt "package:foo/foo.dart" deferred as foo;
662 main(_) async { 646 main(_) async {
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 } else if (arg == "spawnUriMain") { 736 } else if (arg == "spawnUriMain") {
753 target = spawnUri.main; 737 target = spawnUri.main;
754 } else { 738 } else {
755 target = main; 739 target = main;
756 } 740 }
757 Isolate.spawn(target, rest, onError: port.sendPort, onExit: port.sendPort); 741 Isolate.spawn(target, rest, onError: port.sendPort, onExit: port.sendPort);
758 } 742 }
759 """; 743 """;
760 744
761 /// A package directory containing only one package, "foo", with one file. 745 /// A package directory containing only one package, "foo", with one file.
762 const Map fooPackage = const { 746 const Map fooPackage = const { "foo": const { "foo": "var x = 'qux';" }};
763 "foo": const {"foo": "var x = 'qux';"} 747
764 };
765 748
766 /// Runs the Dart executable with the provided parameters. 749 /// Runs the Dart executable with the provided parameters.
767 /// 750 ///
768 /// Captures and returns the output. 751 /// Captures and returns the output.
769 Future<String> execDart(String script, 752 Future<String> execDart(String script,
770 {String root, String config, Iterable<String> scriptArgs}) async { 753 {String root, String config,
754 Iterable<String> scriptArgs}) async {
771 var checked = false; 755 var checked = false;
772 assert((checked = true)); 756 assert((checked = true));
773 // TODO: Find a way to change CWD before running script. 757 // TODO: Find a way to change CWD before running script.
774 var executable = Platform.executable; 758 var executable = Platform.executable;
775 var args = []; 759 var args = [];
776 if (checked) args.add("--checked"); 760 if (checked) args.add("--checked");
777 if (root != null) args.add("--package-root=$root"); 761 if (root != null) args.add("--package-root=$root");
778 if (config != null) args.add("--packages=$config"); 762 if (config != null) args.add("--packages=$config");
779 args.add(script); 763 args.add(script);
780 if (scriptArgs != null) { 764 if (scriptArgs != null) {
(...skipping 23 matching lines...) Expand all
804 File newFile = new File(p.join(base.path, name)); 788 File newFile = new File(p.join(base.path, name));
805 newFile.writeAsStringSync(content); 789 newFile.writeAsStringSync(content);
806 } 790 }
807 791
808 void createRecursive(Directory dir, Map map) { 792 void createRecursive(Directory dir, Map map) {
809 for (var name in map.keys) { 793 for (var name in map.keys) {
810 var content = map[name]; 794 var content = map[name];
811 if (content is String) { 795 if (content is String) {
812 // If the name starts with "." it's a .packages file, otherwise it's 796 // If the name starts with "." it's a .packages file, otherwise it's
813 // a dart file. Those are the only files we care about in this test. 797 // a dart file. Those are the only files we care about in this test.
814 createTextFile( 798 createTextFile(dir,
815 dir, name.startsWith(".") ? name : name + ".dart", content); 799 name.startsWith(".") ? name : name + ".dart",
800 content);
816 } else { 801 } else {
817 assert(content is Map); 802 assert(content is Map);
818 var subdir = createDir(dir, name); 803 var subdir = createDir(dir, name);
819 createRecursive(subdir, content); 804 createRecursive(subdir, content);
820 } 805 }
821 } 806 }
822 } 807 }
823 808
824 createRecursive(createDir(tempDir, subDir), content); 809 createRecursive(createDir(tempDir, subDir), content);
825 } 810 }
826 811
827 /// Start an HTTP server which serves a directory/file structure. 812 /// Start an HTTP server which serves a directory/file structure.
828 /// 813 ///
829 /// The directories and files are described by [files]. 814 /// The directories and files are described by [files].
830 /// 815 ///
831 /// Each map key is an entry in a directory. A `Map` value is a sub-directory 816 /// Each map key is an entry in a directory. A `Map` value is a sub-directory
832 /// and a `String` value is a text file. 817 /// and a `String` value is a text file.
833 /// The file contents are run through [fixPaths] to allow them to be self- 818 /// The file contents are run through [fixPaths] to allow them to be self-
834 /// referential. 819 /// referential.
835 Future<HttpServer> startServer(Map files) async { 820 Future<HttpServer> startServer(Map files) async {
836 return (await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0)) 821 return (await HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, 0))
837 ..forEach((request) { 822 ..forEach((request) {
838 var result = files; 823 var result = files;
839 onFailure: 824 onFailure: {
840 { 825 for (var part in request.uri.pathSegments) {
841 for (var part in request.uri.pathSegments) { 826 if (part.endsWith(".dart")) {
842 if (part.endsWith(".dart")) { 827 part = part.substring(0, part.length - 5);
843 part = part.substring(0, part.length - 5); 828 }
829 if (result is Map) {
830 result = result[part];
831 } else {
832 break onFailure;
833 }
844 } 834 }
845 if (result is Map) { 835 if (result is String) {
846 result = result[part]; 836 request.response..write(result)
847 } else { 837 ..close();
848 break onFailure; 838 return;
849 } 839 }
850 } 840 }
851 if (result is String) { 841 request.response..statusCode = HttpStatus.NOT_FOUND
852 request.response 842 ..close();
853 ..write(result) 843 });
854 ..close();
855 return;
856 }
857 }
858 request.response
859 ..statusCode = HttpStatus.NOT_FOUND
860 ..close();
861 });
862 } 844 }
863 845
864 // Counter used to avoid reusing temporary file or directory names. 846 // Counter used to avoid reusing temporary file or directory names.
865 // 847 //
866 // Used when adding extra files to an existing directory structure, 848 // Used when adding extra files to an existing directory structure,
867 // and when creating temporary directories. 849 // and when creating temporary directories.
868 // 850 //
869 // Some platform temporary-directory implementations are timer based, 851 // Some platform temporary-directory implementations are timer based,
870 // and creating two temp-dirs withing a short duration may cause a collision. 852 // and creating two temp-dirs withing a short duration may cause a collision.
871 int tmpNameCounter = 0; 853 int tmpNameCounter = 0;
872 854
873 // Fresh file name. 855 // Fresh file name.
874 String freshName([String base = "tmp"]) => "$base${tmpNameCounter++}"; 856 String freshName([String base = "tmp"]) => "$base${tmpNameCounter++}";
875 857
876 Directory createTempDir() { 858 Directory createTempDir() {
877 return Directory.systemTemp.createTempSync(freshName("pftest-")); 859 return Directory.systemTemp.createTempSync(freshName("pftest-"));
878 } 860 }
879 861
880 typedef void ConfigUpdate(Configuration configuration); 862 typedef void ConfigUpdate(Configuration configuration);
881 863
882 /// The configuration for a single test. 864 /// The configuration for a single test.
883 class Configuration { 865 class Configuration {
884 /// The "description" of the test - a description of the set-up. 866 /// The "description" of the test - a description of the set-up.
885 final String description; 867 final String description;
886
887 /// The package root parameter passed to the Dart isolate. 868 /// The package root parameter passed to the Dart isolate.
888 /// 869 ///
889 /// At most one of [root] and [config] should be supplied. If both are 870 /// At most one of [root] and [config] should be supplied. If both are
890 /// omitted, a VM will search for a packages file or dir. 871 /// omitted, a VM will search for a packages file or dir.
891 final String root; 872 final String root;
892
893 /// The package configuration file location passed to the Dart isolate. 873 /// The package configuration file location passed to the Dart isolate.
894 final String config; 874 final String config;
895
896 /// Path to the main file to run. 875 /// Path to the main file to run.
897 final String mainFile; 876 final String mainFile;
898
899 /// List of arguments to pass to the main function. 877 /// List of arguments to pass to the main function.
900 final List<String> args; 878 final List<String> args;
901
902 /// The expected values for `Platform.package{Root,Config}`, 879 /// The expected values for `Platform.package{Root,Config}`,
903 /// `Isolate.package{Root,Config}` and resolution of package URIs 880 /// `Isolate.package{Root,Config}` and resolution of package URIs
904 /// in a `foo` package. 881 /// in a `foo` package.
905 /// 882 ///
906 /// The results are found by running the `main.dart` file inside [mainDir]. 883 /// The results are found by running the `main.dart` file inside [mainDir].
907 /// The tests can run this file after doing other `spawn` or `spawnUri` calls. 884 /// The tests can run this file after doing other `spawn` or `spawnUri` calls.
908 final Map expect; 885 final Map expect;
909 886
910 Configuration( 887 Configuration({this.description,
911 {this.description, 888 this.root,
912 this.root, 889 this.config,
913 this.config, 890 this.mainFile,
914 this.mainFile, 891 this.args,
915 this.args, 892 this.expect});
916 this.expect});
917 893
918 // Gets the type of main file, one of `main`, `spawnMain` or `spawnUriMain`. 894 // Gets the type of main file, one of `main`, `spawnMain` or `spawnUriMain`.
919 String get mainType { 895 String get mainType {
920 var lastSlash = mainFile.lastIndexOf("/"); 896 var lastSlash = mainFile.lastIndexOf("/");
921 if (lastSlash < 0) { 897 if (lastSlash < 0) {
922 // Assume it's a Windows path. 898 // Assume it's a Windows path.
923 lastSlash = mainFile.lastIndexOf(r"\"); 899 lastSlash = mainFile.lastIndexOf(r"\");
924 } 900 }
925 var name = mainFile.substring(lastSlash + 1, mainFile.length - 5); 901 var name = mainFile.substring(lastSlash + 1, mainFile.length - 5);
926 assert(name == "main" || name == "spawnMain" || name == "spawnUriMain"); 902 assert(name == "main" || name == "spawnMain" || name == "spawnUriMain");
(...skipping 19 matching lines...) Expand all
946 /// [mainFile] overrides [Configuration.mainFile] completely, and ignores 922 /// [mainFile] overrides [Configuration.mainFile] completely, and ignores
947 /// [main]. 923 /// [main].
948 /// 924 ///
949 /// [newArgs] are prepended to the existing [Configuration.args]. 925 /// [newArgs] are prepended to the existing [Configuration.args].
950 /// 926 ///
951 /// [args] overrides [Configuration.args] completely and ignores [newArgs]. 927 /// [args] overrides [Configuration.args] completely and ignores [newArgs].
952 /// 928 ///
953 /// [expect] overrides individual expectations. 929 /// [expect] overrides individual expectations.
954 /// 930 ///
955 /// [root] and [config] overrides the existing values. 931 /// [root] and [config] overrides the existing values.
956 Configuration update( 932 Configuration update({
957 {String description, 933 String description,
958 String main, 934 String main,
959 String mainFile, 935 String mainFile,
960 String root, 936 String root,
961 String config, 937 String config,
962 List<String> args, 938 List<String> args,
963 List<String> newArgs, 939 List<String> newArgs,
964 Map expect}) { 940 Map expect
941 }) {
965 return new Configuration( 942 return new Configuration(
966 description: description ?? this.description, 943 description: description ?? this.description,
967 root: root ?? this.root, 944 root: root ?? this.root,
968 config: config ?? this.config, 945 config: config ?? this.config,
969 mainFile: mainFile ?? 946 mainFile: mainFile ??
970 ((main == null) ? this.mainFile : "${this.mainPath}$main.dart"), 947 ((main == null) ? this.mainFile : "${this.mainPath}$main.dart"),
971 args: args ?? 948 args:
972 (<String>[] 949 args ?? (<String>[]..addAll(newArgs ?? const <String>[])
973 ..addAll(newArgs ?? const <String>[]) 950 ..addAll(this.args)),
974 ..addAll(this.args)), 951 expect: expect == null
975 expect: expect == null ? this.expect : new Map.from(this.expect) 952 ? this.expect
976 ..addAll(expect ?? const {})); 953 : new Map.from(this.expect)..addAll(expect ?? const {}));
977 } 954 }
978 955
979 // For debugging. 956 // For debugging.
980 String toString() { 957 String toString() {
981 return "Configuration($description\n" 958 return "Configuration($description\n"
982 " root : $root\n" 959 " root : $root\n"
983 " config: $config\n" 960 " config: $config\n"
984 " main : $mainFile\n" 961 " main : $mainFile\n"
985 " args : ${args.map((x) => '"$x"').join(" ")}\n" 962 " args : ${args.map((x) => '"$x"').join(" ")}\n"
986 ") : expect {\n${expect.keys.map((k) => 963 ") : expect {\n${expect.keys.map((k) =>
987 ' "$k"'.padRight(6) + ":${JSON.encode(expect[k])}\n").join()}" 964 ' "$k"'.padRight(6) + ":${JSON.encode(expect[k])}\n").join()}"
988 "}"; 965 "}";
989 } 966 }
990 } 967 }
991 968
969
992 // Inserts the file with generalized [name] at [path] with [content]. 970 // Inserts the file with generalized [name] at [path] with [content].
993 // 971 //
994 // The [path] is a directory where the file is created. It must start with 972 // The [path] is a directory where the file is created. It must start with
995 // either '%file/' or '%http/' to select the structure to put it into. 973 // either '%file/' or '%http/' to select the structure to put it into.
996 // 974 //
997 // The [name] should not have a trailing ".dart" for Dart files. Any file 975 // The [name] should not have a trailing ".dart" for Dart files. Any file
998 // not starting with "." is assumed to be a ".dart" file. 976 // not starting with "." is assumed to be a ".dart" file.
999 void insertFileAt( 977 void insertFileAt(Map file, Map http,
1000 Map file, Map http, String path, String name, String content) { 978 String path, String name, String content) {
1001 var parts = path.split('/').toList(); 979 var parts = path.split('/').toList();
1002 var dir = (parts[0] == "%file") ? file : http; 980 var dir = (parts[0] == "%file") ? file : http;
1003 for (var i = 1; i < parts.length - 1; i++) { 981 for (var i = 1; i < parts.length - 1; i++) {
1004 var entry = parts[i]; 982 var entry = parts[i];
1005 dir = dir[entry] ?? (dir[entry] = {}); 983 dir = dir[entry] ?? (dir[entry] = {});
1006 } 984 }
1007 dir[name] = content; 985 dir[name] = content;
1008 } 986 }
OLDNEW
« no previous file with comments | « tests/standalone/io/platform_resolved_executable_test.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698