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

Side by Side Diff: tools/testing/dart/test_suite.dart

Issue 10683009: Adds support for layout tests. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 8 years, 5 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
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 * Classes and methods for enumerating and preparing tests. 6 * Classes and methods for enumerating and preparing tests.
7 * 7 *
8 * This library includes: 8 * This library includes:
9 * 9 *
10 * - Creating tests by listing all the Dart files in certain directories, 10 * - Creating tests by listing all the Dart files in certain directories,
(...skipping 501 matching lines...) Expand 10 before | Expand all | Expand 10 after
512 * step and an execution step, both with the appropriate executable and 512 * step and an execution step, both with the appropriate executable and
513 * arguments. 513 * arguments.
514 */ 514 */
515 void enqueueBrowserTest(TestInformation info, 515 void enqueueBrowserTest(TestInformation info,
516 String testName, 516 String testName,
517 Set<String> expectations) { 517 Set<String> expectations) {
518 Map optionsFromFile = info.optionsFromFile; 518 Map optionsFromFile = info.optionsFromFile;
519 String filename = info.filename; 519 String filename = info.filename;
520 if (optionsFromFile['isMultitest']) return; 520 if (optionsFromFile['isMultitest']) return;
521 bool isWebTest = optionsFromFile['containsDomImport']; 521 bool isWebTest = optionsFromFile['containsDomImport'];
522 List<String> webTestOutput = optionsFromFile['webTestOutput'];
522 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; 523 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition'];
523 if (!isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { 524 if (!isLibraryDefinition && optionsFromFile['containsSourceOrImport']) {
524 print('Warning for $filename: Browser tests require #library ' 525 print('Warning for $filename: Browser tests require #library '
525 'in any file that uses #import, #source, or #resource'); 526 'in any file that uses #import, #source, or #resource');
526 } 527 }
527 528
528 final String compiler = configuration['compiler']; 529 final String compiler = configuration['compiler'];
529 final String runtime = configuration['runtime']; 530 final String runtime = configuration['runtime'];
530 final String testPath = 531 final String testPath =
531 new File(filename).fullPathSync().replaceAll('\\', '/'); 532 new File(filename).fullPathSync().replaceAll('\\', '/');
(...skipping 17 matching lines...) Expand all
549 if (!isWebTest) { 550 if (!isWebTest) {
550 // test.dart will import the dart test directly, if it is a library, 551 // test.dart will import the dart test directly, if it is a library,
551 // or indirectly through test_as_library.dart, if it is not. 552 // or indirectly through test_as_library.dart, if it is not.
552 String dartLibraryFilename; 553 String dartLibraryFilename;
553 if (isLibraryDefinition) { 554 if (isLibraryDefinition) {
554 dartLibraryFilename = testPath; 555 dartLibraryFilename = testPath;
555 } else { 556 } else {
556 dartLibraryFilename = 'test_as_library.dart'; 557 dartLibraryFilename = 'test_as_library.dart';
557 File file = new File('$tempDir/$dartLibraryFilename'); 558 File file = new File('$tempDir/$dartLibraryFilename');
558 RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE); 559 RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE);
559 dartLibrary.writeStringSync(WrapDartTestInLibrary(testPath)); 560 dartLibrary.writeStringSync(wrapDartTestInLibrary(testPath));
560 dartLibrary.closeSync(); 561 dartLibrary.closeSync();
561 } 562 }
562 563
563 File file = new File(dartWrapperFilename); 564 File file = new File(dartWrapperFilename);
564 RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE); 565 RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE);
565 dartWrapper.writeStringSync( 566 dartWrapper.writeStringSync(
566 DartTestWrapper(dartDir, dartLibraryFilename)); 567 dartTestWrapper(dartDir, dartLibraryFilename));
567 dartWrapper.closeSync(); 568 dartWrapper.closeSync();
568 } else { 569 } else {
569 dartWrapperFilename = testPath; 570 dartWrapperFilename = testPath;
570 // TODO(whesse): Once test.py is retired, adjust the relative path in 571 // TODO(whesse): Once test.py is retired, adjust the relative path in
571 // the client/samples/dartcombat test to its css file, remove the 572 // the client/samples/dartcombat test to its css file, remove the
572 // "../../" from this path, and move this out of the isWebTest guard. 573 // "../../" from this path, and move this out of the isWebTest guard.
573 // Also remove getHtmlName, and just use test.html. 574 // Also remove getHtmlName, and just use test.html.
574 // TODO(efortuna): this shortening of htmlFilename is a band-aid until 575 // TODO(efortuna): this shortening of htmlFilename is a band-aid until
575 // the above TODO gets fixed. Windows cannot have paths that are longer 576 // the above TODO gets fixed. Windows cannot have paths that are longer
576 // than 260 characters, and without this hack, we were running past the 577 // than 260 characters, and without this hack, we were running past the
577 // the limit. 578 // the limit.
578 String htmlFilename = getHtmlName(filename); 579 String htmlFilename = getHtmlName(filename);
579 while ('$tempDir/../$htmlFilename'.length >= 260) { 580 while ('$tempDir/../$htmlFilename'.length >= 260) {
580 htmlFilename = htmlFilename.substring(htmlFilename.length~/2); 581 htmlFilename = htmlFilename.substring(htmlFilename.length~/2);
581 } 582 }
582 htmlPath = '$tempDir/../$htmlFilename'; 583 htmlPath = '$tempDir/../$htmlFilename';
583 } 584 }
584 final String scriptPath = (compiler == 'none') ? 585 final String scriptPath = (compiler == 'none') ?
585 dartWrapperFilename : compiledDartWrapperFilename; 586 dartWrapperFilename : compiledDartWrapperFilename;
586 // Create the HTML file for the test. 587 // Create the HTML file for the test.
587 RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE); 588 RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE);
588 String filePrefix = ''; 589 String filePrefix = '';
589 if (Platform.operatingSystem == 'windows') { 590 if (Platform.operatingSystem == 'windows') {
590 // Firefox on Windows does not like absolute file path names that start 591 // Firefox on Windows does not like absolute file path names that start
591 // with 'C:' adding 'file:///' solves the problem. 592 // with 'C:' adding 'file:///' solves the problem.
592 filePrefix = 'file:///'; 593 filePrefix = 'file:///';
593 } 594 }
594 htmlTest.writeStringSync(GetHtmlContents( 595 String content;
596 if (webTestOutput.isEmpty()) {
597 content = getHtmlContents(
595 filename, 598 filename,
596 '$filePrefix$dartDir/lib/unittest/test_controller.js', 599 '$filePrefix$dartDir/lib/unittest/test_controller.js',
597 scriptType, 600 scriptType,
598 '$filePrefix$scriptPath')); 601 '$filePrefix$scriptPath');
602 } else {
603 content = getHtmlLayoutContents(scriptType, '$filePrefix$scriptPath');
604 }
605 htmlTest.writeStringSync(content);
599 htmlTest.closeSync(); 606 htmlTest.closeSync();
600 607
601 // Construct the command(s) that compile all the inputs needed by the 608 // Construct the command(s) that compile all the inputs needed by the
602 // browser test. For running Dart in DRT, this will be noop commands. 609 // browser test. For running Dart in DRT, this will be noop commands.
603 List<Command> commands = []; 610 List<Command> commands = [];
604 if (compiler != 'none') { 611 if (compiler != 'none') {
605 commands.add(_compileCommand( 612 commands.add(_compileCommand(
606 dartWrapperFilename, compiledDartWrapperFilename, 613 dartWrapperFilename, compiledDartWrapperFilename,
607 compiler, tempDir, vmOptions)); 614 compiler, tempDir, vmOptions));
608 615
609 // some tests require compiling multiple input scripts. 616 // some tests require compiling multiple input scripts.
610 List<String> otherScripts = optionsFromFile['otherScripts']; 617 List<String> otherScripts = optionsFromFile['otherScripts'];
611 for (String name in otherScripts) { 618 for (String name in otherScripts) {
612 int end = filename.lastIndexOf('/'); 619 String dir = _dirNameFromFile(filename);
613 if (end == -1) { 620 if (dir == null) {
614 print('Warning: error processing "OtherScripts" of $filename.'); 621 print('Warning: error processing "OtherScripts" of $filename.');
615 print('Skipping test ($testName).'); 622 print('Skipping test ($testName).');
616 return; 623 return;
617 } 624 }
618 String dir = filename.substring(0, end); 625 int end = name.lastIndexOf('.dart');
619 end = name.lastIndexOf('.dart');
620 if (end == -1) { 626 if (end == -1) {
621 print('Warning: error processing "OtherScripts" in $filename.'); 627 print('Warning: error processing "OtherScripts" in $filename.');
622 print('Skipping test ($testName).'); 628 print('Skipping test ($testName).');
623 return; 629 return;
624 } 630 }
625 String compiledName = '${name.substring(0, end)}.js'; 631 String compiledName = '${name.substring(0, end)}.js';
626 commands.add(_compileCommand( 632 commands.add(_compileCommand(
627 '$dir/$name', '$tempDir/$compiledName', 633 '$dir/$name', '$tempDir/$compiledName',
628 compiler, tempDir, vmOptions)); 634 compiler, tempDir, vmOptions));
629 } 635 }
(...skipping 19 matching lines...) Expand all
649 if (runtime == 'drt' && compiler == 'none') { 655 if (runtime == 'drt' && compiler == 'none') {
650 var dartFlags = ['--ignore-unrecognized-flags']; 656 var dartFlags = ['--ignore-unrecognized-flags'];
651 if (configuration["checked"]) { 657 if (configuration["checked"]) {
652 dartFlags.add('--enable_asserts'); 658 dartFlags.add('--enable_asserts');
653 dartFlags.add("--enable_type_checks"); 659 dartFlags.add("--enable_type_checks");
654 } 660 }
655 dartFlags.addAll(vmOptions); 661 dartFlags.addAll(vmOptions);
656 args.add('--dart-flags=${Strings.join(dartFlags, " ")}'); 662 args.add('--dart-flags=${Strings.join(dartFlags, " ")}');
657 } 663 }
658 args.add(htmlPath); 664 args.add(htmlPath);
665 if (!webTestOutput.isEmpty()) {
666 String dir = _dirNameFromFile(filename);
667 args.add('--out-expectation=$dir/${webTestOutput[0]}');
668 }
659 } 669 }
660 commands.add(new Command('python', args)); 670 commands.add(new Command('python', args));
661 671
662 // Create BrowserTestCase and queue it. 672 // Create BrowserTestCase and queue it.
663 var testCase = new BrowserTestCase('$suiteName/$testName', 673 var testCase = new BrowserTestCase('$suiteName/$testName',
664 commands, configuration, completeHandler, expectations, 674 commands, configuration, completeHandler, expectations,
665 optionsFromFile['isNegative']); 675 optionsFromFile['isNegative']);
666 doTest(testCase); 676 doTest(testCase);
667 } 677 }
668 } 678 }
669 679
680 String _dirNameFromFile(String filename) {
681 int end = filename.lastIndexOf('/');
682 return (end == -1) ? null : filename.substring(0, end);
683 }
684
670 /** Helper to create a compilation command for a single input file. */ 685 /** Helper to create a compilation command for a single input file. */
671 Command _compileCommand(String inputFile, String outputFile, 686 Command _compileCommand(String inputFile, String outputFile,
672 String compiler, String dir, var vmOptions) { 687 String compiler, String dir, var vmOptions) {
673 String executable = TestUtils.compilerPath(configuration); 688 String executable = TestUtils.compilerPath(configuration);
674 List<String> args = TestUtils.standardOptions(configuration); 689 List<String> args = TestUtils.standardOptions(configuration);
675 switch (compiler) { 690 switch (compiler) {
676 case 'frog': 691 case 'frog':
677 String libdir = configuration['froglib']; 692 String libdir = configuration['froglib'];
678 if (libdir == '') { 693 if (libdir == '') {
679 libdir = '$dartDir/frog/lib'; 694 libdir = '$dartDir/frog/lib';
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
845 Expect.isFalse(vmOptionsList.isEmpty(), "empty vmOptionsList"); 860 Expect.isFalse(vmOptionsList.isEmpty(), "empty vmOptionsList");
846 for (var vmOptions in vmOptionsList) { 861 for (var vmOptions in vmOptionsList) {
847 var options = new List<String>.from(vmOptions); 862 var options = new List<String>.from(vmOptions);
848 options.addAll(args); 863 options.addAll(args);
849 result.add(options); 864 result.add(options);
850 } 865 }
851 866
852 return result; 867 return result;
853 } 868 }
854 869
870 /**
871 * Special options for individual tests are specified with comments directly
872 * in test files. Here is a list of parameters available:
873 * - Flags can be passed to the vm or dartium process that runs the test as
874 * follows:
875 *
876 * // VMOptions=--flag1 --flag2
877 *
878 * - Flags can be passed to the dart script that contains the test as
879 * follows:
880 *
881 * // DartOptions=--flag1 --flag2
882 *
883 * - For tests that depend on compiling other files with dart2js (e.g.
884 * isolate tests that use multiple source scripts), you can specify
885 * additional files to compile as follows:
886 *
887 * // OtherScripts=file1.dart file2.dart
888 *
889 * - You can indicate whether a test is treated as a web-only test as
890 * follows:
891 *
892 * // WebTest=true
Siggi Cherem (dart-lang) 2012/06/27 01:50:42 this is something I'm adding on a separate CL (htt
893 *
894 * Most tests are not web tests, but can (and will be) wrapped within
895 * another script file to test them also on browser environments (e.g.
896 * language and corelib tests are run this way). Specifing this flag means
897 * that no wrapping is necessary.
898 *
899 * - Using test expectations for layout tests:
900 *
901 * // WebTestOutput=expected_file.txt
902 * or
903 * // WebTestOutput=expected_file.png
904 *
905 * By default tests are run without expectation files: test.dart assumes
Bill Hesse 2012/06/27 09:24:37 Say "web tests" here, not just "tests". This only
Siggi Cherem (dart-lang) 2012/06/27 20:21:05 Done.
906 * tests fail if the process return a non-zero exit code (in the case of web
907 * tests, we check for PASS/FAIL indications in the test output). Specifying
908 * a test output explicitly will check that the test output matches that
909 * specified in the expectation file. In particular, the output of a web
910 * test will be a rendering representation (either in text form if the
911 * expectation ends in .txt, or an image, if the expectation ends in .png).
912 * These expectations can be recorded for the first time by specifying the
913 * option above, running the test, and running the copy command printed by
914 * the test script.
915 */
855 Map readOptionsFromFile(String filename) { 916 Map readOptionsFromFile(String filename) {
856 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); 917 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)");
857 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); 918 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)");
858 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)"); 919 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)");
920 RegExp testOutputRegExp = const RegExp(@"// WebTestOutput=(.*)");
859 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); 921 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)");
860 RegExp staticTypeRegExp = 922 RegExp staticTypeRegExp =
861 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*static type warning"); 923 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*static type warning");
862 RegExp compileTimeRegExp = 924 RegExp compileTimeRegExp =
863 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*compile-time error"); 925 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*compile-time error");
864 RegExp staticCleanRegExp = const RegExp(@"// @static-clean"); 926 RegExp staticCleanRegExp = const RegExp(@"// @static-clean");
865 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); 927 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true);
866 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); 928 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)");
867 RegExp domImportRegExp = 929 RegExp domImportRegExp =
868 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", 930 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)",
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
908 970
909 matches = staticCleanRegExp.allMatches(contents); 971 matches = staticCleanRegExp.allMatches(contents);
910 for (var match in matches) { 972 for (var match in matches) {
911 if (isStaticClean) { 973 if (isStaticClean) {
912 throw new Exception( 974 throw new Exception(
913 'More than one "// @static-clean=" line in test $filename'); 975 'More than one "// @static-clean=" line in test $filename');
914 } 976 }
915 isStaticClean = true; 977 isStaticClean = true;
916 } 978 }
917 979
918 List<String> otherScripts = new List<String>(); 980 List<String> otherScripts = _readListOption(otherScriptsRegExp, contents);
919 matches = otherScriptsRegExp.allMatches(contents); 981 List<String> webTestOutput = _readListOption(testOutputRegExp, contents);
920 for (var match in matches) { 982 if (!webTestOutput.isEmpty() && webTestOutput.length > 1) {
921 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); 983 throw new Exception(
984 'Please use a single expected output for '
985 '"// WebTestOutput=" in $filename');
922 } 986 }
923 987
924 if (contents.contains("@compile-error")) { 988 if (contents.contains("@compile-error")) {
925 isNegative = true; 989 isNegative = true;
926 } 990 }
927 991
928 if (contents.contains("@runtime-error") && hasRuntime) { 992 if (contents.contains("@runtime-error") && hasRuntime) {
929 isNegative = true; 993 isNegative = true;
930 } 994 }
931 995
(...skipping 15 matching lines...) Expand all
947 1011
948 return { "vmOptions": result, 1012 return { "vmOptions": result,
949 "dartOptions": dartOptions, 1013 "dartOptions": dartOptions,
950 "isNegative": isNegative, 1014 "isNegative": isNegative,
951 "isStaticClean" : isStaticClean, 1015 "isStaticClean" : isStaticClean,
952 "otherScripts": otherScripts, 1016 "otherScripts": otherScripts,
953 "isMultitest": isMultitest, 1017 "isMultitest": isMultitest,
954 "containsLeadingHash": containsLeadingHash, 1018 "containsLeadingHash": containsLeadingHash,
955 "isolateStubs": isolateStubs, 1019 "isolateStubs": isolateStubs,
956 "containsDomImport": containsDomImport, 1020 "containsDomImport": containsDomImport,
1021 "webTestOutput": webTestOutput,
957 "isLibraryDefinition": isLibraryDefinition, 1022 "isLibraryDefinition": isLibraryDefinition,
958 "containsSourceOrImport": containsSourceOrImport, 1023 "containsSourceOrImport": containsSourceOrImport,
959 "numStaticTypeAnnotations": numStaticTypeAnnotations, 1024 "numStaticTypeAnnotations": numStaticTypeAnnotations,
960 "numCompileTimeAnnotations": numCompileTimeAnnotations}; 1025 "numCompileTimeAnnotations": numCompileTimeAnnotations};
961 } 1026 }
962 1027
1028 static List<String> _readListOption(RegExp matcher, String contents) {
1029 List<String> res = new List<String>();
1030 for (var match in matcher.allMatches(contents)) {
1031 res.addAll(match[1].split(' ').filter((e) => e != ''));
1032 }
1033 return res;
1034 }
1035
963 List<List<String>> getVmOptions(Map optionsFromFile) { 1036 List<List<String>> getVmOptions(Map optionsFromFile) {
964 if (configuration['compiler'] == 'dart2js') { 1037 if (configuration['compiler'] == 'dart2js') {
965 return [[]]; 1038 return [[]];
966 } else { 1039 } else {
967 return optionsFromFile['vmOptions']; 1040 return optionsFromFile['vmOptions'];
968 } 1041 }
969 } 1042 }
970 } 1043 }
971 1044
972 1045
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1346 * $noCrash tests are expected to be flaky but not crash 1419 * $noCrash tests are expected to be flaky but not crash
1347 * $pass tests are expected to pass 1420 * $pass tests are expected to pass
1348 * $failOk tests are expected to fail that we won't fix 1421 * $failOk tests are expected to fail that we won't fix
1349 * $fail tests are expected to fail that we should fix 1422 * $fail tests are expected to fail that we should fix
1350 * $crash tests are expected to crash that we should fix 1423 * $crash tests are expected to crash that we should fix
1351 * $timeout tests are allowed to timeout 1424 * $timeout tests are allowed to timeout
1352 """; 1425 """;
1353 print(report); 1426 print(report);
1354 } 1427 }
1355 } 1428 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698