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

Side by Side Diff: bin/au_test_harness/cros_au_test_harness.py

Issue 6698017: Remove test keys from images we test with in the test harness. (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch Set: Change set Created 9 years, 9 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
« no previous file with comments | « bin/au_test_harness/au_test.py ('k') | bin/au_test_harness/dev_server_wrapper.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 #!/usr/bin/python 1 #!/usr/bin/python
2 2
3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """This module runs a suite of Auto Update tests. 7 """This module runs a suite of Auto Update tests.
8 8
9 The tests can be run on either a virtual machine or actual device depending 9 The tests can be run on either a virtual machine or actual device depending
10 on parameters given. Specific tests can be run by invoking --test_prefix. 10 on parameters given. Specific tests can be run by invoking --test_prefix.
11 Verbose is useful for many of the tests if you want to see individual commands 11 Verbose is useful for many of the tests if you want to see individual commands
12 being run during the update process. 12 being run during the update process.
13 """ 13 """
14 14
15 import optparse 15 import optparse
16 import os 16 import os
17 import re 17 import re
18 import sys 18 import sys
19 import tempfile
20 import unittest 19 import unittest
21 20
22 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) 21 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
23 import cros_build_lib as cros_lib 22 import cros_build_lib as cros_lib
24 23
25 import au_test 24 import au_test
26 import au_worker 25 import au_worker
27 import dummy_au_worker 26 import dummy_au_worker
28 import dev_server_wrapper 27 import dev_server_wrapper
29 import parallel_test_job 28 import parallel_test_job
29 import public_key_manager
30 import update_exception 30 import update_exception
31 31
32
33 def _PrepareTestSuite(options, use_dummy_worker=False): 32 def _PrepareTestSuite(options, use_dummy_worker=False):
34 """Returns a prepared test suite given by the options and test class.""" 33 """Returns a prepared test suite given by the options and test class."""
35 au_test.AUTest.ProcessOptions(options, use_dummy_worker) 34 au_test.AUTest.ProcessOptions(options, use_dummy_worker)
36 test_loader = unittest.TestLoader() 35 test_loader = unittest.TestLoader()
37 test_loader.testMethodPrefix = options.test_prefix 36 test_loader.testMethodPrefix = options.test_prefix
38 return test_loader.loadTestsFromTestCase(au_test.AUTest) 37 return test_loader.loadTestsFromTestCase(au_test.AUTest)
39 38
40 39
41 def _PregenerateUpdates(options): 40 def _PregenerateUpdates(options):
42 """Determines all deltas that will be generated and generates them. 41 """Determines all deltas that will be generated and generates them.
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
75 test_suite = _PrepareTestSuite(options, use_dummy_worker=True) 74 test_suite = _PrepareTestSuite(options, use_dummy_worker=True)
76 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) 75 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite)
77 if not test_result.wasSuccessful(): 76 if not test_result.wasSuccessful():
78 raise update_exception.UpdateException(1, 77 raise update_exception.UpdateException(1,
79 'Error finding updates to generate.') 78 'Error finding updates to generate.')
80 79
81 cros_lib.Info('The following delta updates are required.') 80 cros_lib.Info('The following delta updates are required.')
82 update_ids = [] 81 update_ids = []
83 jobs = [] 82 jobs = []
84 args = [] 83 args = []
84 modified_images = set()
85 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items(): 85 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items():
86 modified_images.add(target)
86 for src_key in srcs: 87 for src_key in srcs:
87 (src, _ , key) = src_key.partition('+') 88 (src, _ , key) = src_key.partition('+')
89 if src: modified_images.add(src)
88 # TODO(sosa): Add private key as part of caching name once devserver can 90 # TODO(sosa): Add private key as part of caching name once devserver can
89 # handle it its own cache. 91 # handle it its own cache.
90 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key) 92 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key)
91 print >> sys.stderr, 'AU: %s' % update_id 93 print >> sys.stderr, 'AU: %s' % update_id
92 update_ids.append(update_id) 94 update_ids.append(update_id)
93 jobs.append(_GenerateVMUpdate) 95 jobs.append(_GenerateVMUpdate)
94 args.append((target, src, key)) 96 args.append((target, src, key))
95 97
98 # Always add the base image path. This is only useful for non-delta updates.
99 modified_images.add(options.base_image)
100
101 # Add public key to all images we are using.
102 if options.public_key:
103 cros_lib.Info('Adding public keys to images for testing.')
104 for image in modified_images:
105 manager = public_key_manager.PublicKeyManager(image, options.public_key)
106 manager.AddKeyToImage()
107 au_test.AUTest.public_key_managers.append(manager)
108
96 raw_results = parallel_test_job.RunParallelJobs(options.jobs, jobs, args, 109 raw_results = parallel_test_job.RunParallelJobs(options.jobs, jobs, args,
97 print_status=True) 110 print_status=True)
98 results = [] 111 results = []
99 112
100 # Looking for this line in the output. 113 # Looking for this line in the output.
101 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)') 114 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)')
102 for result in raw_results: 115 for result in raw_results:
103 (return_code, output, _) = result 116 (return_code, output, _) = result
104 if return_code != 0: 117 if return_code != 0:
105 cros_lib.Warning(output) 118 cros_lib.Warning(output)
(...skipping 24 matching lines...) Expand all
130 143
131 144
132 def _RunTestsInParallel(options): 145 def _RunTestsInParallel(options):
133 """Runs the tests given by the options in parallel.""" 146 """Runs the tests given by the options in parallel."""
134 threads = [] 147 threads = []
135 args = [] 148 args = []
136 test_suite = _PrepareTestSuite(options) 149 test_suite = _PrepareTestSuite(options)
137 for test in test_suite: 150 for test in test_suite:
138 test_name = test.id() 151 test_name = test.id()
139 test_case = unittest.TestLoader().loadTestsFromName(test_name) 152 test_case = unittest.TestLoader().loadTestsFromName(test_name)
140 threads.append(unittest.TextTestRunner().run) 153 threads.append(unittest.TextTestRunner(verbosity=2).run)
141 args.append(test_case) 154 args.append(test_case)
142 155
143 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args, 156 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args,
144 print_status=False) 157 print_status=False)
145 for test_result in results: 158 for test_result in results:
146 if not test_result.wasSuccessful(): 159 if not test_result.wasSuccessful():
147 cros_lib.Die('Test harness was not successful') 160 cros_lib.Die('Test harness was not successful')
148 161
149 162
150 def _InsertPublicKeyIntoImage(image_path, key_path):
151 """Inserts public key into image @ static update_engine location."""
152 from_dir = os.path.dirname(image_path)
153 image = os.path.basename(image_path)
154 crosutils_dir = os.path.abspath(__file__).rsplit('/', 2)[0]
155 target_key_path = 'usr/share/update_engine/update-payload-key.pub.pem'
156
157 # Temporary directories for this function.
158 rootfs_dir = tempfile.mkdtemp(suffix='rootfs', prefix='tmp')
159 stateful_dir = tempfile.mkdtemp(suffix='stateful', prefix='tmp')
160
161 cros_lib.Info('Copying %s into %s' % (key_path, image_path))
162 try:
163 cros_lib.RunCommand(['./mount_gpt_image.sh',
164 '--from=%s' % from_dir,
165 '--image=%s' % image,
166 '--rootfs_mountpt=%s' % rootfs_dir,
167 '--stateful_mountpt=%s' % stateful_dir,
168 ], print_cmd=False, redirect_stdout=True,
169 redirect_stderr=True, cwd=crosutils_dir)
170 path = os.path.join(rootfs_dir, target_key_path)
171 dir_path = os.path.dirname(path)
172 cros_lib.RunCommand(['sudo', 'mkdir', '--parents', dir_path],
173 print_cmd=False)
174 cros_lib.RunCommand(['sudo', 'cp', '--force', '-p', key_path, path],
175 print_cmd=False)
176 finally:
177 # Unmount best effort regardless.
178 cros_lib.RunCommand(['./mount_gpt_image.sh',
179 '--unmount',
180 '--rootfs_mountpt=%s' % rootfs_dir,
181 '--stateful_mountpt=%s' % stateful_dir,
182 ], print_cmd=False, redirect_stdout=True,
183 redirect_stderr=True, cwd=crosutils_dir)
184 # Clean up our directories.
185 os.rmdir(rootfs_dir)
186 os.rmdir(stateful_dir)
187
188 cros_lib.RunCommand(['bin/cros_make_image_bootable',
189 cros_lib.ReinterpretPathForChroot(from_dir),
190 image],
191 print_cmd=False, redirect_stdout=True,
192 redirect_stderr=True, enter_chroot=True,
193 cwd=crosutils_dir)
194
195
196 def _CleanPreviousWork(options): 163 def _CleanPreviousWork(options):
197 """Cleans up previous work from the devserver cache and local image cache.""" 164 """Cleans up previous work from the devserver cache and local image cache."""
198 cros_lib.Info('Cleaning up previous work.') 165 cros_lib.Info('Cleaning up previous work.')
199 # Wipe devserver cache. 166 # Wipe devserver cache.
200 cros_lib.RunCommandCaptureOutput( 167 cros_lib.RunCommandCaptureOutput(
201 ['sudo', 'start_devserver', '--clear_cache', '--exit', ], 168 ['sudo', 'start_devserver', '--clear_cache', '--exit', ],
202 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True) 169 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True)
203 170
204 # Clean previous vm images if they exist. 171 # Clean previous vm images if they exist.
205 if options.type == 'vm': 172 if options.type == 'vm':
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 (options, leftover_args) = parser.parse_args() 217 (options, leftover_args) = parser.parse_args()
251 218
252 if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args) 219 if leftover_args: parser.error('Found unsupported flags: %s' % leftover_args)
253 220
254 assert options.target_image and os.path.exists(options.target_image), \ 221 assert options.target_image and os.path.exists(options.target_image), \
255 'Target image path does not exist' 222 'Target image path does not exist'
256 if not options.base_image: 223 if not options.base_image:
257 cros_lib.Info('Base image not specified. Using target as base image.') 224 cros_lib.Info('Base image not specified. Using target as base image.')
258 options.base_image = options.target_image 225 options.base_image = options.target_image
259 226
260 # Sanity checks on keys and insert them onto the image. The caches must be
261 # cleaned so we know that the vm images and payloads match the possibly new
262 # key.
263 if options.private_key or options.public_key: 227 if options.private_key or options.public_key:
264 error_msg = ('Could not find %s key. Both private and public keys must be ' 228 error_msg = ('Could not find %s key. Both private and public keys must be '
265 'specified if either is specified.') 229 'specified if either is specified.')
266 assert options.private_key and os.path.exists(options.private_key), \ 230 assert options.private_key and os.path.exists(options.private_key), \
267 error_msg % 'private' 231 error_msg % 'private'
268 assert options.public_key and os.path.exists(options.public_key), \ 232 assert options.public_key and os.path.exists(options.public_key), \
269 error_msg % 'public' 233 error_msg % 'public'
270 _InsertPublicKeyIntoImage(options.target_image, options.public_key)
271 if options.target_image != options.base_image:
272 _InsertPublicKeyIntoImage(options.base_image, options.public_key)
273 options.clean = True
274 234
275 # Clean up previous work if requested. 235 # Clean up previous work if requested.
276 if options.clean: _CleanPreviousWork(options) 236 if options.clean: _CleanPreviousWork(options)
277 237
278 # Make sure we have a log directory. 238 # Make sure we have a log directory.
279 if not os.path.exists(options.test_results_root): 239 if not os.path.exists(options.test_results_root):
280 os.makedirs(options.test_results_root) 240 os.makedirs(options.test_results_root)
281 241
282 # Generate cache of updates to use during test harness. 242 # Pre-generate update modifies images by adding public keys to them.
283 update_cache = _PregenerateUpdates(options) 243 # Wrap try to make sure we clean this up before we're done.
284 au_worker.AUWorker.SetUpdateCache(update_cache) 244 try:
245 # Generate cache of updates to use during test harness.
246 update_cache = _PregenerateUpdates(options)
247 au_worker.AUWorker.SetUpdateCache(update_cache)
285 248
286 my_server = dev_server_wrapper.DevServerWrapper( 249 my_server = dev_server_wrapper.DevServerWrapper(
287 au_test.AUTest.test_results_root) 250 au_test.AUTest.test_results_root)
288 my_server.start() 251 my_server.start()
289 try: 252 try:
290 if options.type == 'vm': 253 if options.type == 'vm':
291 _RunTestsInParallel(options) 254 _RunTestsInParallel(options)
292 else: 255 else:
293 # TODO(sosa) - Take in a machine pool for a real test. 256 # TODO(sosa) - Take in a machine pool for a real test.
294 # Can't run in parallel with only one remote device. 257 # Can't run in parallel with only one remote device.
295 test_suite = _PrepareTestSuite(options) 258 test_suite = _PrepareTestSuite(options)
296 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) 259 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite)
297 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.') 260 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.')
261
262 finally:
263 my_server.Stop()
264
298 finally: 265 finally:
299 my_server.Stop() 266 # Un-modify any target images we modified. We don't need to un-modify
267 # non-targets because they aren't important for archival steps.
268 if options.public_key:
269 cros_lib.Info('Cleaning up. Removing keys added as part of testing.')
270 target_directory = os.path.dirname(options.target_image)
271 for key_manager in au_test.AUTest.public_key_managers:
272 if key_manager.image_path.startswith(target_directory):
273 key_manager.RemoveKeyFromImage()
300 274
301 275
302 if __name__ == '__main__': 276 if __name__ == '__main__':
303 main() 277 main()
OLDNEW
« no previous file with comments | « bin/au_test_harness/au_test.py ('k') | bin/au_test_harness/dev_server_wrapper.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698