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 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 Function doDone; | 98 Function doDone; |
| 99 ReceivePort receiveTestName; | 99 ReceivePort receiveTestName; |
| 100 TestExpectations testExpectations; | 100 TestExpectations testExpectations; |
| 101 | 101 |
| 102 CCTestSuite(Map this.configuration, | 102 CCTestSuite(Map this.configuration, |
| 103 String this.suiteName, | 103 String this.suiteName, |
| 104 String runnerName, | 104 String runnerName, |
| 105 List<String> this.statusFilePaths) | 105 List<String> this.statusFilePaths) |
| 106 : dartDir = TestUtils.dartDir() { | 106 : dartDir = TestUtils.dartDir() { |
| 107 runnerPath = TestUtils.buildDir(configuration) + '/' + runnerName; | 107 runnerPath = TestUtils.buildDir(configuration) + '/' + runnerName; |
| 108 | |
| 109 } | 108 } |
| 110 | 109 |
| 111 void testNameHandler(String testName, ignore) { | 110 void testNameHandler(String testName, ignore) { |
| 112 if (testName == "") { | 111 if (testName == "") { |
| 113 receiveTestName.close(); | 112 receiveTestName.close(); |
| 114 doDone(true); | 113 doDone(true); |
| 115 } else { | 114 } else { |
| 116 // Only run the tests that match the pattern. Use the name | 115 // Only run the tests that match the pattern. Use the name |
| 117 // "suiteName/testName" for cc tests. | 116 // "suiteName/testName" for cc tests. |
| 118 RegExp pattern = configuration['selectors'][suiteName]; | 117 RegExp pattern = configuration['selectors'][suiteName]; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 } | 170 } |
| 172 | 171 |
| 173 | 172 |
| 174 class TestInformation { | 173 class TestInformation { |
| 175 String filename; | 174 String filename; |
| 176 Map optionsFromFile; | 175 Map optionsFromFile; |
| 177 bool isNegative; | 176 bool isNegative; |
| 178 bool isNegativeIfChecked; | 177 bool isNegativeIfChecked; |
| 179 bool hasFatalTypeErrors; | 178 bool hasFatalTypeErrors; |
| 180 bool hasRuntimeErrors; | 179 bool hasRuntimeErrors; |
| 180 // expected outcome from multi-test "static type error", "compile-time error" , etc | |
| 181 String multitestOutcome; | |
| 181 | 182 |
| 182 TestInformation(this.filename, this.optionsFromFile, this.isNegative, | 183 TestInformation(this.filename, this.optionsFromFile, this.isNegative, |
| 183 this.isNegativeIfChecked, this.hasFatalTypeErrors, | 184 this.isNegativeIfChecked, this.hasFatalTypeErrors, |
| 184 this.hasRuntimeErrors); | 185 this.hasRuntimeErrors, this.multitestOutcome); |
| 185 } | 186 } |
| 186 | 187 |
| 187 | |
| 188 /** | 188 /** |
| 189 * A standard [TestSuite] implementation that searches for tests in a | 189 * A standard [TestSuite] implementation that searches for tests in a |
| 190 * directory, and creates [TestCase]s that compile and/or run them. | 190 * directory, and creates [TestCase]s that compile and/or run them. |
| 191 */ | 191 */ |
| 192 class StandardTestSuite implements TestSuite { | 192 class StandardTestSuite implements TestSuite { |
| 193 Map configuration; | 193 Map configuration; |
| 194 String suiteName; | 194 String suiteName; |
| 195 String directoryPath; | 195 String directoryPath; |
| 196 List<String> statusFilePaths; | 196 List<String> statusFilePaths; |
| 197 Function doTest; | 197 Function doTest; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 331 case 'chromium': | 331 case 'chromium': |
| 332 case 'frogium': | 332 case 'frogium': |
| 333 case 'legium': | 333 case 'legium': |
| 334 case 'webdriver': | 334 case 'webdriver': |
| 335 enqueueBrowserTest(filename, testName, optionsFromFile, | 335 enqueueBrowserTest(filename, testName, optionsFromFile, |
| 336 expectations, isNegative); | 336 expectations, isNegative); |
| 337 break; | 337 break; |
| 338 default: | 338 default: |
| 339 isNegative = isNegative || | 339 isNegative = isNegative || |
| 340 (configuration['checked'] && info.isNegativeIfChecked); | 340 (configuration['checked'] && info.isNegativeIfChecked); |
| 341 bool enableFatalTypeErrors = false; | |
| 342 | 341 |
| 343 if (configuration['component'] == 'dartc') { | 342 if (configuration['component'] == 'dartc') { |
| 344 // Only dartc supports fatal type errors. Enable fatal type | 343 // dartc can detect static type errors by the |
| 345 // errors with a flag and treat tests that have fatal type | 344 // format of the rror line |
|
Bill Hesse
2012/03/02 08:55:18
Typo - rror
| |
| 346 // errors as negative. | |
| 347 // Also, tests that have runtime errors are not negative | |
| 348 // tests for dartc because dartc does not execute the test. | |
| 349 if (info.hasFatalTypeErrors) { | 345 if (info.hasFatalTypeErrors) { |
| 350 enableFatalTypeErrors = true; | |
| 351 isNegative = true; | 346 isNegative = true; |
| 352 } else if (info.hasRuntimeErrors) { | 347 } else if (info.hasRuntimeErrors) { |
| 353 isNegative = false; | 348 isNegative = false; |
| 354 } | 349 } |
| 355 } | 350 } |
| 356 | 351 |
| 357 var argumentLists = argumentListsFromFile(filename, | 352 var argumentLists = argumentListsFromFile(filename, |
| 358 optionsFromFile, | 353 optionsFromFile); |
| 359 enableFatalTypeErrors); | |
| 360 | 354 |
| 361 for (var args in argumentLists) { | 355 for (var args in argumentLists) { |
| 362 doTest(new TestCase('$suiteName/$testName', | 356 doTest(new TestCase('$suiteName/$testName', |
| 363 [new Command(shellPath(), args)], | 357 [new Command(shellPath(), args)], |
| 364 configuration, | 358 configuration, |
| 365 completeHandler, | 359 completeHandler, |
| 366 expectations, | 360 expectations, |
| 367 isNegative)); | 361 isNegative, |
| 362 info)); | |
| 368 } | 363 } |
| 369 } | 364 } |
| 370 } | 365 } |
| 371 | 366 |
| 372 Function makeTestCaseCreator(Map optionsFromFile) { | 367 Function makeTestCaseCreator(Map optionsFromFile) { |
| 373 return (String filename, | 368 return (String filename, |
| 374 bool isNegative, | 369 bool isNegative, |
| 375 [bool isNegativeIfChecked = false, | 370 [bool isNegativeIfChecked = false, |
| 376 bool hasFatalTypeErrors = false, | 371 bool hasFatalTypeErrors = false, |
| 377 bool hasRuntimeErrors = false]) { | 372 bool hasRuntimeErrors = false, |
| 373 String multitestOutcome = null]) { | |
| 378 // Cache the test information for each test case. | 374 // Cache the test information for each test case. |
| 379 var info = new TestInformation(filename, | 375 var info = new TestInformation(filename, |
| 380 optionsFromFile, | 376 optionsFromFile, |
| 381 isNegative, | 377 isNegative, |
| 382 isNegativeIfChecked, | 378 isNegativeIfChecked, |
| 383 hasFatalTypeErrors, | 379 hasFatalTypeErrors, |
| 384 hasRuntimeErrors); | 380 hasRuntimeErrors, |
| 381 multitestOutcome); | |
| 385 cachedTests.add(info); | 382 cachedTests.add(info); |
| 386 enqueueTestCaseFromTestInformation(info); | 383 enqueueTestCaseFromTestInformation(info); |
| 387 }; | 384 }; |
| 388 } | 385 } |
| 389 | 386 |
| 390 void processFile(String filename) { | 387 void processFile(String filename) { |
| 391 if (!isTestFile(filename)) return; | 388 if (!isTestFile(filename)) return; |
| 392 | 389 |
| 393 // Only run the tests that match the pattern. | 390 // Only run the tests that match the pattern. |
| 394 RegExp pattern = configuration['selectors'][suiteName]; | 391 RegExp pattern = configuration['selectors'][suiteName]; |
| (...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 728 listingDone = true; | 725 listingDone = true; |
| 729 if (activeTestGenerators == 0) { | 726 if (activeTestGenerators == 0) { |
| 730 doDone(); | 727 doDone(); |
| 731 } | 728 } |
| 732 } | 729 } |
| 733 | 730 |
| 734 void completeHandler(TestCase testCase) { | 731 void completeHandler(TestCase testCase) { |
| 735 } | 732 } |
| 736 | 733 |
| 737 List<List<String>> argumentListsFromFile(String filename, | 734 List<List<String>> argumentListsFromFile(String filename, |
| 738 Map optionsFromFile, | 735 Map optionsFromFile) { |
| 739 bool enableFatalTypeErrors) { | |
| 740 List args = TestUtils.standardOptions(configuration); | 736 List args = TestUtils.standardOptions(configuration); |
| 741 args.addAll(additionalOptions(filename)); | 737 args.addAll(additionalOptions(filename)); |
| 742 if (enableFatalTypeErrors && configuration['component'] == 'dartc') { | 738 if (configuration['component'] == 'dartc') { |
| 743 args.add('--fatal-type-errors'); | 739 args.add('--error_format'); |
| 740 args.add('machine'); | |
| 744 } | 741 } |
| 745 | 742 |
| 746 bool isMultitest = optionsFromFile["isMultitest"]; | 743 bool isMultitest = optionsFromFile["isMultitest"]; |
| 747 List<String> dartOptions = optionsFromFile["dartOptions"]; | 744 List<String> dartOptions = optionsFromFile["dartOptions"]; |
| 748 List<List<String>> vmOptionsList = optionsFromFile["vmOptions"]; | 745 List<List<String>> vmOptionsList = optionsFromFile["vmOptions"]; |
| 749 Expect.isTrue(!isMultitest || dartOptions == null); | 746 Expect.isTrue(!isMultitest || dartOptions == null); |
| 750 if (dartOptions == null) { | 747 if (dartOptions == null) { |
| 751 args.add(filename); | 748 args.add(filename); |
| 752 } else { | 749 } else { |
| 753 var executable_name = dartOptions[0]; | 750 var executable_name = dartOptions[0]; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 770 } | 767 } |
| 771 | 768 |
| 772 return result; | 769 return result; |
| 773 } | 770 } |
| 774 | 771 |
| 775 Map readOptionsFromFile(String filename) { | 772 Map readOptionsFromFile(String filename) { |
| 776 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); | 773 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); |
| 777 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); | 774 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); |
| 778 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)"); | 775 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)"); |
| 779 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); | 776 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); |
| 777 RegExp staticTypeRegExp = const RegExp(@"/// ([0-9][0-9]:){0,1}\s*static typ e error"); | |
| 778 RegExp compileTimeRegExp = const RegExp(@"/// ([0-9][0-9]:){0,1}\s*compile-t ime error"); | |
| 779 RegExp staticCleanRegExp = const RegExp(@"// @static-clean"); | |
| 780 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); | 780 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); |
| 781 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); | 781 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); |
| 782 RegExp domImportRegExp = | 782 RegExp domImportRegExp = |
| 783 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", | 783 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", |
| 784 multiLine: true); | 784 multiLine: true); |
| 785 RegExp libraryDefinitionRegExp = | 785 RegExp libraryDefinitionRegExp = |
| 786 const RegExp(@"^#library\(", multiLine: true); | 786 const RegExp(@"^#library\(", multiLine: true); |
| 787 RegExp sourceOrImportRegExp = | 787 RegExp sourceOrImportRegExp = |
| 788 const RegExp(@"^#(source|import)\(", multiLine: true); | 788 const RegExp(@"^#(source|import)\(", multiLine: true); |
| 789 | 789 |
| 790 // Read the entire file into a byte buffer and transform it to a | 790 // Read the entire file into a byte buffer and transform it to a |
| 791 // String. This will treat the file as ascii but the only parts | 791 // String. This will treat the file as ascii but the only parts |
| 792 // we are interested in will be ascii in any case. | 792 // we are interested in will be ascii in any case. |
| 793 RandomAccessFile file = new File(filename).openSync(); | 793 RandomAccessFile file = new File(filename).openSync(); |
| 794 List chars = new List(file.lengthSync()); | 794 List chars = new List(file.lengthSync()); |
| 795 var offset = 0; | 795 var offset = 0; |
| 796 while (offset != chars.length) { | 796 while (offset != chars.length) { |
| 797 offset += file.readListSync(chars, offset, chars.length - offset); | 797 offset += file.readListSync(chars, offset, chars.length - offset); |
| 798 } | 798 } |
| 799 file.closeSync(); | 799 file.closeSync(); |
| 800 String contents = new String.fromCharCodes(chars); | 800 String contents = new String.fromCharCodes(chars); |
| 801 chars = null; | 801 chars = null; |
| 802 | 802 |
| 803 // Find the options in the file. | 803 // Find the options in the file. |
| 804 List<List> result = new List<List>(); | 804 List<List> result = new List<List>(); |
| 805 List<String> dartOptions; | 805 List<String> dartOptions; |
| 806 bool isNegative = false; | 806 bool isNegative = false; |
| 807 bool isStaticClean = false; | |
| 807 | 808 |
| 808 Iterable<Match> matches = testOptionsRegExp.allMatches(contents); | 809 Iterable<Match> matches = testOptionsRegExp.allMatches(contents); |
| 809 for (var match in matches) { | 810 for (var match in matches) { |
| 810 result.add(match[1].split(' ').filter((e) => e != '')); | 811 result.add(match[1].split(' ').filter((e) => e != '')); |
| 811 } | 812 } |
| 812 if (result.isEmpty()) result.add([]); | 813 if (result.isEmpty()) result.add([]); |
| 813 | 814 |
| 814 matches = dartOptionsRegExp.allMatches(contents); | 815 matches = dartOptionsRegExp.allMatches(contents); |
| 815 for (var match in matches) { | 816 for (var match in matches) { |
| 816 if (dartOptions != null) { | 817 if (dartOptions != null) { |
| 817 throw new Exception( | 818 throw new Exception( |
| 818 'More than one "// DartOptions=" line in test $filename'); | 819 'More than one "// DartOptions=" line in test $filename'); |
| 819 } | 820 } |
| 820 dartOptions = match[1].split(' ').filter((e) => e != ''); | 821 dartOptions = match[1].split(' ').filter((e) => e != ''); |
| 821 } | 822 } |
| 822 | 823 |
| 824 matches = staticCleanRegExp.allMatches(contents); | |
|
Bill Hesse
2012/03/02 08:55:18
Is this overkill? Why not just a single hasMatch?
zundel
2012/03/02 23:51:00
I did that because I decided that multiple matches
| |
| 825 for (var match in matches) { | |
| 826 if (isStaticClean) { | |
| 827 throw new Exception( | |
| 828 'More than one "// @static-clean=" line in test $filename'); | |
| 829 } | |
| 830 isStaticClean = true; | |
| 831 } | |
| 832 | |
| 823 List<String> otherScripts = new List<String>(); | 833 List<String> otherScripts = new List<String>(); |
| 824 matches = otherScriptsRegExp.allMatches(contents); | 834 matches = otherScriptsRegExp.allMatches(contents); |
| 825 for (var match in matches) { | 835 for (var match in matches) { |
| 826 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); | 836 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); |
| 827 } | 837 } |
| 828 | 838 |
| 829 if (contents.contains("@compile-error") || | 839 if (contents.contains("@compile-error") || |
| 830 contents.contains("@runtime-error")) { | 840 contents.contains("@runtime-error")) { |
| 831 isNegative = true; | 841 isNegative = true; |
| 832 } | 842 } |
| 833 | 843 |
|
Bill Hesse
2012/03/02 08:55:18
Whitespace.
| |
| 834 bool isMultitest = multiTestRegExp.hasMatch(contents); | 844 bool isMultitest = multiTestRegExp.hasMatch(contents); |
| 835 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); | 845 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); |
| 836 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); | 846 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); |
| 837 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; | 847 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; |
| 838 bool containsDomImport = domImportRegExp.hasMatch(contents); | 848 bool containsDomImport = domImportRegExp.hasMatch(contents); |
| 839 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); | 849 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); |
| 840 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); | 850 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); |
| 841 | 851 int numStaticTypeAnnotations = 0; |
| 852 for (var i in staticTypeRegExp.allMatches(contents)) { | |
|
Bill Hesse
2012/03/02 08:55:18
Var dummy?
There is really no length field? It is
zundel
2012/03/02 23:51:00
yes, its an Iterator.
http://api.dartlang.org/dart
| |
| 853 numStaticTypeAnnotations++; | |
| 854 } | |
| 855 int numCompileTimeAnnotations = 0; | |
| 856 for (var i in compileTimeRegExp.allMatches(contents)) { | |
| 857 numCompileTimeAnnotations++; | |
| 858 } | |
| 842 | 859 |
| 843 return { "vmOptions": result, | 860 return { "vmOptions": result, |
| 844 "dartOptions": dartOptions, | 861 "dartOptions": dartOptions, |
| 845 "isNegative": isNegative, | 862 "isNegative": isNegative, |
| 863 "isStaticClean" : isStaticClean, | |
| 846 "otherScripts": otherScripts, | 864 "otherScripts": otherScripts, |
| 847 "isMultitest": isMultitest, | 865 "isMultitest": isMultitest, |
| 848 "containsLeadingHash" : containsLeadingHash, | 866 "containsLeadingHash": containsLeadingHash, |
| 849 "isolateStubs" : isolateStubs, | 867 "isolateStubs": isolateStubs, |
| 850 "containsDomImport": containsDomImport, | 868 "containsDomImport": containsDomImport, |
| 851 "isLibraryDefinition": isLibraryDefinition, | 869 "isLibraryDefinition": isLibraryDefinition, |
| 852 "containsSourceOrImport": containsSourceOrImport }; | 870 "containsSourceOrImport": containsSourceOrImport, |
| 871 "numStaticTypeAnnotations": numStaticTypeAnnotations, | |
| 872 "numCompileTimeAnnotations": numCompileTimeAnnotations}; | |
| 853 } | 873 } |
| 854 } | 874 } |
| 855 | 875 |
| 856 | 876 |
| 857 class DartcCompilationTestSuite extends StandardTestSuite { | 877 class DartcCompilationTestSuite extends StandardTestSuite { |
| 858 List<String> _testDirs; | 878 List<String> _testDirs; |
| 859 int activityCount = 0; | 879 int activityCount = 0; |
| 860 | 880 |
| 861 DartcCompilationTestSuite(Map configuration, | 881 DartcCompilationTestSuite(Map configuration, |
| 862 String suiteName, | 882 String suiteName, |
| (...skipping 310 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1173 * $noCrash tests are expected to be flaky but not crash | 1193 * $noCrash tests are expected to be flaky but not crash |
| 1174 * $pass tests are expected to pass | 1194 * $pass tests are expected to pass |
| 1175 * $failOk tests are expected to fail that we won't fix | 1195 * $failOk tests are expected to fail that we won't fix |
| 1176 * $fail tests are expected to fail that we should fix | 1196 * $fail tests are expected to fail that we should fix |
| 1177 * $crash tests are expected to crash that we should fix | 1197 * $crash tests are expected to crash that we should fix |
| 1178 * $timeout tests are allowed to timeout | 1198 * $timeout tests are allowed to timeout |
| 1179 """; | 1199 """; |
| 1180 print(report); | 1200 print(report); |
| 1181 } | 1201 } |
| 1182 } | 1202 } |
| OLD | NEW |