| 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 /** |
| 448 * The type for callbacks that will be fired during [runPub]. Takes the sandbox | 454 * The type for callbacks that will be fired during [runPub]. Takes the sandbox |
| 449 * directory as a parameter. | 455 * directory as a parameter. |
| 450 */ | 456 */ |
| 451 typedef Future _ScheduledEvent(Directory parentDir); | 457 typedef Future _ScheduledEvent(Directory parentDir); |
| 452 | 458 |
| 453 /** | 459 /** |
| 454 * The list of events that are scheduled to run as part of the test case. | 460 * The list of events that are scheduled to run as part of the test case. |
| 455 */ | 461 */ |
| 456 List<_ScheduledEvent> _scheduled; | 462 List<_ScheduledEvent> _scheduled; |
| 457 | 463 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 502 } | 508 } |
| 503 | 509 |
| 504 /// Get the path to the root "util/test/pub" directory containing the pub tests. | 510 /// Get the path to the root "util/test/pub" directory containing the pub tests. |
| 505 String get testDirectory { | 511 String get testDirectory { |
| 506 var dir = new Path.fromNative(new Options().script); | 512 var dir = new Path.fromNative(new Options().script); |
| 507 while (dir.filename != 'pub') dir = dir.directoryPath; | 513 while (dir.filename != 'pub') dir = dir.directoryPath; |
| 508 | 514 |
| 509 return new File(dir.toNativePath()).fullPathSync(); | 515 return new File(dir.toNativePath()).fullPathSync(); |
| 510 } | 516 } |
| 511 | 517 |
| 518 /// Whether the tests are running on a build bot. |
| 519 bool get onBuildBot => Platform.environment.containsKey('BUILDBOT_BUILDERNAME'); |
| 520 |
| 512 /** | 521 /** |
| 513 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and | 522 * Schedules a call to the Pub command-line utility. Runs Pub with [args] and |
| 514 * validates that its results match [output], [error], and [exitCode]. | 523 * 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. |
| 515 */ | 527 */ |
| 516 void schedulePub({List<String> args, Pattern output, Pattern error, | 528 void schedulePub({List<String> args, Pattern output, Pattern error, |
| 517 int exitCode: 0}) { | 529 int exitCode: 0, bool realSdk: false}) { |
| 518 _schedule((sandboxDir) { | 530 _schedule((sandboxDir) { |
| 519 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); | 531 String pathInSandbox(path) => join(getFullPath(sandboxDir), path); |
| 520 | 532 |
| 521 return ensureDir(pathInSandbox(appPath)).chain((_) { | 533 return ensureDir(pathInSandbox(appPath)).chain((_) { |
| 522 // Find a Dart executable we can use to spawn. Use the same one that was | 534 // Find a Dart executable we can use to spawn. Use the same one that was |
| 523 // used to run this script itself. | 535 // used to run this script itself. |
| 524 var dartBin = new Options().executable; | 536 var dartBin = new Options().executable; |
| 525 | 537 |
| 526 // If the executable looks like a path, get its full path. That way we | 538 // If the executable looks like a path, get its full path. That way we |
| 527 // can still find it when we spawn it with a different working directory. | 539 // can still find it when we spawn it with a different working directory. |
| 528 if (dartBin.contains(Platform.pathSeparator)) { | 540 if (dartBin.contains(Platform.pathSeparator)) { |
| 529 dartBin = new File(dartBin).fullPathSync(); | 541 dartBin = new File(dartBin).fullPathSync(); |
| 530 } | 542 } |
| 531 | 543 |
| 532 // Find the main pub entrypoint. | 544 // Find the main pub entrypoint. |
| 533 var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart'); | 545 var pubPath = fs.joinPaths(testDirectory, '../../pub/pub.dart'); |
| 534 | 546 |
| 535 var dartArgs = | 547 var dartArgs = |
| 536 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace']; | 548 ['--enable-type-checks', '--enable-asserts', pubPath, '--trace']; |
| 537 dartArgs.addAll(args); | 549 dartArgs.addAll(args); |
| 538 | 550 |
| 539 var environment = new Map.from(Platform.environment); | 551 var environment = new Map.from(Platform.environment); |
| 540 environment['PUB_CACHE'] = pathInSandbox(cachePath); | 552 environment['PUB_CACHE'] = pathInSandbox(cachePath); |
| 541 environment['DART_SDK'] = pathInSandbox(sdkPath); | 553 if (realSdk) { |
| 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 } |
| 542 | 561 |
| 543 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath), | 562 return runProcess(dartBin, dartArgs, workingDir: pathInSandbox(appPath), |
| 544 environment: environment); | 563 environment: environment); |
| 545 }).transform((result) { | 564 }).transform((result) { |
| 546 var failures = []; | 565 var failures = []; |
| 547 | 566 |
| 548 _validateOutput(failures, 'stdout', output, result.stdout); | 567 _validateOutput(failures, 'stdout', output, result.stdout); |
| 549 _validateOutput(failures, 'stderr', error, result.stderr); | 568 _validateOutput(failures, 'stderr', error, result.stderr); |
| 550 | 569 |
| 551 if (result.exitCode != exitCode) { | 570 if (result.exitCode != exitCode) { |
| (...skipping 30 matching lines...) Expand all Loading... |
| 582 * Skips the current test if Git is not installed. This validates that the | 601 * Skips the current test if Git is not installed. This validates that the |
| 583 * current test is running on a buildbot in which case we expect git to be | 602 * current test is running on a buildbot in which case we expect git to be |
| 584 * installed. If we are not running on the buildbot, we will instead see if git | 603 * installed. If we are not running on the buildbot, we will instead see if git |
| 585 * is installed and skip the test if not. This way, users don't need to have git | 604 * is installed and skip the test if not. This way, users don't need to have git |
| 586 * installed to run the tests locally (unless they actually care about the pub | 605 * installed to run the tests locally (unless they actually care about the pub |
| 587 * git tests). | 606 * git tests). |
| 588 */ | 607 */ |
| 589 void ensureGit() { | 608 void ensureGit() { |
| 590 _schedule((_) { | 609 _schedule((_) { |
| 591 return isGitInstalled.transform((installed) { | 610 return isGitInstalled.transform((installed) { |
| 592 if (!installed && | 611 if (!installed && !onBuildBot) { |
| 593 !Platform.environment.containsKey('BUILDBOT_BUILDERNAME')) { | |
| 594 _abortScheduled = true; | 612 _abortScheduled = true; |
| 595 } | 613 } |
| 596 return null; | 614 return null; |
| 597 }); | 615 }); |
| 598 }); | 616 }); |
| 599 } | 617 } |
| 600 | 618 |
| 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 |
| 601 Future<Directory> _setUpSandbox() { | 666 Future<Directory> _setUpSandbox() { |
| 602 return createTempDir(); | 667 return createTempDir(); |
| 603 } | 668 } |
| 604 | 669 |
| 605 Future _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { | 670 Future _runScheduled(Directory parentDir, List<_ScheduledEvent> scheduled) { |
| 606 if (scheduled == null) return new Future.immediate(null); | 671 if (scheduled == null) return new Future.immediate(null); |
| 607 var iterator = scheduled.iterator(); | 672 var iterator = scheduled.iterator(); |
| 608 | 673 |
| 609 Future runNextEvent(_) { | 674 Future runNextEvent(_) { |
| 610 if (_abortScheduled || !iterator.hasNext()) { | 675 if (_abortScheduled || !iterator.hasNext()) { |
| (...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1202 } | 1267 } |
| 1203 | 1268 |
| 1204 /** | 1269 /** |
| 1205 * Schedules a callback to be called after Pub is run with [runPub], even if it | 1270 * Schedules a callback to be called after Pub is run with [runPub], even if it |
| 1206 * fails. | 1271 * fails. |
| 1207 */ | 1272 */ |
| 1208 void _scheduleCleanup(_ScheduledEvent event) { | 1273 void _scheduleCleanup(_ScheduledEvent event) { |
| 1209 if (_scheduledCleanup == null) _scheduledCleanup = []; | 1274 if (_scheduledCleanup == null) _scheduledCleanup = []; |
| 1210 _scheduledCleanup.add(event); | 1275 _scheduledCleanup.add(event); |
| 1211 } | 1276 } |
| OLD | NEW |