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

Side by Side Diff: utils/tests/pub/test_pub.dart

Issue 11091015: Better pub integration test error reporting. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Reorganize a bit to get rid of some nesting. Created 8 years, 2 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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) 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 * Test infrastructure for testing pub. Unlike typical unit tests, most pub 6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub
7 * tests are integration tests that stage some stuff on the file system, run 7 * tests are integration tests that stage some stuff on the file system, run
8 * pub, and then validate the results. This library provides an API to build 8 * pub, and then validate the results. This library provides an API to build
9 * tests like that. 9 * tests like that.
10 */ 10 */
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
499 future.chain((_) => cleanup()).then((_) { 499 future.chain((_) => cleanup()).then((_) {
500 asyncDone(); 500 asyncDone();
501 }); 501 });
502 } 502 }
503 503
504 /// Get the path to the root "util/test/pub" directory containing the pub tests. 504 /// Get the path to the root "util/test/pub" directory containing the pub tests.
505 String get testDirectory { 505 String get testDirectory {
506 var dir = new Path.fromNative(new Options().script); 506 var dir = new Path.fromNative(new Options().script);
507 while (dir.filename != 'pub') dir = dir.directoryPath; 507 while (dir.filename != 'pub') dir = dir.directoryPath;
508 508
509 return dir.toNativePath(); 509 return new File(dir.toNativePath()).fullPathSync();
510 } 510 }
511 511
512 /** 512 /**
513 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and 513 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and
514 * validates that its results match [output], [error], and [exitCode]. 514 * validates that its results match [output], [error], and [exitCode].
515 */ 515 */
516 void schedulePub([List<String> args, Pattern output, Pattern error, 516 void schedulePub([List<String> args, Pattern output, Pattern error,
517 int exitCode = 0]) { 517 int exitCode = 0]) {
518 _schedule((sandboxDir) { 518 _schedule((sandboxDir) {
519 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); 519 String pathInSandbox(path) => join(getFullPath(sandboxDir), path);
(...skipping 14 matching lines...) Expand all
534 534
535 var dartArgs = 535 var dartArgs =
536 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace']; 536 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace'];
537 dartArgs.addAll(args); 537 dartArgs.addAll(args);
538 538
539 var environment = new Map.from(Platform.environment); 539 var environment = new Map.from(Platform.environment);
540 environment['PUB_CACHE'] = pathInSandbox(cachePath); 540 environment['PUB_CACHE'] = pathInSandbox(cachePath);
541 environment['DART_SDK'] = pathInSandbox(sdkPath); 541 environment['DART_SDK'] = pathInSandbox(sdkPath);
542 542
543 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath), 543 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath),
544 environment: environment, pipeStdout: output == null, 544 environment: environment);
545 pipeStderr: error == null);
546 }).transform((result) { 545 }).transform((result) {
547 _validateOutput(output, result.stdout); 546 var failures = [];
548 _validateOutput(error, result.stderr);
549 547
550 Expect.equals(result.exitCode, exitCode, 548 _validateOutput(failures, 'stdout', output, result.stdout);
551 'Pub returned exit code ${result.exitCode}, expected $exitCode.'); 549 _validateOutput(failures, 'stderr', error, result.stderr);
550
551 if (result.exitCode != exitCode) {
552 failures.add(
553 'Pub returned exit code ${result.exitCode}, expected $exitCode.');
554 }
555
556 if (failures.length > 0) {
557 if (error == null) {
558 // If we aren't validating the error, still show it on failure.
559 failures.add('Pub stderr:');
560 failures.addAll(result.stderr.map((line) => '| $line'));
561 }
562
563 throw new ExpectException(Strings.join(failures, '\n'));
564 }
552 565
553 return null; 566 return null;
554 }); 567 });
555 }); 568 });
556 } 569 }
557 570
558 /** 571 /**
559 * A shorthand for [schedulePub] and [run] when no validation needs to be done 572 * A shorthand for [schedulePub] and [run] when no validation needs to be done
560 * after Pub has been run. 573 * after Pub has been run.
561 */ 574 */
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
610 623
611 return runNextEvent(null); 624 return runNextEvent(null);
612 } 625 }
613 626
614 /** 627 /**
615 * Compares the [actual] output from running pub with [expected]. For [String] 628 * Compares the [actual] output from running pub with [expected]. For [String]
616 * patterns, ignores leading and trailing whitespace differences and tries to 629 * patterns, ignores leading and trailing whitespace differences and tries to
617 * report the offending difference in a nice way. For other [Pattern]s, just 630 * report the offending difference in a nice way. For other [Pattern]s, just
618 * reports whether the output contained the pattern. 631 * reports whether the output contained the pattern.
619 */ 632 */
620 void _validateOutput(Pattern expected, List<String> actual) { 633 void _validateOutput(List<String> failures, String pipe, Pattern expected,
634 List<String> actual) {
621 if (expected == null) return; 635 if (expected == null) return;
622 636
623 if (expected is String) return _validateOutputString(expected, actual); 637 if (expected is RegExp) {
624 var actualText = Strings.join(actual, "\n"); 638 _validateOutputRegex(failures, pipe, expected, actual);
625 if (actualText.contains(expected)) return; 639 } else {
626 Expect.fail('Expected output to match "$expected", was:\n$actualText'); 640 _validateOutputString(failures, pipe, expected, actual);
641 }
627 } 642 }
628 643
629 void _validateOutputString(String expectedText, List<String> actual) { 644 void _validateOutputRegex(List<String> failures, String pipe,
645 RegExp expected, List<String> actual) {
646 var actualText = Strings.join(actual, '\n');
647 if (actualText.contains(expected)) return;
648
649 if (actual.length == 0) {
650 failures.add('Expected $pipe to match "${expected.pattern}" but got none.');
651 } else {
652 failures.add('Expected $pipe to match "${expected.pattern}" but got:');
653 failures.addAll(actual.map((line) => '| $line'));
654 }
655 }
656
657 void _validateOutputString(List<String> failures, String pipe,
658 String expectedText, List<String> actual) {
630 final expected = expectedText.split('\n'); 659 final expected = expectedText.split('\n');
631 660
632 // Strip off the last line. This lets us have expected multiline strings 661 // Strip off the last line. This lets us have expected multiline strings
633 // where the closing ''' is on its own line. It also fixes '' expected output 662 // where the closing ''' is on its own line. It also fixes '' expected output
634 // to expect zero lines of output, not a single empty line. 663 // to expect zero lines of output, not a single empty line.
635 expected.removeLast(); 664 expected.removeLast();
636 665
637 final length = min(expected.length, actual.length); 666 var results = [];
667 var failed = false;
668
669 // Compare them line by line to see which ones match.
670 var length = max(expected.length, actual.length);
638 for (var i = 0; i < length; i++) { 671 for (var i = 0; i < length; i++) {
639 if (expected[i].trim() != actual[i].trim()) { 672 if (i >= actual.length) {
640 Expect.fail( 673 // Missing output.
641 'Output line ${i + 1} was: ${actual[i]}\nexpected: ${expected[i]}'); 674 failed = true;
675 results.add('? ${expected[i]}');
676 } else if (i >= expected.length) {
677 // Unexpected extra output.
678 failed = true;
679 results.add('X ${actual[i]}');
680 } else {
681 var expectedLine = expected[i].trim();
682 var actualLine = actual[i].trim();
683
684 if (expectedLine != actualLine) {
685 // Mismatched lines.
686 failed = true;
687 results.add('X ${actual[i]}');
688 } else {
689 // Output is OK, but include it in case other lines are wrong.
690 results.add('| ${actual[i]}');
691 }
642 } 692 }
643 } 693 }
644 694
645 if (expected.length > actual.length) { 695 // If any lines mismatched, show the expected and actual.
646 final message = new StringBuffer(); 696 if (failed) {
647 message.add('Missing expected output:\n'); 697 failures.add('Expected $pipe:');
648 for (var i = actual.length; i < expected.length; i++) { 698 failures.addAll(expected.map((line) => '| $line'));
649 message.add(expected[i]); 699 failures.add('Got:');
650 message.add('\n'); 700 failures.addAll(results);
651 }
652
653 Expect.fail(message.toString());
654 }
655
656 if (expected.length < actual.length) {
657 final message = new StringBuffer();
658 message.add('Unexpected output:\n');
659 for (var i = expected.length; i < actual.length; i++) {
660 message.add(actual[i]);
661 message.add('\n');
662 }
663
664 Expect.fail(message.toString());
665 } 701 }
666 } 702 }
667 703
668 /** 704 /**
669 * Base class for [FileDescriptor] and [DirectoryDescriptor] so that a 705 * Base class for [FileDescriptor] and [DirectoryDescriptor] so that a
670 * directory can contain a heterogeneous collection of files and 706 * directory can contain a heterogeneous collection of files and
671 * subdirectories. 707 * subdirectories.
672 */ 708 */
673 abstract class Descriptor { 709 abstract class Descriptor {
674 /** 710 /**
(...skipping 491 matching lines...) Expand 10 before | Expand all | Expand 10 after
1166 } 1202 }
1167 1203
1168 /** 1204 /**
1169 * Schedules a callback to be called after Pub is run with [runPub], even if it 1205 * Schedules a callback to be called after Pub is run with [runPub], even if it
1170 * fails. 1206 * fails.
1171 */ 1207 */
1172 void _scheduleCleanup(_ScheduledEvent event) { 1208 void _scheduleCleanup(_ScheduledEvent event) {
1173 if (_scheduledCleanup == null) _scheduledCleanup = []; 1209 if (_scheduledCleanup == null) _scheduledCleanup = [];
1174 _scheduledCleanup.add(event); 1210 _scheduledCleanup.add(event);
1175 } 1211 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698