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

Side by Side Diff: au_test_harness/cros_au_test_harness.py

Issue 6825062: Fix bug where multiprocessing.Queue hangs on large outputs. (Closed) Base URL: http://git.chromium.org/git/crostestutils.git@master
Patch Set: Fix test Created 9 years, 8 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 | « no previous file | au_test_harness/parallel_test_job.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.
(...skipping 11 matching lines...) Expand all
22 import constants 22 import constants
23 sys.path.append(constants.CROSUTILS_LIB_DIR) 23 sys.path.append(constants.CROSUTILS_LIB_DIR)
24 import cros_build_lib as cros_lib 24 import cros_build_lib as cros_lib
25 25
26 import au_test 26 import au_test
27 import au_worker 27 import au_worker
28 import dummy_au_worker 28 import dummy_au_worker
29 import dev_server_wrapper 29 import dev_server_wrapper
30 import parallel_test_job 30 import parallel_test_job
31 import public_key_manager 31 import public_key_manager
32 import tempfile
32 import update_exception 33 import update_exception
33 34
34 def _PrepareTestSuite(options, use_dummy_worker=False): 35 def _PrepareTestSuite(options, use_dummy_worker=False):
35 """Returns a prepared test suite given by the options and test class.""" 36 """Returns a prepared test suite given by the options and test class."""
36 au_test.AUTest.ProcessOptions(options, use_dummy_worker) 37 au_test.AUTest.ProcessOptions(options, use_dummy_worker)
37 test_loader = unittest.TestLoader() 38 test_loader = unittest.TestLoader()
38 test_loader.testMethodPrefix = options.test_prefix 39 test_loader.testMethodPrefix = options.test_prefix
39 return test_loader.loadTestsFromTestCase(au_test.AUTest) 40 return test_loader.loadTestsFromTestCase(au_test.AUTest)
40 41
41 42
42 def _PregenerateUpdates(options): 43 def _PregenerateUpdates(options):
43 """Determines all deltas that will be generated and generates them. 44 """Determines all deltas that will be generated and generates them.
44 45
45 This method effectively pre-generates the dev server cache for all tests. 46 This method effectively pre-generates the dev server cache for all tests.
46 47
47 Args: 48 Args:
48 options: options from parsed parser. 49 options: options from parsed parser.
49 Returns: 50 Returns:
50 Dictionary of Update Identifiers->Relative cache locations. 51 Dictionary of Update Identifiers->Relative cache locations.
51 Raises: 52 Raises:
52 update_exception.UpdateException if we fail to generate an update. 53 update_exception.UpdateException if we fail to generate an update.
53 """ 54 """
54 def _GenerateVMUpdate(target, src, private_key_path): 55 def _GenerateVMUpdate(target, src, private_key_path, log_file):
55 """Generates an update using the devserver.""" 56 """Returns the error code from generating an update using the devserver."""
56 command = ['sudo', 57 command = ['sudo',
57 'start_devserver', 58 'start_devserver',
58 '--pregenerate_update', 59 '--pregenerate_update',
59 '--exit', 60 '--exit',
60 ] 61 ]
61 # Add actual args to command. 62 # Add actual args to command.
62 command.append('--image=%s' % cros_lib.ReinterpretPathForChroot(target)) 63 command.append('--image=%s' % cros_lib.ReinterpretPathForChroot(target))
63 if src: command.append('--src_image=%s' % 64 if src: command.append('--src_image=%s' %
64 cros_lib.ReinterpretPathForChroot(src)) 65 cros_lib.ReinterpretPathForChroot(src))
65 if options.type == 'vm': command.append('--for_vm') 66 if options.type == 'vm': command.append('--for_vm')
66 if private_key_path: 67 if private_key_path:
67 command.append('--private_key=%s' % 68 command.append('--private_key=%s' %
68 cros_lib.ReinterpretPathForChroot(private_key_path)) 69 cros_lib.ReinterpretPathForChroot(private_key_path))
69 70
70 return cros_lib.RunCommandCaptureOutput(command, combine_stdout_stderr=True, 71 return cros_lib.RunCommand(command, enter_chroot=True, print_cmd=True,
71 enter_chroot=True, 72 cwd=cros_lib.GetCrosUtilsPath(),
72 print_cmd=True, 73 log_to_file=log_file, error_ok=True,
73 cwd=cros_lib.GetCrosUtilsPath()) 74 exit_code=True)
75
76 def _ProcessGeneratorOutputs(log_files, return_codes):
77 """Processes results from the log files of GenerateVMUpdate calls.
78
79 Returns an array of cache entries from the log files.
80 """
81 return_array = []
82 for log_file, return_code in map(lambda x, y: (x, y), log_files,
83 return_codes):
dgarrett 2011/04/12 02:01:52 off by one indention.
sosa 2011/04/12 02:09:50 Done.
84 log_file_handle = open(log_file)
85 output = log_file_handle.read()
86 log_file_handle.close()
87
88 # Looking for this line in the output.
89 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)')
dgarrett 2011/04/12 02:01:52 Can do this outside the outer for loop and not reg
sosa 2011/04/12 02:09:50 Done.
90 if return_code != 0:
dgarrett 2011/04/12 02:01:52 Seems like this line should be the first line afte
sosa 2011/04/12 02:09:50 I actually want to print out the output from a fai
91 cros_lib.Warning(output)
92 raise update_exception.UpdateException(return_code,
93 'Failed to generate update.')
94 else:
95 for line in output.splitlines():
96 match = key_line_re.search(line)
97 if match:
98 # Convert blah/blah/update.gz -> update/blah/blah.
99 path_to_update_gz = match.group(1).rstrip()
100 (path_to_update_dir, _, _) = path_to_update_gz.rpartition(
101 '/update.gz')
102 return_array.append('/'.join(['update', path_to_update_dir]))
103
104 assert len(return_array) == len(log_files), 'Return result size mismatch.'
105 return return_array
74 106
75 # Use dummy class to mock out updates that would be run as part of a test. 107 # Use dummy class to mock out updates that would be run as part of a test.
76 test_suite = _PrepareTestSuite(options, use_dummy_worker=True) 108 test_suite = _PrepareTestSuite(options, use_dummy_worker=True)
77 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) 109 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite)
78 if not test_result.wasSuccessful(): 110 if not test_result.wasSuccessful():
79 raise update_exception.UpdateException(1, 111 raise update_exception.UpdateException(1,
80 'Error finding updates to generate.') 112 'Error finding updates to generate.')
81 113
82 cros_lib.Info('The following delta updates are required.') 114 cros_lib.Info('The following delta updates are required.')
83 update_ids = [] 115 update_ids = []
84 jobs = [] 116 jobs = []
85 args = [] 117 args = []
118 log_files = []
86 modified_images = set() 119 modified_images = set()
87 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items(): 120 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items():
88 modified_images.add(target) 121 modified_images.add(target)
89 for src_key in srcs: 122 for src_key in srcs:
123 log_file = tempfile.mktemp('GenerateVMUpdate')
90 (src, _ , key) = src_key.partition('+') 124 (src, _ , key) = src_key.partition('+')
91 if src: modified_images.add(src) 125 if src: modified_images.add(src)
92 # TODO(sosa): Add private key as part of caching name once devserver can 126 # TODO(sosa): Add private key as part of caching name once devserver can
93 # handle it its own cache. 127 # handle it its own cache.
94 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key) 128 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key)
95 print >> sys.stderr, 'AU: %s' % update_id 129 print >> sys.stderr, 'AU: %s' % update_id
96 update_ids.append(update_id) 130 update_ids.append(update_id)
97 jobs.append(_GenerateVMUpdate) 131 jobs.append(_GenerateVMUpdate)
98 args.append((target, src, key)) 132 args.append((target, src, key, log_file))
133 log_files.append(log_file)
99 134
100 # Always add the base image path. This is only useful for non-delta updates. 135 # Always add the base image path. This is only useful for non-delta updates.
101 modified_images.add(options.base_image) 136 modified_images.add(options.base_image)
102 137
103 # Add public key to all images we are using. 138 # Add public key to all images we are using.
104 if options.public_key: 139 if options.public_key:
105 cros_lib.Info('Adding public keys to images for testing.') 140 cros_lib.Info('Adding public keys to images for testing.')
106 for image in modified_images: 141 for image in modified_images:
107 manager = public_key_manager.PublicKeyManager(image, options.public_key) 142 manager = public_key_manager.PublicKeyManager(image, options.public_key)
108 manager.AddKeyToImage() 143 manager.AddKeyToImage()
109 au_test.AUTest.public_key_managers.append(manager) 144 au_test.AUTest.public_key_managers.append(manager)
110 145
111 raw_results = parallel_test_job.RunParallelJobs(options.jobs, jobs, args, 146 error_codes = parallel_test_job.RunParallelJobs(options.jobs, jobs, args)
112 print_status=True) 147 results = _ProcessGeneratorOutputs(log_files, error_codes)
113 results = []
114
115 # Looking for this line in the output.
116 key_line_re = re.compile('^PREGENERATED_UPDATE=([\w/.]+)')
117 for result in raw_results:
118 (return_code, output, _) = result
119 if return_code != 0:
120 cros_lib.Warning(output)
121 raise update_exception.UpdateException(return_code,
122 'Failed to generate all updates.')
123 else:
124 for line in output.splitlines():
125 match = key_line_re.search(line)
126 if match:
127 # Convert blah/blah/update.gz -> update/blah/blah.
128 path_to_update_gz = match.group(1).rstrip()
129 (path_to_update_dir, _, _) = path_to_update_gz.rpartition(
130 '/update.gz')
131 results.append('/'.join(['update', path_to_update_dir]))
132 break
133
134 # Make sure all generation of updates returned cached locations.
135 if len(raw_results) != len(results):
136 raise update_exception.UpdateException(
137 1, 'Insufficient number cache directories returned.')
138 148
139 # Build the dictionary from our id's and returned cache paths. 149 # Build the dictionary from our id's and returned cache paths.
140 cache_dictionary = {} 150 cache_dictionary = {}
141 for index, id in enumerate(update_ids): 151 for index, id in enumerate(update_ids):
142 cache_dictionary[id] = results[index] 152 cache_dictionary[id] = results[index]
143 153
144 return cache_dictionary 154 return cache_dictionary
145 155
146 156
147 def _RunTestsInParallel(options): 157 def _RunTestsInParallel(options):
148 """Runs the tests given by the options in parallel.""" 158 """Runs the tests given by the options in parallel."""
149 threads = [] 159 threads = []
150 args = [] 160 args = []
151 test_suite = _PrepareTestSuite(options) 161 test_suite = _PrepareTestSuite(options)
152 for test in test_suite: 162 for test in test_suite:
153 test_name = test.id() 163 test_name = test.id()
154 test_case = unittest.TestLoader().loadTestsFromName(test_name) 164 test_case = unittest.TestLoader().loadTestsFromName(test_name)
155 threads.append(unittest.TextTestRunner(verbosity=2).run) 165 threads.append(unittest.TextTestRunner(verbosity=2).run)
156 args.append(test_case) 166 args.append(test_case)
157 167
158 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args, 168 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args)
159 print_status=False)
160 for test_result in results: 169 for test_result in results:
161 if not test_result.wasSuccessful(): 170 if not test_result.wasSuccessful():
162 cros_lib.Die('Test harness was not successful') 171 cros_lib.Die('Test harness was not successful')
163 172
164 173
165 def _CleanPreviousWork(options): 174 def _CleanPreviousWork(options):
166 """Cleans up previous work from the devserver cache and local image cache.""" 175 """Cleans up previous work from the devserver cache and local image cache."""
167 cros_lib.Info('Cleaning up previous work.') 176 cros_lib.Info('Cleaning up previous work.')
168 # Wipe devserver cache. 177 # Wipe devserver cache.
169 cros_lib.RunCommandCaptureOutput( 178 cros_lib.RunCommandCaptureOutput(
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 if options.public_key: 281 if options.public_key:
273 cros_lib.Info('Cleaning up. Removing keys added as part of testing.') 282 cros_lib.Info('Cleaning up. Removing keys added as part of testing.')
274 target_directory = os.path.dirname(options.target_image) 283 target_directory = os.path.dirname(options.target_image)
275 for key_manager in au_test.AUTest.public_key_managers: 284 for key_manager in au_test.AUTest.public_key_managers:
276 if key_manager.image_path.startswith(target_directory): 285 if key_manager.image_path.startswith(target_directory):
277 key_manager.RemoveKeyFromImage() 286 key_manager.RemoveKeyFromImage()
278 287
279 288
280 if __name__ == '__main__': 289 if __name__ == '__main__':
281 main() 290 main()
OLDNEW
« no previous file with comments | « no previous file | au_test_harness/parallel_test_job.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698