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 // compiler, we never need to attempt to run the program (in a | 420 // compiler, we never need to attempt to run the program (in a |
| 421 // browser or otherwise). | 421 // browser or otherwise). |
| 422 enqueueStandardTest(info, testName, expectations); | 422 enqueueStandardTest(info, testName, expectations); |
| 423 } else if (TestUtils.isBrowserRuntime(configuration['runtime'])) { | 423 } else if (TestUtils.isBrowserRuntime(configuration['runtime'])) { |
| 424 bool isWrappingRequired = configuration['compiler'] != 'dart2js'; | 424 bool isWrappingRequired = configuration['compiler'] != 'dart2js'; |
| 425 if (configuration['runtime'] == 'ff' && | 425 if (configuration['runtime'] == 'ff' && |
| 426 Platform.operatingSystem == 'windows') { | 426 Platform.operatingSystem == 'windows') { |
| 427 // TODO(ahe): Investigate why this doesn't work on Windows. | 427 // TODO(ahe): Investigate why this doesn't work on Windows. |
| 428 isWrappingRequired = true; | 428 isWrappingRequired = true; |
| 429 } | 429 } |
| 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 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 |
| 709 // Construct the command that executes the browser test | 725 // Construct the command that executes the browser test |
| 710 List<String> args; | 726 List<String> subtestNames = info.optionsFromFile['subtestNames']; |
| 711 if (TestUtils.usesWebDriver(runtime)) { | 727 int subtestIndex = 0; |
| 712 args = [dartDir.append('tools/testing/run_selenium.py').toNativePath(), | 728 do { |
| 713 '--browser=$runtime', | 729 List<String> args = <String>[]; |
| 714 '--timeout=${configuration["timeout"] - 2}', | 730 String fullHtmlPath = htmlPath; |
| 715 '--out=$htmlPath']; | 731 if (subtestNames.length > 0) { |
| 716 if (runtime == 'dartium') { | 732 fullHtmlPath = '${htmlPath}#${subtestNames[subtestIndex]}'; |
| 717 args.add('--executable=$dartiumFilename'); | |
| 718 } | 733 } |
| 719 } else { | 734 if (TestUtils.usesWebDriver(runtime)) { |
| 720 args = [ | 735 args = [ |
| 721 dartDir.append('tools/testing/drt-trampoline.py').toNativePath(), | 736 dartDir.append('tools/testing/run_selenium.py').toNativePath(), |
| 722 dumpRenderTreeFilename, | 737 '--browser=$runtime', |
| 723 '--no-timeout' | 738 '--timeout=${configuration["timeout"] - 2}', |
| 724 ]; | 739 '--out="$fullHtmlPath"']; |
| 725 if (runtime == 'drt' && | 740 if (runtime == 'dartium') { |
| 726 (compiler == 'none' || compiler == 'dart2dart')) { | 741 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 } | 742 } |
| 732 dartFlags.addAll(vmOptions); | 743 } else { |
| 733 args.add('--dart-flags=${Strings.join(dartFlags, " ")}'); | 744 args = [ |
| 745 dartDir.append('tools/testing/drt-trampoline.py').toNativePath(), | |
| 746 dumpRenderTreeFilename, | |
| 747 '--no-timeout' | |
| 748 ]; | |
| 749 if (runtime == 'drt' && | |
| 750 (compiler == 'none' || compiler == 'dart2dart')) { | |
| 751 var dartFlags = ['--ignore-unrecognized-flags']; | |
| 752 if (configuration["checked"]) { | |
| 753 dartFlags.add('--enable_asserts'); | |
| 754 dartFlags.add("--enable_type_checks"); | |
| 755 } | |
| 756 dartFlags.addAll(vmOptions); | |
| 757 args.add('--dart-flags=${Strings.join(dartFlags, " ")}'); | |
| 758 } | |
| 759 args.add(fullHtmlPath); | |
| 760 if (expectedOutput != null) { | |
| 761 args.add('--out-expectation=${expectedOutput.toNativePath()}'); | |
| 762 } | |
| 734 } | 763 } |
| 735 args.add(htmlPath); | 764 List<String> commandSet = new List<String>.from(commands); |
| 736 if (expectedOutput != null) { | 765 commandSet.add(new Command('python', args)); |
|
Bill Hesse
2012/11/01 20:26:00
All of the test cases created from a multitest are
| |
| 737 args.add('--out-expectation=${expectedOutput.toNativePath()}'); | 766 |
| 767 // Create BrowserTestCase and queue it. | |
| 768 String testDisplayName = '$suiteName/$testName'; | |
| 769 var testCase; | |
| 770 if (info.optionsFromFile['isMultiHtmlTest']) { | |
| 771 testDisplayName = '$testDisplayName/${subtestNames[subtestIndex]}'; | |
| 772 testCase = new BrowserTestCase(testDisplayName, | |
| 773 commandSet, configuration, completeHandler, | |
| 774 expectations['$testName/${subtestNames[subtestIndex]}'], | |
| 775 info, info.hasCompileError || info.hasRuntimeError); | |
| 776 } else { | |
| 777 testCase = new BrowserTestCase(testDisplayName, | |
| 778 commandSet, configuration, completeHandler, expectations, | |
| 779 info, info.hasCompileError || info.hasRuntimeError); | |
| 738 } | 780 } |
| 739 } | 781 doTest(testCase); |
| 740 commands.add(new Command('python', args)); | 782 subtestIndex++; |
| 741 | 783 } while(subtestIndex < subtestNames.length); |
| 742 // Create BrowserTestCase and queue it. | |
| 743 var testCase = new BrowserTestCase('$suiteName/$testName', | |
| 744 commands, configuration, completeHandler, expectations, | |
| 745 info, info.hasCompileError || info.hasRuntimeError); | |
| 746 doTest(testCase); | |
| 747 } | 784 } |
| 748 } | 785 } |
| 749 | 786 |
| 750 /** Helper to create a compilation command for a single input file. */ | 787 /** Helper to create a compilation command for a single input file. */ |
| 751 Command _compileCommand(String inputFile, String outputFile, | 788 Command _compileCommand(String inputFile, String outputFile, |
| 752 String compiler, String dir, var vmOptions) { | 789 String compiler, String dir, var vmOptions) { |
| 753 String executable = TestUtils.compilerPath(configuration); | 790 String executable = TestUtils.compilerPath(configuration); |
| 754 List<String> args = TestUtils.standardOptions(configuration); | 791 List<String> args = TestUtils.standardOptions(configuration); |
| 755 switch (compiler) { | 792 switch (compiler) { |
| 756 case 'dart2js': | 793 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. | 999 * executing the copy command printed by the test script. |
| 963 * | 1000 * |
| 964 * This method is static as the map is cached and shared amongst | 1001 * This method is static as the map is cached and shared amongst |
| 965 * configurations, so it may not use [configuration]. | 1002 * configurations, so it may not use [configuration]. |
| 966 */ | 1003 */ |
| 967 static Map readOptionsFromFile(Path filePath) { | 1004 static Map readOptionsFromFile(Path filePath) { |
| 968 RegExp testOptionsRegExp = const RegExp(r"// VMOptions=(.*)"); | 1005 RegExp testOptionsRegExp = const RegExp(r"// VMOptions=(.*)"); |
| 969 RegExp dartOptionsRegExp = const RegExp(r"// DartOptions=(.*)"); | 1006 RegExp dartOptionsRegExp = const RegExp(r"// DartOptions=(.*)"); |
| 970 RegExp otherScriptsRegExp = const RegExp(r"// OtherScripts=(.*)"); | 1007 RegExp otherScriptsRegExp = const RegExp(r"// OtherScripts=(.*)"); |
| 971 RegExp multiTestRegExp = const RegExp(r"/// [0-9][0-9]:(.*)"); | 1008 RegExp multiTestRegExp = const RegExp(r"/// [0-9][0-9]:(.*)"); |
| 1009 RegExp multiHtmlTestRegExp = | |
| 1010 const RegExp(r"useHtmlIndividualConfiguration()"); | |
| 972 RegExp staticTypeRegExp = | 1011 RegExp staticTypeRegExp = |
| 973 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning"); | 1012 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*static type warning"); |
| 974 RegExp compileTimeRegExp = | 1013 RegExp compileTimeRegExp = |
| 975 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error"); | 1014 const RegExp(r"/// ([0-9][0-9]:){0,1}\s*compile-time error"); |
| 976 RegExp staticCleanRegExp = const RegExp(r"// @static-clean"); | 1015 RegExp staticCleanRegExp = const RegExp(r"// @static-clean"); |
| 977 RegExp leadingHashRegExp = const RegExp(r"^#", multiLine: true); | 1016 RegExp leadingHashRegExp = const RegExp(r"^#", multiLine: true); |
| 978 RegExp isolateStubsRegExp = const RegExp(r"// IsolateStubs=(.*)"); | 1017 RegExp isolateStubsRegExp = const RegExp(r"// IsolateStubs=(.*)"); |
| 979 RegExp domImportRegExp = | 1018 RegExp domImportRegExp = |
| 980 const RegExp(r"^#import.*(dart:(dom|html)|html\.dart).*\)", | 1019 const RegExp(r"^#import.*(dart:(dom|html)|html\.dart).*\)", |
| 981 multiLine: true); | 1020 multiLine: true); |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1028 isStaticClean = true; | 1067 isStaticClean = true; |
| 1029 } | 1068 } |
| 1030 | 1069 |
| 1031 List<String> otherScripts = new List<String>(); | 1070 List<String> otherScripts = new List<String>(); |
| 1032 matches = otherScriptsRegExp.allMatches(contents); | 1071 matches = otherScriptsRegExp.allMatches(contents); |
| 1033 for (var match in matches) { | 1072 for (var match in matches) { |
| 1034 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); | 1073 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); |
| 1035 } | 1074 } |
| 1036 | 1075 |
| 1037 bool isMultitest = multiTestRegExp.hasMatch(contents); | 1076 bool isMultitest = multiTestRegExp.hasMatch(contents); |
| 1077 bool isMultiHtmlTest = multiHtmlTestRegExp.hasMatch(contents); | |
| 1038 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); | 1078 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); |
| 1039 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); | 1079 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); |
| 1040 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; | 1080 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; |
| 1041 bool containsDomImport = domImportRegExp.hasMatch(contents); | 1081 bool containsDomImport = domImportRegExp.hasMatch(contents); |
| 1042 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); | 1082 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); |
| 1043 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); | 1083 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); |
| 1044 int numStaticTypeAnnotations = 0; | 1084 int numStaticTypeAnnotations = 0; |
| 1045 for (var i in staticTypeRegExp.allMatches(contents)) { | 1085 for (var i in staticTypeRegExp.allMatches(contents)) { |
| 1046 numStaticTypeAnnotations++; | 1086 numStaticTypeAnnotations++; |
| 1047 } | 1087 } |
| 1048 int numCompileTimeAnnotations = 0; | 1088 int numCompileTimeAnnotations = 0; |
| 1049 for (var i in compileTimeRegExp.allMatches(contents)) { | 1089 for (var i in compileTimeRegExp.allMatches(contents)) { |
| 1050 numCompileTimeAnnotations++; | 1090 numCompileTimeAnnotations++; |
| 1051 } | 1091 } |
| 1052 | 1092 |
| 1093 // Note: This is brittle. It assumes you import unittest with no prefix and | |
| 1094 // always directly call "test(". | |
|
Bill Hesse
2012/11/01 20:26:00
It would be nice if there was something more expli
| |
| 1095 RegExp numTests = new RegExp(r"\s*[^/]\s*test\('[^,']*"); | |
| 1096 List<String> subtestNames = []; | |
| 1097 Iterator matchesIter = numTests.allMatches(contents).iterator(); | |
| 1098 while(matchesIter.hasNext && isMultiHtmlTest) { | |
| 1099 String fullMatch = matchesIter.next().group(0); | |
| 1100 subtestNames.add(fullMatch.substring(fullMatch.indexOf("'") + 1)); | |
| 1101 } | |
| 1102 | |
| 1053 return { "vmOptions": result, | 1103 return { "vmOptions": result, |
| 1054 "dartOptions": dartOptions, | 1104 "dartOptions": dartOptions, |
| 1055 "hasCompileError": hasCompileError, | 1105 "hasCompileError": hasCompileError, |
| 1056 "hasRuntimeError": hasRuntimeError, | 1106 "hasRuntimeError": hasRuntimeError, |
| 1057 "isStaticClean" : isStaticClean, | 1107 "isStaticClean" : isStaticClean, |
| 1058 "otherScripts": otherScripts, | 1108 "otherScripts": otherScripts, |
| 1059 "isMultitest": isMultitest, | 1109 "isMultitest": isMultitest, |
| 1110 "isMultiHtmlTest": isMultiHtmlTest, | |
| 1111 "subtestNames": subtestNames, | |
| 1060 "containsLeadingHash": containsLeadingHash, | 1112 "containsLeadingHash": containsLeadingHash, |
| 1061 "isolateStubs": isolateStubs, | 1113 "isolateStubs": isolateStubs, |
| 1062 "containsDomImport": containsDomImport, | 1114 "containsDomImport": containsDomImport, |
| 1063 "isLibraryDefinition": isLibraryDefinition, | 1115 "isLibraryDefinition": isLibraryDefinition, |
| 1064 "containsSourceOrImport": containsSourceOrImport, | 1116 "containsSourceOrImport": containsSourceOrImport, |
| 1065 "numStaticTypeAnnotations": numStaticTypeAnnotations, | 1117 "numStaticTypeAnnotations": numStaticTypeAnnotations, |
| 1066 "numCompileTimeAnnotations": numCompileTimeAnnotations }; | 1118 "numCompileTimeAnnotations": numCompileTimeAnnotations }; |
| 1067 } | 1119 } |
| 1068 | 1120 |
| 1069 List<List<String>> getVmOptions(Map optionsFromFile) { | 1121 List<List<String>> getVmOptions(Map optionsFromFile) { |
| (...skipping 416 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1486 * $noCrash tests are expected to be flaky but not crash | 1538 * $noCrash tests are expected to be flaky but not crash |
| 1487 * $pass tests are expected to pass | 1539 * $pass tests are expected to pass |
| 1488 * $failOk tests are expected to fail that we won't fix | 1540 * $failOk tests are expected to fail that we won't fix |
| 1489 * $fail tests are expected to fail that we should fix | 1541 * $fail tests are expected to fail that we should fix |
| 1490 * $crash tests are expected to crash that we should fix | 1542 * $crash tests are expected to crash that we should fix |
| 1491 * $timeout tests are allowed to timeout | 1543 * $timeout tests are allowed to timeout |
| 1492 """; | 1544 """; |
| 1493 print(report); | 1545 print(report); |
| 1494 } | 1546 } |
| 1495 } | 1547 } |
| OLD | NEW |