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 /** | 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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 } |
OLD | NEW |