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 /// 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 |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 return result; | 416 return result; |
417 }); | 417 }); |
418 } | 418 } |
419 | 419 |
420 /// Return the name for the package described by [description] and from | 420 /// Return the name for the package described by [description] and from |
421 /// [sourceName]. | 421 /// [sourceName]. |
422 String _packageName(String sourceName, description) { | 422 String _packageName(String sourceName, description) { |
423 switch (sourceName) { | 423 switch (sourceName) { |
424 case "git": | 424 case "git": |
425 var url = description is String ? description : description['url']; | 425 var url = description is String ? description : description['url']; |
426 return basename(url.replaceFirst(new RegExp(r"(\.git)?/?$"), "")); | 426 // TODO(rnystrom): Using path.basename on a URL is hacky. If we add URL |
| 427 // support to pkg/path, should use an explicit builder for that. |
| 428 return path.basename(url.replaceFirst(new RegExp(r"(\.git)?/?$"), "")); |
427 case "hosted": | 429 case "hosted": |
428 if (description is String) return description; | 430 if (description is String) return description; |
429 return description['name']; | 431 return description['name']; |
430 case "sdk": | 432 case "sdk": |
431 return description; | 433 return description; |
432 default: | 434 default: |
433 return description; | 435 return description; |
434 } | 436 } |
435 } | 437 } |
436 | 438 |
437 /// The path of the package cache directory used for tests. Relative to the | 439 /// The path of the package cache directory used for tests. Relative to the |
438 /// sandbox directory. | 440 /// sandbox directory. |
439 final String cachePath = "cache"; | 441 final String cachePath = "cache"; |
440 | 442 |
441 /// The path of the mock SDK directory used for tests. Relative to the sandbox | 443 /// The path of the mock SDK directory used for tests. Relative to the sandbox |
442 /// directory. | 444 /// directory. |
443 final String sdkPath = "sdk"; | 445 final String sdkPath = "sdk"; |
444 | 446 |
445 /// The path of the mock app directory used for tests. Relative to the sandbox | 447 /// The path of the mock app directory used for tests. Relative to the sandbox |
446 /// directory. | 448 /// directory. |
447 final String appPath = "myapp"; | 449 final String appPath = "myapp"; |
448 | 450 |
449 /// The path of the packages directory in the mock app used for tests. Relative | 451 /// The path of the packages directory in the mock app used for tests. Relative |
450 /// to the sandbox directory. | 452 /// to the sandbox directory. |
451 final String packagesPath = "$appPath/packages"; | 453 final String packagesPath = "$appPath/packages"; |
452 | 454 |
453 /// The type for callbacks that will be fired during [schedulePub]. Takes the | 455 /// The type for callbacks that will be fired during [schedulePub]. Takes the |
454 /// sandbox directory as a parameter. | 456 /// sandbox directory as a parameter. |
455 typedef Future _ScheduledEvent(Directory parentDir); | 457 typedef Future _ScheduledEvent(String parentDir); |
456 | 458 |
457 /// The list of events that are scheduled to run as part of the test case. | 459 /// The list of events that are scheduled to run as part of the test case. |
458 List<_ScheduledEvent> _scheduled; | 460 List<_ScheduledEvent> _scheduled; |
459 | 461 |
460 /// The list of events that are scheduled to run after the test case, even if | 462 /// The list of events that are scheduled to run after the test case, even if |
461 /// it failed. | 463 /// it failed. |
462 List<_ScheduledEvent> _scheduledCleanup; | 464 List<_ScheduledEvent> _scheduledCleanup; |
463 | 465 |
464 /// The list of events that are scheduled to run after the test case only if it | 466 /// The list of events that are scheduled to run after the test case only if it |
465 /// failed. | 467 /// failed. |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
520 // advance to the next test and run it. | 522 // advance to the next test and run it. |
521 registerException(e.error, e.stackTrace); | 523 registerException(e.error, e.stackTrace); |
522 }); | 524 }); |
523 }); | 525 }); |
524 } | 526 } |
525 | 527 |
526 /// Get the path to the root "util/test/pub" directory containing the pub | 528 /// Get the path to the root "util/test/pub" directory containing the pub |
527 /// tests. | 529 /// tests. |
528 String get testDirectory { | 530 String get testDirectory { |
529 var dir = new Options().script; | 531 var dir = new Options().script; |
530 while (basename(dir) != 'pub') dir = dirname(dir); | 532 while (path.basename(dir) != 'pub') dir = path.dirname(dir); |
531 | 533 |
532 return getFullPath(dir); | 534 return path.absolute(dir); |
533 } | 535 } |
534 | 536 |
535 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and | 537 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and |
536 /// validates that its results match [output], [error], and [exitCode]. | 538 /// validates that its results match [output], [error], and [exitCode]. |
537 void schedulePub({List args, Pattern output, Pattern error, | 539 void schedulePub({List args, Pattern output, Pattern error, |
538 Future<Uri> tokenEndpoint, int exitCode: 0}) { | 540 Future<Uri> tokenEndpoint, int exitCode: 0}) { |
539 _schedule((sandboxDir) { | 541 _schedule((sandboxDir) { |
540 return _doPub(runProcess, sandboxDir, args, tokenEndpoint).then((result) { | 542 return _doPub(runProcess, sandboxDir, args, tokenEndpoint).then((result) { |
541 var failures = []; | 543 var failures = []; |
542 | 544 |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
600 expectLater(pub.nextLine(), equals("")); | 602 expectLater(pub.nextLine(), equals("")); |
601 | 603 |
602 pub.writeLine("y"); | 604 pub.writeLine("y"); |
603 } | 605 } |
604 | 606 |
605 | 607 |
606 /// Calls [fn] with appropriately modified arguments to run a pub process. [fn] | 608 /// Calls [fn] with appropriately modified arguments to run a pub process. [fn] |
607 /// should have the same signature as [startProcess], except that the returned | 609 /// should have the same signature as [startProcess], except that the returned |
608 /// [Future] may have a type other than [Process]. | 610 /// [Future] may have a type other than [Process]. |
609 Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) { | 611 Future _doPub(Function fn, sandboxDir, List args, Future<Uri> tokenEndpoint) { |
610 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); | 612 String pathInSandbox(String relPath) { |
| 613 return join(path.absolute(sandboxDir), relPath); |
| 614 } |
| 615 |
611 return defer(() { | 616 return defer(() { |
612 ensureDir(pathInSandbox(appPath)); | 617 ensureDir(pathInSandbox(appPath)); |
613 return Future.wait([ | 618 return Future.wait([ |
614 _awaitObject(args), | 619 _awaitObject(args), |
615 tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint | 620 tokenEndpoint == null ? new Future.immediate(null) : tokenEndpoint |
616 ]); | 621 ]); |
617 }).then((results) { | 622 }).then((results) { |
618 var args = results[0]; | 623 var args = results[0]; |
619 var tokenEndpoint = results[1]; | 624 var tokenEndpoint = results[1]; |
620 // Find a Dart executable we can use to spawn. Use the same one that was | 625 // Find a Dart executable we can use to spawn. Use the same one that was |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
670 /// Note that this will only affect HTTP requests made via http.dart in the | 675 /// Note that this will only affect HTTP requests made via http.dart in the |
671 /// parent process. | 676 /// parent process. |
672 void useMockClient(MockClient client) { | 677 void useMockClient(MockClient client) { |
673 var oldInnerClient = httpClient.inner; | 678 var oldInnerClient = httpClient.inner; |
674 httpClient.inner = client; | 679 httpClient.inner = client; |
675 _scheduleCleanup((_) { | 680 _scheduleCleanup((_) { |
676 httpClient.inner = oldInnerClient; | 681 httpClient.inner = oldInnerClient; |
677 }); | 682 }); |
678 } | 683 } |
679 | 684 |
680 Future _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { | 685 Future _runScheduled(String parentDir, List<_ScheduledEvent> scheduled) { |
681 if (scheduled == null) return new Future.immediate(null); | 686 if (scheduled == null) return new Future.immediate(null); |
682 var iterator = scheduled.iterator; | 687 var iterator = scheduled.iterator; |
683 | 688 |
684 Future runNextEvent(_) { | 689 Future runNextEvent(_) { |
685 if (_abortScheduled || !iterator.moveNext()) { | 690 if (_abortScheduled || !iterator.moveNext()) { |
686 _abortScheduled = false; | 691 _abortScheduled = false; |
687 scheduled.clear(); | 692 scheduled.clear(); |
688 return new Future.immediate(null); | 693 return new Future.immediate(null); |
689 } | 694 } |
690 | 695 |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
808 /// directory. | 813 /// directory. |
809 // TODO(nweiz): Use implicit closurization once issue 2984 is fixed. | 814 // TODO(nweiz): Use implicit closurization once issue 2984 is fixed. |
810 void scheduleCreate() => _schedule((dir) => this.create(dir)); | 815 void scheduleCreate() => _schedule((dir) => this.create(dir)); |
811 | 816 |
812 /// Schedules the file or directory to be deleted recursively. | 817 /// Schedules the file or directory to be deleted recursively. |
813 void scheduleDelete() => _schedule((dir) => this.delete(dir)); | 818 void scheduleDelete() => _schedule((dir) => this.delete(dir)); |
814 | 819 |
815 /// Schedules the directory to be validated after Pub is run with | 820 /// Schedules the directory to be validated after Pub is run with |
816 /// [schedulePub]. The directory will be validated relative to the sandbox | 821 /// [schedulePub]. The directory will be validated relative to the sandbox |
817 /// directory. | 822 /// directory. |
818 void scheduleValidate() => _schedule((parentDir) => validate(parentDir.path)); | 823 void scheduleValidate() => _schedule((parentDir) => validate(parentDir)); |
819 | 824 |
820 /// Asserts that the name of the descriptor is a [String] and returns it. | 825 /// Asserts that the name of the descriptor is a [String] and returns it. |
821 String get _stringName { | 826 String get _stringName { |
822 if (name is String) return name; | 827 if (name is String) return name; |
823 throw 'Pattern $name must be a string.'; | 828 throw 'Pattern $name must be a string.'; |
824 } | 829 } |
825 | 830 |
826 /// Validates that at least one file in [dir] matching [name] is valid | 831 /// Validates that at least one file in [dir] matching [name] is valid |
827 /// according to [validate]. [validate] should throw or complete to an | 832 /// according to [validate]. [validate] should throw or complete to an |
828 /// exception if the input path is invalid. | 833 /// exception if the input path is invalid. |
(...skipping 772 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1601 /// calling [completion] is unnecessary. | 1606 /// calling [completion] is unnecessary. |
1602 void expectLater(Future actual, matcher, {String reason, | 1607 void expectLater(Future actual, matcher, {String reason, |
1603 FailureHandler failureHandler, bool verbose: false}) { | 1608 FailureHandler failureHandler, bool verbose: false}) { |
1604 _schedule((_) { | 1609 _schedule((_) { |
1605 return actual.then((value) { | 1610 return actual.then((value) { |
1606 expect(value, matcher, reason: reason, failureHandler: failureHandler, | 1611 expect(value, matcher, reason: reason, failureHandler: failureHandler, |
1607 verbose: false); | 1612 verbose: false); |
1608 }); | 1613 }); |
1609 }); | 1614 }); |
1610 } | 1615 } |
OLD | NEW |