| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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 #library("test_suite"); | 5 #library("test_suite"); |
| 6 | 6 |
| 7 #import("status_file_parser.dart"); | 7 #import("status_file_parser.dart"); |
| 8 #import("test_runner.dart"); | 8 #import("test_runner.dart"); |
| 9 #import("multitest.dart"); | 9 #import("multitest.dart"); |
| 10 | 10 |
| 11 #source("browser_test.dart"); |
| 11 | 12 |
| 12 interface TestSuite { | 13 interface TestSuite { |
| 13 void forEachTest(Function onTest, Map testCache, [Function onDone]); | 14 void forEachTest(Function onTest, Map testCache, [Function onDone]); |
| 14 } | 15 } |
| 15 | 16 |
| 16 | 17 |
| 17 class CCTestListerIsolate extends Isolate { | 18 class CCTestListerIsolate extends Isolate { |
| 18 CCTestListerIsolate() : super.heavy(); | 19 CCTestListerIsolate() : super.heavy(); |
| 19 | 20 |
| 20 void main() { | 21 void main() { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 139 Map configuration; | 140 Map configuration; |
| 140 String suiteName; | 141 String suiteName; |
| 141 String directoryPath; | 142 String directoryPath; |
| 142 List<String> statusFilePaths; | 143 List<String> statusFilePaths; |
| 143 Function doTest; | 144 Function doTest; |
| 144 Function doDone; | 145 Function doDone; |
| 145 int activeTestGenerators = 0; | 146 int activeTestGenerators = 0; |
| 146 bool listingDone = false; | 147 bool listingDone = false; |
| 147 TestExpectations testExpectations; | 148 TestExpectations testExpectations; |
| 148 List<TestInformation> cachedTests; | 149 List<TestInformation> cachedTests; |
| 150 final String pathSeparator; |
| 149 | 151 |
| 150 StandardTestSuite(Map this.configuration, | 152 StandardTestSuite(Map this.configuration, |
| 151 String this.suiteName, | 153 String this.suiteName, |
| 152 String this.directoryPath, | 154 String this.directoryPath, |
| 153 List<String> this.statusFilePaths); | 155 List<String> this.statusFilePaths) |
| 156 : pathSeparator = new Platform().pathSeparator(); |
| 154 | 157 |
| 155 void isTestFile(String filename) => filename.endsWith("Test.dart"); | 158 void isTestFile(String filename) => filename.endsWith("Test.dart"); |
| 156 | 159 |
| 157 void listRecursively() => false; | 160 void listRecursively() => false; |
| 158 | 161 |
| 159 void complexStatusMatching() => false; | 162 void complexStatusMatching() => false; |
| 160 | 163 |
| 161 String shellPath() => TestUtils.dartShellFileName(configuration); | 164 String shellPath() => TestUtils.dartShellFileName(configuration); |
| 162 | 165 |
| 163 List<String> additionalOptions() => []; | 166 List<String> additionalOptions() => []; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 203 dir.doneHandler = directoryListingDone; | 206 dir.doneHandler = directoryListingDone; |
| 204 dir.list(recursive: listRecursively()); | 207 dir.list(recursive: listRecursively()); |
| 205 } | 208 } |
| 206 | 209 |
| 207 void enqueueTestCaseFromTestInformation(TestInformation info) { | 210 void enqueueTestCaseFromTestInformation(TestInformation info) { |
| 208 var filename = info.filename; | 211 var filename = info.filename; |
| 209 var optionsFromFile = info.optionsFromFile; | 212 var optionsFromFile = info.optionsFromFile; |
| 210 var isNegative = info.isNegative; | 213 var isNegative = info.isNegative; |
| 211 | 214 |
| 212 // Look up expectations in status files using a modified file path. | 215 // Look up expectations in status files using a modified file path. |
| 213 String pathSeparator = new Platform().pathSeparator(); | |
| 214 String testName; | 216 String testName; |
| 215 int start = filename.lastIndexOf('src' + pathSeparator); | 217 int start = filename.lastIndexOf('src' + pathSeparator); |
| 216 if (start != -1) { | 218 if (start != -1) { |
| 217 testName = filename.substring(start + 4, filename.length - 5); | 219 testName = filename.substring(start + 4, filename.length - 5); |
| 218 } else if (optionsFromFile['isMultitest']) { | 220 } else if (optionsFromFile['isMultitest']) { |
| 219 start = filename.lastIndexOf(pathSeparator); | 221 start = filename.lastIndexOf(pathSeparator); |
| 220 int middle = filename.lastIndexOf('_'); | 222 int middle = filename.lastIndexOf('_'); |
| 221 testName = filename.substring(start + 1, middle) + pathSeparator + | 223 testName = filename.substring(start + 1, middle) + pathSeparator + |
| 222 filename.substring(middle + 1, filename.length - 5); | 224 filename.substring(middle + 1, filename.length - 5); |
| 223 } else { | 225 } else { |
| 224 // This case is hit by the dartc client compilation | 226 // This case is hit by the dartc client compilation |
| 225 // tests. These tests are pretty broken compared to the | 227 // tests. These tests are pretty broken compared to the |
| 226 // rest. They use the .dart suffix in the status files. They | 228 // rest. They use the .dart suffix in the status files. They |
| 227 // find tests in weird ways (testing that they contain "#"). | 229 // find tests in weird ways (testing that they contain "#"). |
| 228 // They need to be redone. | 230 // They need to be redone. |
| 229 start = filename.indexOf(directoryPath); | 231 start = filename.indexOf(directoryPath); |
| 230 testName = filename.substring(start + directoryPath.length + 1, | 232 testName = filename.substring(start + directoryPath.length + 1, |
| 231 filename.length); | 233 filename.length); |
| 232 } | 234 } |
| 233 Set<String> expectations = testExpectations.expectations(testName); | 235 Set<String> expectations = testExpectations.expectations(testName); |
| 234 if (configuration["report"]) { | 236 if (configuration["report"]) { |
| 235 // Tests with multiple VMOptions are counted more than once. | 237 // Tests with multiple VMOptions are counted more than once. |
| 236 for (var dummy in optionsFromFile["vmOptions"]) { | 238 for (var dummy in optionsFromFile["vmOptions"]) { |
| 237 SummaryReport.add(expectations); | 239 SummaryReport.add(expectations); |
| 238 } | 240 } |
| 239 } | 241 } |
| 240 if (expectations.contains(SKIP)) return; | 242 if (expectations.contains(SKIP)) return; |
| 241 | 243 |
| 244 if (configuration['component'] == 'dartium') { |
| 245 enqueueDartiumTest(filename, testName, optionsFromFile, |
| 246 expectations, isNegative); |
| 247 return; |
| 248 } |
| 242 // Only dartc supports fatal type errors. Enable fatal type | 249 // Only dartc supports fatal type errors. Enable fatal type |
| 243 // errors with a flag and treat tests that have fatal type | 250 // errors with a flag and treat tests that have fatal type |
| 244 // errors as negative. | 251 // errors as negative. |
| 245 var enableFatalTypeErrors = | 252 var enableFatalTypeErrors = |
| 246 (info.hasFatalTypeErrors && configuration['component'] == 'dartc'); | 253 (info.hasFatalTypeErrors && configuration['component'] == 'dartc'); |
| 247 var argumentLists = argumentListsFromFile(filename, | 254 var argumentLists = argumentListsFromFile(filename, |
| 248 optionsFromFile, | 255 optionsFromFile, |
| 249 enableFatalTypeErrors); | 256 enableFatalTypeErrors); |
| 250 isNegative = isNegative || | 257 isNegative = isNegative || |
| 251 (configuration['checked'] && info.isNegativeIfChecked) || | 258 (configuration['checked'] && info.isNegativeIfChecked) || |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 293 DoMultitest(filename, | 300 DoMultitest(filename, |
| 294 TestUtils.outputDir(configuration), | 301 TestUtils.outputDir(configuration), |
| 295 directoryPath, | 302 directoryPath, |
| 296 createTestCase, | 303 createTestCase, |
| 297 testGeneratorDone); | 304 testGeneratorDone); |
| 298 } else { | 305 } else { |
| 299 createTestCase(filename, optionsFromFile['isNegative']); | 306 createTestCase(filename, optionsFromFile['isNegative']); |
| 300 } | 307 } |
| 301 } | 308 } |
| 302 | 309 |
| 310 void enqueueDartiumTest(String filename, |
| 311 String testName, |
| 312 Map optionsFromFile, |
| 313 Set<String> expectations, |
| 314 bool isNegative) { |
| 315 if (optionsFromFile['isMultitest']) return; |
| 316 bool isWebTest = optionsFromFile['containsDomImport']; |
| 317 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; |
| 318 if (!isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { |
| 319 print('Warning for $filename: Browser tests require #library ' + |
| 320 'in any file that uses #import or #source'); |
| 321 } |
| 322 |
| 323 Directory tempDir = new Directory((isWebTest ? 'client/' : '') + |
| 324 TestUtils.buildDir(configuration) + |
| 325 'tmp'); |
| 326 // TODO(whesse): When implementing client web tests, |
| 327 // create directory in the client case, if it doesn't exist. |
| 328 tempDir.createTempSync(); |
| 329 |
| 330 String dartTestFilename = new File(filename).fullPathSync(); |
| 331 String dartWrapperFilename = '${tempDir.path}/test.dart'; |
| 332 if (!isWebTest) { |
| 333 // test.dart will import the dart test directly, if it is a library, |
| 334 // or indirectly through test_as_library.dart, if it is not. |
| 335 String dartLibraryFilename; |
| 336 if (isLibraryDefinition) { |
| 337 dartLibraryFilename = dartTestFilename; |
| 338 } else { |
| 339 dartLibraryFilename = 'test_as_library.dart'; |
| 340 File file = new File('${tempDir.path}/$dartLibraryFilename'); |
| 341 RandomAccessFile dartLibrary = file.openSync(writable: true); |
| 342 dartLibrary.writeStringSync(WrapDartTestInLibrary(dartTestFilename)); |
| 343 dartLibrary.closeSync(); |
| 344 } |
| 345 |
| 346 File file = new File(dartWrapperFilename); |
| 347 RandomAccessFile dartWrapper = file.openSync(writable: true); |
| 348 dartWrapper.writeStringSync(dartTestWrapper(dartLibraryFilename)); |
| 349 dartWrapper.closeSync(); |
| 350 } else { |
| 351 return; // TODO(whesse): Implement client web tests on dartium. |
| 352 } |
| 353 // Create the HTML file for the test. |
| 354 File htmlTestBase = new File('${tempDir.path}/${getHtmlName(filename)}'); |
| 355 RandomAccessFile htmlTest = htmlTestBase.openSync(writable: true); |
| 356 htmlTest.writeStringSync(GetHtmlContents( |
| 357 filename, |
| 358 'client/testing/unittest/test_controller.js', |
| 359 scriptType, |
| 360 dartWrapperFilename)); |
| 361 htmlTest.closeSync(); |
| 362 |
| 363 for (var vmOptions in optionsFromFile["vmOptions"]) { |
| 364 var drtFlags = ['-no-timeout']; |
| 365 var dartFlags = ['--enable_asserts', '--enable_type_checks']; |
| 366 dartFlags.addAll(vmOptions); |
| 367 drtFlags.add('--dart-flags=${Strings.join(dartFlags, " ")}'); |
| 368 var args = drtFlags; |
| 369 args.add(htmlTestBase.fullPathSync()); |
| 370 |
| 371 // Create BrowserTestCase and queue it. |
| 372 var testCase = new BrowserTestCase( |
| 373 testName, |
| 374 '/bin/echo', |
| 375 ['No compilation step for component dartium.'], |
| 376 dumpRenderTreeFilename, |
| 377 args, |
| 378 configuration, |
| 379 completeHandler, |
| 380 expectations, optionsFromFile['isNegative']); |
| 381 doTest(testCase); |
| 382 } |
| 383 } |
| 384 |
| 385 static String dartTestWrapper(String library) { |
| 386 return DartTestWrapper('', '', 'dart:dom', |
| 387 '../../../tests/isolate/src/TestFramework.dart', |
| 388 library); |
| 389 } |
| 390 |
| 391 static String get scriptType() => 'application/dart'; |
| 392 |
| 393 String getHtmlName(String filename) { |
| 394 return filename.replaceAll(pathSeparator, '_') + 'dartium.html'; |
| 395 } |
| 396 |
| 397 static String get dumpRenderTreeFilename() { |
| 398 if (new Platform().operatingSystem() == 'macos') { |
| 399 return 'client/tests/drt/.app/Contents/MacOS/DumpRenderTree'; |
| 400 } |
| 401 return 'client/tests/drt/DumpRenderTree'; |
| 402 } |
| 403 |
| 404 |
| 303 void testGeneratorStarted() { | 405 void testGeneratorStarted() { |
| 304 ++activeTestGenerators; | 406 ++activeTestGenerators; |
| 305 } | 407 } |
| 306 | 408 |
| 307 void testGeneratorDone() { | 409 void testGeneratorDone() { |
| 308 --activeTestGenerators; | 410 --activeTestGenerators; |
| 309 if (activeTestGenerators == 0 && listingDone) { | 411 if (activeTestGenerators == 0 && listingDone) { |
| 310 doDone(); | 412 doDone(); |
| 311 } | 413 } |
| 312 } | 414 } |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 358 | 460 |
| 359 return result; | 461 return result; |
| 360 } | 462 } |
| 361 | 463 |
| 362 Map optionsFromFile(String filename) { | 464 Map optionsFromFile(String filename) { |
| 363 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); | 465 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); |
| 364 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); | 466 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); |
| 365 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); | 467 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); |
| 366 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); | 468 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); |
| 367 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); | 469 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); |
| 368 | 470 RegExp domImportRegExp = |
| 471 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", |
| 472 multiLine: true); |
| 473 RegExp libraryDefinitionRegExp = |
| 474 const RegExp(@"^#library\(", multiLine: true); |
| 475 RegExp sourceOrImportRegExp = |
| 476 const RegExp(@"^#(source|import)\(", multiLine: true); |
| 477 |
| 369 // Read the entire file into a byte buffer and transform it to a | 478 // Read the entire file into a byte buffer and transform it to a |
| 370 // String. This will treat the file as ascii but the only parts | 479 // String. This will treat the file as ascii but the only parts |
| 371 // we are interested in will be ascii in any case. | 480 // we are interested in will be ascii in any case. |
| 372 RandomAccessFile file = (new File(filename)).openSync(); | 481 RandomAccessFile file = new File(filename).openSync(); |
| 373 List chars = new List(file.lengthSync()); | 482 List chars = new List(file.lengthSync()); |
| 374 var offset = 0; | 483 var offset = 0; |
| 375 while (offset != chars.length) { | 484 while (offset != chars.length) { |
| 376 offset += file.readListSync(chars, offset, chars.length - offset); | 485 offset += file.readListSync(chars, offset, chars.length - offset); |
| 377 } | 486 } |
| 378 file.closeSync(); | 487 file.closeSync(); |
| 379 String contents = new String.fromCharCodes(chars); | 488 String contents = new String.fromCharCodes(chars); |
| 380 chars = null; | 489 chars = null; |
| 381 | 490 |
| 382 // Find the options in the file. | 491 // Find the options in the file. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 404 isNegative = true; | 513 isNegative = true; |
| 405 } else if (contents.contains("@dynamic-type-error") && | 514 } else if (contents.contains("@dynamic-type-error") && |
| 406 configuration['checked']) { | 515 configuration['checked']) { |
| 407 isNegative = true; | 516 isNegative = true; |
| 408 } | 517 } |
| 409 | 518 |
| 410 bool isMultitest = multiTestRegExp.hasMatch(contents); | 519 bool isMultitest = multiTestRegExp.hasMatch(contents); |
| 411 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); | 520 bool containsLeadingHash = leadingHashRegExp.hasMatch(contents); |
| 412 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); | 521 Match isolateMatch = isolateStubsRegExp.firstMatch(contents); |
| 413 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; | 522 String isolateStubs = isolateMatch != null ? isolateMatch[1] : ''; |
| 523 bool containsDomImport = domImportRegExp.hasMatch(contents); |
| 524 bool isLibraryDefinition = libraryDefinitionRegExp.hasMatch(contents); |
| 525 bool containsSourceOrImport = sourceOrImportRegExp.hasMatch(contents); |
| 526 |
| 414 | 527 |
| 415 return { "vmOptions": result, | 528 return { "vmOptions": result, |
| 416 "dartOptions": dartOptions, | 529 "dartOptions": dartOptions, |
| 417 "isNegative": isNegative, | 530 "isNegative": isNegative, |
| 418 "isMultitest": isMultitest, | 531 "isMultitest": isMultitest, |
| 419 "containsLeadingHash" : containsLeadingHash, | 532 "containsLeadingHash" : containsLeadingHash, |
| 420 "isolateStubs" : isolateStubs }; | 533 "isolateStubs" : isolateStubs, |
| 534 "containsDomImport": containsDomImport, |
| 535 "isLibraryDefinition": isLibraryDefinition, |
| 536 "containsSourceOrImport": containsSourceOrImport }; |
| 421 } | 537 } |
| 422 } | 538 } |
| 423 | 539 |
| 424 | 540 |
| 425 class DartcCompilationTestSuite extends StandardTestSuite { | 541 class DartcCompilationTestSuite extends StandardTestSuite { |
| 426 List<String> _testDirs; | 542 List<String> _testDirs; |
| 427 int activityCount = 0; | 543 int activityCount = 0; |
| 428 | 544 |
| 429 DartcCompilationTestSuite(Map configuration, | 545 DartcCompilationTestSuite(Map configuration, |
| 430 String suiteName, | 546 String suiteName, |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 592 * $noCrash tests are expected to be flaky but not crash | 708 * $noCrash tests are expected to be flaky but not crash |
| 593 * $pass tests are expected to pass | 709 * $pass tests are expected to pass |
| 594 * $failOk tests are expected to fail that we won't fix | 710 * $failOk tests are expected to fail that we won't fix |
| 595 * $fail tests are expected to fail that we should fix | 711 * $fail tests are expected to fail that we should fix |
| 596 * $crash tests are expected to crash that we should fix | 712 * $crash tests are expected to crash that we should fix |
| 597 * $timeout tests are allowed to timeout\ | 713 * $timeout tests are allowed to timeout\ |
| 598 """; | 714 """; |
| 599 print(report); | 715 print(report); |
| 600 } | 716 } |
| 601 } | 717 } |
| OLD | NEW |