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

Side by Side Diff: saft_utility.py

Issue 3781016: Introduce SAFT TPM testing support. (Closed) Base URL: http://git.chromium.org/git/saft.git
Patch Set: Addressed review comments. 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 | « runtests.sh ('k') | test_tpm_handler.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 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved. 2 # Copyright (c) 2010 The Chromium OS Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be 3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file. 4 # found in the LICENSE file.
5 5
6 '''Test utility for verifying ChromeOS firmware.''' 6 '''Test utility for verifying ChromeOS firmware.'''
7 7
8 import datetime 8 import datetime
9 import functools 9 import functools
10 import getopt 10 import getopt
11 import os 11 import os
12 import re 12 import re
13 import shutil 13 import shutil
14 import sys 14 import sys
15 import tempfile 15 import tempfile
16 import traceback 16 import traceback
17 17
18 import cgpt_handler 18 import cgpt_handler
19 import chromeos_interface 19 import chromeos_interface
20 import flashrom_handler 20 import flashrom_handler
21 import kernel_handler 21 import kernel_handler
22 import saft_flashrom_util 22 import saft_flashrom_util
23 import tpm_handler
23 24
24 # 25 #
25 # We need to know the names of two files: 26 # We need to know the names of two files:
26 # 27 #
27 # - the SAFT shell script used by the upstart script (/etc/init/saft.conf) to 28 # - the SAFT shell script used by the upstart script (/etc/init/saft.conf) to
28 # determine if SAFT is in progress 29 # determine if SAFT is in progress
29 # 30 #
30 # - the name of the log file where the upstart script redirects its output. 31 # - the name of the log file where the upstart script redirects its output.
31 # 32 #
32 # These file names are defined in the upstart script as <NAME>=<VALUE>, one 33 # These file names are defined in the upstart script as <NAME>=<VALUE>, one
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
66 mkdir "${mount_point}" 67 mkdir "${mount_point}"
67 mount "${saft_dev}" "${mount_point}" 68 mount "${saft_dev}" "${mount_point}"
68 fi 69 fi
69 70
70 cd "${mount_point}%s" 71 cd "${mount_point}%s"
71 72
72 # Start our own X server to make it easier to control the screen 73 # Start our own X server to make it easier to control the screen
73 X_PORT=1 74 X_PORT=1
74 X :"${X_PORT}" -config saft.xorg.conf vt02 > /dev/null 2>&1 & 75 X :"${X_PORT}" -config saft.xorg.conf vt02 > /dev/null 2>&1 &
75 xpid="$!" 76 xpid="$!"
77 initctl stop update-engine # Prevent messing with cgpt attributes
76 export DISPLAY=":${X_PORT}.0" 78 export DISPLAY=":${X_PORT}.0"
77 ./%s --next_step 79 ./%s --next_step
78 kill "${xpid}" 80 kill "${xpid}"
79 ''' 81 '''
80 82
81 # Subdirectory to keep the state of this test over reboots. Created in the 83 # Subdirectory to keep the state of this test over reboots. Created in the
82 # /var on the USB flash drive the test is running from. 84 # /var on the USB flash drive the test is running from.
83 STATE_SUBDIR = '.fw_test' 85 STATE_SUBDIR = '.fw_test'
84 86
85 # Files storing SAFT state over reboots, located in state_dir defined below. 87 # Files storing SAFT state over reboots, located in state_dir defined below.
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 def __init__(self): 156 def __init__(self):
155 '''Object initializer, does nothing to make mocking easier.''' 157 '''Object initializer, does nothing to make mocking easier.'''
156 self.mydir = None 158 self.mydir = None
157 self.base_partition = None 159 self.base_partition = None
158 self.chros_if = None 160 self.chros_if = None
159 self.progname = None 161 self.progname = None
160 self.test_state_sequence = None 162 self.test_state_sequence = None
161 self.kern_handler = None 163 self.kern_handler = None
162 self.step_failed = False 164 self.step_failed = False
163 self.window = None 165 self.window = None
166 self.tpm_handler = None
164 167
165 def _verify_fw_id(self, compare_to_file): 168 def _verify_fw_id(self, compare_to_file):
166 '''Verify if the current firmware ID matches the contents a file. 169 '''Verify if the current firmware ID matches the contents a file.
167 170
168 compare_to_file - a string, name of the file in the state directory. 171 compare_to_file - a string, name of the file in the state directory.
169 ''' 172 '''
170 old_fwid = open( 173 old_fwid = open(
171 self.chros_if.state_dir_file(compare_to_file), 'r').read() 174 self.chros_if.state_dir_file(compare_to_file), 'r').read()
172 now_fwid = open(self.chros_if.acpi_file('FWID'), 'r').read() 175 now_fwid = open(self.chros_if.acpi_file('FWID'), 'r').read()
173 return old_fwid == now_fwid 176 return old_fwid == now_fwid
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
266 mount_point = line.split()[2] 269 mount_point = line.split()[2]
267 state_root = mount_point + env_root 270 state_root = mount_point + env_root
268 break 271 break
269 else: 272 else:
270 tmp_dir = tempfile.mkdtemp() 273 tmp_dir = tempfile.mkdtemp()
271 self.chros_if.run_shell_command('mount %s %s' % (state_fs, tmp_dir)) 274 self.chros_if.run_shell_command('mount %s %s' % (state_fs, tmp_dir))
272 state_root = '%s%s' % (tmp_dir, env_root) 275 state_root = '%s%s' % (tmp_dir, env_root)
273 276
274 self.chros_if.init(os.path.join(state_root, STATE_SUBDIR), LOG_FILE) 277 self.chros_if.init(os.path.join(state_root, STATE_SUBDIR), LOG_FILE)
275 278
276 def init(self, progname, chros_if, kern_handler=None, state_sequence=None): 279 def init(self, progname, chros_if,
280 kern_handler=None, state_sequence=None, tpm_handler=None):
277 '''Initialize the Firmware self test instance. 281 '''Initialize the Firmware self test instance.
278 282
279 progname - a string, name of this program as it was invoked. 283 progname - a string, name of this program as it was invoked.
280 284
281 chros_if - an object of ChromeOSInterface type to be initialized and 285 chros_if - an object of ChromeOSInterface type to be initialized and
282 used by this instance of FirmwareTest. 286 used by this instance of FirmwareTest.
283 287
284 kern_handler - an object providing SAFT with services manipulating 288 kern_handler - an object providing SAFT with services manipulating
285 kernel images. Unittest does not provide this object. 289 kernel images. Unittest does not provide this object.
286 290
287 test_state_sequence - a tuple of three-tuples driving test execution, 291 test_state_sequence - a tuple of three-tuples driving test execution,
288 see description below. Unittest does not provide this 292 see description below. Unittest does not provide this
289 sequence. 293 sequence.
290 ''' 294 '''
291 real_name = os.path.realpath(progname) 295 real_name = os.path.realpath(progname)
292 self.mydir = os.path.dirname(real_name) 296 self.mydir = os.path.dirname(real_name)
293 self.progname = os.path.basename(real_name) 297 self.progname = os.path.basename(real_name)
294 self.chros_if = chros_if 298 self.chros_if = chros_if
295 self._check_runtime_env() 299 self._check_runtime_env()
296 self.test_state_sequence = state_sequence 300 self.test_state_sequence = state_sequence
297 if kern_handler: 301 if kern_handler:
298 self.kern_handler = kern_handler 302 self.kern_handler = kern_handler
299 self.kern_handler.init(self.chros_if) 303 self.kern_handler.init(self.chros_if)
304 if tpm_handler:
305 self.tpm_handler = tpm_handler
306 self.tpm_handler.init(self.chros_if)
307
308 if self.kern_handler and self.tpm_handler:
309 if not self.chros_if.is_removable_device(self.base_partition):
310 # On each non USB flash rooted start confirm that kernel
311 # versions and TPM setting match.
312 vers_a = self.kern_handler.get_version('a')
313 vers_b = self.kern_handler.get_version('b')
314 if not self.tpm_handler.kernel_version_good(vers_a, vers_b):
315 raise FwError('TPM kernel version mismatch (%d %d %s)' % (
316 vers_a, vers_b, self.base_partition))
300 317
301 def set_try_fw_b(self): 318 def set_try_fw_b(self):
302 '''Request running firmware B on the next restart.''' 319 '''Request running firmware B on the next restart.'''
303 self.chros_if.log('Requesting restart with FW B') 320 self.chros_if.log('Requesting restart with FW B')
304 self.chros_if.run_shell_command('reboot_mode --try_firmware_b=1') 321 self.chros_if.run_shell_command('reboot_mode --try_firmware_b=1')
305 322
323 def request_recovery_boot(self):
324 '''Request running in recovery mode on the restart.'''
325 self.chros_if.log('Requesting restart in recovery mode')
326 self.chros_if.run_shell_command('reboot_mode --recovery=1')
327
306 @allow_multiple_section_input 328 @allow_multiple_section_input
307 def restore_firmware(self, section): 329 def restore_firmware(self, section):
308 '''Restore the requested firmware section (previously corrupted).''' 330 '''Restore the requested firmware section (previously corrupted).'''
309 self.chros_if.log('Restoring firmware %s' % section) 331 self.chros_if.log('Restoring firmware %s' % section)
310 FLASHROM_HANDLER.new_image() 332 FLASHROM_HANDLER.new_image()
311 FLASHROM_HANDLER.restore_firmware(section) 333 FLASHROM_HANDLER.restore_firmware(section)
312 334
313 @allow_multiple_section_input 335 @allow_multiple_section_input
314 def corrupt_firmware(self, section): 336 def corrupt_firmware(self, section):
315 '''Corrupt the requested firmware section.''' 337 '''Corrupt the requested firmware section.'''
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
356 for part, state in expected_cgpt.iteritems(): 378 for part, state in expected_cgpt.iteritems():
357 props = cgpth.get_partition(BASE_STORAGE_DEVICE, part) 379 props = cgpth.get_partition(BASE_STORAGE_DEVICE, part)
358 for prop, value in state.iteritems(): 380 for prop, value in state.iteritems():
359 if value != props[prop]: 381 if value != props[prop]:
360 self.chros_if.log('wrong partition %s value' % part) 382 self.chros_if.log('wrong partition %s value' % part)
361 self.chros_if.log(cgpth.dump_partition(BASE_STORAGE_DEVICE, 383 self.chros_if.log(cgpth.dump_partition(BASE_STORAGE_DEVICE,
362 part)) 384 part))
363 self.step_failed = True 385 self.step_failed = True
364 break 386 break
365 387
388 def move_kernel_backward(self, section):
389 '''Decrement kernel version for the requested section.'''
390 new_version = self.kern_handler.get_version(section) - 1
391 self.chros_if.log(
392 'setting section %s version to %d' % (section, new_version))
393 self.kern_handler.set_version(section, new_version)
394
395 def jump_kernels_forward(self):
396 '''Add two to both kernels' versions.
397
398 This compensates for the previous decrement and increases the version
399 number by one as compared to the original state (at the start of the
400 test).
401 '''
402 for section in ('a', 'b'):
403 new_version = self.kern_handler.get_version(section) + 2
404 self.chros_if.log(
405 'setting section %s version to %d' % (section, new_version))
406 self.kern_handler.set_version(section, new_version)
407
408 def terminate_tpm_tests(self):
409 '''Restore TPM and kernel states.
410
411 Move kernel versions to where they were before SAFT started, set the
412 TPM kernel version to the biggest of the two kernels and prevent
413 future TPM write accesses by restoring the upstart file.
414 '''
415 new_tpm_version = 0
416 for section in ('a', 'b'):
417 new_version = self.kern_handler.get_version(section) - 1
418 self.chros_if.log(
419 'setting section %s version to %d' % (section, new_version))
420 self.kern_handler.set_version(section, new_version)
421 new_tpm_version = max(new_version, new_tpm_version)
422 self.tpm_handler.set_kernel_version(new_tpm_version)
423 self.tpm_handler.disable_write_access()
424
366 def revert_firmware(self): 425 def revert_firmware(self):
367 '''Restore firmware to the image backed up when SAFT started.''' 426 '''Restore firmware to the image backed up when SAFT started.'''
368 self.chros_if.log('restoring original firmware image') 427 self.chros_if.log('restoring original firmware image')
369 self.chros_if.run_shell_command( 428 self.chros_if.run_shell_command(
370 'flashrom -w %s' % self.chros_if.state_dir_file(FW_BACKUP_FILE)) 429 'flashrom -w %s' % self.chros_if.state_dir_file(FW_BACKUP_FILE))
371 430
431 def new_fw_image(self, image_file = None):
432 FLASHROM_HANDLER.new_image(image_file)
433 FLASHROM_HANDLER.verify_image()
434 if self.tpm_handler:
435 vers_a = FLASHROM_HANDLER.get_section_version('a')
436 vers_b = FLASHROM_HANDLER.get_section_version('b')
437 if not self.tpm_handler.fw_version_good(vers_a, vers_b):
438 raise FwError('TPM firmware version mismatch')
439
440 def prepare_tpm_tests(self):
441 '''Prepare TPM for testing.
442
443 Enable write access on the next reboot, and roll back the kernel we
444 are running now (the other kernel is expected to be used on the next
445 restart).
446 '''
447 mount_point = self.chros_if.run_shell_command_get_output(
448 'df %s' % self.mydir)[-1].split()[-1]
449 cfg_file = os.path.join(mount_point, 'etc/init/tcsd.conf')
450 self.tpm_handler.enable_write_access(cfg_file)
451 self.move_kernel_backward('a')
452
372 def init_fw_test(self, opt_dictionary, chros_if): 453 def init_fw_test(self, opt_dictionary, chros_if):
373 '''Prepare firmware test context. 454 '''Prepare firmware test context.
374 455
375 This function tries creating the state directory for the fw test and 456 This function tries creating the state directory for the fw test and
376 initializes the test state machine. 457 initializes the test state machine.
377 458
378 Return 459 Return
379 True on success 460 True on success
380 False on any failure or if the directory already exists 461 False on any failure or if the directory already exists
381 ''' 462 '''
382 chros_if.init_environment() 463 chros_if.init_environment()
383 chros_if.log('Automated firmware test log generated on %s' % ( 464 chros_if.log('Automated firmware test log generated on %s' % (
384 datetime.datetime.strftime(datetime.datetime.now(), 465 datetime.datetime.strftime(
385 '%b %d %Y'))) 466 datetime.datetime.now(), '%b %d %Y')))
386 chros_if.log('Original boot state %s' % chros_if.boot_state_vector()) 467 chros_if.log('Original boot state %s' % chros_if.boot_state_vector())
387 self.chros_if = chros_if 468 self.chros_if = chros_if
388 fw_image = opt_dictionary['image_file'] 469 fw_image = opt_dictionary['image_file']
389 FLASHROM_HANDLER.new_image() 470 self.new_fw_image()
390 FLASHROM_HANDLER.verify_image()
391 FLASHROM_HANDLER.dump_whole( 471 FLASHROM_HANDLER.dump_whole(
392 self.chros_if.state_dir_file(FW_BACKUP_FILE)) 472 self.chros_if.state_dir_file(FW_BACKUP_FILE))
393 FLASHROM_HANDLER.new_image(fw_image) 473 self.new_fw_image(fw_image)
394 FLASHROM_HANDLER.verify_image()
395 self._handle_saft_script(True) 474 self._handle_saft_script(True)
396 shutil.copyfile(self.chros_if.acpi_file('FWID'), 475 shutil.copyfile(self.chros_if.acpi_file('FWID'),
397 self.chros_if.state_dir_file(FWID_BACKUP_FILE)) 476 self.chros_if.state_dir_file(FWID_BACKUP_FILE))
398 shutil.copyfile(fw_image, self.chros_if.state_dir_file(FW_COPY_FILE)) 477 shutil.copyfile(fw_image, self.chros_if.state_dir_file(FW_COPY_FILE))
478
399 self._set_step(0) 479 self._set_step(0)
400 480
401 def next_step(self): 481 def next_step(self):
402 '''Function to execute a single SAFT step. 482 '''Function to execute a single SAFT step.
403 483
404 This function is running after each reboot. It determines the current 484 This function is running after each reboot. It determines the current
405 step the SAFT is on, executes the appropriate action, increments the 485 step the SAFT is on, executes the appropriate action, increments the
406 step value and then restats the machine. 486 step value and then restats the machine.
407 ''' 487 '''
408 488
(...skipping 11 matching lines...) Expand all
420 500
421 if self._verify_fw_id(FWID_BACKUP_FILE): 501 if self._verify_fw_id(FWID_BACKUP_FILE):
422 # we expected FWID to change, but it did not - have the firmware 502 # we expected FWID to change, but it did not - have the firmware
423 # been even replaced? 503 # been even replaced?
424 self.chros_if.log('New firmware - old FWID') 504 self.chros_if.log('New firmware - old FWID')
425 self.finish_saft(False) 505 self.finish_saft(False)
426 test_state_tuple = self.test_state_sequence[this_step] 506 test_state_tuple = self.test_state_sequence[this_step]
427 expected_vector = test_state_tuple[0] 507 expected_vector = test_state_tuple[0]
428 action = test_state_tuple[1] 508 action = test_state_tuple[1]
429 boot_vector = self.chros_if.boot_state_vector() 509 boot_vector = self.chros_if.boot_state_vector()
430 self.chros_if.log('Rebooted into state %s on step %d' % ( 510 self.chros_if.log('\nRebooted into state %s on step %d' % (
431 boot_vector, this_step)) 511 boot_vector, this_step))
432 512
433 conf_log_file = RetriveSaftConfDefinion(CONF_LOG_VAR_NAME) 513 conf_log_file = RetriveSaftConfDefinion(CONF_LOG_VAR_NAME)
434 514
435 if os.path.exists(conf_log_file): 515 if os.path.exists(conf_log_file):
436 contents = open(conf_log_file).read().rstrip() 516 contents = open(conf_log_file).read().rstrip()
437 if len(contents): 517 if len(contents):
438 self.chros_if.log('startup log contents:') 518 self.chros_if.log('startup log contents:')
439 self.chros_if.log(contents) 519 self.chros_if.log(contents)
440 520
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 # 582 #
503 # The second element of the component tuples is the action to take to 583 # The second element of the component tuples is the action to take to
504 # advance the test. The action is a function to call. The last line has 584 # advance the test. The action is a function to call. The last line has
505 # action set to None, which indicates to the state machine that the test 585 # action set to None, which indicates to the state machine that the test
506 # is over. 586 # is over.
507 # 587 #
508 # The third component, if present, is the parameter to pass to the action 588 # The third component, if present, is the parameter to pass to the action
509 # function. 589 # function.
510 590
511 TEST_STATE_SEQUENCE = ( 591 TEST_STATE_SEQUENCE = (
512 ('1:1:1:0:3', FST.set_try_fw_b), 592 ('1:1:1:0:3', FST.set_try_fw_b), # Step 0
513 ('1:2:1:0:3', None), 593 ('1:2:1:0:3', None),
514 ('1:1:1:0:3', FST.corrupt_firmware, 'a'), 594 ('1:1:1:0:3', FST.corrupt_firmware, 'a'),
515 ('1:2:1:0:3', FST.restore_firmware, 'a'), 595 ('1:2:1:0:3', FST.restore_firmware, 'a'),
516 ('1:1:1:0:3', FST.corrupt_firmware, ('a', 'b')), 596 ('1:1:1:0:3', FST.corrupt_firmware, ('a', 'b')),
517 ('5:0:1:1:3', FST.restore_firmware, ('a', 'b')), 597 ('5:0:1:1:3', FST.restore_firmware, ('a', 'b')), # Step 5
518 ('1:1:1:0:3', FST.corrupt_kernel, 'a'), 598 ('1:1:1:0:3', FST.corrupt_kernel, 'a'),
519 ('1:1:1:0:5', FST.corrupt_kernel, 'b'), 599 ('1:1:1:0:5', FST.corrupt_kernel, 'b'),
520 ('6:0:1:1:3', FST.restore_kernel, ('a', 'b')), 600 ('6:0:1:1:3', FST.restore_kernel, ('a', 'b')),
521 ('1:1:1:0:3', FST.cgpt_test_start), 601 ('1:1:1:0:3', FST.request_recovery_boot),
602 ('8:0:1:1:3', FST.prepare_tpm_tests), # Step 10
603 ('1:1:1:0:5', FST.move_kernel_backward, 'b'),
604 ('6:0:1:1:3', FST.jump_kernels_forward),
605 ('1:1:1:0:3', FST.request_recovery_boot),
606 ('8:0:1:1:3', FST.terminate_tpm_tests),
607 ('1:1:1:0:3', FST.cgpt_test_start), # Step 15
522 ('1:1:1:0:3', FST.cgpt_test_1), 608 ('1:1:1:0:3', FST.cgpt_test_1),
523 ('1:1:1:0:3', FST.revert_firmware), 609 ('1:1:1:0:3', FST.revert_firmware),
524 ('1:1:1:0:3', None), 610 ('1:1:1:0:3', None),
525 ) 611 )
526 612
527 613
528 # The string below serves two purposes: 614 # The string below serves two purposes:
529 # 615 #
530 # - spell out the usage string for this program 616 # - spell out the usage string for this program
531 # 617 #
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 '''Process command line options and invoke the proper test entry point.''' 681 '''Process command line options and invoke the proper test entry point.'''
596 (opts, params) = getopt.gnu_getopt(argv[1:], '', get_options_set()) 682 (opts, params) = getopt.gnu_getopt(argv[1:], '', get_options_set())
597 if params: 683 if params:
598 raise FwError('unrecognized parameters: %s' % ' '.join(params)) 684 raise FwError('unrecognized parameters: %s' % ' '.join(params))
599 685
600 opt_dictionary = {} 686 opt_dictionary = {}
601 for (name, value) in opts: 687 for (name, value) in opts:
602 opt_dictionary[name.lstrip('-')] = value 688 opt_dictionary[name.lstrip('-')] = value
603 689
604 FST.init(argv[0], CHROS_IF, 690 FST.init(argv[0], CHROS_IF,
605 kernel_handler.KernelHandler(), TEST_STATE_SEQUENCE) 691 kernel_handler.KernelHandler(), TEST_STATE_SEQUENCE,
692 tpm_handler.TpmHandler())
606 693
607 FLASHROM_HANDLER.init(saft_flashrom_util, CHROS_IF, 694 FLASHROM_HANDLER.init(saft_flashrom_util, CHROS_IF,
608 opt_dictionary.get('pub_key')) 695 opt_dictionary.get('pub_key'))
609 if 'next_step' in opt_dictionary: 696 if 'next_step' in opt_dictionary:
610 if len(opt_dictionary) != 1: 697 if len(opt_dictionary) != 1:
611 usage('--next_step (when specified) must be the only parameter', 1) 698 usage('--next_step (when specified) must be the only parameter', 1)
612 try: 699 try:
613 FST.next_step() 700 FST.next_step()
614 except SystemExit: 701 except SystemExit:
615 pass # No real exception, this is just an exit (for whatever 702 pass # No real exception, this is just an exit (for whatever
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 main(sys.argv) 738 main(sys.argv)
652 except (getopt.GetoptError, ImportError): 739 except (getopt.GetoptError, ImportError):
653 usage(sys.exc_info()[1], 1) 740 usage(sys.exc_info()[1], 1)
654 except (FwError, flashrom_handler.FlashromHandlerError): 741 except (FwError, flashrom_handler.FlashromHandlerError):
655 MSG = 'Error: %s' % str(sys.exc_info()[1]) 742 MSG = 'Error: %s' % str(sys.exc_info()[1])
656 print MSG 743 print MSG
657 CHROS_IF.log(MSG) 744 CHROS_IF.log(MSG)
658 sys.exit(1) 745 sys.exit(1)
659 746
660 sys.exit(0) 747 sys.exit(0)
OLDNEW
« no previous file with comments | « runtests.sh ('k') | test_tpm_handler.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698