Chromium Code Reviews| 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 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 420 } | 420 } |
| 421 if (expectations.contains(SKIP)) return; | 421 if (expectations.contains(SKIP)) return; |
| 422 | 422 |
| 423 if (configuration['compiler'] != 'none' && info.hasCompileError) { | 423 if (configuration['compiler'] != 'none' && info.hasCompileError) { |
| 424 // If a compile-time error is expected, and we're testing a | 424 // If a compile-time error is expected, and we're testing a |
| 425 // compiler, we never need to attempt to run the program (in a | 425 // compiler, we never need to attempt to run the program (in a |
| 426 // browser or otherwise). | 426 // browser or otherwise). |
| 427 enqueueStandardTest(info, testName, expectations); | 427 enqueueStandardTest(info, testName, expectations); |
| 428 } else if (TestUtils.isBrowserRuntime(configuration['runtime'])) { | 428 } else if (TestUtils.isBrowserRuntime(configuration['runtime'])) { |
| 429 bool isWrappingRequired = configuration['compiler'] != 'dart2js'; | 429 bool isWrappingRequired = configuration['compiler'] != 'dart2js'; |
| 430 enqueueBrowserTest(info, testName, expectations, isWrappingRequired); | 430 if (info.optionsFromFile['isMultiHtmlTest']) { |
| 431 // A browser multi-test has multiple expectations for one test file. | |
| 432 // Find all the different sub-test expecations for one entire test file. | |
| 433 List<String> subtestNames = info.optionsFromFile['subtestNames']; | |
| 434 Map<String, Set<String>> multiHtmlTestExpectations = {}; | |
| 435 for (String name in subtestNames) { | |
| 436 String fullTestName = '$testName/$name'; | |
| 437 multiHtmlTestExpectations[fullTestName] = | |
| 438 testExpectations.expectations(fullTestName); | |
| 439 } | |
| 440 enqueueBrowserTest(info, testName, multiHtmlTestExpectations, | |
| 441 isWrappingRequired); | |
| 442 } else { | |
| 443 enqueueBrowserTest(info, testName, expectations, isWrappingRequired); | |
| 444 } | |
| 431 } else { | 445 } else { |
| 432 enqueueStandardTest(info, testName, expectations); | 446 enqueueStandardTest(info, testName, expectations); |
| 433 } | 447 } |
| 434 } | 448 } |
| 435 | 449 |
| 436 void enqueueStandardTest(TestInformation info, | 450 void enqueueStandardTest(TestInformation info, |
| 437 String testName, | 451 String testName, |
| 438 Set<String> expectations) { | 452 Set<String> expectations) { |
| 439 bool isNegative = info.hasCompileError || | 453 bool isNegative = info.hasCompileError || |
| 440 (configuration['checked'] && info.isNegativeIfChecked); | 454 (configuration['checked'] && info.isNegativeIfChecked); |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 572 } | 586 } |
| 573 } | 587 } |
| 574 | 588 |
| 575 /** | 589 /** |
| 576 * The [StandardTestSuite] has support for tests that | 590 * The [StandardTestSuite] has support for tests that |
| 577 * compile a test from Dart to JavaScript, and then run the resulting | 591 * compile a test from Dart to JavaScript, and then run the resulting |
| 578 * JavaScript. This function creates a working directory to hold the | 592 * JavaScript. This function creates a working directory to hold the |
| 579 * JavaScript version of the test, and copies the appropriate framework | 593 * JavaScript version of the test, and copies the appropriate framework |
| 580 * files to that directory. It creates a [BrowserTestCase], which has | 594 * files to that directory. It creates a [BrowserTestCase], which has |
| 581 * two sequential steps to be run by the [ProcessQueue] when the test is | 595 * two sequential steps to be run by the [ProcessQueue] when the test is |
| 582 * executed: a compilation | 596 * executed: a compilation step and an execution step, both with the |
| 583 * step and an execution step, both with the appropriate executable and | 597 * appropriate executable and arguments. The [expectations] object can be |
| 584 * arguments. | 598 * either a Set<String> if the test is a regular test, or a Map<String |
| 599 * subTestName, Set<String>> if we are running a browser multi-test (one | |
| 600 * compilation and many browser runs). | |
| 585 */ | 601 */ |
| 586 void enqueueBrowserTest(TestInformation info, | 602 void enqueueBrowserTest(TestInformation info, |
| 587 String testName, | 603 String testName, |
| 588 Set<String> expectations, | 604 Object expectations, |
| 589 bool isWrappingRequired) { | 605 bool isWrappingRequired) { |
| 590 Map optionsFromFile = info.optionsFromFile; | 606 Map optionsFromFile = info.optionsFromFile; |
| 591 Path filePath = info.filePath; | 607 Path filePath = info.filePath; |
| 592 String filename = filePath.toString(); | 608 String filename = filePath.toString(); |
| 593 bool isWebTest = optionsFromFile['containsDomImport']; | 609 bool isWebTest = optionsFromFile['containsDomImport']; |
| 594 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; | 610 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; |
| 595 if (isWrappingRequired | 611 if (isWrappingRequired |
| 596 && !isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { | 612 && !isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { |
| 597 print('Warning for $filename: Browser tests require #library ' | 613 print('Warning for $filename: Browser tests require #library ' |
| 598 'in any file that uses #import, #source, or #resource'); | 614 'in any file that uses #import, #source, or #resource'); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 699 Path namePath = new Path(name); | 715 Path namePath = new Path(name); |
| 700 Expect.equals(namePath.extension, 'dart'); | 716 Expect.equals(namePath.extension, 'dart'); |
| 701 String baseName = namePath.filenameWithoutExtension; | 717 String baseName = namePath.filenameWithoutExtension; |
| 702 Path fromPath = filePath.directoryPath.join(namePath); | 718 Path fromPath = filePath.directoryPath.join(namePath); |
| 703 commands.add(_compileCommand( | 719 commands.add(_compileCommand( |
| 704 fromPath.toNativePath(), '$tempDir/$baseName.js', | 720 fromPath.toNativePath(), '$tempDir/$baseName.js', |
| 705 compiler, tempDir, vmOptions)); | 721 compiler, tempDir, vmOptions)); |
| 706 } | 722 } |
| 707 } | 723 } |
| 708 | 724 |
| 725 // Variables for browser multi-tests. | |
| 726 List<String> subtestNames = info.optionsFromFile['subtestNames']; | |
| 727 TestCase multitestParentTest; | |
| 728 int subtestIndex = 0; | |
| 709 // Construct the command that executes the browser test | 729 // Construct the command that executes the browser test |
| 710 List<String> args; | 730 do { |
| 711 if (TestUtils.usesWebDriver(runtime)) { | 731 List<String> args = <String>[]; |
| 712 args = [dartDir.append('tools/testing/run_selenium.py').toNativePath(), | 732 String fullHtmlPath = htmlPath.startsWith('http:')? htmlPath: |
|
Siggi Cherem (dart-lang)
2012/11/08 02:50:14
nit: spacing - add space between )? and before :
Bill Hesse
2012/11/08 09:09:49
Seconded: spacing before ? and :.
On 2012/11/08 02
Emily Fortuna
2012/11/08 18:33:14
Done.
| |
| 713 '--browser=$runtime', | 733 'file://$htmlPath'; |
|
Emily Fortuna
2012/11/08 02:19:09
lines 732-733 are new (adding file://)
Bill Hesse
2012/11/08 09:09:49
This is really Resolve(htmlPath, "file://"), isn't
Emily Fortuna
2012/11/08 18:33:14
We don't want to add a test that htmlPath starts w
| |
| 714 '--timeout=${configuration["timeout"] - 2}', | 734 if (info.optionsFromFile['isMultiHtmlTest'] |
| 715 '--out=$htmlPath']; | 735 && subtestNames.length > 0) { |
| 716 if (runtime == 'dartium') { | 736 fullHtmlPath = '${fullHtmlPath}#${subtestNames[subtestIndex]}'; |
| 717 args.add('--executable=$dartiumFilename'); | |
| 718 } | 737 } |
| 719 } else { | 738 if (TestUtils.usesWebDriver(runtime)) { |
| 720 args = [ | 739 args = [ |
| 721 dartDir.append('tools/testing/drt-trampoline.py').toNativePath(), | 740 dartDir.append('tools/testing/run_selenium.py').toNativePath(), |
| 722 dumpRenderTreeFilename, | 741 '--browser=$runtime', |
| 723 '--no-timeout' | 742 '--timeout=${configuration["timeout"] - 2}', |
| 724 ]; | 743 '--out="$fullHtmlPath"']; |
| 725 if (runtime == 'drt' && | 744 if (runtime == 'dartium') { |
| 726 (compiler == 'none' || compiler == 'dart2dart')) { | 745 args.add('--executable=$dartiumFilename'); |
| 727 var dartFlags = ['--ignore-unrecognized-flags']; | |
| 728 if (configuration["checked"]) { | |
| 729 dartFlags.add('--enable_asserts'); | |
| 730 dartFlags.add("--enable_type_checks"); | |
| 731 } | 746 } |
| 732 dartFlags.addAll(vmOptions); | 747 } else { |
| 733 args.add('--dart-flags=${Strings.join(dartFlags, " ")}'); | 748 args = [ |
| 749 dartDir.append('tools/testing/drt-trampoline.py').toNativePath(), | |
| 750 dumpRenderTreeFilename, | |
| 751 '--no-timeout' | |
| 752 ]; | |
| 753 if (runtime == 'drt' && | |
| 754 (compiler == 'none' || compiler == 'dart2dart')) { | |
| 755 var dartFlags = ['--ignore-unrecognized-flags']; | |
| 756 if (configuration["checked"]) { | |
| 757 dartFlags.add('--enable_asserts'); | |
| 758 dartFlags.add("--enable_type_checks"); | |
| 759 } | |
| 760 dartFlags.addAll(vmOptions); | |
| 761 args.add('--dart-flags=${Strings.join(dartFlags, " ")}'); | |
| 762 } | |
| 763 args.add(fullHtmlPath); | |
| 764 if (expectedOutput != null) { | |
| 765 args.add('--out-expectation=${expectedOutput.toNativePath()}'); | |
| 766 } | |
| 734 } | 767 } |
| 735 args.add(htmlPath); | 768 List<String> commandSet = new List<String>.from(commands); |
| 736 if (expectedOutput != null) { | 769 if (subtestIndex != 0) { |
| 737 args.add('--out-expectation=${expectedOutput.toNativePath()}'); | 770 commandSet = []; |
| 771 if(TestUtils.usesWebDriver(runtime)) args.add('--force-refresh'); | |
| 738 } | 772 } |
| 739 } | 773 commandSet.add(new Command('python', args)); |
| 740 commands.add(new Command('python', args)); | |
| 741 | 774 |
| 742 // Create BrowserTestCase and queue it. | 775 // Create BrowserTestCase and queue it. |
| 743 var testCase = new BrowserTestCase('$suiteName/$testName', | 776 String testDisplayName = '$suiteName/$testName'; |
| 744 commands, configuration, completeHandler, expectations, | 777 var testCase; |
| 745 info, info.hasCompileError || info.hasRuntimeError); | 778 if (info.optionsFromFile['isMultiHtmlTest']) { |
| 746 doTest(testCase); | 779 testDisplayName = '$testDisplayName/${subtestNames[subtestIndex]}'; |
| 780 testCase = new BrowserTestCase(testDisplayName, | |
| 781 commandSet, configuration, completeHandler, | |
| 782 expectations['$testName/${subtestNames[subtestIndex]}'], | |
| 783 info, info.hasCompileError || info.hasRuntimeError, | |
| 784 subtestIndex != 0); | |
| 785 } else { | |
| 786 testCase = new BrowserTestCase(testDisplayName, | |
| 787 commandSet, configuration, completeHandler, expectations, | |
| 788 info, info.hasCompileError || info.hasRuntimeError, false); | |
| 789 } | |
| 790 if (subtestIndex == 0) { | |
| 791 multitestParentTest = testCase; | |
| 792 } else { | |
| 793 multitestParentTest.addObserver(testCase); | |
| 794 } | |
| 795 doTest(testCase); | |
| 796 subtestIndex++; | |
| 797 } while(subtestIndex < subtestNames.length); | |
| 747 } | 798 } |
| 748 } | 799 } |
| 749 | 800 |
| 750 /** Helper to create a compilation command for a single input file. */ | 801 /** Helper to create a compilation command for a single input file. */ |
| 751 Command _compileCommand(String inputFile, String outputFile, | 802 Command _compileCommand(String inputFile, String outputFile, |
| 752 String compiler, String dir, var vmOptions) { | 803 String compiler, String dir, var vmOptions) { |
| 753 String executable = TestUtils.compilerPath(configuration); | 804 String executable = TestUtils.compilerPath(configuration); |
| 754 List<String> args = TestUtils.standardOptions(configuration); | 805 List<String> args = TestUtils.standardOptions(configuration); |
| 755 switch (compiler) { | 806 switch (compiler) { |
| 756 case 'dart2js': | 807 case 'dart2js': |
| (...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 962 * executing the copy command printed by the test script. | 1013 * executing the copy command printed by the test script. |
| 963 * | 1014 * |
| 964 * This method is static as the map is cached and shared amongst | 1015 * This method is static as the map is cached and shared amongst |
| 965 * configurations, so it may not use [configuration]. | 1016 * configurations, so it may not use [configuration]. |
| 966 */ | 1017 */ |
| 967 static Map readOptionsFromFile(Path filePath) { | 1018 static Map readOptionsFromFile(Path filePath) { |
| 968 RegExp testOptionsRegExp = const RegExp(r"// VMOptions=(.*)"); | 1019 RegExp testOptionsRegExp = const RegExp(r"// VMOptions=(.*)"); |
| 969 RegExp dartOptionsRegExp = const RegExp(r"// DartOptions=(.*)"); | 1020 RegExp dartOptionsRegExp = const RegExp(r"// DartOptions=(.*)"); |
| 970 RegExp otherScriptsRegExp = const RegExp(r"// OtherScripts=(.*)"); | 1021 RegExp otherScriptsRegExp = const RegExp(r"// OtherScripts=(.*)"); |
| 971 RegExp multiTestRegExp = const RegExp(r"/// [0-9][0-9]:(.*)"); | 1022 RegExp multiTestRegExp = const RegExp(r"/// [0-9][0-9]:(.*)"); |
| 1023 RegExp multiHtmlTestRegExp = | |
| 1024 const RegExp(r"useHtmlIndividualConfiguration()"); | |
| 972 RegExp staticTypeRegExp = | 1025 RegExp staticTypeRegExp = |
| 973 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning"); | 1026 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning"); |
| 974 RegExp compileTimeRegExp = | 1027 RegExp compileTimeRegExp = |
| 975 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error"); | 1028 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error"); |
| 976 RegExp staticCleanRegExp = const RegExp(r"// @static-clean"); | 1029 RegExp staticCleanRegExp = const RegExp(r"// @static-clean"); |
| 977 RegExp leadingHashRegExp = const RegExp(r"^#", multiLine: true); | 1030 RegExp leadingHashRegExp = const RegExp(r"^#", multiLine: true); |
| 978 RegExp isolateStubsRegExp = const RegExp(r"// IsolateStubs=(.*)"); | 1031 RegExp isolateStubsRegExp = const RegExp(r"// IsolateStubs=(.*)"); |
| 979 // TODO(gram) Clean these up once the old directives are not supported. | 1032 // TODO(gram) Clean these up once the old directives are not supported. |
| 980 RegExp domImportRegExp = | 1033 RegExp domImportRegExp = |
| 981 const RegExp(r"^[#]?import.*dart:html", multiLine: true); | 1034 const RegExp(r"^[#]?import.*dart:html", multiLine: true); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1028 isStaticClean = true; | 1081 isStaticClean = true; |
| 1029 } | 1082 } |
| 1030 | 1083 |
| 1031 List<String> otherScripts = new List<String>(); | 1084 List<String> otherScripts = new List<String>(); |
| 1032 matches = otherScriptsRegExp.allMatches(contents); | 1085 matches = otherScriptsRegExp.allMatches(contents); |
| 1033 for (var match in matches) { | 1086 for (var match in matches) { |
| 1034 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); | 1087 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); |
| 1035 } | 1088 } |
| 1036 | 1089 |
| 1037 bool isMultitest = multiTestRegExp.hasMatch(contents); | 1090 bool isMultitest = multiTestRegExp.hasMatch(contents); |
| 1091 bool isMultiHtmlTest = multiHtmlTestRegExp.hasMatch(contents); | |
| 1038 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); | 1092 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); |
| 1039 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); | 1093 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); |
| 1040 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; | 1094 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; |
| 1041 bool containsDomImport = domImportRegExp.hasMatch(contents); | 1095 bool containsDomImport = domImportRegExp.hasMatch(contents); |
| 1042 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); | 1096 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); |
| 1043 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); | 1097 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); |
| 1044 int numStaticTypeAnnotations = 0; | 1098 int numStaticTypeAnnotations = 0; |
| 1045 for (var i in staticTypeRegExp.allMatches(contents)) { | 1099 for (var i in staticTypeRegExp.allMatches(contents)) { |
| 1046 numStaticTypeAnnotations++; | 1100 numStaticTypeAnnotations++; |
| 1047 } | 1101 } |
| 1048 int numCompileTimeAnnotations = 0; | 1102 int numCompileTimeAnnotations = 0; |
| 1049 for (var i in compileTimeRegExp.allMatches(contents)) { | 1103 for (var i in compileTimeRegExp.allMatches(contents)) { |
| 1050 numCompileTimeAnnotations++; | 1104 numCompileTimeAnnotations++; |
| 1051 } | 1105 } |
| 1052 | 1106 |
| 1107 // Note: This is brittle. It's the age-old problem of having a context free | |
| 1108 // language but the means to easily identify the construct is a regular | |
| 1109 // expression, aka impossible. Therefore we just make an approximation of | |
| 1110 // the number of top-level "group(...)" occurrences. This assumes you import | |
| 1111 // unittest with no prefix and always directly call "group(". It only uses | |
| 1112 // top-level "groups" so tests running nested groups will be no-ops. | |
| 1113 RegExp numTests = new RegExp(r"\s*[^/]\s*group\('[^,']*"); | |
| 1114 List<String> subtestNames = []; | |
| 1115 Iterator matchesIter = numTests.allMatches(contents).iterator(); | |
| 1116 while(matchesIter.hasNext && isMultiHtmlTest) { | |
| 1117 String fullMatch = matchesIter.next().group(0); | |
| 1118 subtestNames.add(fullMatch.substring(fullMatch.indexOf("'") + 1)); | |
| 1119 } | |
| 1120 | |
| 1053 return { "vmOptions": result, | 1121 return { "vmOptions": result, |
| 1054 "dartOptions": dartOptions, | 1122 "dartOptions": dartOptions, |
| 1055 "hasCompileError": hasCompileError, | 1123 "hasCompileError": hasCompileError, |
| 1056 "hasRuntimeError": hasRuntimeError, | 1124 "hasRuntimeError": hasRuntimeError, |
| 1057 "isStaticClean" : isStaticClean, | 1125 "isStaticClean" : isStaticClean, |
| 1058 "otherScripts": otherScripts, | 1126 "otherScripts": otherScripts, |
| 1059 "isMultitest": isMultitest, | 1127 "isMultitest": isMultitest, |
| 1128 "isMultiHtmlTest": isMultiHtmlTest, | |
| 1129 "subtestNames": subtestNames, | |
| 1060 "containsLeadingHash": containsLeadingHash, | 1130 "containsLeadingHash": containsLeadingHash, |
| 1061 "isolateStubs": isolateStubs, | 1131 "isolateStubs": isolateStubs, |
| 1062 "containsDomImport": containsDomImport, | 1132 "containsDomImport": containsDomImport, |
| 1063 "isLibraryDefinition": isLibraryDefinition, | 1133 "isLibraryDefinition": isLibraryDefinition, |
| 1064 "containsSourceOrImport": containsSourceOrImport, | 1134 "containsSourceOrImport": containsSourceOrImport, |
| 1065 "numStaticTypeAnnotations": numStaticTypeAnnotations, | 1135 "numStaticTypeAnnotations": numStaticTypeAnnotations, |
| 1066 "numCompileTimeAnnotations": numCompileTimeAnnotations }; | 1136 "numCompileTimeAnnotations": numCompileTimeAnnotations }; |
| 1067 } | 1137 } |
| 1068 | 1138 |
| 1069 List<List<String>> getVmOptions(Map optionsFromFile) { | 1139 List<List<String>> getVmOptions(Map optionsFromFile) { |
| (...skipping 423 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1493 * $pass tests are expected to pass | 1563 * $pass tests are expected to pass |
| 1494 * $failOk tests are expected to fail that we won't fix | 1564 * $failOk tests are expected to fail that we won't fix |
| 1495 * $fail tests are expected to fail that we should fix | 1565 * $fail tests are expected to fail that we should fix |
| 1496 * $crash tests are expected to crash that we should fix | 1566 * $crash tests are expected to crash that we should fix |
| 1497 * $timeout tests are allowed to timeout | 1567 * $timeout tests are allowed to timeout |
| 1498 * $compileErrorSkip tests are skipped on browsers due to compile-time error | 1568 * $compileErrorSkip tests are skipped on browsers due to compile-time error |
| 1499 """; | 1569 """; |
| 1500 print(report); | 1570 print(report); |
| 1501 } | 1571 } |
| 1502 } | 1572 } |
| OLD | NEW |