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

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

Issue 6717011: Remove au_test_harness code and change symlinks to point to new location (Closed) Base URL: http://git.chromium.org/git/crosutils.git@master
Patch 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/cros_au_test_harness.py » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 # Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
4
5 """Module that contains the interface for au_test_harness workers.
6
7 An au test harnss worker is a class that contains the logic for performing
8 and validating updates on a target. This should be subclassed to handle
9 various types of target. Types of targets include VM's, real devices, etc.
10 """
11
12 import inspect
13 import threading
14 import os
15 import sys
16
17 import cros_build_lib as cros_lib
18
19 import dev_server_wrapper
20 import update_exception
21
22
23 class AUWorker(object):
24 """Interface for a worker that updates and verifies images."""
25 # Mapping between cached payloads to directory locations.
26 update_cache = None
27
28 # --- INTERFACE ---
29
30 def __init__(self, options, test_results_root):
31 """Processes options for the specific-type of worker."""
32 self.board = options.board
33 self.private_key = options.private_key
34 self.test_results_root = test_results_root
35 self.use_delta_updates = options.delta
36 self.verbose = options.verbose
37 self.vm_image_path = None
38 if options.quick_test:
39 self.verify_suite = 'build_RootFilesystemSize'
40 else:
41 self.verify_suite = 'suite_Smoke'
42
43 # Set these up as they are used often.
44 self.crosutils = os.path.join(os.path.dirname(__file__), '..', '..')
45 self.crosutilsbin = os.path.join(os.path.dirname(__file__), '..')
46
47 def CleanUp(self):
48 """Called at the end of every test."""
49 pass
50
51 def UpdateImage(self, image_path, src_image_path='', stateful_change='old',
52 proxy_port=None, private_key_path=None):
53 """Implementation of an actual update.
54
55 See PerformUpdate for description of args. Subclasses must override this
56 method with the correct update procedure for the class.
57 """
58 pass
59
60 def UpdateUsingPayload(self, update_path, stateful_change='old',
61 proxy_port=None):
62 """Updates target with the pre-generated update stored in update_path.
63
64 Subclasses must override this method with the correct update procedure for
65 the class.
66
67 Args:
68 update_path: Path to the image to update with. This directory should
69 contain both update.gz, and stateful.image.gz
70 proxy_port: Port to have the client connect to. For use with
71 CrosTestProxy.
72 """
73 pass
74
75 def VerifyImage(self, unittest, percent_required_to_pass=100):
76 """Verifies the image with tests.
77
78 Verifies that the test images passes the percent required. Subclasses must
79 override this method with the correct update procedure for the class.
80
81 Args:
82 unittest: pointer to a unittest to fail if we cannot verify the image.
83 percent_required_to_pass: percentage required to pass. This should be
84 fall between 0-100.
85
86 Returns:
87 Returns the percent that passed.
88 """
89 pass
90
91 # --- INTERFACE TO AU_TEST ---
92
93 def PerformUpdate(self, image_path, src_image_path='', stateful_change='old',
94 proxy_port=None, private_key_path=None):
95 """Performs an update using _UpdateImage and reports any error.
96
97 Subclasses should not override this method but override _UpdateImage
98 instead.
99
100 Args:
101 image_path: Path to the image to update with. This image must be a test
102 image.
103 src_image_path: Optional. If set, perform a delta update using the
104 image specified by the path as the source image.
105 stateful_change: How to modify the stateful partition. Values are:
106 'old': Don't modify stateful partition. Just update normally.
107 'clean': Uses clobber-state to wipe the stateful partition with the
108 exception of code needed for ssh.
109 proxy_port: Port to have the client connect to. For use with
110 CrosTestProxy.
111 private_key_path: Path to a private key to use with update payload.
112 Raises an update_exception.UpdateException if _UpdateImage returns an error.
113 """
114 try:
115 if not self.use_delta_updates: src_image_path = ''
116 if private_key_path:
117 key_to_use = private_key_path
118 else:
119 key_to_use = self.private_key
120
121 self.UpdateImage(image_path, src_image_path, stateful_change,
122 proxy_port, key_to_use)
123 except update_exception.UpdateException as err:
124 # If the update fails, print it out
125 Warning(err.stdout)
126 raise
127
128 @classmethod
129 def SetUpdateCache(cls, update_cache):
130 """Sets the global update cache for getting paths to devserver payloads."""
131 cls.update_cache = update_cache
132
133 # --- METHODS FOR SUB CLASS USE ---
134
135 def PrepareRealBase(self, image_path):
136 """Prepares a remote device for worker test by updating it to the image."""
137 self.UpdateImage(image_path)
138
139 def PrepareVMBase(self, image_path):
140 """Prepares a VM image for worker test by creating the VM file from the img.
141 """
142 # VM Constants.
143 FULL_VDISK_SIZE = 6072
144 FULL_STATEFULFS_SIZE = 3074
145 # Needed for VM delta updates. We need to use the qemu image rather
146 # than the base image on a first update. By tracking the first_update
147 # we can set src_image to the qemu form of the base image when
148 # performing generating the delta payload.
149 self._first_update = True
150 self.vm_image_path = '%s/chromiumos_qemu_image.bin' % os.path.dirname(
151 image_path)
152 if not os.path.exists(self.vm_image_path):
153 cros_lib.Info('Creating %s' % self.vm_image_path)
154 cros_lib.RunCommand(['./image_to_vm.sh',
155 '--full',
156 '--from=%s' % cros_lib.ReinterpretPathForChroot(
157 os.path.dirname(image_path)),
158 '--vdisk_size=%s' % FULL_VDISK_SIZE,
159 '--statefulfs_size=%s' % FULL_STATEFULFS_SIZE,
160 '--board=%s' % self.board,
161 '--test_image'
162 ], enter_chroot=True, cwd=self.crosutils)
163
164 cros_lib.Info('Using %s as base' % self.vm_image_path)
165 assert os.path.exists(self.vm_image_path)
166
167 def GetStatefulChangeFlag(self, stateful_change):
168 """Returns the flag to pass to image_to_vm for the stateful change."""
169 stateful_change_flag = ''
170 if stateful_change:
171 stateful_change_flag = '--stateful_update_flag=%s' % stateful_change
172
173 return stateful_change_flag
174
175 def AppendUpdateFlags(self, cmd, image_path, src_image_path, proxy_port,
176 private_key_path):
177 """Appends common args to an update cmd defined by an array.
178
179 Modifies cmd in places by appending appropriate items given args.
180 """
181 if proxy_port: cmd.append('--proxy_port=%s' % proxy_port)
182
183 # Get pregenerated update if we have one.
184 update_id = dev_server_wrapper.GenerateUpdateId(image_path, src_image_path,
185 private_key_path)
186 cache_path = self.update_cache[update_id]
187 if cache_path:
188 update_url = dev_server_wrapper.DevServerWrapper.GetDevServerURL(
189 proxy_port, cache_path)
190 cmd.append('--update_url=%s' % update_url)
191 else:
192 cmd.append('--image=%s' % image_path)
193 if src_image_path: cmd.append('--src_image=%s' % src_image_path)
194
195 def RunUpdateCmd(self, cmd, log_directory=None):
196 """Runs the given update cmd given verbose options.
197
198 Raises an update_exception.UpdateException if the update fails.
199 """
200 if self.verbose:
201 try:
202 if log_directory:
203 cros_lib.RunCommand(cmd, log_to_file=os.path.join(log_directory,
204 'update.log'))
205 else:
206 cros_lib.RunCommand(cmd)
207 except Exception as e:
208 Warning(str(e))
209 raise update_exception.UpdateException(1, str(e))
210 else:
211 (code, stdout, stderr) = cros_lib.RunCommandCaptureOutput(cmd)
212 if code != 0:
213 Warning(stdout)
214 raise update_exception.UpdateException(code, stdout)
215
216 def AssertEnoughTestsPassed(self, unittest, output, percent_required_to_pass):
217 """Helper function that asserts a sufficient number of tests passed.
218
219 Args:
220 output: stdout from a test run.
221 percent_required_to_pass: percentage required to pass. This should be
222 fall between 0-100.
223 Returns:
224 percent that passed.
225 """
226 cros_lib.Info('Output from VerifyImage():')
227 print >> sys.stderr, output
228 sys.stderr.flush()
229 percent_passed = self._ParseGenerateTestReportOutput(output)
230 cros_lib.Info('Percent passed: %d vs. Percent required: %d' % (
231 percent_passed, percent_required_to_pass))
232 unittest.assertTrue(percent_passed >= percent_required_to_pass)
233 return percent_passed
234
235 def InitializeResultsDirectory(self):
236 """Called by a test to initialize a results directory for this worker."""
237 # Use the name of the test.
238 test_name = inspect.stack()[1][3]
239 self.results_directory = os.path.join(self.test_results_root, test_name)
240 self.results_count = 0
241
242 def GetNextResultsPath(self, label):
243 """Returns a path for the results directory for this label.
244
245 Prefixes directory returned for worker with time called i.e. 1_label,
246 2_label, etc. The directory returned is outside the chroot so if passing
247 to an script that is called with enther_chroot, make sure to use
248 ReinterpretPathForChroot.
249 """
250 self.results_count += 1
251 dir = os.path.join(self.results_directory, '%s_%s' % (self.results_count,
252 label))
253 if not os.path.exists(dir):
254 os.makedirs(dir)
255
256 return dir
257
258 # --- PRIVATE HELPER FUNCTIONS ---
259
260 def _ParseGenerateTestReportOutput(self, output):
261 """Returns the percentage of tests that passed based on output."""
262 percent_passed = 0
263 lines = output.split('\n')
264
265 for line in lines:
266 if line.startswith("Total PASS:"):
267 # FORMAT: ^TOTAL PASS: num_passed/num_total (percent%)$
268 percent_passed = line.split()[3].strip('()%')
269 cros_lib.Info('Percent of tests passed %s' % percent_passed)
270 break
271
272 return int(percent_passed)
OLDNEW
« no previous file with comments | « bin/au_test_harness/au_test.py ('k') | bin/au_test_harness/cros_au_test_harness.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698