| 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 |
| (...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 359 /// Schedules creating a symlink at path [symlink] that points to [target], | 359 /// Schedules creating a symlink at path [symlink] that points to [target], |
| 360 /// both of which are assumed to be relative to [sandboxDir]. | 360 /// both of which are assumed to be relative to [sandboxDir]. |
| 361 void scheduleSymlink(String target, String symlink) { | 361 void scheduleSymlink(String target, String symlink) { |
| 362 schedule( | 362 schedule( |
| 363 () => createSymlink( | 363 () => createSymlink( |
| 364 path.join(sandboxDir, target), | 364 path.join(sandboxDir, target), |
| 365 path.join(sandboxDir, symlink)), | 365 path.join(sandboxDir, symlink)), |
| 366 'symlinking $target to $symlink'); | 366 'symlinking $target to $symlink'); |
| 367 } | 367 } |
| 368 | 368 |
| 369 /// Schedules a call to the Pub command-line utility. Runs Pub with [args] and | 369 /// Schedules a call to the Pub command-line utility. |
| 370 /// validates that its results match [output], [error], and [exitCode]. | 370 /// |
| 371 void schedulePub({List args, Pattern output, Pattern error, | 371 /// Runs Pub with [args] and validates that its results match [output] (or |
| 372 /// [outputJson]), [error], and [exitCode]. If [outputJson] is given, validates |
| 373 /// that pub outputs stringified JSON matching that object. |
| 374 void schedulePub({List args, Pattern output, Pattern error, outputJson, |
| 372 Future<Uri> tokenEndpoint, int exitCode: 0}) { | 375 Future<Uri> tokenEndpoint, int exitCode: 0}) { |
| 376 // Cannot pass both output and outputJson. |
| 377 assert(output == null || outputJson == null); |
| 378 |
| 373 var pub = startPub(args: args, tokenEndpoint: tokenEndpoint); | 379 var pub = startPub(args: args, tokenEndpoint: tokenEndpoint); |
| 374 pub.shouldExit(exitCode); | 380 pub.shouldExit(exitCode); |
| 375 | 381 |
| 382 var failures = []; |
| 383 var stderr; |
| 384 |
| 376 expect(Future.wait([ | 385 expect(Future.wait([ |
| 377 pub.remainingStdout(), | 386 pub.remainingStdout(), |
| 378 pub.remainingStderr() | 387 pub.remainingStderr() |
| 379 ]).then((results) { | 388 ]).then((results) { |
| 380 var failures = []; | 389 stderr = results[1]; |
| 381 _validateOutput(failures, 'stdout', output, results[0].split('\n')); | 390 |
| 382 _validateOutput(failures, 'stderr', error, results[1].split('\n')); | 391 if (outputJson == null) { |
| 392 _validateOutput(failures, 'stdout', output, results[0]); |
| 393 return; |
| 394 } |
| 395 |
| 396 // Allow the expected JSON to contain futures. |
| 397 return awaitObject(outputJson).then((resolved) { |
| 398 _validateOutputJson(failures, 'stdout', resolved, results[0]); |
| 399 }); |
| 400 }).then((_) { |
| 401 _validateOutput(failures, 'stderr', error, stderr); |
| 402 |
| 383 if (!failures.isEmpty) throw new TestFailure(failures.join('\n')); | 403 if (!failures.isEmpty) throw new TestFailure(failures.join('\n')); |
| 384 }), completes); | 404 }), completes); |
| 385 } | 405 } |
| 386 | 406 |
| 387 /// Like [startPub], but runs `pub lish` in particular with [server] used both | 407 /// Like [startPub], but runs `pub lish` in particular with [server] used both |
| 388 /// as the OAuth2 server (with "/token" as the token endpoint) and as the | 408 /// as the OAuth2 server (with "/token" as the token endpoint) and as the |
| 389 /// package server. | 409 /// package server. |
| 390 /// | 410 /// |
| 391 /// Any futures in [args] will be resolved before the process is started. | 411 /// Any futures in [args] will be resolved before the process is started. |
| 392 ScheduledProcess startPublish(ScheduledServer server, {List args}) { | 412 ScheduledProcess startPublish(ScheduledServer server, {List args}) { |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 640 } | 660 } |
| 641 | 661 |
| 642 return map; | 662 return map; |
| 643 } | 663 } |
| 644 | 664 |
| 645 /// Compares the [actual] output from running pub with [expected]. For [String] | 665 /// Compares the [actual] output from running pub with [expected]. For [String] |
| 646 /// patterns, ignores leading and trailing whitespace differences and tries to | 666 /// patterns, ignores leading and trailing whitespace differences and tries to |
| 647 /// report the offending difference in a nice way. For other [Pattern]s, just | 667 /// report the offending difference in a nice way. For other [Pattern]s, just |
| 648 /// reports whether the output contained the pattern. | 668 /// reports whether the output contained the pattern. |
| 649 void _validateOutput(List<String> failures, String pipe, Pattern expected, | 669 void _validateOutput(List<String> failures, String pipe, Pattern expected, |
| 650 List<String> actual) { | 670 String actual) { |
| 651 if (expected == null) return; | 671 if (expected == null) return; |
| 652 | 672 |
| 673 var actualLines = actual.split("\n"); |
| 653 if (expected is RegExp) { | 674 if (expected is RegExp) { |
| 654 _validateOutputRegex(failures, pipe, expected, actual); | 675 _validateOutputRegex(failures, pipe, expected, actualLines); |
| 655 } else { | 676 } else { |
| 656 _validateOutputString(failures, pipe, expected, actual); | 677 _validateOutputString(failures, pipe, expected, actualLines); |
| 657 } | 678 } |
| 658 } | 679 } |
| 659 | 680 |
| 660 void _validateOutputRegex(List<String> failures, String pipe, | 681 void _validateOutputRegex(List<String> failures, String pipe, |
| 661 RegExp expected, List<String> actual) { | 682 RegExp expected, List<String> actual) { |
| 662 var actualText = actual.join('\n'); | 683 var actualText = actual.join('\n'); |
| 663 if (actualText.contains(expected)) return; | 684 if (actualText.contains(expected)) return; |
| 664 | 685 |
| 665 if (actual.length == 0) { | 686 if (actual.length == 0) { |
| 666 failures.add('Expected $pipe to match "${expected.pattern}" but got none.'); | 687 failures.add('Expected $pipe to match "${expected.pattern}" but got none.'); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 712 | 733 |
| 713 // If any lines mismatched, show the expected and actual. | 734 // If any lines mismatched, show the expected and actual. |
| 714 if (failed) { | 735 if (failed) { |
| 715 failures.add('Expected $pipe:'); | 736 failures.add('Expected $pipe:'); |
| 716 failures.addAll(expected.map((line) => '| $line')); | 737 failures.addAll(expected.map((line) => '| $line')); |
| 717 failures.add('Got:'); | 738 failures.add('Got:'); |
| 718 failures.addAll(results); | 739 failures.addAll(results); |
| 719 } | 740 } |
| 720 } | 741 } |
| 721 | 742 |
| 743 void _validateOutputJson(List<String> failures, String pipe, |
| 744 expected, String actualText) { |
| 745 var actual; |
| 746 try { |
| 747 actual = json.parse(actualText); |
| 748 } on FormatException catch(error) { |
| 749 failures.add('Expected $pipe JSON:'); |
| 750 failures.add(expected); |
| 751 failures.add('Got invalid JSON:'); |
| 752 failures.add(actualText); |
| 753 } |
| 754 |
| 755 // Do a deep comparison of the JSON objects. |
| 756 expect(actual, equals(expected)); |
| 757 } |
| 758 |
| 722 /// A function that creates a [Validator] subclass. | 759 /// A function that creates a [Validator] subclass. |
| 723 typedef Validator ValidatorCreator(Entrypoint entrypoint); | 760 typedef Validator ValidatorCreator(Entrypoint entrypoint); |
| 724 | 761 |
| 725 /// Schedules a single [Validator] to run on the [appPath]. Returns a scheduled | 762 /// Schedules a single [Validator] to run on the [appPath]. Returns a scheduled |
| 726 /// Future that contains the errors and warnings produced by that validator. | 763 /// Future that contains the errors and warnings produced by that validator. |
| 727 Future<Pair<List<String>, List<String>>> schedulePackageValidation( | 764 Future<Pair<List<String>, List<String>>> schedulePackageValidation( |
| 728 ValidatorCreator fn) { | 765 ValidatorCreator fn) { |
| 729 return schedule(() { | 766 return schedule(() { |
| 730 var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath)); | 767 var cache = new SystemCache.withSources(path.join(sandboxDir, cachePath)); |
| 731 | 768 |
| (...skipping 19 matching lines...) Expand all Loading... |
| 751 bool matches(item, Map matchState) { | 788 bool matches(item, Map matchState) { |
| 752 if (item is! Pair) return false; | 789 if (item is! Pair) return false; |
| 753 return _firstMatcher.matches(item.first, matchState) && | 790 return _firstMatcher.matches(item.first, matchState) && |
| 754 _lastMatcher.matches(item.last, matchState); | 791 _lastMatcher.matches(item.last, matchState); |
| 755 } | 792 } |
| 756 | 793 |
| 757 Description describe(Description description) { | 794 Description describe(Description description) { |
| 758 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); | 795 description.addAll("(", ", ", ")", [_firstMatcher, _lastMatcher]); |
| 759 } | 796 } |
| 760 } | 797 } |
| OLD | NEW |