OLD | NEW |
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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 ] | 61 ] |
62 # Add actual args to command. | 62 # Add actual args to command. |
63 command.append('--image=%s' % cros_lib.ReinterpretPathForChroot(target)) | 63 command.append('--image=%s' % cros_lib.ReinterpretPathForChroot(target)) |
64 if src: command.append('--src_image=%s' % | 64 if src: command.append('--src_image=%s' % |
65 cros_lib.ReinterpretPathForChroot(src)) | 65 cros_lib.ReinterpretPathForChroot(src)) |
66 if options.type == 'vm': command.append('--for_vm') | 66 if options.type == 'vm': command.append('--for_vm') |
67 if private_key_path: | 67 if private_key_path: |
68 command.append('--private_key=%s' % | 68 command.append('--private_key=%s' % |
69 cros_lib.ReinterpretPathForChroot(private_key_path)) | 69 cros_lib.ReinterpretPathForChroot(private_key_path)) |
70 | 70 |
71 return cros_lib.RunCommand(command, enter_chroot=True, print_cmd=True, | 71 if src: |
| 72 debug_message = 'delta update payload from %s to %s' % (target, src) |
| 73 else: |
| 74 debug_message = 'full update payload to %s' % target |
| 75 |
| 76 if private_key_path: |
| 77 debug_message = 'Generating a signed ' + debug_message |
| 78 else: |
| 79 debug_message = 'Generating an unsigned ' + debug_message |
| 80 |
| 81 cros_lib.Info(debug_message) |
| 82 return cros_lib.RunCommand(command, enter_chroot=True, print_cmd=False, |
72 cwd=cros_lib.GetCrosUtilsPath(), | 83 cwd=cros_lib.GetCrosUtilsPath(), |
73 log_to_file=log_file, error_ok=True, | 84 log_to_file=log_file, error_ok=True, |
74 exit_code=True) | 85 exit_code=True) |
75 | 86 |
76 def _ProcessGeneratorOutputs(log_files, return_codes): | 87 def _ProcessGeneratorOutputs(log_files, return_codes): |
77 """Processes results from the log files of GenerateVMUpdate calls. | 88 """Processes results from the log files of GenerateVMUpdate calls. |
78 | 89 |
79 Returns an array of cache entries from the log files. | 90 Returns an array of cache entries from the log files. |
80 """ | 91 """ |
81 return_array = [] | 92 return_array = [] |
(...skipping 17 matching lines...) Expand all Loading... |
99 path_to_update_gz = match.group(1).rstrip() | 110 path_to_update_gz = match.group(1).rstrip() |
100 (path_to_update_dir, _, _) = path_to_update_gz.rpartition( | 111 (path_to_update_dir, _, _) = path_to_update_gz.rpartition( |
101 '/update.gz') | 112 '/update.gz') |
102 return_array.append('/'.join(['update', path_to_update_dir])) | 113 return_array.append('/'.join(['update', path_to_update_dir])) |
103 | 114 |
104 assert len(return_array) == len(log_files), 'Return result size mismatch.' | 115 assert len(return_array) == len(log_files), 'Return result size mismatch.' |
105 return return_array | 116 return return_array |
106 | 117 |
107 # Use dummy class to mock out updates that would be run as part of a test. | 118 # Use dummy class to mock out updates that would be run as part of a test. |
108 test_suite = _PrepareTestSuite(options, use_dummy_worker=True) | 119 test_suite = _PrepareTestSuite(options, use_dummy_worker=True) |
109 test_result = unittest.TextTestRunner(verbosity=0).run(test_suite) | 120 test_result = unittest.TextTestRunner( |
| 121 stream=open(os.devnull, 'w')).run(test_suite) |
110 if not test_result.wasSuccessful(): | 122 if not test_result.wasSuccessful(): |
111 raise update_exception.UpdateException(1, | 123 raise update_exception.UpdateException(1, |
112 'Error finding updates to generate.') | 124 'Error finding updates to generate.') |
113 | |
114 cros_lib.Info('The following delta updates are required.') | |
115 update_ids = [] | 125 update_ids = [] |
116 jobs = [] | 126 jobs = [] |
117 args = [] | 127 args = [] |
118 log_files = [] | 128 log_files = [] |
119 modified_images = set() | 129 modified_images = set() |
120 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items(): | 130 for target, srcs in dummy_au_worker.DummyAUWorker.delta_list.items(): |
121 modified_images.add(target) | 131 modified_images.add(target) |
122 for src_key in srcs: | 132 for src_key in srcs: |
123 log_file = tempfile.mktemp('GenerateVMUpdate') | 133 log_file = tempfile.mktemp('GenerateVMUpdate') |
124 (src, _ , key) = src_key.partition('+') | 134 (src, _ , key) = src_key.partition('+') |
125 if src: modified_images.add(src) | 135 if src: modified_images.add(src) |
126 # TODO(sosa): Add private key as part of caching name once devserver can | 136 # TODO(sosa): Add private key as part of caching name once devserver can |
127 # handle it its own cache. | 137 # handle it its own cache. |
128 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key) | 138 update_id = dev_server_wrapper.GenerateUpdateId(target, src, key) |
129 print >> sys.stderr, 'AU: %s' % update_id | |
130 update_ids.append(update_id) | 139 update_ids.append(update_id) |
131 jobs.append(_GenerateVMUpdate) | 140 jobs.append(_GenerateVMUpdate) |
132 args.append((target, src, key, log_file)) | 141 args.append((target, src, key, log_file)) |
133 log_files.append(log_file) | 142 log_files.append(log_file) |
134 | 143 |
135 # Always add the base image path. This is only useful for non-delta updates. | 144 # Always add the base image path. This is only useful for non-delta updates. |
136 modified_images.add(options.base_image) | 145 modified_images.add(options.base_image) |
137 | 146 |
138 # Add public key to all images we are using. | 147 # Add public key to all images we are using. |
139 if options.public_key: | 148 if options.public_key: |
140 cros_lib.Info('Adding public keys to images for testing.') | 149 cros_lib.Info('Adding public keys to images for testing.') |
141 for image in modified_images: | 150 for image in modified_images: |
142 manager = public_key_manager.PublicKeyManager(image, options.public_key) | 151 manager = public_key_manager.PublicKeyManager(image, options.public_key) |
143 manager.AddKeyToImage() | 152 manager.AddKeyToImage() |
144 au_test.AUTest.public_key_managers.append(manager) | 153 au_test.AUTest.public_key_managers.append(manager) |
145 | 154 |
| 155 cros_lib.Info('Generating updates required for this test suite in parallel.') |
146 error_codes = parallel_test_job.RunParallelJobs(options.jobs, jobs, args) | 156 error_codes = parallel_test_job.RunParallelJobs(options.jobs, jobs, args) |
147 results = _ProcessGeneratorOutputs(log_files, error_codes) | 157 results = _ProcessGeneratorOutputs(log_files, error_codes) |
148 | 158 |
149 # Build the dictionary from our id's and returned cache paths. | 159 # Build the dictionary from our id's and returned cache paths. |
150 cache_dictionary = {} | 160 cache_dictionary = {} |
151 for index, id in enumerate(update_ids): | 161 for index, id in enumerate(update_ids): |
152 cache_dictionary[id] = results[index] | 162 cache_dictionary[id] = results[index] |
153 | 163 |
154 return cache_dictionary | 164 return cache_dictionary |
155 | 165 |
156 | 166 |
157 def _RunTestsInParallel(options): | 167 def _RunTestsInParallel(options): |
158 """Runs the tests given by the options in parallel.""" | 168 """Runs the tests given by the options in parallel.""" |
159 threads = [] | 169 threads = [] |
160 args = [] | 170 args = [] |
161 test_suite = _PrepareTestSuite(options) | 171 test_suite = _PrepareTestSuite(options) |
162 for test in test_suite: | 172 for test in test_suite: |
163 test_name = test.id() | 173 test_name = test.id() |
164 test_case = unittest.TestLoader().loadTestsFromName(test_name) | 174 test_case = unittest.TestLoader().loadTestsFromName(test_name) |
165 threads.append(unittest.TextTestRunner(verbosity=2).run) | 175 threads.append(unittest.TextTestRunner().run) |
166 args.append(test_case) | 176 args.append(test_case) |
167 | 177 |
| 178 cros_lib.Info('Running tests in test suite in parallel.') |
168 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args) | 179 results = parallel_test_job.RunParallelJobs(options.jobs, threads, args) |
169 for test_result in results: | 180 for test_result in results: |
170 if not test_result.wasSuccessful(): | 181 if not test_result.wasSuccessful(): |
171 cros_lib.Die('Test harness was not successful') | 182 cros_lib.Die( |
| 183 'Test harness was not successful. See logs for details. ' |
| 184 'Note: Ignore max recursion depth errors crosbug.com/14274') |
172 | 185 |
173 | 186 |
174 def _CleanPreviousWork(options): | 187 def _CleanPreviousWork(options): |
175 """Cleans up previous work from the devserver cache and local image cache.""" | 188 """Cleans up previous work from the devserver cache and local image cache.""" |
176 cros_lib.Info('Cleaning up previous work.') | 189 cros_lib.Info('Cleaning up previous work.') |
177 # Wipe devserver cache. | 190 # Wipe devserver cache. |
178 cros_lib.RunCommandCaptureOutput( | 191 cros_lib.RunCommandCaptureOutput( |
179 ['sudo', 'start_devserver', '--clear_cache', '--exit', ], | 192 ['sudo', 'start_devserver', '--clear_cache', '--exit', ], |
180 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True, | 193 enter_chroot=True, print_cmd=False, combine_stdout_stderr=True, |
181 cwd=cros_lib.GetCrosUtilsPath()) | 194 cwd=cros_lib.GetCrosUtilsPath()) |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
262 my_server = dev_server_wrapper.DevServerWrapper( | 275 my_server = dev_server_wrapper.DevServerWrapper( |
263 au_test.AUTest.test_results_root) | 276 au_test.AUTest.test_results_root) |
264 my_server.start() | 277 my_server.start() |
265 try: | 278 try: |
266 if options.type == 'vm': | 279 if options.type == 'vm': |
267 _RunTestsInParallel(options) | 280 _RunTestsInParallel(options) |
268 else: | 281 else: |
269 # TODO(sosa) - Take in a machine pool for a real test. | 282 # TODO(sosa) - Take in a machine pool for a real test. |
270 # Can't run in parallel with only one remote device. | 283 # Can't run in parallel with only one remote device. |
271 test_suite = _PrepareTestSuite(options) | 284 test_suite = _PrepareTestSuite(options) |
272 test_result = unittest.TextTestRunner(verbosity=2).run(test_suite) | 285 test_result = unittest.TextTestRunner().run(test_suite) |
273 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.') | 286 if not test_result.wasSuccessful(): cros_lib.Die('Test harness failed.') |
274 | 287 |
275 finally: | 288 finally: |
276 my_server.Stop() | 289 my_server.Stop() |
277 | 290 |
278 finally: | 291 finally: |
279 # Un-modify any target images we modified. We don't need to un-modify | 292 # Un-modify any target images we modified. We don't need to un-modify |
280 # non-targets because they aren't important for archival steps. | 293 # non-targets because they aren't important for archival steps. |
281 if options.public_key: | 294 if options.public_key: |
282 cros_lib.Info('Cleaning up. Removing keys added as part of testing.') | 295 cros_lib.Info('Cleaning up. Removing keys added as part of testing.') |
283 target_directory = os.path.dirname(options.target_image) | 296 target_directory = os.path.dirname(options.target_image) |
284 for key_manager in au_test.AUTest.public_key_managers: | 297 for key_manager in au_test.AUTest.public_key_managers: |
285 if key_manager.image_path.startswith(target_directory): | 298 if key_manager.image_path.startswith(target_directory): |
286 key_manager.RemoveKeyFromImage() | 299 key_manager.RemoveKeyFromImage() |
287 | 300 |
288 | 301 |
289 if __name__ == '__main__': | 302 if __name__ == '__main__': |
290 main() | 303 main() |
OLD | NEW |