| 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 * Test infrastructure for testing pub. Unlike typical unit tests, most pub | 6 * Test infrastructure for testing pub. Unlike typical unit tests, most pub |
| 7 * tests are integration tests that stage some stuff on the file system, run | 7 * tests are integration tests that stage some stuff on the file system, run |
| 8 * pub, and then validate the results. This library provides an API to build | 8 * pub, and then validate the results. This library provides an API to build |
| 9 * tests like that. | 9 * tests like that. |
| 10 */ | 10 */ |
| (...skipping 427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 438 */ | 438 */ |
| 439 final String appPath = "myapp"; | 439 final String appPath = "myapp"; |
| 440 | 440 |
| 441 /** | 441 /** |
| 442 * The path of the packages directory in the mock app used for tests. Relative | 442 * The path of the packages directory in the mock app used for tests. Relative |
| 443 * to the sandbox directory. | 443 * to the sandbox directory. |
| 444 */ | 444 */ |
| 445 final String packagesPath = "$appPath/packages"; | 445 final String packagesPath = "$appPath/packages"; |
| 446 | 446 |
| 447 /** | 447 /** |
| 448 * The path to the build directory of the Dart repository. This is only set if | |
| 449 * [ensureBuild] has been run for this test. | |
| 450 */ | |
| 451 String _buildPath; | |
| 452 | |
| 453 /** | |
| 454 * The type for callbacks that will be fired during [runPub]. Takes the sandbox | 448 * The type for callbacks that will be fired during [runPub]. Takes the sandbox |
| 455 * directory as a parameter. | 449 * directory as a parameter. |
| 456 */ | 450 */ |
| 457 typedef Future _ScheduledEvent(Directory parentDir); | 451 typedef Future _ScheduledEvent(Directory parentDir); |
| 458 | 452 |
| 459 /** | 453 /** |
| 460 * The list of events that are scheduled to run as part of the test case. | 454 * The list of events that are scheduled to run as part of the test case. |
| 461 */ | 455 */ |
| 462 List<_ScheduledEvent> _scheduled; | 456 List<_ScheduledEvent> _scheduled; |
| 463 | 457 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 508 } | 502 } |
| 509 | 503 |
| 510 /// Get the path to the root "util/test/pub" directory containing the pub tests. | 504 /// Get the path to the root "util/test/pub" directory containing the pub tests. |
| 511 String get testDirectory { | 505 String get testDirectory { |
| 512 var dir = new Path.fromNative(new Options().script); | 506 var dir = new Path.fromNative(new Options().script); |
| 513 while (dir.filename != 'pub') dir = dir.directoryPath; | 507 while (dir.filename != 'pub') dir = dir.directoryPath; |
| 514 | 508 |
| 515 return new File(dir.toNativePath()).fullPathSync(); | 509 return new File(dir.toNativePath()).fullPathSync(); |
| 516 } | 510 } |
| 517 | 511 |
| 518 /// Whether the tests are running on a build bot. | |
| 519 bool get onBuildBot => Platform.environment.containsKey('BUILDBOT_BUILDERNAME'); | |
| 520 | |
| 521 /** | 512 /** |
| 522 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and | 513 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and |
| 523 * validates that its results match [output], [error], and [exitCode]. | 514 * validates that its results match [output], [error], and [exitCode]. |
| 524 * | |
| 525 * If [realSdk] is true, runs Pub against the real Dart SDK. [ensureBuild] must | |
| 526 * be called before this method if [realSdk] is true. | |
| 527 */ | 515 */ |
| 528 void schedulePub({List<String> args, Pattern output, Pattern error, | 516 void schedulePub({List<String> args, Pattern output, Pattern error, |
| 529 int exitCode: 0, bool realSdk: false}) { | 517 int exitCode: 0}) { |
| 530 _schedule((sandboxDir) { | 518 _schedule((sandboxDir) { |
| 531 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); | 519 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); |
| 532 | 520 |
| 533 return ensureDir(pathInSandbox(appPath)).chain((_) { | 521 return ensureDir(pathInSandbox(appPath)).chain((_) { |
| 534 // Find a Dart executable we can use to spawn. Use the same one that was | 522 // Find a Dart executable we can use to spawn. Use the same one that was |
| 535 // used to run this script itself. | 523 // used to run this script itself. |
| 536 var dartBin = new Options().executable; | 524 var dartBin = new Options().executable; |
| 537 | 525 |
| 538 // If the executable looks like a path, get its full path. That way we | 526 // If the executable looks like a path, get its full path. That way we |
| 539 // can still find it when we spawn it with a different working directory. | 527 // can still find it when we spawn it with a different working directory. |
| 540 if (dartBin.contains(Platform.pathSeparator)) { | 528 if (dartBin.contains(Platform.pathSeparator)) { |
| 541 dartBin = new File(dartBin).fullPathSync(); | 529 dartBin = new File(dartBin).fullPathSync(); |
| 542 } | 530 } |
| 543 | 531 |
| 544 // Find the main pub entrypoint. | 532 // Find the main pub entrypoint. |
| 545 var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart'); | 533 var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart'); |
| 546 | 534 |
| 547 var dartArgs = | 535 var dartArgs = |
| 548 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace']; | 536 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace']; |
| 549 dartArgs.addAll(args); | 537 dartArgs.addAll(args); |
| 550 | 538 |
| 551 var environment = new Map.from(Platform.environment); | 539 var environment = new Map.from(Platform.environment); |
| 552 environment['PUB_CACHE'] = pathInSandbox(cachePath); | 540 environment['PUB_CACHE'] = pathInSandbox(cachePath); |
| 553 if (realSdk) { | 541 environment['DART_SDK'] = pathInSandbox(sdkPath); |
| 554 if (_buildPath == null) { | |
| 555 throw "Test error: expected a Dart build directory to exist."; | |
| 556 } | |
| 557 environment['DART_SDK'] = join(_buildPath, "dart-sdk"); | |
| 558 } else { | |
| 559 environment['DART_SDK'] = pathInSandbox(sdkPath); | |
| 560 } | |
| 561 | 542 |
| 562 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath), | 543 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath), |
| 563 environment: environment); | 544 environment: environment); |
| 564 }).transform((result) { | 545 }).transform((result) { |
| 565 var failures = []; | 546 var failures = []; |
| 566 | 547 |
| 567 _validateOutput(failures, 'stdout', output, result.stdout); | 548 _validateOutput(failures, 'stdout', output, result.stdout); |
| 568 _validateOutput(failures, 'stderr', error, result.stderr); | 549 _validateOutput(failures, 'stderr', error, result.stderr); |
| 569 | 550 |
| 570 if (result.exitCode != exitCode) { | 551 if (result.exitCode != exitCode) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 601 * Skips the current test if Git is not installed. This validates that the | 582 * Skips the current test if Git is not installed. This validates that the |
| 602 * current test is running on a buildbot in which case we expect git to be | 583 * current test is running on a buildbot in which case we expect git to be |
| 603 * installed. If we are not running on the buildbot, we will instead see if git | 584 * installed. If we are not running on the buildbot, we will instead see if git |
| 604 * is installed and skip the test if not. This way, users don't need to have git | 585 * is installed and skip the test if not. This way, users don't need to have git |
| 605 * installed to run the tests locally (unless they actually care about the pub | 586 * installed to run the tests locally (unless they actually care about the pub |
| 606 * git tests). | 587 * git tests). |
| 607 */ | 588 */ |
| 608 void ensureGit() { | 589 void ensureGit() { |
| 609 _schedule((_) { | 590 _schedule((_) { |
| 610 return isGitInstalled.transform((installed) { | 591 return isGitInstalled.transform((installed) { |
| 611 if (!installed && !onBuildBot) { | 592 if (!installed && |
| 593 !Platform.environment.containsKey('BUILDBOT_BUILDERNAME')) { |
| 612 _abortScheduled = true; | 594 _abortScheduled = true; |
| 613 } | 595 } |
| 614 return null; | 596 return null; |
| 615 }); | 597 }); |
| 616 }); | 598 }); |
| 617 } | 599 } |
| 618 | 600 |
| 619 /// Skips the current test if the Dart repository's build step has not been run. | |
| 620 /// If we're running on a build bot, this will not skip the test. | |
| 621 /// | |
| 622 /// This ensures that users don't need to have built Dart themselves to run the | |
| 623 /// test, but that the test will always run on the build bot. | |
| 624 void ensureBuild() { | |
| 625 _schedule((_) { | |
| 626 return _findBuildDirectory().transform((dir) { | |
| 627 if (dir == null && !onBuildBot) { | |
| 628 _abortScheduled = true; | |
| 629 } | |
| 630 }); | |
| 631 }); | |
| 632 } | |
| 633 | |
| 634 /// All possible names for the output directory of the Dart build. | |
| 635 final List<String> _buildNames = [ | |
| 636 'ReleaseIA32', 'DebugIA32', 'ReleaseX64', 'DebugX64', 'ReleaseSIMARM', | |
| 637 'DebugSIMARM', 'ReleaseARM', 'DebugARM' | |
| 638 ]; | |
| 639 | |
| 640 /// All possible names for the parent directory of the Dart build. | |
| 641 final Map<String, String> _buildParentNames = { | |
| 642 'mac': 'xcodebuild', 'linux': 'out', 'windows': 'build' | |
| 643 }; | |
| 644 | |
| 645 /// Returns the path to the output directory of the Dart build, or null if none | |
| 646 /// is found. This also sets [_buildPath] if a build directory is found. | |
| 647 Future<String> _findBuildDirectory() { | |
| 648 if (_buildPath != null) return new Future.immediate(_buildPath); | |
| 649 | |
| 650 var buildDirectories = flatten(_buildNames.map((name) { | |
| 651 var parent = _buildParentNames[Platform.operatingSystem]; | |
| 652 return join(testDirectory, '../../..', parent, name); | |
| 653 })); | |
| 654 | |
| 655 return Futures.wait(buildDirectories.map(dirExists)).transform((found) { | |
| 656 for (var i = 0; i < found.length; i++) { | |
| 657 if (found[i]) { | |
| 658 _buildPath = buildDirectories[i]; | |
| 659 return _buildPath; | |
| 660 } | |
| 661 } | |
| 662 return null; | |
| 663 }); | |
| 664 } | |
| 665 | |
| 666 Future<Directory> _setUpSandbox() { | 601 Future<Directory> _setUpSandbox() { |
| 667 return createTempDir(); | 602 return createTempDir(); |
| 668 } | 603 } |
| 669 | 604 |
| 670 Future _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { | 605 Future _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { |
| 671 if (scheduled == null) return new Future.immediate(null); | 606 if (scheduled == null) return new Future.immediate(null); |
| 672 var iterator = scheduled.iterator(); | 607 var iterator = scheduled.iterator(); |
| 673 | 608 |
| 674 Future runNextEvent(_) { | 609 Future runNextEvent(_) { |
| 675 if (_abortScheduled || !iterator.hasNext()) { | 610 if (_abortScheduled || !iterator.hasNext()) { |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1267 } | 1202 } |
| 1268 | 1203 |
| 1269 /** | 1204 /** |
| 1270 * Schedules a callback to be called after Pub is run with [runPub], even if it | 1205 * Schedules a callback to be called after Pub is run with [runPub], even if it |
| 1271 * fails. | 1206 * fails. |
| 1272 */ | 1207 */ |
| 1273 void _scheduleCleanup(_ScheduledEvent event) { | 1208 void _scheduleCleanup(_ScheduledEvent event) { |
| 1274 if (_scheduledCleanup == null) _scheduledCleanup = []; | 1209 if (_scheduledCleanup == null) _scheduledCleanup = []; |
| 1275 _scheduledCleanup.add(event); | 1210 _scheduledCleanup.add(event); |
| 1276 } | 1211 } |
| OLD | NEW |