| 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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 Function doTest; | 104 Function doTest; |
| 105 Function doDone; | 105 Function doDone; |
| 106 ReceivePort receiveTestName; | 106 ReceivePort receiveTestName; |
| 107 TestExpectations testExpectations; | 107 TestExpectations testExpectations; |
| 108 | 108 |
| 109 CCTestSuite(Map this.configuration, | 109 CCTestSuite(Map this.configuration, |
| 110 String this.suiteName, | 110 String this.suiteName, |
| 111 String runnerName, | 111 String runnerName, |
| 112 List<String> this.statusFilePaths, | 112 List<String> this.statusFilePaths, |
| 113 [this.testPrefix = '']) | 113 [this.testPrefix = '']) |
| 114 : dartDir = TestUtils.dartDir() { | 114 : dartDir = TestUtils.dartDir().toNativePath() { |
| 115 runnerPath = '${TestUtils.buildDir(configuration)}/$runnerName'; | 115 runnerPath = '${TestUtils.buildDir(configuration)}/$runnerName'; |
| 116 } | 116 } |
| 117 | 117 |
| 118 void testNameHandler(String testName, ignore) { | 118 void testNameHandler(String testName, ignore) { |
| 119 if (testName == "") { | 119 if (testName == "") { |
| 120 receiveTestName.close(); | 120 receiveTestName.close(); |
| 121 doDone(true); | 121 doDone(true); |
| 122 } else { | 122 } else { |
| 123 // Only run the tests that match the pattern. Use the name | 123 // Only run the tests that match the pattern. Use the name |
| 124 // "suiteName/testName" for cc tests. | 124 // "suiteName/testName" for cc tests. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 statusFileRead); | 172 statusFileRead); |
| 173 } | 173 } |
| 174 } | 174 } |
| 175 | 175 |
| 176 void completeHandler(TestCase testCase) { | 176 void completeHandler(TestCase testCase) { |
| 177 } | 177 } |
| 178 } | 178 } |
| 179 | 179 |
| 180 | 180 |
| 181 class TestInformation { | 181 class TestInformation { |
| 182 String filename; | 182 Path filePath; |
| 183 Map optionsFromFile; | 183 Map optionsFromFile; |
| 184 bool isNegative; | 184 bool isNegative; |
| 185 bool isNegativeIfChecked; | 185 bool isNegativeIfChecked; |
| 186 bool hasFatalTypeErrors; | 186 bool hasFatalTypeErrors; |
| 187 bool hasRuntimeErrors; | 187 bool hasRuntimeErrors; |
| 188 Set<String> multitestOutcome; | 188 Set<String> multitestOutcome; |
| 189 | 189 |
| 190 TestInformation(this.filename, this.optionsFromFile, this.isNegative, | 190 TestInformation(this.filePath, this.optionsFromFile, this.isNegative, |
| 191 this.isNegativeIfChecked, this.hasFatalTypeErrors, | 191 this.isNegativeIfChecked, this.hasFatalTypeErrors, |
| 192 this.hasRuntimeErrors, this.multitestOutcome); | 192 this.hasRuntimeErrors, this.multitestOutcome) { |
| 193 Expect.isTrue(filePath.isAbsolute); |
| 194 } |
| 193 } | 195 } |
| 194 | 196 |
| 195 | 197 |
| 196 /** | 198 /** |
| 197 * A standard [TestSuite] implementation that searches for tests in a | 199 * A standard [TestSuite] implementation that searches for tests in a |
| 198 * directory, and creates [TestCase]s that compile and/or run them. | 200 * directory, and creates [TestCase]s that compile and/or run them. |
| 199 */ | 201 */ |
| 200 class StandardTestSuite implements TestSuite { | 202 class StandardTestSuite implements TestSuite { |
| 201 Map configuration; | 203 Map configuration; |
| 202 String suiteName; | 204 String suiteName; |
| 203 String directoryPath; | 205 Path suiteDir; |
| 204 List<String> statusFilePaths; | 206 List<String> statusFilePaths; |
| 205 Function doTest; | 207 Function doTest; |
| 206 Function doDone; | 208 Function doDone; |
| 207 int activeTestGenerators = 0; | 209 int activeTestGenerators = 0; |
| 208 bool listingDone = false; | 210 bool listingDone = false; |
| 209 TestExpectations testExpectations; | 211 TestExpectations testExpectations; |
| 210 List<TestInformation> cachedTests; | 212 List<TestInformation> cachedTests; |
| 211 final String dartDir; | 213 final Path dartDir; |
| 212 Predicate<String> isTestFilePredicate; | 214 Predicate<String> isTestFilePredicate; |
| 213 bool _listRecursive; | 215 bool _listRecursive; |
| 214 | 216 |
| 215 StandardTestSuite(Map this.configuration, | 217 StandardTestSuite(this.configuration, |
| 216 String this.suiteName, | 218 this.suiteName, |
| 217 String this.directoryPath, | 219 Path suiteDirectory, |
| 218 List<String> this.statusFilePaths, | 220 this.statusFilePaths, |
| 219 [Predicate<String> this.isTestFilePredicate, | 221 [this.isTestFilePredicate, |
| 220 bool recursive = false]) | 222 bool recursive = false]) |
| 221 : dartDir = TestUtils.dartDir(), _listRecursive = recursive; | 223 : dartDir = TestUtils.dartDir(), _listRecursive = recursive, |
| 224 suiteDir = TestUtils.dartDir().join(suiteDirectory); |
| 222 | 225 |
| 223 /** | 226 /** |
| 224 * Creates a test suite whose file organization matches an expected structure. | 227 * Creates a test suite whose file organization matches an expected structure. |
| 225 * To use this, your suite should look like: | 228 * To use this, your suite should look like: |
| 226 * | 229 * |
| 227 * dart/ | 230 * dart/ |
| 228 * path/ | 231 * path/ |
| 229 * to/ | 232 * to/ |
| 230 * mytestsuite/ | 233 * mytestsuite/ |
| 231 * mytestsuite.status | 234 * mytestsuite.status |
| 232 * example1_test.dart | 235 * example1_test.dart |
| 233 * example2_test.dart | 236 * example2_test.dart |
| 234 * example3_test.dart | 237 * example3_test.dart |
| 235 * | 238 * |
| 236 * The important parts: | 239 * The important parts: |
| 237 * | 240 * |
| 238 * * The leaf directory name is the name of your test suite. | 241 * * The leaf directory name is the name of your test suite. |
| 239 * * The status file uses the same name. | 242 * * The status file uses the same name. |
| 240 * * Test files are directly in that directory and end in "_test.dart". | 243 * * Test files are directly in that directory and end in "_test.dart". |
| 241 * | 244 * |
| 242 * If you follow that convention, then you can construct one of these like: | 245 * If you follow that convention, then you can construct one of these like: |
| 243 * | 246 * |
| 244 * new StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite'); | 247 * new StandardTestSuite.forDirectory(configuration, 'path/to/mytestsuite'); |
| 245 * | 248 * |
| 246 * instead of having to create a custom [StandardTestSuite] subclass. In | 249 * instead of having to create a custom [StandardTestSuite] subclass. In |
| 247 * particular, if you add 'path/to/mytestsuite' to [TEST_SUITE_DIRECTORIES] | 250 * particular, if you add 'path/to/mytestsuite' to [TEST_SUITE_DIRECTORIES] |
| 248 * in test.dart, this will all be set up for you. | 251 * in test.dart, this will all be set up for you. |
| 249 */ | 252 */ |
| 250 factory StandardTestSuite.forDirectory( | 253 factory StandardTestSuite.forDirectory( |
| 251 Map configuration, String directory) { | 254 Map configuration, Path directory) { |
| 252 final name = directory.substring(directory.lastIndexOf('/') + 1); | 255 final name = directory.filename; |
| 253 | 256 |
| 254 return new StandardTestSuite(configuration, | 257 return new StandardTestSuite(configuration, |
| 255 name, directory, | 258 name, directory, |
| 256 ['$directory/$name.status', '$directory/${name}_dart2js.status'], | 259 ['$directory/$name.status', '$directory/${name}_dart2js.status'], |
| 257 (filename) => filename.endsWith('_test.dart'), | 260 (filename) => filename.endsWith('_test.dart'), |
| 258 recursive: true); | 261 recursive: true); |
| 259 } | 262 } |
| 260 | 263 |
| 261 /** | 264 /** |
| 262 * The default implementation assumes a file is a test if | 265 * The default implementation assumes a file is a test if |
| 263 * it ends in "Test.dart". | 266 * it ends in "Test.dart". |
| 264 */ | 267 */ |
| 265 bool isTestFile(String filename) { | 268 bool isTestFile(String filename) { |
| 266 // Use the specified predicate, if provided. | 269 // Use the specified predicate, if provided. |
| 267 if (isTestFilePredicate != null) return isTestFilePredicate(filename); | 270 if (isTestFilePredicate != null) return isTestFilePredicate(filename); |
| 268 | 271 |
| 269 return filename.endsWith("Test.dart"); | 272 return filename.endsWith("Test.dart"); |
| 270 } | 273 } |
| 271 | 274 |
| 272 bool listRecursively() => _listRecursive; | 275 bool listRecursively() => _listRecursive; |
| 273 | 276 |
| 274 String shellPath() => TestUtils.dartShellFileName(configuration); | 277 String shellPath() => TestUtils.dartShellFileName(configuration); |
| 275 | 278 |
| 276 List<String> additionalOptions(String filename) => []; | 279 List<String> additionalOptions(Path filePath) => []; |
| 277 | 280 |
| 278 void forEachTest(Function onTest, Map testCache, [Function onDone = null]) { | 281 void forEachTest(Function onTest, Map testCache, [Function onDone = null]) { |
| 279 // If DumpRenderTree/Dartium is required, and not yet updated, | 282 // If DumpRenderTree/Dartium is required, and not yet updated, |
| 280 // wait for update. | 283 // wait for update. |
| 281 var updater = runtimeUpdater(configuration); | 284 var updater = runtimeUpdater(configuration); |
| 282 if (updater !== null && !updater.updated) { | 285 if (updater !== null && !updater.updated) { |
| 283 Expect.isTrue(updater.isActive); | 286 Expect.isTrue(updater.isActive); |
| 284 updater.onUpdated.add(() { | 287 updater.onUpdated.add(() { |
| 285 forEachTest(onTest, testCache, onDone); | 288 forEachTest(onTest, testCache, onDone); |
| 286 }); | 289 }); |
| (...skipping 25 matching lines...) Expand all Loading... |
| 312 } | 315 } |
| 313 } | 316 } |
| 314 } | 317 } |
| 315 | 318 |
| 316 // Read test expectations from status files. | 319 // Read test expectations from status files. |
| 317 testExpectations = new TestExpectations(); | 320 testExpectations = new TestExpectations(); |
| 318 for (var statusFilePath in statusFilePaths) { | 321 for (var statusFilePath in statusFilePaths) { |
| 319 // [forDirectory] adds name_dart2js.status for all tests suites, use it if | 322 // [forDirectory] adds name_dart2js.status for all tests suites, use it if |
| 320 // it exists, but otherwise skip it and don't fail. | 323 // it exists, but otherwise skip it and don't fail. |
| 321 if (statusFilePath.endsWith('_dart2js.status')) { | 324 if (statusFilePath.endsWith('_dart2js.status')) { |
| 322 File file = new File('$dartDir/$statusFilePath'); | 325 File file = new File.fromPath(dartDir.append(statusFilePath)); |
| 323 if (!file.existsSync()) { | 326 if (!file.existsSync()) { |
| 324 filesRead++; | 327 filesRead++; |
| 325 continue; | 328 continue; |
| 326 } | 329 } |
| 327 } | 330 } |
| 328 ReadTestExpectationsInto(testExpectations, | 331 ReadTestExpectationsInto(testExpectations, |
| 329 '$dartDir/$statusFilePath', | 332 dartDir.append(statusFilePath).toString(), |
| 330 configuration, | 333 configuration, |
| 331 statusFileRead); | 334 statusFileRead); |
| 332 } | 335 } |
| 333 } | 336 } |
| 334 | 337 |
| 335 void processDirectory() { | 338 void processDirectory() { |
| 336 directoryPath = '$dartDir/$directoryPath'; | 339 Directory dir = new Directory.fromPath(suiteDir); |
| 337 Directory dir = new Directory(directoryPath); | |
| 338 dir.exists().then((exists) { | 340 dir.exists().then((exists) { |
| 339 if (!exists) { | 341 if (!exists) { |
| 340 print('Directory containing tests not found: $directoryPath'); | 342 print('Directory containing tests not found: $suiteDir'); |
| 341 directoryListingDone(false); | 343 directoryListingDone(false); |
| 342 } else { | 344 } else { |
| 343 var lister = dir.list(recursive: listRecursively()); | 345 var lister = dir.list(recursive: listRecursively()); |
| 344 lister.onFile = processFile; | 346 lister.onFile = processFile; |
| 345 lister.onDone = directoryListingDone; | 347 lister.onDone = directoryListingDone; |
| 346 } | 348 } |
| 347 }); | 349 }); |
| 348 } | 350 } |
| 349 | 351 |
| 350 void enqueueTestCaseFromTestInformation(TestInformation info) { | 352 void enqueueTestCaseFromTestInformation(TestInformation info) { |
| 351 var filename = info.filename; | 353 var filePath = info.filePath; |
| 352 var optionsFromFile = info.optionsFromFile; | 354 var optionsFromFile = info.optionsFromFile; |
| 353 var isNegative = info.isNegative; | 355 var isNegative = info.isNegative; |
| 354 | 356 |
| 355 // Look up expectations in status files using a modified file path. | 357 // Look up expectations in status files using a test name generated |
| 358 // from the test file's path. |
| 356 String testName; | 359 String testName; |
| 357 filename = filename.replaceAll('\\', '/'); | |
| 358 | 360 |
| 359 // See if there's a 'src' directory inside the 'tests' one. | 361 if (optionsFromFile['isMultitest']) { |
| 360 int testsStart = filename.lastIndexOf('tests/'); | 362 // Multitests do not run on browsers. |
| 361 int start = filename.lastIndexOf('src/'); | 363 if (TestUtils.isBrowserRuntime(configuration['runtime'])) return; |
| 362 if (start > testsStart) { | 364 // Multitests are in [build directory]/generated_tests/... . |
| 363 // Old-style test suites with tests in a 'src' subdirectory. | 365 // The test name will be '[test filename (no extension)]/[multitest key]. |
| 364 // TODO(sigmund): delete this branch once all tests stop using the src/ | 366 String name = filePath.filenameWithoutExtension; |
| 365 // directory | 367 int middle = name.lastIndexOf('_'); |
| 366 testName = filename.substring(start + 4, filename.length - 5); | 368 testName = '${name.substring(0, middle)}/${name.substring(middle + 1)}'; |
| 367 } else if (optionsFromFile['isMultitest']) { | |
| 368 start = filename.lastIndexOf('/'); | |
| 369 int middle = filename.lastIndexOf('_'); | |
| 370 var multitestBase = filename.substring(start + 1, middle); | |
| 371 var multitestKey = filename.substring(middle + 1, filename.length - 5); | |
| 372 testName = '$multitestBase/$multitestKey'; | |
| 373 } else { | 369 } else { |
| 374 // New-style test suites created by StandardTestSuite.forDirectory(). | 370 // The test name is the relative path from the test suite directory to |
| 375 start = filename.indexOf(directoryPath); | 371 // the test, with the .dart extension removed. |
| 376 if (start != -1) { | 372 Expect.isTrue(filePath.toNativePath().startsWith( |
| 377 testName = filename.substring(start + directoryPath.length + 1); | 373 suiteDir.toNativePath())); |
| 378 } else { | 374 var testNamePath = filePath.relativeTo(suiteDir); |
| 379 testName = filename; | 375 Expect.isTrue(testNamePath.extension == 'dart'); |
| 380 } | 376 if (testNamePath.extension == 'dart') { |
| 381 if (testName.endsWith('.dart')) { | 377 testName = testNamePath.directoryPath.append( |
| 382 testName = testName.substring(0, testName.length - 5); | 378 testNamePath.filenameWithoutExtension).toString(); |
| 383 } | 379 } |
| 384 } | 380 } |
| 385 int shards = configuration['shards']; | 381 int shards = configuration['shards']; |
| 386 if (shards > 1) { | 382 if (shards > 1) { |
| 387 int shard = configuration['shard']; | 383 int shard = configuration['shard']; |
| 388 if (testName.hashCode() % shards != shard - 1) { | 384 if (testName.hashCode() % shards != shard - 1) { |
| 389 return; | 385 return; |
| 390 } | 386 } |
| 391 } | 387 } |
| 392 | 388 |
| 393 Set<String> expectations = testExpectations.expectations(testName); | 389 Set<String> expectations = testExpectations.expectations(testName); |
| 394 if (configuration['report']) { | 390 if (configuration['report']) { |
| 395 // Tests with multiple VMOptions are counted more than once. | 391 // Tests with multiple VMOptions are counted more than once. |
| 396 for (var dummy in getVmOptions(optionsFromFile)) { | 392 for (var dummy in getVmOptions(optionsFromFile)) { |
| 397 if (TestUtils.isBrowserRuntime(configuration['runtime']) && | |
| 398 optionsFromFile['isMultitest']) { | |
| 399 break; // Browser tests skip multitests. | |
| 400 } | |
| 401 SummaryReport.add(expectations); | 393 SummaryReport.add(expectations); |
| 402 } | 394 } |
| 403 } | 395 } |
| 404 if (expectations.contains(SKIP)) return; | 396 if (expectations.contains(SKIP)) return; |
| 405 | 397 |
| 406 if (TestUtils.isBrowserRuntime(configuration['runtime'])) { | 398 if (TestUtils.isBrowserRuntime(configuration['runtime'])) { |
| 407 enqueueBrowserTest(info, testName, expectations); | 399 enqueueBrowserTest(info, testName, expectations); |
| 408 } else { | 400 } else { |
| 409 enqueueStandardTest(info, testName, expectations); | 401 enqueueStandardTest(info, testName, expectations); |
| 410 } | 402 } |
| 411 } | 403 } |
| 412 | 404 |
| 413 void enqueueStandardTest(TestInformation info, | 405 void enqueueStandardTest(TestInformation info, |
| 414 String testName, | 406 String testName, |
| 415 Set<String> expectations) { | 407 Set<String> expectations) { |
| 416 bool isNegative = info.isNegative || | 408 bool isNegative = info.isNegative || |
| 417 (configuration['checked'] && info.isNegativeIfChecked); | 409 (configuration['checked'] && info.isNegativeIfChecked); |
| 418 | 410 |
| 419 if (configuration['compiler'] == 'dartc') { | 411 if (configuration['compiler'] == 'dartc') { |
| 420 // dartc can detect static type warnings by the | 412 // dartc can detect static type warnings by the |
| 421 // format of the error line | 413 // format of the error line |
| 422 if (info.hasFatalTypeErrors) { | 414 if (info.hasFatalTypeErrors) { |
| 423 isNegative = true; | 415 isNegative = true; |
| 424 } else if (info.hasRuntimeErrors) { | 416 } else if (info.hasRuntimeErrors) { |
| 425 isNegative = false; | 417 isNegative = false; |
| 426 } | 418 } |
| 427 } | 419 } |
| 428 | 420 |
| 429 var argumentLists = argumentListsFromFile(info.filename, | 421 var argumentLists = argumentListsFromFile(info.filePath, |
| 430 info.optionsFromFile); | 422 info.optionsFromFile); |
| 431 | 423 |
| 432 for (var args in argumentLists) { | 424 for (var args in argumentLists) { |
| 433 doTest(new TestCase('$suiteName/$testName', | 425 doTest(new TestCase('$suiteName/$testName', |
| 434 makeCommands(info, args), | 426 makeCommands(info, args), |
| 435 configuration, | 427 configuration, |
| 436 completeHandler, | 428 completeHandler, |
| 437 expectations, | 429 expectations, |
| 438 isNegative, | 430 isNegative, |
| 439 info)); | 431 info)); |
| 440 } | 432 } |
| 441 } | 433 } |
| 442 | 434 |
| 443 List<Command> makeCommands(TestInformation info, var args) { | 435 List<Command> makeCommands(TestInformation info, var args) { |
| 444 if (configuration['compiler'] == 'dart2js') { | 436 if (configuration['compiler'] == 'dart2js') { |
| 445 args = new List.from(args); | 437 args = new List.from(args); |
| 446 String testPath = | 438 String tempDir = createOutputDirectory(info.filePath, ''); |
| 447 new File(info.filename).fullPathSync().replaceAll('\\', '/'); | |
| 448 String tempDir = createOutputDirectory(testPath, ''); | |
| 449 args.add('--out=$tempDir/out.js'); | 439 args.add('--out=$tempDir/out.js'); |
| 450 List<Command> commands = <Command>[new Command(shellPath(), args)]; | 440 List<Command> commands = <Command>[new Command(shellPath(), args)]; |
| 451 if (configuration['runtime'] == 'd8') { | 441 if (configuration['runtime'] == 'd8') { |
| 452 var d8 = TestUtils.d8FileName(configuration); | 442 var d8 = TestUtils.d8FileName(configuration); |
| 453 commands.add(new Command(d8, ['$tempDir/out.js'])); | 443 commands.add(new Command(d8, ['$tempDir/out.js'])); |
| 454 } | 444 } |
| 455 return commands; | 445 return commands; |
| 456 } else { | 446 } else { |
| 457 return <Command>[new Command(shellPath(), args)]; | 447 return <Command>[new Command(shellPath(), args)]; |
| 458 } | 448 } |
| 459 } | 449 } |
| 460 | 450 |
| 461 Function makeTestCaseCreator(Map optionsFromFile) { | 451 Function makeTestCaseCreator(Map optionsFromFile) { |
| 462 return (String filename, | 452 return (Path filePath, |
| 463 bool isNegative, | 453 bool isNegative, |
| 464 [bool isNegativeIfChecked = false, | 454 [bool isNegativeIfChecked = false, |
| 465 bool hasFatalTypeErrors = false, | 455 bool hasFatalTypeErrors = false, |
| 466 bool hasRuntimeErrors = false, | 456 bool hasRuntimeErrors = false, |
| 467 Set<String> multitestOutcome = null]) { | 457 Set<String> multitestOutcome = null]) { |
| 468 // Cache the test information for each test case. | 458 // Cache the test information for each test case. |
| 469 var info = new TestInformation(filename, | 459 var info = new TestInformation(filePath, |
| 470 optionsFromFile, | 460 optionsFromFile, |
| 471 isNegative, | 461 isNegative, |
| 472 isNegativeIfChecked, | 462 isNegativeIfChecked, |
| 473 hasFatalTypeErrors, | 463 hasFatalTypeErrors, |
| 474 hasRuntimeErrors, | 464 hasRuntimeErrors, |
| 475 multitestOutcome); | 465 multitestOutcome); |
| 476 cachedTests.add(info); | 466 cachedTests.add(info); |
| 477 enqueueTestCaseFromTestInformation(info); | 467 enqueueTestCaseFromTestInformation(info); |
| 478 }; | 468 }; |
| 479 } | 469 } |
| 480 | 470 |
| 481 void processFile(String filename) { | 471 void processFile(String filename) { |
| 482 if (!isTestFile(filename)) return; | 472 if (!isTestFile(filename)) return; |
| 473 Path filePath = new Path.fromNative(filename); |
| 483 | 474 |
| 484 // Only run the tests that match the pattern. | 475 // Only run the tests that match the pattern. |
| 485 RegExp pattern = configuration['selectors'][suiteName]; | 476 RegExp pattern = configuration['selectors'][suiteName]; |
| 486 if (!pattern.hasMatch(filename)) return; | 477 if (!pattern.hasMatch('$filePath')) return; |
| 487 if (filename.endsWith('test_config.dart')) return; | 478 if (filePath.filename.endsWith('test_config.dart')) return; |
| 488 | 479 |
| 489 var optionsFromFile = readOptionsFromFile(filename); | 480 var optionsFromFile = readOptionsFromFile(filePath); |
| 490 Function createTestCase = makeTestCaseCreator(optionsFromFile); | 481 Function createTestCase = makeTestCaseCreator(optionsFromFile); |
| 491 | 482 |
| 492 if (optionsFromFile['isMultitest']) { | 483 if (optionsFromFile['isMultitest']) { |
| 493 testGeneratorStarted(); | 484 testGeneratorStarted(); |
| 494 DoMultitest(filename, | 485 DoMultitest(filePath, |
| 495 TestUtils.buildDir(configuration), | 486 TestUtils.buildDir(configuration), |
| 496 directoryPath, | 487 suiteDir, |
| 497 createTestCase, | 488 createTestCase, |
| 498 testGeneratorDone); | 489 testGeneratorDone); |
| 499 } else { | 490 } else { |
| 500 createTestCase(filename, optionsFromFile['isNegative']); | 491 createTestCase(filePath, optionsFromFile['isNegative']); |
| 501 } | 492 } |
| 502 } | 493 } |
| 503 | 494 |
| 504 /** | 495 /** |
| 505 * The [StandardTestSuite] has support for tests that | 496 * The [StandardTestSuite] has support for tests that |
| 506 * compile a test from Dart to Javascript, and then run the resulting | 497 * compile a test from Dart to Javascript, and then run the resulting |
| 507 * Javascript. This function creates a working directory to hold the | 498 * Javascript. This function creates a working directory to hold the |
| 508 * Javascript version of the test, and copies the appropriate framework | 499 * Javascript version of the test, and copies the appropriate framework |
| 509 * files to that directory. It creates a [BrowserTestCase], which has | 500 * files to that directory. It creates a [BrowserTestCase], which has |
| 510 * two sequential steps to be run by the [ProcessQueue when] the test is | 501 * two sequential steps to be run by the [ProcessQueue when] the test is |
| 511 * executed: a compilation | 502 * executed: a compilation |
| 512 * step and an execution step, both with the appropriate executable and | 503 * step and an execution step, both with the appropriate executable and |
| 513 * arguments. | 504 * arguments. |
| 514 */ | 505 */ |
| 515 void enqueueBrowserTest(TestInformation info, | 506 void enqueueBrowserTest(TestInformation info, |
| 516 String testName, | 507 String testName, |
| 517 Set<String> expectations) { | 508 Set<String> expectations) { |
| 518 Map optionsFromFile = info.optionsFromFile; | 509 Map optionsFromFile = info.optionsFromFile; |
| 519 String filename = info.filename; | 510 Path filePath = info.filePath; |
| 520 if (optionsFromFile['isMultitest']) return; | 511 String filename = filePath.toString(); |
| 521 bool isWebTest = optionsFromFile['containsDomImport']; | 512 bool isWebTest = optionsFromFile['containsDomImport']; |
| 522 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; | 513 bool isLibraryDefinition = optionsFromFile['isLibraryDefinition']; |
| 523 if (!isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { | 514 if (!isLibraryDefinition && optionsFromFile['containsSourceOrImport']) { |
| 524 print('Warning for $filename: Browser tests require #library ' | 515 print('Warning for $filename: Browser tests require #library ' |
| 525 'in any file that uses #import, #source, or #resource'); | 516 'in any file that uses #import, #source, or #resource'); |
| 526 } | 517 } |
| 527 | 518 |
| 528 final String compiler = configuration['compiler']; | 519 final String compiler = configuration['compiler']; |
| 529 final String runtime = configuration['runtime']; | 520 final String runtime = configuration['runtime']; |
| 530 final String testPath = | |
| 531 new File(filename).fullPathSync().replaceAll('\\', '/'); | |
| 532 | 521 |
| 533 for (var vmOptions in getVmOptions(optionsFromFile)) { | 522 for (var vmOptions in getVmOptions(optionsFromFile)) { |
| 534 // Create a unique temporary directory for each set of vmOptions. | 523 // Create a unique temporary directory for each set of vmOptions. |
| 535 // TODO(dart:429): Replace separate replaceAlls with a RegExp when | 524 // TODO(dart:429): Replace separate replaceAlls with a RegExp when |
| 536 // replaceAll(RegExp, String) is implemented. | 525 // replaceAll(RegExp, String) is implemented. |
| 537 String optionsName = ''; | 526 String optionsName = ''; |
| 538 if (getVmOptions(optionsFromFile).length > 1) { | 527 if (getVmOptions(optionsFromFile).length > 1) { |
| 539 optionsName = Strings.join(vmOptions, '-').replaceAll('-','') | 528 optionsName = Strings.join(vmOptions, '-').replaceAll('-','') |
| 540 .replaceAll('=','') | 529 .replaceAll('=','') |
| 541 .replaceAll('/',''); | 530 .replaceAll('/',''); |
| 542 } | 531 } |
| 543 final String tempDir = createOutputDirectory(testPath, optionsName); | 532 final String tempDir = createOutputDirectory(info.filePath, optionsName); |
| 544 | 533 |
| 545 String dartWrapperFilename = '$tempDir/test.dart'; | 534 String dartWrapperFilename = '$tempDir/test.dart'; |
| 546 String compiledDartWrapperFilename = '$tempDir/test.js'; | 535 String compiledDartWrapperFilename = '$tempDir/test.js'; |
| 547 | 536 |
| 548 String htmlPath = '$tempDir/test.html'; | 537 String htmlPath = '$tempDir/test.html'; |
| 549 if (!isWebTest) { | 538 if (!isWebTest) { |
| 550 // test.dart will import the dart test directly, if it is a library, | 539 // 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. | 540 // or indirectly through test_as_library.dart, if it is not. |
| 552 String dartLibraryFilename; | 541 Path dartLibraryFilename = filePath; |
| 553 if (isLibraryDefinition) { | 542 if (!isLibraryDefinition) { |
| 554 dartLibraryFilename = testPath; | 543 dartLibraryFilename = new Path('test_as_library.dart'); |
| 555 } else { | |
| 556 dartLibraryFilename = 'test_as_library.dart'; | |
| 557 File file = new File('$tempDir/$dartLibraryFilename'); | 544 File file = new File('$tempDir/$dartLibraryFilename'); |
| 558 RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE); | 545 RandomAccessFile dartLibrary = file.openSync(FileMode.WRITE); |
| 559 dartLibrary.writeStringSync(WrapDartTestInLibrary(testPath)); | 546 dartLibrary.writeStringSync(WrapDartTestInLibrary(filePath)); |
| 560 dartLibrary.closeSync(); | 547 dartLibrary.closeSync(); |
| 561 } | 548 } |
| 562 | 549 |
| 563 File file = new File(dartWrapperFilename); | 550 File file = new File(dartWrapperFilename); |
| 564 RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE); | 551 RandomAccessFile dartWrapper = file.openSync(FileMode.WRITE); |
| 565 dartWrapper.writeStringSync( | 552 dartWrapper.writeStringSync( |
| 566 DartTestWrapper(dartDir, dartLibraryFilename)); | 553 DartTestWrapper(dartDir, dartLibraryFilename)); |
| 567 dartWrapper.closeSync(); | 554 dartWrapper.closeSync(); |
| 568 } else { | 555 } else { |
| 569 dartWrapperFilename = testPath; | 556 dartWrapperFilename = filename; |
| 570 // TODO(whesse): Once test.py is retired, adjust the relative path in | 557 // TODO(whesse): Once test.py is retired, adjust the relative path in |
| 571 // the client/samples/dartcombat test to its css file, remove the | 558 // the client/samples/dartcombat test to its css file, remove the |
| 572 // "../../" from this path, and move this out of the isWebTest guard. | 559 // "../../" from this path, and move this out of the isWebTest guard. |
| 573 // Also remove getHtmlName, and just use test.html. | 560 // Also remove getHtmlName, and just use test.html. |
| 574 // TODO(efortuna): this shortening of htmlFilename is a band-aid until | 561 // TODO(efortuna): this shortening of htmlFilename is a band-aid until |
| 575 // the above TODO gets fixed. Windows cannot have paths that are longer | 562 // 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 | 563 // than 260 characters, and without this hack, we were running past the |
| 577 // the limit. | 564 // the limit. |
| 578 String htmlFilename = getHtmlName(filename); | 565 String htmlFilename = getHtmlName(filename); |
| 579 while ('$tempDir/../$htmlFilename'.length >= 260) { | 566 while ('$tempDir/../$htmlFilename'.length >= 260) { |
| 580 htmlFilename = htmlFilename.substring(htmlFilename.length~/2); | 567 htmlFilename = htmlFilename.substring(htmlFilename.length~/2); |
| 581 } | 568 } |
| 582 htmlPath = '$tempDir/../$htmlFilename'; | 569 htmlPath = '$tempDir/../$htmlFilename'; |
| 583 } | 570 } |
| 584 final String scriptPath = (compiler == 'none') ? | 571 final String scriptPath = (compiler == 'none') ? |
| 585 dartWrapperFilename : compiledDartWrapperFilename; | 572 dartWrapperFilename : compiledDartWrapperFilename; |
| 586 // Create the HTML file for the test. | 573 // Create the HTML file for the test. |
| 587 RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE); | 574 RandomAccessFile htmlTest = new File(htmlPath).openSync(FileMode.WRITE); |
| 588 String filePrefix = ''; | 575 String filePrefix = ''; |
| 589 if (Platform.operatingSystem == 'windows') { | 576 if (Platform.operatingSystem == 'windows') { |
| 590 // Firefox on Windows does not like absolute file path names that start | 577 // Firefox on Windows does not like absolute file path names that start |
| 591 // with 'C:' adding 'file:///' solves the problem. | 578 // with 'C:' adding 'file:///' solves the problem. |
| 592 filePrefix = 'file:///'; | 579 filePrefix = 'file:///'; |
| 593 } | 580 } |
| 594 htmlTest.writeStringSync(GetHtmlContents( | 581 htmlTest.writeStringSync(GetHtmlContents( |
| 595 filename, | 582 filename, |
| 596 '$filePrefix$dartDir/lib/unittest/test_controller.js', | 583 '$filePrefix${dartDir.append("lib/unittest/test_controller.js")}', |
| 597 scriptType, | 584 scriptType, |
| 598 '$filePrefix$scriptPath')); | 585 '$filePrefix$scriptPath')); |
| 599 htmlTest.closeSync(); | 586 htmlTest.closeSync(); |
| 600 | 587 |
| 601 // Construct the command(s) that compile all the inputs needed by the | 588 // 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. | 589 // browser test. For running Dart in DRT, this will be noop commands. |
| 603 List<Command> commands = []; | 590 List<Command> commands = []; |
| 604 if (compiler != 'none') { | 591 if (compiler != 'none') { |
| 605 commands.add(_compileCommand( | 592 commands.add(_compileCommand( |
| 606 dartWrapperFilename, compiledDartWrapperFilename, | 593 dartWrapperFilename, compiledDartWrapperFilename, |
| 607 compiler, tempDir, vmOptions)); | 594 compiler, tempDir, vmOptions)); |
| 608 | 595 |
| 609 // some tests require compiling multiple input scripts. | 596 // some tests require compiling multiple input scripts. |
| 610 List<String> otherScripts = optionsFromFile['otherScripts']; | 597 List<String> otherScripts = optionsFromFile['otherScripts']; |
| 611 for (String name in otherScripts) { | 598 for (String name in otherScripts) { |
| 612 int end = filename.lastIndexOf('/'); | 599 Path namePath = new Path(name); |
| 613 if (end == -1) { | 600 Expect.equals(namePath.extension, 'dart'); |
| 614 print('Warning: error processing "OtherScripts" of $filename.'); | 601 String baseName = namePath.filenameWithoutExtension; |
| 615 print('Skipping test ($testName).'); | 602 Path fromPath = filePath.directoryPath.join(namePath); |
| 616 return; | |
| 617 } | |
| 618 String dir = filename.substring(0, end); | |
| 619 end = name.lastIndexOf('.dart'); | |
| 620 if (end == -1) { | |
| 621 print('Warning: error processing "OtherScripts" in $filename.'); | |
| 622 print('Skipping test ($testName).'); | |
| 623 return; | |
| 624 } | |
| 625 String compiledName = '${name.substring(0, end)}.js'; | |
| 626 commands.add(_compileCommand( | 603 commands.add(_compileCommand( |
| 627 '$dir/$name', '$tempDir/$compiledName', | 604 fromPath.toNativePath(), '$tempDir/$baseName.js', |
| 628 compiler, tempDir, vmOptions)); | 605 compiler, tempDir, vmOptions)); |
| 629 } | 606 } |
| 630 } | 607 } |
| 631 | 608 |
| 632 // Construct the command that executes the browser test | 609 // Construct the command that executes the browser test |
| 633 List<String> args; | 610 List<String> args; |
| 634 if (runtime == 'ie' || runtime == 'ff' || runtime == 'chrome' || | 611 if (runtime == 'ie' || runtime == 'ff' || runtime == 'chrome' || |
| 635 runtime == 'safari' || runtime == 'opera' || runtime == 'dartium') { | 612 runtime == 'safari' || runtime == 'opera' || runtime == 'dartium') { |
| 636 args = ['$dartDir/tools/testing/run_selenium.py', | 613 args = [dartDir.append('tools/testing/run_selenium.py').toNativePath(), |
| 637 '--browser=$runtime', | 614 '--browser=$runtime', |
| 638 '--timeout=${configuration["timeout"] - 2}', | 615 '--timeout=${configuration["timeout"] - 2}', |
| 639 '--out=$htmlPath']; | 616 '--out=$htmlPath']; |
| 640 if (runtime == 'dartium') { | 617 if (runtime == 'dartium') { |
| 641 args.add('--executable=$dartiumFilename'); | 618 args.add('--executable=$dartiumFilename'); |
| 642 } | 619 } |
| 643 } else { | 620 } else { |
| 644 args = [ | 621 args = [ |
| 645 '$dartDir/tools/testing/drt-trampoline.py', | 622 dartDir.append('tools/testing/drt-trampoline.py').toNativePath(), |
| 646 dumpRenderTreeFilename, | 623 dumpRenderTreeFilename, |
| 647 '--no-timeout' | 624 '--no-timeout' |
| 648 ]; | 625 ]; |
| 649 if (runtime == 'drt' && compiler == 'none') { | 626 if (runtime == 'drt' && compiler == 'none') { |
| 650 var dartFlags = ['--ignore-unrecognized-flags']; | 627 var dartFlags = ['--ignore-unrecognized-flags']; |
| 651 if (configuration["checked"]) { | 628 if (configuration["checked"]) { |
| 652 dartFlags.add('--enable_asserts'); | 629 dartFlags.add('--enable_asserts'); |
| 653 dartFlags.add("--enable_type_checks"); | 630 dartFlags.add("--enable_type_checks"); |
| 654 } | 631 } |
| 655 dartFlags.addAll(vmOptions); | 632 dartFlags.addAll(vmOptions); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 669 | 646 |
| 670 /** Helper to create a compilation command for a single input file. */ | 647 /** Helper to create a compilation command for a single input file. */ |
| 671 Command _compileCommand(String inputFile, String outputFile, | 648 Command _compileCommand(String inputFile, String outputFile, |
| 672 String compiler, String dir, var vmOptions) { | 649 String compiler, String dir, var vmOptions) { |
| 673 String executable = TestUtils.compilerPath(configuration); | 650 String executable = TestUtils.compilerPath(configuration); |
| 674 List<String> args = TestUtils.standardOptions(configuration); | 651 List<String> args = TestUtils.standardOptions(configuration); |
| 675 switch (compiler) { | 652 switch (compiler) { |
| 676 case 'frog': | 653 case 'frog': |
| 677 String libdir = configuration['froglib']; | 654 String libdir = configuration['froglib']; |
| 678 if (libdir == '') { | 655 if (libdir == '') { |
| 679 libdir = '$dartDir/frog/lib'; | 656 libdir = dartDir.append('frog/lib').toNativePath(); |
| 680 } | 657 } |
| 681 args.addAll(['--libdir=$libdir', | 658 args.addAll(['--libdir=$libdir', |
| 682 '--compile-only', | 659 '--compile-only', |
| 683 '--out=$outputFile']); | 660 '--out=$outputFile']); |
| 684 args.addAll(vmOptions); | 661 args.addAll(vmOptions); |
| 685 args.add(inputFile); | 662 args.add(inputFile); |
| 686 break; | 663 break; |
| 687 case 'dart2js': | 664 case 'dart2js': |
| 688 args.add('--out=$outputFile'); | 665 args.add('--out=$outputFile'); |
| 689 args.add(inputFile); | 666 args.add(inputFile); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 705 * an HTML page, with a testing framework based on scripting and DOM events. | 682 * an HTML page, with a testing framework based on scripting and DOM events. |
| 706 * These scripts and pages are written to a generated_test directory | 683 * These scripts and pages are written to a generated_test directory |
| 707 * inside the build directory of the checkout. | 684 * inside the build directory of the checkout. |
| 708 * | 685 * |
| 709 * Those tests which are already HTML web applications (web tests), with | 686 * Those tests which are already HTML web applications (web tests), with |
| 710 * resources including CSS files and HTML files, need to be compiled into | 687 * resources including CSS files and HTML files, need to be compiled into |
| 711 * a work directory where the relative URLS to the resources work. | 688 * a work directory where the relative URLS to the resources work. |
| 712 * We use a subdirectory of the build directory that is the same number | 689 * We use a subdirectory of the build directory that is the same number |
| 713 * of levels down in the checkout as the original path of the web test. | 690 * of levels down in the checkout as the original path of the web test. |
| 714 */ | 691 */ |
| 715 String createOutputDirectory(String testPath, String optionsName) { | 692 String createOutputDirectory(Path testPath, String optionsName) { |
| 716 String testUniqueName = | 693 Path relative = testPath.relativeTo(TestUtils.dartDir()); |
| 717 testPath.substring(dartDir.length + 1, testPath.length - 5); | 694 relative = relative.directoryPath.append(relative.filenameWithoutExtension); |
| 718 testUniqueName = testUniqueName.replaceAll('/', '_'); | 695 String testUniqueName = relative.toString().replaceAll('/', '_'); |
| 719 if (!optionsName.isEmpty()) { | 696 if (!optionsName.isEmpty()) { |
| 720 testUniqueName = '$testUniqueName-$optionsName'; | 697 testUniqueName = '$testUniqueName-$optionsName'; |
| 721 } | 698 } |
| 722 | 699 |
| 723 // Create '[build dir]/generated_tests/$compiler-$runtime/$testUniqueName', | 700 // Create '[build dir]/generated_tests/$compiler-$runtime/$testUniqueName', |
| 724 // including any intermediate directories that don't exist. | 701 // including any intermediate directories that don't exist. |
| 725 var generatedTestPath = Strings.join( | 702 var generatedTestPath = Strings.join( |
| 726 [TestUtils.buildDir(configuration), | 703 [TestUtils.buildDir(configuration), |
| 727 'generated_tests', | 704 'generated_tests', |
| 728 "${configuration['compiler']}-${configuration['runtime']}", | 705 "${configuration['compiler']}-${configuration['runtime']}", |
| 729 testUniqueName], '/'); | 706 testUniqueName], '/'); |
| 730 | 707 |
| 731 TestUtils.mkdirRecursive('.', generatedTestPath); | 708 TestUtils.mkdirRecursive(new Path('.'), new Path(generatedTestPath)); |
| 732 return new File(generatedTestPath).fullPathSync().replaceAll('\\', '/'); | 709 return new File(generatedTestPath).fullPathSync().replaceAll('\\', '/'); |
| 733 } | 710 } |
| 734 | 711 |
| 735 String get scriptType() { | 712 String get scriptType() { |
| 736 switch (configuration['compiler']) { | 713 switch (configuration['compiler']) { |
| 737 case 'none': | 714 case 'none': |
| 738 return 'application/dart'; | 715 return 'application/dart'; |
| 739 case 'frog': | 716 case 'frog': |
| 740 case 'dart2js': | 717 case 'dart2js': |
| 741 case 'dartc': | 718 case 'dartc': |
| (...skipping 23 matching lines...) Expand all Loading... |
| 765 | 742 |
| 766 return "$cleanFilename" | 743 return "$cleanFilename" |
| 767 "${configuration['compiler']}-${configuration['runtime']}.html"; | 744 "${configuration['compiler']}-${configuration['runtime']}.html"; |
| 768 } | 745 } |
| 769 | 746 |
| 770 String get dumpRenderTreeFilename() { | 747 String get dumpRenderTreeFilename() { |
| 771 if (configuration['drt'] != '') { | 748 if (configuration['drt'] != '') { |
| 772 return configuration['drt']; | 749 return configuration['drt']; |
| 773 } | 750 } |
| 774 if (Platform.operatingSystem == 'macos') { | 751 if (Platform.operatingSystem == 'macos') { |
| 775 return '$dartDir/client/tests/drt/DumpRenderTree.app/Contents/' | 752 return dartDir.append('/client/tests/drt/DumpRenderTree.app/Contents/' |
| 776 'MacOS/DumpRenderTree'; | 753 'MacOS/DumpRenderTree').toNativePath(); |
| 777 } | 754 } |
| 778 return '$dartDir/client/tests/drt/DumpRenderTree'; | 755 return dartDir.append('client/tests/drt/DumpRenderTree').toNativePath(); |
| 779 } | 756 } |
| 780 | 757 |
| 781 String get dartiumFilename() { | 758 String get dartiumFilename() { |
| 782 if (configuration['dartium'] != '') { | 759 if (configuration['dartium'] != '') { |
| 783 return configuration['dartium']; | 760 return configuration['dartium']; |
| 784 } | 761 } |
| 785 if (Platform.operatingSystem == 'macos') { | 762 if (Platform.operatingSystem == 'macos') { |
| 786 return '$dartDir/client/tests/dartium/Chromium.app/Contents/' | 763 return dartDir.append('client/tests/dartium/Chromium.app/Contents/' |
| 787 'MacOS/Chromium'; | 764 'MacOS/Chromium').toNativePath(); |
| 788 } | 765 } |
| 789 return '$dartDir/client/tests/dartium/chrome'; | 766 return dartDir.append('client/tests/dartium/chrome').toNativePath(); |
| 790 } | 767 } |
| 791 | 768 |
| 792 void testGeneratorStarted() { | 769 void testGeneratorStarted() { |
| 793 ++activeTestGenerators; | 770 ++activeTestGenerators; |
| 794 } | 771 } |
| 795 | 772 |
| 796 void testGeneratorDone() { | 773 void testGeneratorDone() { |
| 797 --activeTestGenerators; | 774 --activeTestGenerators; |
| 798 if (activeTestGenerators == 0 && listingDone) { | 775 if (activeTestGenerators == 0 && listingDone) { |
| 799 doDone(); | 776 doDone(); |
| 800 } | 777 } |
| 801 } | 778 } |
| 802 | 779 |
| 803 void directoryListingDone(ignore) { | 780 void directoryListingDone(ignore) { |
| 804 listingDone = true; | 781 listingDone = true; |
| 805 if (activeTestGenerators == 0) { | 782 if (activeTestGenerators == 0) { |
| 806 doDone(); | 783 doDone(); |
| 807 } | 784 } |
| 808 } | 785 } |
| 809 | 786 |
| 810 void completeHandler(TestCase testCase) { | 787 void completeHandler(TestCase testCase) { |
| 811 } | 788 } |
| 812 | 789 |
| 813 List<List<String>> argumentListsFromFile(String filename, | 790 List<List<String>> argumentListsFromFile(Path filePath, |
| 814 Map optionsFromFile) { | 791 Map optionsFromFile) { |
| 815 List args = TestUtils.standardOptions(configuration); | 792 List args = TestUtils.standardOptions(configuration); |
| 816 args.addAll(additionalOptions(filename)); | 793 args.addAll(additionalOptions(filePath)); |
| 817 if (configuration['compiler'] == 'dartc') { | 794 if (configuration['compiler'] == 'dartc') { |
| 818 args.add('--error_format'); | 795 args.add('--error_format'); |
| 819 args.add('machine'); | 796 args.add('machine'); |
| 820 } | 797 } |
| 821 if ((configuration['compiler'] == 'frog') | 798 if ((configuration['compiler'] == 'frog') |
| 822 && (configuration['runtime'] == 'none')) { | 799 && (configuration['runtime'] == 'none')) { |
| 823 args.add('--compile-only'); | 800 args.add('--compile-only'); |
| 824 } | 801 } |
| 825 | 802 |
| 826 bool isMultitest = optionsFromFile["isMultitest"]; | 803 bool isMultitest = optionsFromFile["isMultitest"]; |
| 827 List<String> dartOptions = optionsFromFile["dartOptions"]; | 804 List<String> dartOptions = optionsFromFile["dartOptions"]; |
| 828 List<List<String>> vmOptionsList = getVmOptions(optionsFromFile); | 805 List<List<String>> vmOptionsList = getVmOptions(optionsFromFile); |
| 829 Expect.isTrue(!isMultitest || dartOptions == null); | 806 Expect.isTrue(!isMultitest || dartOptions == null); |
| 830 if (dartOptions == null) { | 807 if (dartOptions == null) { |
| 831 args.add(filename); | 808 args.add(filePath.toNativePath()); |
| 832 } else { | 809 } else { |
| 833 var executable_name = dartOptions[0]; | 810 var executable_name = dartOptions[0]; |
| 834 // TODO(ager): Get rid of this hack when the runtime checkout goes away. | 811 // TODO(ager): Get rid of this hack when the runtime checkout goes away. |
| 835 var file = new File(executable_name); | 812 var file = new File(executable_name); |
| 836 if (!file.existsSync()) { | 813 if (!file.existsSync()) { |
| 837 executable_name = '../$executable_name'; | 814 executable_name = '../$executable_name'; |
| 838 Expect.isTrue(new File(executable_name).existsSync()); | 815 Expect.isTrue(new File(executable_name).existsSync()); |
| 839 dartOptions[0] = executable_name; | 816 dartOptions[0] = executable_name; |
| 840 } | 817 } |
| 841 args.addAll(dartOptions); | 818 args.addAll(dartOptions); |
| 842 } | 819 } |
| 843 | 820 |
| 844 var result = new List<List<String>>(); | 821 var result = new List<List<String>>(); |
| 845 Expect.isFalse(vmOptionsList.isEmpty(), "empty vmOptionsList"); | 822 Expect.isFalse(vmOptionsList.isEmpty(), "empty vmOptionsList"); |
| 846 for (var vmOptions in vmOptionsList) { | 823 for (var vmOptions in vmOptionsList) { |
| 847 var options = new List<String>.from(vmOptions); | 824 var options = new List<String>.from(vmOptions); |
| 848 options.addAll(args); | 825 options.addAll(args); |
| 849 result.add(options); | 826 result.add(options); |
| 850 } | 827 } |
| 851 | 828 |
| 852 return result; | 829 return result; |
| 853 } | 830 } |
| 854 | 831 |
| 855 Map readOptionsFromFile(String filename) { | 832 Map readOptionsFromFile(Path filePath) { |
| 856 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); | 833 RegExp testOptionsRegExp = const RegExp(@"// VMOptions=(.*)"); |
| 857 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); | 834 RegExp dartOptionsRegExp = const RegExp(@"// DartOptions=(.*)"); |
| 858 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)"); | 835 RegExp otherScriptsRegExp = const RegExp(@"// OtherScripts=(.*)"); |
| 859 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); | 836 RegExp multiTestRegExp = const RegExp(@"/// [0-9][0-9]:(.*)"); |
| 860 RegExp staticTypeRegExp = | 837 RegExp staticTypeRegExp = |
| 861 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*static type warning"); | 838 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*static type warning"); |
| 862 RegExp compileTimeRegExp = | 839 RegExp compileTimeRegExp = |
| 863 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*compile-time error"); | 840 const RegExp(@"/// ([0-9][0-9]:){0,1}\s*compile-time error"); |
| 864 RegExp staticCleanRegExp = const RegExp(@"// @static-clean"); | 841 RegExp staticCleanRegExp = const RegExp(@"// @static-clean"); |
| 865 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); | 842 RegExp leadingHashRegExp = const RegExp(@"^#", multiLine: true); |
| 866 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); | 843 RegExp isolateStubsRegExp = const RegExp(@"// IsolateStubs=(.*)"); |
| 867 RegExp domImportRegExp = | 844 RegExp domImportRegExp = |
| 868 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", | 845 const RegExp(@"^#import.*(dart:(dom|html)|html\.dart).*\)", |
| 869 multiLine: true); | 846 multiLine: true); |
| 870 RegExp libraryDefinitionRegExp = | 847 RegExp libraryDefinitionRegExp = |
| 871 const RegExp(@"^#library\(", multiLine: true); | 848 const RegExp(@"^#library\(", multiLine: true); |
| 872 RegExp sourceOrImportRegExp = | 849 RegExp sourceOrImportRegExp = |
| 873 const RegExp(@"^#(source|import|resource)\(", multiLine: true); | 850 const RegExp(@"^#(source|import|resource)\(", multiLine: true); |
| 874 | 851 |
| 875 // Read the entire file into a byte buffer and transform it to a | 852 // Read the entire file into a byte buffer and transform it to a |
| 876 // String. This will treat the file as ascii but the only parts | 853 // String. This will treat the file as ascii but the only parts |
| 877 // we are interested in will be ascii in any case. | 854 // we are interested in will be ascii in any case. |
| 878 RandomAccessFile file = new File(filename).openSync(FileMode.READ); | 855 RandomAccessFile file = new File.fromPath(filePath).openSync(FileMode.READ); |
| 879 List chars = new List(file.lengthSync()); | 856 List chars = new List(file.lengthSync()); |
| 880 var offset = 0; | 857 var offset = 0; |
| 881 while (offset != chars.length) { | 858 while (offset != chars.length) { |
| 882 offset += file.readListSync(chars, offset, chars.length - offset); | 859 offset += file.readListSync(chars, offset, chars.length - offset); |
| 883 } | 860 } |
| 884 file.closeSync(); | 861 file.closeSync(); |
| 885 String contents = new String.fromCharCodes(chars); | 862 String contents = new String.fromCharCodes(chars); |
| 886 chars = null; | 863 chars = null; |
| 887 | 864 |
| 888 // Find the options in the file. | 865 // Find the options in the file. |
| 889 List<List> result = new List<List>(); | 866 List<List> result = new List<List>(); |
| 890 List<String> dartOptions; | 867 List<String> dartOptions; |
| 891 bool isNegative = false; | 868 bool isNegative = false; |
| 892 bool isStaticClean = false; | 869 bool isStaticClean = false; |
| 893 | 870 |
| 894 Iterable<Match> matches = testOptionsRegExp.allMatches(contents); | 871 Iterable<Match> matches = testOptionsRegExp.allMatches(contents); |
| 895 for (var match in matches) { | 872 for (var match in matches) { |
| 896 result.add(match[1].split(' ').filter((e) => e != '')); | 873 result.add(match[1].split(' ').filter((e) => e != '')); |
| 897 } | 874 } |
| 898 if (result.isEmpty()) result.add([]); | 875 if (result.isEmpty()) result.add([]); |
| 899 | 876 |
| 900 matches = dartOptionsRegExp.allMatches(contents); | 877 matches = dartOptionsRegExp.allMatches(contents); |
| 901 for (var match in matches) { | 878 for (var match in matches) { |
| 902 if (dartOptions != null) { | 879 if (dartOptions != null) { |
| 903 throw new Exception( | 880 throw new Exception( |
| 904 'More than one "// DartOptions=" line in test $filename'); | 881 'More than one "// DartOptions=" line in test $filePath'); |
| 905 } | 882 } |
| 906 dartOptions = match[1].split(' ').filter((e) => e != ''); | 883 dartOptions = match[1].split(' ').filter((e) => e != ''); |
| 907 } | 884 } |
| 908 | 885 |
| 909 matches = staticCleanRegExp.allMatches(contents); | 886 matches = staticCleanRegExp.allMatches(contents); |
| 910 for (var match in matches) { | 887 for (var match in matches) { |
| 911 if (isStaticClean) { | 888 if (isStaticClean) { |
| 912 throw new Exception( | 889 throw new Exception( |
| 913 'More than one "// @static-clean=" line in test $filename'); | 890 'More than one "// @static-clean=" line in test $filePath'); |
| 914 } | 891 } |
| 915 isStaticClean = true; | 892 isStaticClean = true; |
| 916 } | 893 } |
| 917 | 894 |
| 918 List<String> otherScripts = new List<String>(); | 895 List<String> otherScripts = new List<String>(); |
| 919 matches = otherScriptsRegExp.allMatches(contents); | 896 matches = otherScriptsRegExp.allMatches(contents); |
| 920 for (var match in matches) { | 897 for (var match in matches) { |
| 921 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); | 898 otherScripts.addAll(match[1].split(' ').filter((e) => e != '')); |
| 922 } | 899 } |
| 923 | 900 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 974 List<String> _testDirs; | 951 List<String> _testDirs; |
| 975 int activityCount = 0; | 952 int activityCount = 0; |
| 976 | 953 |
| 977 DartcCompilationTestSuite(Map configuration, | 954 DartcCompilationTestSuite(Map configuration, |
| 978 String suiteName, | 955 String suiteName, |
| 979 String directoryPath, | 956 String directoryPath, |
| 980 List<String> this._testDirs, | 957 List<String> this._testDirs, |
| 981 List<String> expectations) | 958 List<String> expectations) |
| 982 : super(configuration, | 959 : super(configuration, |
| 983 suiteName, | 960 suiteName, |
| 984 directoryPath, | 961 new Path.fromNative(directoryPath), |
| 985 expectations); | 962 expectations); |
| 986 | 963 |
| 987 void activityStarted() { ++activityCount; } | 964 void activityStarted() { ++activityCount; } |
| 988 | 965 |
| 989 void activityCompleted() { | 966 void activityCompleted() { |
| 990 if (--activityCount == 0) { | 967 if (--activityCount == 0) { |
| 991 directoryListingDone(true); | 968 directoryListingDone(true); |
| 992 } | 969 } |
| 993 } | 970 } |
| 994 | 971 |
| 995 String shellPath() => TestUtils.compilerPath(configuration); | 972 String shellPath() => TestUtils.compilerPath(configuration); |
| 996 | 973 |
| 997 List<String> additionalOptions(String filename) { | 974 List<String> additionalOptions(Path filePath) { |
| 998 return ['--fatal-warnings', '--fatal-type-errors']; | 975 return ['--fatal-warnings', '--fatal-type-errors']; |
| 999 } | 976 } |
| 1000 | 977 |
| 1001 void processDirectory() { | 978 void processDirectory() { |
| 1002 directoryPath = '$dartDir/$directoryPath'; | |
| 1003 // Enqueueing the directory listers is an activity. | 979 // Enqueueing the directory listers is an activity. |
| 1004 activityStarted(); | 980 activityStarted(); |
| 1005 for (String testDir in _testDirs) { | 981 for (String testDir in _testDirs) { |
| 1006 Directory dir = new Directory("$directoryPath/$testDir"); | 982 Directory dir = new Directory.fromPath(suiteDir.append(testDir)); |
| 1007 if (dir.existsSync()) { | 983 if (dir.existsSync()) { |
| 1008 activityStarted(); | 984 activityStarted(); |
| 1009 var lister = dir.list(recursive: listRecursively()); | 985 var lister = dir.list(recursive: listRecursively()); |
| 1010 lister.onFile = processFile; | 986 lister.onFile = processFile; |
| 1011 lister.onDone = (ignore) => activityCompleted(); | 987 lister.onDone = (ignore) => activityCompleted(); |
| 1012 } | 988 } |
| 1013 } | 989 } |
| 1014 // Completed the enqueueing of listers. | 990 // Completed the enqueueing of listers. |
| 1015 activityCompleted(); | 991 activityCompleted(); |
| 1016 } | 992 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1027 String classPath; | 1003 String classPath; |
| 1028 List<String> testClasses; | 1004 List<String> testClasses; |
| 1029 Function doTest; | 1005 Function doTest; |
| 1030 Function doDone; | 1006 Function doDone; |
| 1031 TestExpectations testExpectations; | 1007 TestExpectations testExpectations; |
| 1032 | 1008 |
| 1033 JUnitTestSuite(Map this.configuration, | 1009 JUnitTestSuite(Map this.configuration, |
| 1034 String this.suiteName, | 1010 String this.suiteName, |
| 1035 String this.directoryPath, | 1011 String this.directoryPath, |
| 1036 String this.statusFilePath) | 1012 String this.statusFilePath) |
| 1037 : dartDir = TestUtils.dartDir(); | 1013 : dartDir = TestUtils.dartDir().toNativePath(); |
| 1038 | 1014 |
| 1039 bool isTestFile(String filename) => filename.endsWith("Tests.java") && | 1015 bool isTestFile(String filename) => filename.endsWith("Tests.java") && |
| 1040 !filename.contains('com/google/dart/compiler/vm') && | 1016 !filename.contains('com/google/dart/compiler/vm') && |
| 1041 !filename.contains('com/google/dart/corelib/SharedTests.java'); | 1017 !filename.contains('com/google/dart/corelib/SharedTests.java'); |
| 1042 | 1018 |
| 1043 void forEachTest(Function onTest, | 1019 void forEachTest(Function onTest, |
| 1044 Map testCacheIgnored, | 1020 Map testCacheIgnored, |
| 1045 [Function onDone = null]) { | 1021 [Function onDone = null]) { |
| 1046 doTest = onTest; | 1022 doTest = onTest; |
| 1047 doDone = (onDone != null) ? onDone : (() => null); | 1023 doDone = (onDone != null) ? onDone : (() => null); |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1131 ':'); // Path separator. | 1107 ':'); // Path separator. |
| 1132 } | 1108 } |
| 1133 } | 1109 } |
| 1134 | 1110 |
| 1135 | 1111 |
| 1136 class TestUtils { | 1112 class TestUtils { |
| 1137 /** | 1113 /** |
| 1138 * Creates a directory using a [relativePath] to an existing | 1114 * Creates a directory using a [relativePath] to an existing |
| 1139 * [base] directory if that [relativePath] does not already exist. | 1115 * [base] directory if that [relativePath] does not already exist. |
| 1140 */ | 1116 */ |
| 1141 static Directory mkdirRecursive(String base, String relativePath) { | 1117 static Directory mkdirRecursive(Path base, Path relativePath) { |
| 1142 Directory baseDir = new Directory(base); | 1118 Directory dir = new Directory.fromPath(base); |
| 1143 Expect.isTrue(baseDir.existsSync(), | 1119 Expect.isTrue(dir.existsSync(), |
| 1144 "Expected ${base} to already exist"); | 1120 "Expected ${dir} to already exist"); |
| 1145 var tempDir = new Directory(base); | 1121 var segments = relativePath.segments(); |
| 1146 for (String dir in relativePath.split('/')) { | 1122 for (String segment in segments) { |
| 1147 base = "$base/$dir"; | 1123 base = base.append(segment); |
| 1148 tempDir = new Directory(base); | 1124 dir = new Directory.fromPath(base); |
| 1149 if (!tempDir.existsSync()) { | 1125 if (!dir.existsSync()) { |
| 1150 tempDir.createSync(); | 1126 dir.createSync(); |
| 1151 } | 1127 } |
| 1152 Expect.isTrue(tempDir.existsSync(), "Failed to create ${tempDir.path}"); | 1128 Expect.isTrue(dir.existsSync(), "Failed to create ${dir.path}"); |
| 1153 } | 1129 } |
| 1154 return tempDir; | 1130 return dir; |
| 1155 } | 1131 } |
| 1156 | 1132 |
| 1157 /** | 1133 /** |
| 1158 * Copy a [source] file to a new place. | 1134 * Copy a [source] file to a new place. |
| 1159 * Assumes that the directory for [dest] already exists. | 1135 * Assumes that the directory for [dest] already exists. |
| 1160 */ | 1136 */ |
| 1161 static void copyFile(File source, File dest) { | 1137 static Future copyFile(Path source, Path dest) { |
| 1162 List contents = source.readAsBytesSync(); | 1138 var output = new File.fromPath(dest).openOutputStream(); |
| 1163 RandomAccessFile handle = dest.openSync(FileMode.WRITE); | 1139 new File.fromPath(source).openInputStream().pipe(output); |
| 1164 handle.writeListSync(contents, 0, contents.length); | 1140 var completer = new Completer(); |
| 1165 handle.closeSync(); | 1141 output.onClosed = (){ completer.complete(null); }; |
| 1142 return completer.future; |
| 1166 } | 1143 } |
| 1167 | 1144 |
| 1168 static String executableSuffix(String executable) { | 1145 static String executableSuffix(String executable) { |
| 1169 if (Platform.operatingSystem == 'windows') { | 1146 if (Platform.operatingSystem == 'windows') { |
| 1170 if (executable == 'd8' || executable == 'vm' || executable == 'none') { | 1147 if (executable == 'd8' || executable == 'vm' || executable == 'none') { |
| 1171 return '.exe'; | 1148 return '.exe'; |
| 1172 } else { | 1149 } else { |
| 1173 return '.bat'; | 1150 return '.bat'; |
| 1174 } | 1151 } |
| 1175 } | 1152 } |
| (...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1260 } | 1237 } |
| 1261 return result; | 1238 return result; |
| 1262 } | 1239 } |
| 1263 | 1240 |
| 1264 static String buildDir(Map configuration) { | 1241 static String buildDir(Map configuration) { |
| 1265 String mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release'; | 1242 String mode = (configuration['mode'] == 'debug') ? 'Debug' : 'Release'; |
| 1266 String arch = configuration['arch'].toUpperCase(); | 1243 String arch = configuration['arch'].toUpperCase(); |
| 1267 return "${outputDir(configuration)}$mode$arch"; | 1244 return "${outputDir(configuration)}$mode$arch"; |
| 1268 } | 1245 } |
| 1269 | 1246 |
| 1270 static String dartDir() { | 1247 static Path dartDir() { |
| 1271 String scriptPath = new Options().script.replaceAll('\\', '/'); | 1248 File scriptFile = new File(new Options().script); |
| 1272 String toolsDir = scriptPath.substring(0, scriptPath.lastIndexOf('/')); | 1249 Path scriptPath = new Path.fromNative(scriptFile.fullPathSync()); |
| 1273 return new File('$toolsDir/..').fullPathSync().replaceAll('\\', '/'); | 1250 return scriptPath.directoryPath.directoryPath; |
| 1274 } | 1251 } |
| 1275 | 1252 |
| 1276 static List<String> standardOptions(Map configuration) { | 1253 static List<String> standardOptions(Map configuration) { |
| 1277 List args = ["--ignore-unrecognized-flags"]; | 1254 List args = ["--ignore-unrecognized-flags"]; |
| 1278 if (configuration["checked"]) { | 1255 if (configuration["checked"]) { |
| 1279 args.add('--enable_asserts'); | 1256 args.add('--enable_asserts'); |
| 1280 args.add("--enable_type_checks"); | 1257 args.add("--enable_type_checks"); |
| 1281 } | 1258 } |
| 1282 if (configuration["compiler"] == "dart2js") { | 1259 if (configuration["compiler"] == "dart2js") { |
| 1283 args = []; | 1260 args = []; |
| 1284 if (configuration["checked"]) { | 1261 if (configuration["checked"]) { |
| 1285 args.add('--enable-checked-mode'); | 1262 args.add('--enable-checked-mode'); |
| 1286 } | 1263 } |
| 1287 args.add("--verbose"); | 1264 args.add("--verbose"); |
| 1288 if (!isBrowserRuntime(configuration['runtime'])) { | 1265 if (!isBrowserRuntime(configuration['runtime'])) { |
| 1289 args.add("--allow-mock-compilation"); | 1266 args.add("--allow-mock-compilation"); |
| 1290 } | 1267 } |
| 1291 } | 1268 } |
| 1292 return args; | 1269 return args; |
| 1293 } | 1270 } |
| 1294 | 1271 |
| 1295 static bool isBrowserRuntime(String runtime) => | 1272 static bool isBrowserRuntime(String runtime) => |
| 1296 const <String>['drt', | 1273 const <String>['drt', |
| 1297 'dartium', | 1274 'dartium', |
| 1298 'ie', | 1275 'ie', |
| 1299 'safari', | 1276 'safari', |
| 1300 'opera', | 1277 'opera', |
| 1301 'chrome', | 1278 'chrome', |
| 1302 'ff'].some((x) => x == runtime); | 1279 'ff'].indexOf(runtime) != -1; |
| 1303 } | 1280 } |
| 1304 | 1281 |
| 1305 class SummaryReport { | 1282 class SummaryReport { |
| 1306 static int total = 0; | 1283 static int total = 0; |
| 1307 static int skipped = 0; | 1284 static int skipped = 0; |
| 1308 static int noCrash = 0; | 1285 static int noCrash = 0; |
| 1309 static int pass = 0; | 1286 static int pass = 0; |
| 1310 static int failOk = 0; | 1287 static int failOk = 0; |
| 1311 static int fail = 0; | 1288 static int fail = 0; |
| 1312 static int crash = 0; | 1289 static int crash = 0; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1346 * $noCrash tests are expected to be flaky but not crash | 1323 * $noCrash tests are expected to be flaky but not crash |
| 1347 * $pass tests are expected to pass | 1324 * $pass tests are expected to pass |
| 1348 * $failOk tests are expected to fail that we won't fix | 1325 * $failOk tests are expected to fail that we won't fix |
| 1349 * $fail tests are expected to fail that we should fix | 1326 * $fail tests are expected to fail that we should fix |
| 1350 * $crash tests are expected to crash that we should fix | 1327 * $crash tests are expected to crash that we should fix |
| 1351 * $timeout tests are allowed to timeout | 1328 * $timeout tests are allowed to timeout |
| 1352 """; | 1329 """; |
| 1353 print(report); | 1330 print(report); |
| 1354 } | 1331 } |
| 1355 } | 1332 } |
| OLD | NEW |