Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(56)

Side by Side Diff: recipe_engine/test.py

Issue 2848443003: [recipes.py] add missing helpstrings, merge test subcommands into main parser. (Closed)
Patch Set: rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « recipe_engine/run.py ('k') | recipes.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 # Copyright 2017 The LUCI Authors. All rights reserved. 1 # Copyright 2017 The LUCI Authors. All rights reserved.
2 # Use of this source code is governed under the Apache License, Version 2.0 2 # Use of this source code is governed under the Apache License, Version 2.0
3 # that can be found in the LICENSE file. 3 # that can be found in the LICENSE file.
4 4
5 from __future__ import print_function 5 from __future__ import print_function
6 6
7 import bdb 7 import bdb
8 import cStringIO 8 import cStringIO
9 import contextlib 9 import contextlib
10 import copy 10 import copy
(...skipping 806 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 elif isinstance(obj, list): 817 elif isinstance(obj, list):
818 return [re_encode(i) for i in obj] 818 return [re_encode(i) for i in obj]
819 elif isinstance(obj, (unicode, str)): 819 elif isinstance(obj, (unicode, str)):
820 if isinstance(obj, str): 820 if isinstance(obj, str):
821 obj = obj.decode('utf-8', 'replace') 821 obj = obj.decode('utf-8', 'replace')
822 return obj.encode('utf-8', 'replace') 822 return obj.encode('utf-8', 'replace')
823 else: 823 else:
824 return obj 824 return obj
825 825
826 826
827 def parse_args(args): 827 def add_subparser(parser):
828 """Returns parsed command line arguments.""" 828 helpstr='Generate or check expectations by simulation.'
829 parser = argparse.ArgumentParser() 829 test_p = parser.add_parser(
830 'test',
831 help=helpstr, description=helpstr)
830 832
831 def normalize_filter(filt): 833 def normalize_filter(filt):
832 if not filt: 834 if not filt:
833 parser.error('empty filters not allowed') 835 raise argparse.ArgumentTypeError('empty filters not allowed')
834 # filters missing a test_name portion imply that its a recipe prefix and we 836 # filters missing a test_name portion imply that its a recipe prefix and we
835 # should run all tests for the matching recipes. 837 # should run all tests for the matching recipes.
836 return filt if '.' in filt else filt+'*.*' 838 return filt if '.' in filt else filt+'*.*'
837 839
838 subp = parser.add_subparsers(dest='command') 840 subp = test_p.add_subparsers(dest='subcommand')
839 841
840 list_p = subp.add_parser('list', description='Print all test names') 842 helpstr = 'Print all test names.'
841 list_p.set_defaults(func=lambda opts: run_list(opts.json)) 843 list_p = subp.add_parser(
844 'list', help=helpstr, description=helpstr)
845 list_p.set_defaults(subfunc=lambda opts: run_list(opts.json))
842 list_p.add_argument( 846 list_p.add_argument(
843 '--json', metavar='FILE', type=argparse.FileType('w'), 847 '--json', metavar='FILE', type=argparse.FileType('w'),
844 help='path to JSON output file') 848 help='path to JSON output file')
845 849
850 helpstr='Compare results of two test runs.'
846 diff_p = subp.add_parser( 851 diff_p = subp.add_parser(
847 'diff', description='Compare results of two test runs') 852 'diff', help=helpstr, description=helpstr)
848 diff_p.set_defaults(func=lambda opts: run_diff( 853 diff_p.set_defaults(subfunc=lambda opts: run_diff(
849 opts.baseline, opts.actual, json_file=opts.json)) 854 opts.baseline, opts.actual, json_file=opts.json))
850 diff_p.add_argument( 855 diff_p.add_argument(
851 '--baseline', metavar='FILE', type=argparse.FileType('r'), 856 '--baseline', metavar='FILE', type=argparse.FileType('r'),
852 required=True, 857 required=True,
853 help='path to baseline JSON file') 858 help='path to baseline JSON file')
854 diff_p.add_argument( 859 diff_p.add_argument(
855 '--actual', metavar='FILE', type=argparse.FileType('r'), 860 '--actual', metavar='FILE', type=argparse.FileType('r'),
856 required=True, 861 required=True,
857 help='path to actual JSON file') 862 help='path to actual JSON file')
858 diff_p.add_argument( 863 diff_p.add_argument(
859 '--json', metavar='FILE', type=argparse.FileType('w'), 864 '--json', metavar='FILE', type=argparse.FileType('w'),
860 help='path to JSON output file') 865 help='path to JSON output file')
861 866
862 run_p = subp.add_parser('run', description='Run the tests') 867 glob_helpstr = (
863 run_p.set_defaults(func=lambda opts: run_run( 868 'glob filter for the tests to run; '
864 opts.filter, jobs=opts.jobs, train=opts.train, json_file=opts.json)) 869 'can be specified multiple times; '
870 'the globs have the form of '
871 '`<recipe_name_glob>[.<test_name_glob>]`. If `.<test_name_glob>` '
872 'is omitted, it is implied to be `*.*`, i.e. any recipe with this '
873 'prefix and all tests.')
874
875 helpstr = 'Run the tests.'
876 run_p = subp.add_parser('run', help=helpstr, description=helpstr)
877 run_p.set_defaults(subfunc=lambda opts: run_run(
878 opts.filter, jobs=opts.jobs, train=opts.train, json_file=opts.json))
865 run_p.add_argument( 879 run_p.add_argument(
866 '--jobs', metavar='N', type=int, 880 '--jobs', metavar='N', type=int,
867 default=multiprocessing.cpu_count(), 881 default=multiprocessing.cpu_count(),
868 help='run N jobs in parallel (default %(default)s)') 882 help='run N jobs in parallel (default %(default)s)')
869 run_p.add_argument( 883 run_p.add_argument(
870 '--json', metavar='FILE', type=argparse.FileType('w'), 884 '--json', metavar='FILE', type=argparse.FileType('w'),
871 help='path to JSON output file') 885 help='path to JSON output file')
872 run_p.add_argument( 886 run_p.add_argument(
873 '--filter', action='append', type=normalize_filter, 887 '--filter', action='append', type=normalize_filter,
874 help='glob filter for the tests to run; ' 888 help=glob_helpstr)
875 'can be specified multiple times; '
876 'the globs have the form of '
877 '`<recipe_name_glob>[.<test_name_glob>]`. If `.<test_name_glob>` '
878 'is omitted, it is implied to be `*.*`, i.e. any recipe with this '
879 'prefix and all tests.)')
880 # TODO(phajdan.jr): remove --train the switch in favor of train subcommand. 889 # TODO(phajdan.jr): remove --train the switch in favor of train subcommand.
881 run_p.add_argument( 890 run_p.add_argument(
882 '--train', action='store_true', 891 '--train', action='store_true',
883 help='re-generate recipe expectations (DEPRECATED)') 892 help='re-generate recipe expectations (DEPRECATED)')
884 893
885 train_p = subp.add_parser('train', description='Re-train recipe expectations') 894 helpstr = 'Re-train recipe expectations.'
886 train_p.set_defaults(func=lambda opts: run_run( 895 train_p = subp.add_parser('train', help=helpstr, description=helpstr)
887 opts.filter, jobs=opts.jobs, json_file=opts.json, train=True)) 896 train_p.set_defaults(subfunc=lambda opts: run_run(
897 opts.filter, jobs=opts.jobs, json_file=opts.json, train=True))
888 train_p.add_argument( 898 train_p.add_argument(
889 '--jobs', metavar='N', type=int, 899 '--jobs', metavar='N', type=int,
890 default=multiprocessing.cpu_count(), 900 default=multiprocessing.cpu_count(),
891 help='run N jobs in parallel (default %(default)s)') 901 help='run N jobs in parallel (default %(default)s)')
892 train_p.add_argument( 902 train_p.add_argument(
893 '--json', metavar='FILE', type=argparse.FileType('w'), 903 '--json', metavar='FILE', type=argparse.FileType('w'),
894 help='path to JSON output file') 904 help='path to JSON output file')
895 train_p.add_argument( 905 train_p.add_argument(
896 '--filter', action='append', type=normalize_filter, 906 '--filter', action='append', type=normalize_filter,
897 help='glob filter for the tests to run; ' 907 help=glob_helpstr)
898 'can be specified multiple times; '
899 'the globs have the form of '
900 '`<recipe_name_glob>[.<test_name_glob>]`. If `.<test_name_glob>` '
901 'is omitted, it is implied to be `*.*`, i.e. any recipe with this '
902 'prefix and all tests.)')
903 908
909 helpstr = 'Run the tests under debugger (pdb).'
904 debug_p = subp.add_parser( 910 debug_p = subp.add_parser(
905 'debug', description='Run the tests under debugger (pdb)') 911 'debug', help=helpstr, description=helpstr)
906 debug_p.set_defaults(func=lambda opts: run_run( 912 debug_p.set_defaults(subfunc=lambda opts: run_run(
907 opts.filter, debug=True)) 913 opts.filter, debug=True))
908 debug_p.add_argument( 914 debug_p.add_argument(
909 '--filter', action='append', type=normalize_filter, 915 '--filter', action='append', type=normalize_filter,
910 help='glob filter for the tests to run; ' 916 help=glob_helpstr)
911 'can be specified multiple times; '
912 'the globs have the form of '
913 '`<recipe_name_glob>[.<test_name_glob>]`. If `.<test_name_glob>` '
914 'is omitted, it is implied to be `*.*`, i.e. any recipe with this '
915 'prefix and all tests.)')
916
917 return parser.parse_args(args)
918
919
920 def add_subparser(parser):
921 # TODO(iannucci): add actual subparsers here, make main argparse parser to do
922 # full commandline parsing to allow --help to work correctly.
923 test_p = parser.add_parser(
924 'test',
925 description='Generate or check expectations by simulation')
926 test_p.add_argument('args', nargs=argparse.REMAINDER)
927 917
928 def postprocess_func(_parser, args): 918 def postprocess_func(_parser, args):
929 # Auto-enable bootstrap for test command invocations (necessary to get 919 # Auto-enable bootstrap for test command invocations (necessary to get
930 # recent enough version of coverage package), unless explicitly disabled. 920 # recent enough version of coverage package), unless explicitly disabled.
931 if args.use_bootstrap is None: 921 if args.use_bootstrap is None:
932 args.use_bootstrap = True 922 args.use_bootstrap = True
933 923
934 test_p.set_defaults(command='test', func=main, 924 test_p.set_defaults(
935 postprocess_func=postprocess_func) 925 command='test', func=main,
926 postprocess_func=postprocess_func,
927 )
936 928
937 929
938 def main(package_deps, args): 930 def main(package_deps, args):
939 """Runs simulation tests on a given repo of recipes. 931 """Runs simulation tests on a given repo of recipes.
940 932
941 Args: 933 Args:
942 universe_view: an UniverseView object to operate on 934 package_deps (PackageDeps)
943 raw_args: command line arguments to the 'test' command 935 args: the parsed args (see add_subparser).
944 engine_flags: recipe engine command-line flags
945 Returns: 936 Returns:
946 Exit code 937 Exit code
947 """ 938 """
948 universe = loader.RecipeUniverse(package_deps, args.package) 939 universe = loader.RecipeUniverse(package_deps, args.package)
949 universe_view = loader.UniverseView(universe, package_deps.root_package) 940 universe_view = loader.UniverseView(universe, package_deps.root_package)
950 raw_args=args.args
951 engine_flags=args.operational_args.engine_flags 941 engine_flags=args.operational_args.engine_flags
952 942
953 # Prevent flakiness caused by stale pyc files. 943 # Prevent flakiness caused by stale pyc files.
954 package.cleanup_pyc(package_deps.root_package.recipes_dir) 944 package.cleanup_pyc(package_deps.root_package.recipes_dir)
955 945
956 global _UNIVERSE_VIEW 946 global _UNIVERSE_VIEW
957 _UNIVERSE_VIEW = universe_view 947 _UNIVERSE_VIEW = universe_view
958 global _ENGINE_FLAGS 948 global _ENGINE_FLAGS
959 _ENGINE_FLAGS = engine_flags 949 _ENGINE_FLAGS = engine_flags
960 950
961 args = parse_args(raw_args) 951 return args.subfunc(args)
962 return args.func(args)
OLDNEW
« no previous file with comments | « recipe_engine/run.py ('k') | recipes.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698