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

Side by Side Diff: bin/cros_au_test_harness.py

Issue 3536018: Fixes for cbuild to work with ctest. (Closed) Base URL: http://git.chromium.org/git/crosutils.git
Patch Set: Fixes for petkov Created 10 years, 2 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 | bin/ctest.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) 2010 The Chromium OS Authors. All rights reserved. 3 # Copyright (c) 2010 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 import optparse 7 import optparse
8 import os 8 import os
9 import sys 9 import sys
10 import unittest 10 import unittest
11 11
12 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib')) 12 sys.path.append(os.path.join(os.path.dirname(__file__), '../lib'))
13 from cros_build_lib import RunCommand, Info, Warning, ReinterpretPathForChroot 13 from cros_build_lib import Die
14 from cros_build_lib import Info
15 from cros_build_lib import ReinterpretPathForChroot
16 from cros_build_lib import RunCommand
17 from cros_build_lib import Warning
18
14 19
15 _KVM_PID_FILE = '/tmp/harness_pid' 20 _KVM_PID_FILE = '/tmp/harness_pid'
16 _FULL_VDISK_SIZE = 6072 21 _FULL_VDISK_SIZE = 6072
17 _FULL_STATEFULFS_SIZE = 2048 22 _FULL_STATEFULFS_SIZE = 2048
18 23
19 # Globals to communicate options to unit tests. 24 # Globals to communicate options to unit tests.
20 global base_image_path 25 global base_image_path
21 global board 26 global board
22 global remote 27 global remote
23 global target_image_path 28 global target_image_path
29 global vm_graphics_flag
30
24 31
25 _VERIFY_SUITE = 'suite_Smoke' 32 _VERIFY_SUITE = 'suite_Smoke'
26 33
27 class AUTest(object): 34 class AUTest(object):
28 """Abstract interface that defines an Auto Update test.""" 35 """Abstract interface that defines an Auto Update test."""
29 36
30 def setUp(self): 37 def setUp(self):
31 unittest.TestCase.setUp(self) 38 unittest.TestCase.setUp(self)
32 # Set these up as they are used often. 39 # Set these up as they are used often.
33 self.crosutils = os.path.join(os.path.dirname(__file__), '..') 40 self.crosutils = os.path.join(os.path.dirname(__file__), '..')
34 self.crosutilsbin = os.path.join(os.path.dirname(__file__)) 41 self.crosutilsbin = os.path.join(os.path.dirname(__file__))
35 42
36 def GetStatefulChangeFlag(self, stateful_change): 43 def GetStatefulChangeFlag(self, stateful_change):
37 """Returns the flag to pass to image_to_vm for the stateful change.""" 44 """Returns the flag to pass to image_to_vm for the stateful change."""
38 stateful_change_flag = '' 45 stateful_change_flag = ''
39 if stateful_change: 46 if stateful_change:
40 stateful_change_flag = '--stateful_update_flag=%s' % stateful_change 47 stateful_change_flag = '--stateful_update_flag=%s' % stateful_change
41 48
42 return stateful_change_flag 49 return stateful_change_flag
43 50
51 def ParseGenerateTestReportOutput(self, output):
52 """Returns the percentage of tests that passed based on output."""
53 percent_passed = 0
54 lines = output.split('\n')
55
56 for line in lines:
57 if line.startswith("Total PASS:"):
58 # FORMAT: ^TOTAL PASS: num_passed/num_total (percent%)$
59 percent_passed = line.split()[3].strip('()%')
60 Info('Percent of tests passed %s' % percent_passed)
61 break
62
63 return int(percent_passed)
64
44 def PrepareBase(self): 65 def PrepareBase(self):
45 """Prepares target with base_image_path.""" 66 """Prepares target with base_image_path."""
46 pass 67 pass
47 68
48 def UpdateImage(self, image_path, stateful_change='old'): 69 def UpdateImage(self, image_path, stateful_change='old'):
49 """Updates target with the image given by the image_path. 70 """Updates target with the image given by the image_path.
50 71
51 Args: 72 Args:
52 image_path: Path to the image to update with. This image must be a test 73 image_path: Path to the image to update with. This image must be a test
53 image. 74 image.
54 stateful_change: How to modify the stateful partition. Values are: 75 stateful_change: How to modify the stateful partition. Values are:
55 'old': Don't modify stateful partition. Just update normally. 76 'old': Don't modify stateful partition. Just update normally.
56 'clean': Uses clobber-state to wipe the stateful partition with the 77 'clean': Uses clobber-state to wipe the stateful partition with the
57 exception of code needed for ssh. 78 exception of code needed for ssh.
58 """ 79 """
59 pass 80 pass
60 81
61 def VerifyImage(self): 82 def VerifyImage(self, percent_required_to_pass):
62 """Verifies the image is correct.""" 83 """Verifies the image with tests.
84
85 Verifies that the test images passes the percent required.
86
87 Args:
88 percent_required_to_pass: percentage required to pass. This should be
89 fall between 0-100.
90
91 Returns:
92 Returns the percent that passed.
93 """
63 pass 94 pass
64 95
96 def CommonVerifyImage(self, unittest, output, percent_required_to_pass):
97 """Helper function for VerifyImage that returns percent of tests passed.
98
99 Takes output from a test suite, verifies the number of tests passed is
100 sufficient and outputs info.
101
102 Args:
103 unittest: Handle to the unittest.
104 output: stdout from a test run.
105 percent_required_to_pass: percentage required to pass. This should be
106 fall between 0-100.
107 Returns:
108 percent that passed.
109 """
110 Info('Output from VerifyImage():')
111 print output
112 percent_passed = self.ParseGenerateTestReportOutput(output)
113 Info('Percent passed: %d vs. Percent required: %d' % (
114 percent_passed, percent_required_to_pass))
115 unittest.assertTrue(percent_passed >=
116 percent_required_to_pass)
117 return percent_passed
118
65 def testFullUpdateKeepStateful(self): 119 def testFullUpdateKeepStateful(self):
66 """Tests if we can update normally. 120 """Tests if we can update normally.
67 121
68 This test checks that we can update by updating the stateful partition 122 This test checks that we can update by updating the stateful partition
69 rather than wiping it. 123 rather than wiping it.
70 """ 124 """
71 # Prepare and verify the base image has been prepared correctly. 125 # Just make sure some tests pass on original image. Some old images
126 # don't pass many tests.
72 self.PrepareBase() 127 self.PrepareBase()
73 self.VerifyImage() 128 # TODO(sosa): move to 100% once we start testing using the autotest paired
129 # with the dev channel.
130 percent_passed = self.VerifyImage(42)
74 131
75 # Update to. 132 # Update to - all tests should pass on new image.
76 Info('Updating from base image on vm to target image.') 133 Info('Updating from base image on vm to target image.')
77 self.UpdateImage(target_image_path) 134 self.UpdateImage(target_image_path)
78 self.VerifyImage() 135 self.VerifyImage(100)
79 136
80 # Update from. 137 # Update from - same percentage should pass that originally passed.
81 Info('Updating from updated image on vm back to base image.') 138 Info('Updating from updated image on vm back to base image.')
82 self.UpdateImage(base_image_path) 139 self.UpdateImage(base_image_path)
83 self.VerifyImage() 140 self.VerifyImage(percent_passed)
84 141
85 # TODO(sosa): Re-enable once we have a good way of checking for version 142 # TODO(sosa): Re-enable once we have a good way of checking for version
86 # compatability. 143 # compatibility.
87 def NotestFullUpdateWipeStateful(self): 144 def NotestFullUpdateWipeStateful(self):
88 """Tests if we can update after cleaning the stateful partition. 145 """Tests if we can update after cleaning the stateful partition.
89 146
90 This test checks that we can update successfully after wiping the 147 This test checks that we can update successfully after wiping the
91 stateful partition. 148 stateful partition.
92 """ 149 """
93 # Prepare and verify the base image has been prepared correctly. 150 # Just make sure some tests pass on original image. Some old images
151 # don't pass many tests.
94 self.PrepareBase() 152 self.PrepareBase()
95 self.VerifyImage() 153 # TODO(sosa): move to 100% once we start testing using the autotest paired
154 # with the dev channel.
155 percent_passed = self.VerifyImage(42)
96 156
97 # Update to. 157 # Update to - all tests should pass on new image.
98 Info('Updating from base image on vm to target image and wiping stateful.') 158 Info('Updating from base image on vm to target image and wiping stateful.')
99 self.UpdateImage(target_image_path, 'clean') 159 self.UpdateImage(target_image_path, 'clean')
100 self.VerifyImage() 160 self.VerifyImage(100)
101 161
102 # Update from. 162 # Update from - same percentage should pass that originally passed.
103 Info('Updating from updated image back to base image and wiping stateful.') 163 Info('Updating from updated image back to base image and wiping stateful.')
104 self.UpdateImage(base_image_path, 'clean') 164 self.UpdateImage(base_image_path, 'clean')
105 self.VerifyImage() 165 self.VerifyImage(percent_passed)
106 166
107 167
108 class RealAUTest(unittest.TestCase, AUTest): 168 class RealAUTest(unittest.TestCase, AUTest):
109 """Test harness for updating real images.""" 169 """Test harness for updating real images."""
110 170
111 def setUp(self): 171 def setUp(self):
112 AUTest.setUp(self) 172 AUTest.setUp(self)
113 173
174 def PrepareBase(self):
175 """Auto-update to base image to prepare for test."""
176 self.UpdateImage(base_image_path)
177
114 def UpdateImage(self, image_path, stateful_change='old'): 178 def UpdateImage(self, image_path, stateful_change='old'):
115 """Updates a remote image using image_to_live.sh.""" 179 """Updates a remote image using image_to_live.sh."""
116 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 180 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
117 181
118 RunCommand([ 182 RunCommand([
119 '%s/image_to_live.sh' % self.crosutils, 183 '%s/image_to_live.sh' % self.crosutils,
120 '--image=%s' % image_path, 184 '--image=%s' % image_path,
121 '--remote=%s' % remote, 185 '--remote=%s' % remote,
122 stateful_change_flag, 186 stateful_change_flag,
123 '--verify', 187 '--verify',
124 ], enter_chroot=False) 188 ], enter_chroot=False)
125 189
126 190
127 def VerifyImage(self): 191 def VerifyImage(self, percent_required_to_pass):
128 """Verifies an image using run_remote_tests.sh with verification suite.""" 192 """Verifies an image using run_remote_tests.sh with verification suite."""
129 RunCommand([ 193 output = RunCommand([
130 '%s/run_remote_tests.sh' % self.crosutils, 194 '%s/run_remote_tests.sh' % self.crosutils,
131 '--remote=%s' % remote, 195 '--remote=%s' % remote,
132 _VERIFY_SUITE, 196 _VERIFY_SUITE,
133 ], error_ok=False, enter_chroot=False) 197 ], error_ok=True, enter_chroot=False, redirect_stdout=True)
198 return self.CommonVerifyImage(self, output, percent_required_to_pass)
134 199
135 200
136 class VirtualAUTest(unittest.TestCase, AUTest): 201 class VirtualAUTest(unittest.TestCase, AUTest):
137 """Test harness for updating virtual machines.""" 202 """Test harness for updating virtual machines."""
138 vm_image_path = None 203 vm_image_path = None
139 204
140 def _KillExistingVM(self, pid_file): 205 def _KillExistingVM(self, pid_file):
141 if os.path.exists(pid_file): 206 if os.path.exists(pid_file):
142 Warning('Existing %s found. Deleting and killing process' % 207 Warning('Existing %s found. Deleting and killing process' %
143 pid_file) 208 pid_file)
(...skipping 30 matching lines...) Expand all
174 self.assertTrue(os.path.exists(self.vm_image_path)) 239 self.assertTrue(os.path.exists(self.vm_image_path))
175 240
176 def UpdateImage(self, image_path, stateful_change='old'): 241 def UpdateImage(self, image_path, stateful_change='old'):
177 """Updates VM image with image_path.""" 242 """Updates VM image with image_path."""
178 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change) 243 stateful_change_flag = self.GetStatefulChangeFlag(stateful_change)
179 244
180 RunCommand(['%s/cros_run_vm_update' % self.crosutilsbin, 245 RunCommand(['%s/cros_run_vm_update' % self.crosutilsbin,
181 '--update_image_path=%s' % image_path, 246 '--update_image_path=%s' % image_path,
182 '--vm_image_path=%s' % self.vm_image_path, 247 '--vm_image_path=%s' % self.vm_image_path,
183 '--snapshot', 248 '--snapshot',
249 vm_graphics_flag,
184 '--persist', 250 '--persist',
185 '--kvm_pid=%s' % _KVM_PID_FILE, 251 '--kvm_pid=%s' % _KVM_PID_FILE,
186 stateful_change_flag, 252 stateful_change_flag,
187 ], enter_chroot=False) 253 ], enter_chroot=False)
188 254
189 def VerifyImage(self): 255 def VerifyImage(self, percent_required_to_pass):
190 """Runs vm smoke suite to verify image.""" 256 """Runs vm smoke suite to verify image."""
191 # image_to_live already verifies lsb-release matching. This is just 257 # image_to_live already verifies lsb-release matching. This is just
192 # for additional steps. 258 # for additional steps.
193 RunCommand(['%s/cros_run_vm_test' % self.crosutilsbin, 259 output = RunCommand(['%s/cros_run_vm_test' % self.crosutilsbin,
194 '--image_path=%s' % self.vm_image_path, 260 '--image_path=%s' % self.vm_image_path,
195 '--snapshot', 261 '--snapshot',
196 '--persist', 262 '--persist',
197 '--kvm_pid=%s' % _KVM_PID_FILE, 263 vm_graphics_flag,
198 '--test_case=%s' % _VERIFY_SUITE, 264 '--kvm_pid=%s' % _KVM_PID_FILE,
199 ], error_ok=False, enter_chroot=False) 265 '--test_case=%s' % _VERIFY_SUITE,
266 ], error_ok=True, enter_chroot=False,
267 redirect_stdout=True)
268 return self.CommonVerifyImage(self, output, percent_required_to_pass)
200 269
201 270
202 if __name__ == '__main__': 271 if __name__ == '__main__':
203 parser = optparse.OptionParser() 272 parser = optparse.OptionParser()
204 parser.add_option('-b', '--base_image', 273 parser.add_option('-b', '--base_image',
205 help='path to the base image.') 274 help='path to the base image.')
206 parser.add_option('-t', '--target_image', 275 parser.add_option('-t', '--target_image',
207 help='path to the target image.') 276 help='path to the target image.')
208 parser.add_option('-r', '--board', 277 parser.add_option('-r', '--board',
209 help='board for the images.') 278 help='board for the images.')
210 parser.add_option('-p', '--type', default='vm', 279 parser.add_option('-p', '--type', default='vm',
211 help='type of test to run: [vm, real]. Default: vm.') 280 help='type of test to run: [vm, real]. Default: vm.')
212 parser.add_option('-m', '--remote', 281 parser.add_option('-m', '--remote',
213 help='Remote address for real test.') 282 help='Remote address for real test.')
283 parser.add_option('--no_graphics', action='store_true',
284 help='Disable graphics for the vm test.')
214 # Set the usage to include flags. 285 # Set the usage to include flags.
215 parser.set_usage(parser.format_help()) 286 parser.set_usage(parser.format_help())
216 # Parse existing sys.argv so we can pass rest to unittest.main. 287 # Parse existing sys.argv so we can pass rest to unittest.main.
217 (options, sys.argv) = parser.parse_args(sys.argv) 288 (options, sys.argv) = parser.parse_args(sys.argv)
218 289
219 base_image_path = options.base_image 290 base_image_path = options.base_image
220 target_image_path = options.target_image 291 target_image_path = options.target_image
221 board = options.board 292 board = options.board
222 293
223 if not base_image_path: 294 if not base_image_path:
224 parser.error('Need path to base image for vm.') 295 parser.error('Need path to base image for vm.')
296 elif not os.path.exists(base_image_path):
297 Die('%s does not exist' % base_image_path)
225 298
226 if not target_image_path: 299 if not target_image_path:
227 parser.error('Need path to target image to update with.') 300 parser.error('Need path to target image to update with.')
301 elif not os.path.exists(target_image_path):
302 Die('%s does not exist' % target_image_path)
228 303
229 if not board: 304 if not board:
230 parser.error('Need board to convert base image to vm.') 305 parser.error('Need board to convert base image to vm.')
231 306
232 return_code = 0 307 vm_graphics_flag = ''
308 if options.no_graphics: vm_graphics_flag = '--no_graphics'
233 309
234 # Only run the test harness we care about. 310 # Only run the test harness we care about.
235 if options.type == 'vm': 311 if options.type == 'vm':
236 suite = unittest.TestLoader().loadTestsFromTestCase(VirtualAUTest) 312 suite = unittest.TestLoader().loadTestsFromTestCase(VirtualAUTest)
237 return_code = unittest.TextTestRunner(verbosity=2).run(suite) 313 test_result = unittest.TextTestRunner(verbosity=2).run(suite)
238 elif options.type == 'real': 314 elif options.type == 'real':
239 if not options.remote: 315 if not options.remote:
240 parser.error('Real tests require a remote test machine.') 316 parser.error('Real tests require a remote test machine.')
241 else: 317 else:
242 remote = options.remote 318 remote = options.remote
243 319
244 suite = unittest.TestLoader().loadTestsFromTestCase(RealAUTest) 320 suite = unittest.TestLoader().loadTestsFromTestCase(RealAUTest)
245 return_code = unittest.TextTestRunner(verbosity=2).run(suite) 321 test_result = unittest.TextTestRunner(verbosity=2).run(suite)
246 else: 322 else:
247 parser.error('Could not parse harness type %s.' % options.type) 323 parser.error('Could not parse harness type %s.' % options.type)
248 324
249 sys.exit(return_code) 325 if not test_result.wasSuccessful():
326 Die('Test harness was not successful')
OLDNEW
« no previous file with comments | « no previous file | bin/ctest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698