OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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 import 'dart:io'; | 5 import 'dart:io'; |
6 import 'drt_updater.dart'; | 6 import 'drt_updater.dart'; |
7 import 'test_suite.dart'; | 7 import 'test_suite.dart'; |
8 import 'path.dart'; | 8 import 'path.dart'; |
9 import 'compiler_configuration.dart' show CompilerConfiguration; | 9 import 'compiler_configuration.dart' show CompilerConfiguration; |
10 import 'runtime_configuration.dart' show RuntimeConfiguration; | 10 import 'runtime_configuration.dart' show RuntimeConfiguration; |
(...skipping 379 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
390 'write_debug_log', | 390 'write_debug_log', |
391 'write_test_outcome_log', | 391 'write_test_outcome_log', |
392 ].toSet(); | 392 ].toSet(); |
393 | 393 |
394 /// Parses a list of strings as test options. | 394 /// Parses a list of strings as test options. |
395 /// | 395 /// |
396 /// Returns a list of configurations in which to run the tests. | 396 /// Returns a list of configurations in which to run the tests. |
397 /// Configurations are maps mapping from option keys to values. When | 397 /// Configurations are maps mapping from option keys to values. When |
398 /// encountering the first non-option string, the rest of the arguments are | 398 /// encountering the first non-option string, the rest of the arguments are |
399 /// stored in the returned Map under the 'rest' key. | 399 /// stored in the returned Map under the 'rest' key. |
400 List<Map> parse(List<String> arguments) { | 400 List<Map<String, dynamic>> parse(List<String> arguments) { |
401 // TODO(rnystrom): The builders on the buildbots still pass this even | 401 // TODO(rnystrom): The builders on the buildbots still pass this even |
402 // though it does nothing. Until those can be fixed, silently ignore the | 402 // though it does nothing. Until those can be fixed, silently ignore the |
403 // option. Remove this once the buildbot scripts are fixed. | 403 // option. Remove this once the buildbot scripts are fixed. |
404 if (arguments.contains("--failure-summary")) { | 404 if (arguments.contains("--failure-summary")) { |
405 arguments = arguments.where((arg) => arg != "--failure-summary").toList(); | 405 arguments = arguments.where((arg) => arg != "--failure-summary").toList(); |
406 print('Note: Ignoring unsupported "--failure-summary" option.'); | 406 print('Note: Ignoring unsupported "--failure-summary" option.'); |
407 } | 407 } |
408 | 408 |
409 var configuration = {}; | 409 var configuration = <String, dynamic>{}; |
410 | 410 |
411 // Fill in configuration with arguments passed to the test script. | 411 // Fill in configuration with arguments passed to the test script. |
412 for (var i = 0; i < arguments.length; i++) { | 412 for (var i = 0; i < arguments.length; i++) { |
413 var arg = arguments[i]; | 413 var arg = arguments[i]; |
414 | 414 |
415 // Help supersedes all other arguments. | 415 // Help supersedes all other arguments. |
416 if (arg == "--help" || arg == "-h") { | 416 if (arg == "--help" || arg == "-h") { |
417 _printHelp(); | 417 _printHelp(); |
418 return null; | 418 return null; |
419 } | 419 } |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
558 } | 558 } |
559 | 559 |
560 return arguments; | 560 return arguments; |
561 } | 561 } |
562 | 562 |
563 /// Determines if a particular configuration has a valid combination of | 563 /// Determines if a particular configuration has a valid combination of |
564 /// compiler and runtime elements. | 564 /// compiler and runtime elements. |
565 bool _isValidConfig(Map config) { | 565 bool _isValidConfig(Map config) { |
566 var isValid = true; | 566 var isValid = true; |
567 List<String> validRuntimes; | 567 List<String> validRuntimes; |
568 switch (config['compiler']) { | 568 switch (config['compiler'] as String) { |
569 case 'dart2js': | 569 case 'dart2js': |
570 // Note: by adding 'none' as a configuration, if the user | 570 // Note: by adding 'none' as a configuration, if the user |
571 // runs test.py -c dart2js -r drt,none the dart2js_none and | 571 // runs test.py -c dart2js -r drt,none the dart2js_none and |
572 // dart2js_drt will be duplicating work. If later we don't need 'none' | 572 // dart2js_drt will be duplicating work. If later we don't need 'none' |
573 // with dart2js, we should remove it from here. | 573 // with dart2js, we should remove it from here. |
574 validRuntimes = const [ | 574 validRuntimes = const [ |
575 'd8', | 575 'd8', |
576 'jsshell', | 576 'jsshell', |
577 'drt', | 577 'drt', |
578 'none', | 578 'none', |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
611 break; | 611 break; |
612 } | 612 } |
613 | 613 |
614 if (!validRuntimes.contains(config['runtime'])) { | 614 if (!validRuntimes.contains(config['runtime'])) { |
615 isValid = false; | 615 isValid = false; |
616 print("Warning: combination of compiler '${config['compiler']}' and " | 616 print("Warning: combination of compiler '${config['compiler']}' and " |
617 "runtime '${config['runtime']}' is invalid. " | 617 "runtime '${config['runtime']}' is invalid. " |
618 "Skipping this combination."); | 618 "Skipping this combination."); |
619 } | 619 } |
620 | 620 |
621 if (config['ie'] && Platform.operatingSystem != 'windows') { | 621 if ((config['ie'] as bool) && Platform.operatingSystem != 'windows') { |
622 isValid = false; | 622 isValid = false; |
623 print("Warning: cannot run Internet Explorer on non-Windows operating" | 623 print("Warning: cannot run Internet Explorer on non-Windows operating" |
624 " system."); | 624 " system."); |
625 } | 625 } |
626 | 626 |
627 if (config['shard'] < 1 || config['shard'] > config['shards']) { | 627 if ((config['shard'] as int) < 1 || |
| 628 (config['shard'] as int) > (config['shards'] as int)) { |
628 isValid = false; | 629 isValid = false; |
629 print("Error: shard index is ${config['shard']} out of " | 630 print("Error: shard index is ${config['shard']} out of " |
630 "${config['shards']} shards"); | 631 "${config['shards']} shards"); |
631 } | 632 } |
632 | 633 |
633 if (config['runtime'] == 'flutter' && config['flutter'] == '') { | 634 if (config['runtime'] == 'flutter' && config['flutter'] == '') { |
634 isValid = false; | 635 isValid = false; |
635 print("-rflutter requires the flutter engine executable to " | 636 print("-rflutter requires the flutter engine executable to " |
636 "be specified using --flutter="); | 637 "be specified using --flutter="); |
637 } | 638 } |
638 | 639 |
639 if (config['runtime'] == 'flutter' && config['arch'] != 'x64') { | 640 if (config['runtime'] == 'flutter' && config['arch'] != 'x64') { |
640 isValid = false; | 641 isValid = false; |
641 print("-rflutter is applicable only for --arch=x64"); | 642 print("-rflutter is applicable only for --arch=x64"); |
642 } | 643 } |
643 | 644 |
644 return isValid; | 645 return isValid; |
645 } | 646 } |
646 | 647 |
647 /// Recursively expands a configuration with multiple values per key into a | 648 /// Recursively expands a configuration with multiple values per key into a |
648 /// list of configurations with exactly one value per key. | 649 /// list of configurations with exactly one value per key. |
649 List<Map> _expandConfigurations(Map configuration) { | 650 List<Map<String, dynamic>> _expandConfigurations( |
| 651 Map<String, dynamic> configuration) { |
650 // Expand the pseudo-values such as 'all'. | 652 // Expand the pseudo-values such as 'all'. |
651 if (configuration['arch'] == 'all') { | 653 if (configuration['arch'] == 'all') { |
652 configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips,simdbc64'; | 654 configuration['arch'] = 'ia32,x64,simarm,simarm64,simmips,simdbc64'; |
653 } | 655 } |
654 | 656 |
655 if (configuration['mode'] == 'all') { | 657 if (configuration['mode'] == 'all') { |
656 configuration['mode'] = 'debug,release,product'; | 658 configuration['mode'] = 'debug,release,product'; |
657 } | 659 } |
658 | 660 |
659 if (configuration['report_in_json']) { | 661 if (configuration['report_in_json'] as bool) { |
660 configuration['list'] = true; | 662 configuration['list'] = true; |
661 configuration['report'] = true; | 663 configuration['report'] = true; |
662 } | 664 } |
663 | 665 |
664 // Use verbose progress indication for verbose output unless buildbot | 666 // Use verbose progress indication for verbose output unless buildbot |
665 // progress indication is requested. | 667 // progress indication is requested. |
666 if (configuration['verbose'] && configuration['progress'] != 'buildbot') { | 668 if ((configuration['verbose'] as bool) && |
| 669 (configuration['progress'] as String) != 'buildbot') { |
667 configuration['progress'] = 'verbose'; | 670 configuration['progress'] = 'verbose'; |
668 } | 671 } |
669 | 672 |
670 // Create the artificial negative options that test status files | 673 // Create the artificial negative options that test status files |
671 // expect. | 674 // expect. |
672 configuration['unchecked'] = !configuration['checked']; | 675 configuration['unchecked'] = !(configuration['checked'] as bool); |
673 configuration['host_unchecked'] = !configuration['host_checked']; | 676 configuration['host_unchecked'] = !(configuration['host_checked'] as bool); |
674 configuration['unminified'] = !configuration['minified']; | 677 configuration['unminified'] = !(configuration['minified'] as bool); |
675 configuration['nocsp'] = !configuration['csp']; | 678 configuration['nocsp'] = !(configuration['csp'] as bool); |
676 | 679 |
677 String runtime = configuration['runtime']; | 680 var runtime = configuration['runtime'] as String; |
678 if (runtime == 'firefox') { | 681 if (runtime == 'firefox') { |
679 configuration['runtime'] == 'ff'; | 682 configuration['runtime'] == 'ff'; |
680 } | 683 } |
681 | 684 |
682 String compiler = configuration['compiler']; | 685 var compiler = configuration['compiler'] as String; |
683 configuration['browser'] = TestUtils.isBrowserRuntime(runtime); | 686 configuration['browser'] = TestUtils.isBrowserRuntime(runtime); |
684 configuration['analyzer'] = TestUtils.isCommandLineAnalyzer(compiler); | 687 configuration['analyzer'] = TestUtils.isCommandLineAnalyzer(compiler); |
685 | 688 |
686 // Set the javascript command line flag for less verbose status files. | 689 // Set the javascript command line flag for less verbose status files. |
687 configuration['jscl'] = TestUtils.isJsCommandLineRuntime(runtime); | 690 configuration['jscl'] = TestUtils.isJsCommandLineRuntime(runtime); |
688 | 691 |
689 // Allow suppression that is valid for all ie versions | 692 // Allow suppression that is valid for all ie versions |
690 configuration['ie'] = runtime.startsWith('ie'); | 693 configuration['ie'] = runtime.startsWith('ie'); |
691 | 694 |
692 // Expand the test selectors into a suite name and a simple | 695 // Expand the test selectors into a suite name and a simple |
693 // regular expressions to be used on the full path of a test file | 696 // regular expressions to be used on the full path of a test file |
694 // in that test suite. If no selectors are explicitly given use | 697 // in that test suite. If no selectors are explicitly given use |
695 // the default suite patterns. | 698 // the default suite patterns. |
696 var selectors = configuration['selectors']; | 699 var selectors = configuration['selectors']; |
697 if (selectors is! Map) { | 700 if (selectors is! Map) { |
698 if (selectors == null) { | 701 if (selectors == null) { |
699 if (configuration['suite_dir'] != null) { | 702 if (configuration['suite_dir'] != null) { |
700 var suite_path = new Path(configuration['suite_dir']); | 703 var suite_path = new Path(configuration['suite_dir'] as String); |
701 selectors = [suite_path.filename]; | 704 selectors = [suite_path.filename]; |
702 } else { | 705 } else { |
703 selectors = _defaultTestSelectors.toList(); | 706 selectors = _defaultTestSelectors.toList(); |
704 } | 707 } |
705 | 708 |
706 var excludeSuites = configuration['exclude_suite'] != null | 709 var excludeSuites = configuration['exclude_suite'] != null |
707 ? configuration['exclude_suite'].split(',') | 710 ? configuration['exclude_suite'].split(',') |
708 : []; | 711 : []; |
709 for (var exclude in excludeSuites) { | 712 for (var exclude in excludeSuites) { |
710 if (selectors.contains(exclude)) { | 713 if ((selectors as List).contains(exclude)) { |
711 selectors.remove(exclude); | 714 selectors.remove(exclude); |
712 } else { | 715 } else { |
713 print("Warning: default selectors does not contain $exclude"); | 716 print("Warning: default selectors does not contain $exclude"); |
714 } | 717 } |
715 } | 718 } |
716 } | 719 } |
717 var selectorMap = <String, RegExp>{}; | 720 var selectorMap = <String, RegExp>{}; |
718 for (var i = 0; i < selectors.length; i++) { | 721 for (var i = 0; i < (selectors as List).length; i++) { |
719 var pattern = selectors[i]; | 722 var pattern = selectors[i] as String; |
720 var suite = pattern; | 723 var suite = pattern; |
721 var slashLocation = pattern.indexOf('/'); | 724 var slashLocation = pattern.indexOf('/'); |
722 if (slashLocation != -1) { | 725 if (slashLocation != -1) { |
723 suite = pattern.substring(0, slashLocation); | 726 suite = pattern.substring(0, slashLocation); |
724 pattern = pattern.substring(slashLocation + 1); | 727 pattern = pattern.substring(slashLocation + 1); |
725 pattern = pattern.replaceAll('*', '.*'); | 728 pattern = pattern.replaceAll('*', '.*'); |
726 } else { | 729 } else { |
727 pattern = ".?"; | 730 pattern = ".?"; |
728 } | 731 } |
729 if (selectorMap.containsKey(suite)) { | 732 if (selectorMap.containsKey(suite)) { |
730 print("Error: '$suite/$pattern'. Only one test selection" | 733 print("Error: '$suite/$pattern'. Only one test selection" |
731 " pattern is allowed to start with '$suite/'"); | 734 " pattern is allowed to start with '$suite/'"); |
732 exit(1); | 735 exit(1); |
733 } | 736 } |
734 selectorMap[suite] = new RegExp(pattern); | 737 selectorMap[suite] = new RegExp(pattern); |
735 } | 738 } |
736 configuration['selectors'] = selectorMap; | 739 configuration['selectors'] = selectorMap; |
737 } | 740 } |
738 | 741 |
739 // Put observatory_ui in a configuration with its own packages override. | 742 // Put observatory_ui in a configuration with its own packages override. |
740 // Only one value in the configuration map is mutable: | 743 // Only one value in the configuration map is mutable: |
741 selectors = configuration['selectors']; | 744 selectors = configuration['selectors']; |
742 if (selectors.containsKey('observatory_ui')) { | 745 if ((selectors as Map<String, dynamic>).containsKey('observatory_ui')) { |
743 if (selectors.length == 1) { | 746 if (selectors.length == 1) { |
744 configuration['packages'] = TestUtils.dartDirUri | 747 configuration['packages'] = TestUtils.dartDirUri |
745 .resolve('runtime/observatory/.packages') | 748 .resolve('runtime/observatory/.packages') |
746 .toFilePath(); | 749 .toFilePath(); |
747 } else { | 750 } else { |
748 // Make a new configuration whose selectors map only contains | 751 // Make a new configuration whose selectors map only contains |
749 // observatory_ui, and remove the key from the original selectors. | 752 // observatory_ui, and remove the key from the original selectors. |
750 // The only mutable value in the map is the selectors, so a | 753 // The only mutable value in the map is the selectors, so a |
751 // shallow copy is safe. | 754 // shallow copy is safe. |
752 var observatoryConfiguration = new Map.from(configuration); | 755 var observatoryConfiguration = |
| 756 new Map<String, dynamic>.from(configuration); |
753 observatoryConfiguration['selectors'] = { | 757 observatoryConfiguration['selectors'] = { |
754 'observatory_ui': selectors['observatory_ui'] | 758 'observatory_ui': selectors['observatory_ui'] |
755 }; | 759 }; |
756 selectors.remove('observatory_ui'); | 760 selectors.remove('observatory_ui'); |
757 | 761 |
758 // Set the packages flag. | 762 // Set the packages flag. |
759 observatoryConfiguration['packages'] = TestUtils.dartDirUri | 763 observatoryConfiguration['packages'] = TestUtils.dartDirUri |
760 .resolve('runtime/observatory/.packages') | 764 .resolve('runtime/observatory/.packages') |
761 .toFilePath(); | 765 .toFilePath(); |
762 | 766 |
763 // Return the expansions of both configurations. Neither will reach | 767 // Return the expansions of both configurations. Neither will reach |
764 // this line in the recursive call to _expandConfigurations. | 768 // this line in the recursive call to _expandConfigurations. |
765 return _expandConfigurations(configuration) | 769 return _expandConfigurations(configuration) |
766 ..addAll(_expandConfigurations(observatoryConfiguration)); | 770 ..addAll(_expandConfigurations(observatoryConfiguration)); |
767 } | 771 } |
768 } | 772 } |
769 | 773 |
770 // Set the default package spec explicitly. | 774 // Set the default package spec explicitly. |
771 if (configuration['package_root'] == null && | 775 if (configuration['package_root'] == null && |
772 configuration['packages'] == null) { | 776 configuration['packages'] == null) { |
773 configuration['packages'] = | 777 configuration['packages'] = |
774 TestUtils.dartDirUri.resolve('.packages').toFilePath(); | 778 TestUtils.dartDirUri.resolve('.packages').toFilePath(); |
775 } | 779 } |
776 | 780 |
777 // Expand the architectures. | 781 // Expand the architectures. |
778 if (configuration['arch'].contains(',')) { | 782 if ((configuration['arch'] as String).contains(',')) { |
779 return _expandHelper('arch', configuration); | 783 return _expandHelper('arch', configuration); |
780 } | 784 } |
781 | 785 |
782 // Expand modes. | 786 // Expand modes. |
783 if (configuration['mode'].contains(',')) { | 787 if ((configuration['mode'] as String).contains(',')) { |
784 return _expandHelper('mode', configuration); | 788 return _expandHelper('mode', configuration); |
785 } | 789 } |
786 | 790 |
787 // Expand compilers. | 791 // Expand compilers. |
788 if (configuration['compiler'].contains(',')) { | 792 if ((configuration['compiler'] as String).contains(',')) { |
789 return _expandHelper('compiler', configuration); | 793 return _expandHelper('compiler', configuration); |
790 } | 794 } |
791 | 795 |
792 // Expand runtimes. | 796 // Expand runtimes. |
793 var runtimes = configuration['runtime']; | 797 var runtimes = configuration['runtime'] as String; |
794 if (runtimes.contains(',')) { | 798 if (runtimes.contains(',')) { |
795 return _expandHelper('runtime', configuration); | 799 return _expandHelper('runtime', configuration); |
796 } else { | 800 } else { |
797 // All runtimes eventually go through this path, after expansion. | 801 // All runtimes eventually go through this path, after expansion. |
798 var updater = runtimeUpdater(configuration); | 802 var updater = runtimeUpdater(configuration); |
799 if (updater != null) { | 803 if (updater != null) { |
800 updater.update(); | 804 updater.update(); |
801 } | 805 } |
802 } | 806 } |
803 | 807 |
804 // Adjust default timeout based on mode, compiler, and sometimes runtime. | 808 // Adjust default timeout based on mode, compiler, and sometimes runtime. |
805 if (configuration['timeout'] == -1) { | 809 if (configuration['timeout'] == -1) { |
806 var isReload = | 810 var isReload = (configuration['hot_reload'] as bool) || |
807 configuration['hot_reload'] || configuration['hot_reload_rollback']; | 811 (configuration['hot_reload_rollback'] as bool); |
808 int compilerMulitiplier = | 812 int compilerMulitiplier = |
809 new CompilerConfiguration(configuration).computeTimeoutMultiplier(); | 813 new CompilerConfiguration(configuration).computeTimeoutMultiplier(); |
810 int runtimeMultiplier = new RuntimeConfiguration(configuration) | 814 int runtimeMultiplier = new RuntimeConfiguration(configuration) |
811 .computeTimeoutMultiplier( | 815 .computeTimeoutMultiplier( |
812 mode: configuration['mode'], | 816 mode: configuration['mode'] as String, |
813 isChecked: configuration['checked'], | 817 isChecked: configuration['checked'] as bool, |
814 isReload: isReload, | 818 isReload: isReload, |
815 arch: configuration['arch']); | 819 arch: configuration['arch'] as String); |
816 configuration['timeout'] = 60 * compilerMulitiplier * runtimeMultiplier; | 820 configuration['timeout'] = 60 * compilerMulitiplier * runtimeMultiplier; |
817 } | 821 } |
818 | 822 |
819 return [configuration]; | 823 return [configuration]; |
820 } | 824 } |
821 | 825 |
822 /// Helper for _expandConfigurations. Creates a new configuration and adds it | 826 /// Helper for _expandConfigurations. Creates a new configuration and adds it |
823 /// to a list, for use in a case when a particular configuration has multiple | 827 /// to a list, for use in a case when a particular configuration has multiple |
824 /// results (separated by a ','). | 828 /// results (separated by a ','). |
825 /// Arguments: | 829 /// Arguments: |
826 /// option: The particular test option we are expanding. | 830 /// option: The particular test option we are expanding. |
827 /// configuration: The map containing all test configuration information | 831 /// configuration: The map containing all test configuration information |
828 /// specified. | 832 /// specified. |
829 List<Map> _expandHelper(String option, Map configuration) { | 833 List<Map<String, dynamic>> _expandHelper( |
830 var result = <Map>[]; | 834 String option, Map<String, dynamic> configuration) { |
| 835 var result = <Map<String, dynamic>>[]; |
831 var configs = configuration[option]; | 836 var configs = configuration[option]; |
832 for (var config in configs.split(',')) { | 837 for (var config in configs.split(',')) { |
833 var newConfiguration = new Map.from(configuration); | 838 var newConfiguration = new Map<String, dynamic>.from(configuration); |
834 newConfiguration[option] = config; | 839 newConfiguration[option] = config; |
835 result.addAll(_expandConfigurations(newConfiguration)); | 840 result.addAll(_expandConfigurations(newConfiguration)); |
836 } | 841 } |
837 return result; | 842 return result; |
838 } | 843 } |
839 | 844 |
840 /// Print out usage information. | 845 /// Print out usage information. |
841 void _printHelp() { | 846 void _printHelp() { |
842 var buffer = new StringBuffer(); | 847 var buffer = new StringBuffer(); |
843 | 848 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
907 if (name == option.name) return option; | 912 if (name == option.name) return option; |
908 | 913 |
909 // Allow hyphens instead of underscores as the separator since they are | 914 // Allow hyphens instead of underscores as the separator since they are |
910 // more common for command line flags. | 915 // more common for command line flags. |
911 if (name == option.name.replaceAll("_", "-")) return option; | 916 if (name == option.name.replaceAll("_", "-")) return option; |
912 } | 917 } |
913 | 918 |
914 return null; | 919 return null; |
915 } | 920 } |
916 } | 921 } |
OLD | NEW |