OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub | 5 /// Test infrastructure for testing pub. Unlike typical unit tests, most pub |
6 /// tests are integration tests that stage some stuff on the file system, run | 6 /// tests are integration tests that stage some stuff on the file system, run |
7 /// pub, and then validate the results. This library provides an API to build | 7 /// pub, and then validate the results. This library provides an API to build |
8 /// tests like that. | 8 /// tests like that. |
9 library test_pub; | 9 library test_pub; |
10 | 10 |
11 import 'dart:async'; | 11 import 'dart:async'; |
12 import 'dart:collection' show Queue; | 12 import 'dart:collection' show Queue; |
13 import 'dart:io' hide sleep; | 13 import 'dart:io' hide sleep; |
14 import 'dart:json' as json; | 14 import 'dart:json' as json; |
15 import 'dart:math'; | 15 import 'dart:math'; |
16 import 'dart:uri'; | 16 import 'dart:uri'; |
17 import 'dart:utf'; | 17 import 'dart:utf'; |
18 | 18 |
19 import 'package:http/testing.dart'; | 19 import 'package:http/testing.dart'; |
20 import 'package:oauth2/oauth2.dart' as oauth2; | 20 import 'package:oauth2/oauth2.dart' as oauth2; |
21 import 'package:pathos/path.dart' as path; | 21 import 'package:pathos/path.dart' as path; |
22 import 'package:scheduled_test/scheduled_process.dart'; | 22 import 'package:scheduled_test/scheduled_process.dart'; |
23 import 'package:scheduled_test/scheduled_server.dart'; | 23 import 'package:scheduled_test/scheduled_server.dart'; |
24 import 'package:scheduled_test/scheduled_test.dart'; | 24 import 'package:scheduled_test/scheduled_test.dart'; |
25 import 'package:yaml/yaml.dart'; | 25 import 'package:yaml/yaml.dart'; |
26 | 26 |
27 import '../../pub/entrypoint.dart'; | 27 import '../lib/src/entrypoint.dart'; |
28 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides | 28 // TODO(rnystrom): Using "gitlib" as the prefix here is ugly, but "git" collides |
29 // with the git descriptor method. Maybe we should try to clean up the top level | 29 // with the git descriptor method. Maybe we should try to clean up the top level |
30 // scope a bit? | 30 // scope a bit? |
31 import '../../pub/git.dart' as gitlib; | 31 import '../lib/src/git.dart' as gitlib; |
32 import '../../pub/git_source.dart'; | 32 import '../lib/src/git_source.dart'; |
33 import '../../pub/hosted_source.dart'; | 33 import '../lib/src/hosted_source.dart'; |
34 import '../../pub/http.dart'; | 34 import '../lib/src/http.dart'; |
35 import '../../pub/io.dart'; | 35 import '../lib/src/io.dart'; |
36 import '../../pub/path_source.dart'; | 36 import '../lib/src/path_source.dart'; |
37 import '../../pub/safe_http_server.dart'; | 37 import '../lib/src/safe_http_server.dart'; |
38 import '../../pub/system_cache.dart'; | 38 import '../lib/src/system_cache.dart'; |
39 import '../../pub/utils.dart'; | 39 import '../lib/src/utils.dart'; |
40 import '../../pub/validator.dart'; | 40 import '../lib/src/validator.dart'; |
41 import 'command_line_config.dart'; | 41 import 'command_line_config.dart'; |
42 import 'descriptor.dart' as d; | 42 import 'descriptor.dart' as d; |
43 | 43 |
44 /// This should be called at the top of a test file to set up an appropriate | 44 /// This should be called at the top of a test file to set up an appropriate |
45 /// test configuration for the machine running the tests. | 45 /// test configuration for the machine running the tests. |
46 initConfig() { | 46 initConfig() { |
47 // If we aren't running on the bots, use the human-friendly config. | 47 // If we aren't running on the bots, use the human-friendly config. |
48 if (!runningOnBuildbot) { | 48 if (!runningOnBuildbot) { |
49 unittestConfiguration = new CommandLineConfiguration(); | 49 unittestConfiguration = new CommandLineConfiguration(); |
50 } | 50 } |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
263 _sandboxDir = createTempDir(); | 263 _sandboxDir = createTempDir(); |
264 d.defaultRoot = sandboxDir; | 264 d.defaultRoot = sandboxDir; |
265 currentSchedule.onComplete.schedule(() => deleteEntry(_sandboxDir), | 265 currentSchedule.onComplete.schedule(() => deleteEntry(_sandboxDir), |
266 'deleting the sandbox directory'); | 266 'deleting the sandbox directory'); |
267 | 267 |
268 // Schedule the test. | 268 // Schedule the test. |
269 body(); | 269 body(); |
270 }); | 270 }); |
271 } | 271 } |
272 | 272 |
273 /// Get the path to the root "util/test/pub" directory containing the pub | 273 /// Get the path to the root "pub/test" directory containing the pub |
274 /// tests. | 274 /// tests. |
275 String get testDirectory { | 275 String get testDirectory { |
276 var dir = new Options().script; | 276 var dir = new Options().script; |
277 while (path.basename(dir) != 'pub') dir = path.dirname(dir); | 277 while (path.basename(dir) != 'test') dir = path.dirname(dir); |
278 | 278 |
279 return path.absolute(dir); | 279 return path.absolute(dir); |
280 } | 280 } |
281 | 281 |
282 /// Schedules renaming (moving) the directory at [from] to [to], both of which | 282 /// Schedules renaming (moving) the directory at [from] to [to], both of which |
283 /// are assumed to be relative to [sandboxDir]. | 283 /// are assumed to be relative to [sandboxDir]. |
284 void scheduleRename(String from, String to) { | 284 void scheduleRename(String from, String to) { |
285 schedule( | 285 schedule( |
286 () => renameDir( | 286 () => renameDir( |
287 path.join(sandboxDir, from), | 287 path.join(sandboxDir, from), |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 // used to run this script itself. | 361 // used to run this script itself. |
362 var dartBin = new Options().executable; | 362 var dartBin = new Options().executable; |
363 | 363 |
364 // If the executable looks like a path, get its full path. That way we | 364 // If the executable looks like a path, get its full path. That way we |
365 // can still find it when we spawn it with a different working directory. | 365 // can still find it when we spawn it with a different working directory. |
366 if (dartBin.contains(Platform.pathSeparator)) { | 366 if (dartBin.contains(Platform.pathSeparator)) { |
367 dartBin = new File(dartBin).fullPathSync(); | 367 dartBin = new File(dartBin).fullPathSync(); |
368 } | 368 } |
369 | 369 |
370 // Find the main pub entrypoint. | 370 // Find the main pub entrypoint. |
371 var pubPath = path.join(testDirectory, '..', '..', 'pub', 'pub.dart'); | 371 var pubPath = path.join(testDirectory, '..', 'bin', 'pub.dart'); |
372 | 372 |
373 var dartArgs = ['--package-root=$_packageRoot/', '--checked', pubPath, | 373 var dartArgs = ['--package-root=$_packageRoot/', '--checked', pubPath, |
374 '--trace']; | 374 '--trace']; |
375 dartArgs.addAll(args); | 375 dartArgs.addAll(args); |
376 | 376 |
377 if (tokenEndpoint == null) tokenEndpoint = new Future.value(); | 377 if (tokenEndpoint == null) tokenEndpoint = new Future.value(); |
378 var optionsFuture = tokenEndpoint.then((tokenEndpoint) { | 378 var optionsFuture = tokenEndpoint.then((tokenEndpoint) { |
379 var options = new ProcessOptions(); | 379 var options = new ProcessOptions(); |
380 options.workingDirectory = pathInSandbox(appPath); | 380 options.workingDirectory = pathInSandbox(appPath); |
381 // TODO(nweiz): remove this when issue 9294 is fixed. | 381 // TODO(nweiz): remove this when issue 9294 is fixed. |
382 options.environment = new Map.from(Platform.environment); | 382 options.environment = new Map.from(Platform.environment); |
383 options.environment['PUB_CACHE'] = pathInSandbox(cachePath); | 383 options.environment['PUB_CACHE'] = pathInSandbox(cachePath); |
384 options.environment['DART_SDK'] = pathInSandbox(sdkPath); | 384 options.environment['DART_SDK'] = pathInSandbox(sdkPath); |
385 if (tokenEndpoint != null) { | 385 if (tokenEndpoint != null) { |
386 options.environment['_PUB_TEST_TOKEN_ENDPOINT'] = | 386 options.environment['_PUB_TEST_TOKEN_ENDPOINT'] = |
387 tokenEndpoint.toString(); | 387 tokenEndpoint.toString(); |
388 } | 388 } |
389 return options; | 389 return options; |
390 }); | 390 }); |
391 | 391 |
392 return new ScheduledProcess.start(dartBin, dartArgs, options: optionsFuture, | 392 return new ScheduledProcess.start(dartBin, dartArgs, options: optionsFuture, |
393 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); | 393 description: args.isEmpty ? 'pub' : 'pub ${args.first}'); |
394 } | 394 } |
395 | 395 |
396 /// Whether pub is running from within the Dart SDK, as opposed to from the Dart | 396 /// Whether pub is running from within the Dart SDK, as opposed to from the Dart |
397 /// source repository. | 397 /// source repository. |
398 bool get _runningFromSdk => path.dirname(relativeToPub('..')) == 'util'; | 398 bool get _runningFromSdk => |
| 399 fileExists(relativeToPub(path.join('..', '..', '..', '..', 'version'))); |
399 | 400 |
400 // TODO(nweiz): use the built-in mechanism for accessing this once it exists | 401 // TODO(nweiz): use the built-in mechanism for accessing this once it exists |
401 // (issue 9119). | 402 // (issue 9119). |
402 /// The path to the `packages` directory from which pub loads its dependencies. | 403 /// The path to the `packages` directory from which pub loads its dependencies. |
403 String get _packageRoot { | 404 String get _packageRoot { |
404 if (_runningFromSdk) { | 405 if (_runningFromSdk) { |
405 return path.absolute(relativeToPub(path.join('..', '..', 'packages'))); | 406 return path.absolute(relativeToPub( |
| 407 path.join('..', '..', '..', '..', 'packages'))); |
406 } else { | 408 } else { |
407 return path.absolute(path.join( | 409 return path.absolute(path.join( |
408 path.dirname(new Options().executable), '..', '..', 'packages')); | 410 path.dirname(new Options().executable), '..', '..', 'packages')); |
409 } | 411 } |
410 } | 412 } |
411 | 413 |
412 /// Skips the current test if Git is not installed. This validates that the | 414 /// Skips the current test if Git is not installed. This validates that the |
413 /// current test is running on a buildbot in which case we expect git to be | 415 /// current test is running on a buildbot in which case we expect git to be |
414 /// installed. If we are not running on the buildbot, we will instead see if | 416 /// installed. If we are not running on the buildbot, we will instead see if |
415 /// git is installed and skip the test if not. This way, users don't need to | 417 /// git is installed and skip the test if not. This way, users don't need to |
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 bool matches(item, MatchState matchState) { | 630 bool matches(item, MatchState matchState) { |
629 if (item is! Pair) return false; | 631 if (item is! Pair) return false; |
630 return _firstMatcher.matches(item.first, matchState) && | 632 return _firstMatcher.matches(item.first, matchState) && |
631 _lastMatcher.matches(item.last, matchState); | 633 _lastMatcher.matches(item.last, matchState); |
632 } | 634 } |
633 | 635 |
634 Description describe(Description description) { | 636 Description describe(Description description) { |
635 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 637 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
636 } | 638 } |
637 } | 639 } |
OLD | NEW |