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

Side by Side Diff: scripts/slave/unittests/recipe_configs_test.py

Issue 1111413005: Some changes to allow recipes and modules to live noncentrally (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Little bitty cleanup Created 5 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 | Annotate | Revision Log
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 """Provides test coverage for common recipe configurations. 6 """Provides test coverage for common recipe configurations.
7 7
8 recipe config expectations are located in ../recipe_configs_test/*.expected 8 recipe config expectations are located in ../recipe_configs_test/*.expected
9 9
10 In training mode, this will loop over every config item in ../recipe_configs.py 10 In training mode, this will loop over every config item in ../recipe_configs.py
(...skipping 25 matching lines...) Expand all
36 for x in recipe_util.MODULE_DIRS()], 36 for x in recipe_util.MODULE_DIRS()],
37 data_file='.recipe_configs_test_coverage', data_suffix=True))() 37 data_file='.recipe_configs_test_coverage', data_suffix=True))()
38 38
39 def covered(fn, *args, **kwargs): 39 def covered(fn, *args, **kwargs):
40 COVERAGE.start() 40 COVERAGE.start()
41 try: 41 try:
42 return fn(*args, **kwargs) 42 return fn(*args, **kwargs)
43 finally: 43 finally:
44 COVERAGE.stop() 44 COVERAGE.stop()
45 45
46 LOADER = recipe_loader.ModuleLoader()
47
48 def load_recipe_modules():
49 modules = {}
50 for modpath in recipe_loader.loop_over_recipe_modules():
51 # That's right, we're using the path as the local name! The local
52 # name really could be anything unique, we don't use it.
53 modules[modpath] = LOADER.load(recipe_loader.PathDependency(
54 modpath, local_name=modpath, base_path=os.curdir))
55 return modules
56
57
46 RECIPE_MODULES = None 58 RECIPE_MODULES = None
47 def init_recipe_modules(): 59 def init_recipe_modules():
48 global RECIPE_MODULES 60 global RECIPE_MODULES
49 RECIPE_MODULES = covered(recipe_loader.load_recipe_modules, 61 RECIPE_MODULES = covered(load_recipe_modules)
50 recipe_util.MODULE_DIRS())
51 62
52 from slave import recipe_config # pylint: disable=F0401 63 from slave import recipe_config # pylint: disable=F0401
53 64
54 65
55 def evaluate_configurations(args): 66 def evaluate_configurations(args):
56 mod_id, var_assignments, verbose = args 67 mod_id, var_assignments, verbose = args
57 mod = getattr(RECIPE_MODULES, mod_id) 68 mod = RECIPE_MODULES[mod_id]
58 ctx = mod.CONFIG_CTX 69 ctx = mod.CONFIG_CTX
59 70
60 config_name = None 71 config_name = None
61 try: 72 try:
62 make_item = lambda: covered(ctx.CONFIG_SCHEMA, **var_assignments) 73 make_item = lambda: covered(ctx.CONFIG_SCHEMA, **var_assignments)
63 74
64 # Try ROOT_CONFIG_ITEM first. If it raises BadConf, then we can skip 75 # Try ROOT_CONFIG_ITEM first. If it raises BadConf, then we can skip
65 # this config. 76 # this config.
66 root_item = ctx.ROOT_CONFIG_ITEM 77 root_item = ctx.ROOT_CONFIG_ITEM
67 if root_item: 78 if root_item:
(...skipping 20 matching lines...) Expand all
88 return True 99 return True
89 except Exception as e: 100 except Exception as e:
90 print 'Caught exception [%s] with args (%s, %s): %s' % ( 101 print 'Caught exception [%s] with args (%s, %s): %s' % (
91 e, mod_id, var_assignments, config_name) 102 e, mod_id, var_assignments, config_name)
92 if verbose: 103 if verbose:
93 traceback.print_exc() 104 traceback.print_exc()
94 return False 105 return False
95 106
96 107
97 def multiprocessing_init(): 108 def multiprocessing_init():
98 init_recipe_modules()
iannucci 2015/05/05 23:35:59 ???????
99
100 # HACK: multiprocessing doesn't work with atexit, so shim the exit functions 109 # HACK: multiprocessing doesn't work with atexit, so shim the exit functions
101 # instead. This allows us to save exactly one coverage file per subprocess. 110 # instead. This allows us to save exactly one coverage file per subprocess.
102 # pylint: disable=W0212 111 # pylint: disable=W0212
103 real_os_exit = multiprocessing.forking.exit 112 real_os_exit = multiprocessing.forking.exit
104 def exitfn(code): 113 def exitfn(code):
105 COVERAGE.save() 114 COVERAGE.save()
106 real_os_exit(code) 115 real_os_exit(code)
107 multiprocessing.forking.exit = exitfn 116 multiprocessing.forking.exit = exitfn
108 117
109 # This check mirrors the logic in multiprocessing.forking.exit 118 # This check mirrors the logic in multiprocessing.forking.exit
110 if sys.platform != 'win32': 119 if sys.platform != 'win32':
111 # Even though multiprocessing.forking.exit is defined, it's not used in the 120 # Even though multiprocessing.forking.exit is defined, it's not used in the
112 # non-win32 version of multiprocessing.forking.Popen... *loss for words* 121 # non-win32 version of multiprocessing.forking.Popen... *loss for words*
113 os._exit = exitfn 122 os._exit = exitfn
114 123
115 124
116 def coverage_parallel_map(fn, verbose): 125 def coverage_parallel_map(fn, verbose):
117 combination_generator = ( 126 combination_generator = (
118 (mod_id, var_assignments, verbose) 127 (mod_id, var_assignments, verbose)
119 for mod_id, mod in RECIPE_MODULES.__dict__.iteritems() 128 for mod_id, mod in RECIPE_MODULES.iteritems()
120 if mod_id[0] != '_' and mod.CONFIG_CTX 129 if mod.CONFIG_CTX
121 for var_assignments in imap(dict, product(*[ 130 for var_assignments in imap(dict, product(*[
122 [(key_name, val) for val in vals] 131 [(key_name, val) for val in vals]
123 for key_name, vals in mod.CONFIG_CTX.VAR_TEST_MAP.iteritems() 132 for key_name, vals in mod.CONFIG_CTX.VAR_TEST_MAP.iteritems()
124 ])) 133 ]))
125 ) 134 )
126 135
127 pool = multiprocessing.Pool(initializer=multiprocessing_init) 136 pool = multiprocessing.Pool(initializer=multiprocessing_init)
128 try: 137 try:
129 return pool.map_async(fn, combination_generator).get(999999) 138 return pool.map_async(fn, combination_generator).get(999999)
130 finally: 139 finally:
(...skipping 21 matching lines...) Expand all
152 if not success: 161 if not success:
153 print 'FATAL: Some recipe configuration(s) failed' 162 print 'FATAL: Some recipe configuration(s) failed'
154 if not all_covered: 163 if not all_covered:
155 print 'FATAL: Recipes configs are not at 100% coverage.' 164 print 'FATAL: Recipes configs are not at 100% coverage.'
156 165
157 return 1 if (not success or not all_covered) else 0 166 return 1 if (not success or not all_covered) else 0
158 167
159 168
160 if __name__ == '__main__': 169 if __name__ == '__main__':
161 sys.exit(main(sys.argv)) 170 sys.exit(main(sys.argv))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698