diff options
author | Chris Chen <twothreecc@google.com> | 2016-07-25 16:53:14 -0700 |
---|---|---|
committer | chrome-bot <chrome-bot@chromium.org> | 2016-08-08 13:53:25 -0700 |
commit | c2a841a489eb2a9a2f3efbc73664681b0f7839e8 (patch) | |
tree | 7fbaaa94f50c1fafe66bc4b19fb5d89a9d697b0b /cts | |
parent | 1e6cbc725f90784bbe80361e9c1dd07da1ab6a79 (diff) | |
download | chrome-ec-c2a841a489eb2a9a2f3efbc73664681b0f7839e8.tar.gz |
cts: Refactored script
Added in classes for Board (parent), DeviceUnderTest,
and TestHarness. Reading, etc. should be easier now
BRANCH=None
BUG=None
TEST=Manual
- Build default
- Flash default
- Run
- Open /tmp/cts_results/nucleo-f072rb/gpio.html
- Should see a clean results page
Change-Id: Ide3f75281f0b5b8b40dabd36f8c239737dc527d6
Reviewed-on: https://chromium-review.googlesource.com/364236
Commit-Ready: Chris Chen <twothreecc@google.com>
Tested-by: Chris Chen <twothreecc@google.com>
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'cts')
-rwxr-xr-x | cts/cts.py | 694 |
1 files changed, 398 insertions, 296 deletions
diff --git a/cts/cts.py b/cts/cts.py index 8eb57f6100..aa1203ebe4 100755 --- a/cts/cts.py +++ b/cts/cts.py @@ -12,296 +12,401 @@ import os import select import subprocess as sp import time +from copy import deepcopy +from abc import ABCMeta, abstractmethod # For most tests, error codes should never conflict CTS_CONFLICTING_CODE = -1 CTS_SUCCESS_CODE = 0 +TH_BOARD = 'stm32l476g-eval' +OCD_SCRIPT_DIR = '/usr/local/share/openocd/scripts' +MAX_SUITE_TIME_SEC = 3 +class Board(object): + """Class representing a single board connected to a host machine -class Cts(object): - """Class that represents a CTS testing setup and provides - interface to boards (building, flashing, etc.) + This class is abstract, subclasses must define the updateSerial() + method Attributes: - ocd_script_dir: String containing locations of openocd's config files - th_board: String containing name of the Test Harness (th) board - results_dir: String containing test output directory path - dut_board: Name of Device Under Test (DUT) board - module: Name of module to build/run tests for - ec_directory: String containing path to EC top level directory - th_hla: String containing hla_serial for the th - dut_hla: String containing hla_serial for the dut, only used for - boards which have an st-link v2.1 debugger - th_ser_path: String which contains full path to th serial file - test_names: List of strings of test names contained in given module - test_results: Dictionary of results of each test from module - return_codes: List of strings of return codes, with a code's integer - value being the index for the corresponding string representation + board: String containing actual type of board, i.e. nucleo-f072rb + config: Directory of board config file relative to openocd's + scripts directory + hla_serial: String containing board's hla_serial number (if board + is an stm32 board) + tty_port: String that is the path to the tty port which board's + UART outputs to + _tty_descriptor: String of file descriptor for tty_port """ - def __init__(self, ec_dir, dut_board='nucleo-f072rb', module='gpio'): - """Initializes cts class object with given arguments. + configs = { + 'stm32l476g-eval': 'board/stm32l4discovery.cfg', + 'nucleo-f072rb': 'board/st_nucleo_f0.cfg' + } + + __metaclass__ = ABCMeta # This is an Abstract Base Class (ABC) + def __init__(self, board, hla_serial=None, flash_offset='0x08000000'): + """Initializes a board object with given attributes Args: - dut_board: Name of Device Under Test (DUT) board - module: Name of module to build/run tests for + board: String containing board name + hla_serial: Serial number if board's adaptor is an HLA """ - self.ocd_script_dir = '/usr/local/share/openocd/scripts' - self.th_board = 'stm32l476g-eval' - self.results_dir = '/tmp/cts_results' - self.dut_board = dut_board - self.module = module - self.ec_directory = ec_dir - self.th_hla = '' - self.dut_hla = '' - self.th_ser_path = os.path.join( - self.ec_directory, - 'build', - self.th_board, - 'th_hla_serial') - testlist_path = os.path.join( - self.ec_directory, - 'cts', - self.module, - 'cts.testlist') - self.test_names = self.getMacroArgs(testlist_path, 'CTS_TEST') - return_codes_path = os.path.join(self.ec_directory, - 'cts', - 'common', - 'cts.rc') - self.return_codes = self.getMacroArgs( - return_codes_path, 'CTS_RC_') - self.test_results = collections.OrderedDict() + self.board = board + self.hla_serial = hla_serial + self.tty_port = None + self._tty_descriptor = None + self.flash_offset = flash_offset - def set_dut_board(self, brd): - """Sets the dut_board instance variable + @abstractmethod + def updateSerial(self): + """Subclass should implement this""" + pass + + def sendOpenOcdCommands(self, commands): + """Send a command to the board via openocd Args: - brd: String of board name + commands: A list of commands to send """ - self.dut_board = brd + args = ['openocd', '-s', OCD_SCRIPT_DIR, + '-f', Board.configs[self.board], '-c', 'hla_serial ' + self.hla_serial] - def set_module(self, mod): - """Sets the module instance variable + for cmd in commands: + args += ['-c', cmd] + args += ['-c', 'shutdown'] + sp.call(args) - Args: - brd: String of board name + def make(self, module, ec_dir): + """Builds test suite module for board""" + cmds = ['make', + '--directory=' + ec_dir, + 'BOARD=' + self.board, + 'CTS_MODULE=' + module, + '-j', + '-B'] + + print 'EC directory is ' + ec_dir + print 'Building module \'' + module + '\' for ' + self.board + sp.call(cmds) + + def flash(self): + """Flashes board with most recent build ec.bin""" + flash_cmds = [ + 'reset_config connect_assert_srst', + 'init', + 'reset init', + 'flash write_image erase build/' + + self.board + + '/ec.bin ' + + self.flash_offset, + 'reset'] + + self.sendOpenOcdCommands(flash_cmds) + + def toString(self): + s = ('Type: Board\n' + 'board: ' + self.board + '\n' + 'hla_serial: ' + self.hla_serial + '\n' + 'config: ' + Board.configs[self.board] + '\n' + 'tty_port ' + self.tty_port + '\n' + '_tty_descriptor: ' + str(self._tty_descriptor) + '\n') + return s + + def reset(self): + """Reset board (used when can't connect to TTY)""" + self.sendOpenOcdCommands(['init', 'reset init', 'resume']) + + def setupForOutput(self): + """Call this before trying to call readOutput for the first time. + This is not in the initialization because caller only should call + this function after serial numbers are setup """ - self.module = mod + self.updateSerial() + self.reset() + self._identifyTtyPort() + + # In testing 3 retries is enough to reset board (2 can fail) + num_file_setup_retries = 3 + # In testing, 10 seconds is sufficient to allow board to reconnect + reset_wait_time_seconds = 10 + try: + self._getDevFileDescriptor() + # If board was just connected, must be reset to be read from + except (IOError, OSError): + for i in range(num_file_setup_retries): + self.reset() + time.sleep(reset_wait_time_seconds) + try: + self._getDevFileDescriptor() + break + except (IOError, OSError): + continue + if self._tty_descriptor is None: + raise ValueError('Unable to read ' + self.name + '\n' + 'If you are running cat on a ttyACMx file,\n' + 'please kill that process and try again') - def make(self): - """Builds test suite module for given th/dut boards""" - print 'Building module \'' + self.module + '\' for th ' + self.th_board - sp.call(['make', - '--directory=' + str(self.ec_directory), - 'BOARD=' + self.th_board, - 'CTS_MODULE=' + self.module, - '-j']) - - print 'Building module \'' + self.module + '\' for dut ' + self.dut_board - sp.call(['make', - '--directory=' + str(self.ec_directory), - 'BOARD=' + self.dut_board, - 'CTS_MODULE=' + self.module, - '-j']) - - def openocdCmd(self, command_list, board): - """Sends the specified commands to openocd for a board + def readAvailableBytes(self): + """Read info from a serial port described by a file descriptor - Args: - board: String that contains board name + Return: + Bytes that UART has output """ + buf = [] + while True: + if select.select([self._tty_descriptor], [], [], 1)[0]: + buf.append(os.read(self._tty_descriptor, 1)) + else: + break + result = ''.join(buf) + return result - board_cfg = self.getBoardConfigName(board) + def _identifyTtyPort(self): + """Saves this board's serial port""" + dev_dir = '/dev/' + id_prefix = 'ID_SERIAL_SHORT=' + num_reset_tries = 3 + reset_wait_time_s = 10 + com_devices = [f for f in os.listdir( + dev_dir) if f.startswith('ttyACM')] + + for i in range(num_reset_tries): + for device in com_devices: + self.tty_port = os.path.join(dev_dir, device) + properties = sp.check_output(['udevadm', + 'info', + '-a', + '-n', + self.tty_port, + '--query=property']) + for line in [l.strip() for l in properties.split('\n')]: + if line.startswith(id_prefix): + if self.hla_serial == line[len(id_prefix):]: + return + if i != num_reset_tries - 1: # No need to reset the obard the last time + self.reset() # May need to reset to connect + time.sleep(reset_wait_time_s) + + # If we get here without returning, something is wrong + raise RuntimeError('The device dev path could not be found') + + def _getDevFileDescriptor(self): + """Read available bytes from device dev path""" + fd = os.open(self.tty_port, os.O_RDONLY) + flag = fcntl.fcntl(fd, fcntl.F_GETFL) + fcntl.fcntl(fd, fcntl.F_SETFL, flag | os.O_NONBLOCK) + self._tty_descriptor = fd - args = ['openocd', '-s', self.ocd_script_dir, - '-f', board_cfg] - for cmd in command_list: - args.append('-c') - args.append(cmd) - args.append('-c') - args.append('shutdown') - sp.call(args) +class TestHarness(Board): + """Subclass of Board representing a Test Harness - def getStLinkSerialNumbers(self): - """Gets serial numbers of all st-link v2.1 board attached to host + Attributes: + serial_path: Path to file containing serial number + """ - Returns: - List of serials + def __init__(self, serial_path=None): + """Initializes a board object with given attributes + + Args: + serial_path: Path to file containing serial number """ - usb_args = ['lsusb', '-v', '-d', '0x0483:0x374b'] - usb_process = sp.Popen(usb_args, stdout=sp.PIPE, shell=False) - st_link_info = usb_process.communicate()[0] - st_serials = [] - for line in st_link_info.split('\n'): - if 'iSerial' in line: - st_serials.append(line.split()[2]) - return st_serials + Board.__init__(self, TH_BOARD) + self.serial_path = serial_path - # params: th_hla_serial is your personal th board's serial - def saveDutSerial(self): - """If dut uses same debugger as th, save its serial""" - stlink_serials = self.getStLinkSerialNumbers() - if len(stlink_serials) == 1: # dut doesn't use same debugger - return '' - elif len(stlink_serials) == 2: - dut = [s for s in stlink_serials if self.th_hla not in s] - if len(dut) != 1: - raise RuntimeError('Incorrect TH hla_serial') - else: - return dut[0] # Found your other st-link device serial! - else: - msg = ('Please connect TH and your DUT\n' - 'and remove all other st-link devices') + def updateSerial(self): + """Loads serial number from saved location""" + if self.hla_serial: + return # serial was already loaded + try: + with open(self.serial_path, mode='r') as ser_f: + self.hla_serial = ser_f.read() + return + except IOError: + msg = ('Your th hla_serial may not have been saved.\n' + 'Connect only your th and run ./cts --setup, then try again.') raise RuntimeError(msg) - def saveThSerial(self): - """Saves the th serial number to a file located at th_ser_path + def saveSerial(self): + """Saves the th serial number to a file Return: the serial number saved """ - serial = self.getStLinkSerialNumbers() + serial = Cts.getSerialNumbers() if len(serial) != 1: msg = ('TH could not be identified.\n' '\nConnect your TH and remove other st-link devices') raise RuntimeError(msg) else: ser = serial[0] - if not os.path.exists(os.path.dirname(self.th_ser_path)): - os.makedirs(os.path.dirname(self.th_ser_path)) - with open(self.th_ser_path, mode='w') as ser_f: + if not ser: + msg = ('Unable to save serial') + raise RuntimeError(msg) + if not os.path.exists(os.path.dirname(self.serial_path)): + os.makedirs(os.path.dirname(self.serial_path)) + with open(self.serial_path, mode='w') as ser_f: ser_f.write(ser) - return ser + self.hla_serial = ser + return ser - def getBoardConfigName(self, board): - """Gets the path for the config file relative to the - openocd scripts directory +class DeviceUnderTest(Board): + """Subclass of Board representing a DUT board - Args: - board: String containing name of board to get the config file for + Attributes: + th: Reference to test harness board to which this DUT is attached + """ + + def __init__(self, board, th, hla_ser=None, f_offset='0x08000000'): + """Initializes a Device Under Test object with given attributes - Returns: String containing relative path to board config file + Args: + board: String containing board name + th: Reference to test harness board to which this DUT is attached + hla_serial: Serial number if board uses an HLA adaptor """ - board_config_locs = { - 'stm32l476g-eval': 'board/stm32l4discovery.cfg', - 'nucleo-f072rb': 'board/st_nucleo_f0.cfg' - } + Board.__init__(self, board, hla_serial=hla_ser, flash_offset=f_offset) + self.th = th - try: - cfg = board_config_locs[board] - return cfg - except KeyError: - raise ValueError( - 'The config file for board ' + - board + - ' was not found') + def updateSerial(self): + """Stores the DUT's serial number. - def flashBoards(self): - """Flashes th and dut boards with their most recently build ec.bin""" - self.updateSerials() - th_flash_cmds = [ - 'hla_serial ' + - self.th_hla, - 'reset_config connect_assert_srst', - 'init', - 'reset init', - 'flash write_image erase build/' + - self.th_board + - '/ec.bin 0x08000000', - 'reset halt'] - - dut_flash_cmds = [ - 'hla_serial ' + - self.dut_hla, - 'reset_config connect_assert_srst', - 'init', - 'reset init', - 'flash write_image erase build/' + - self.dut_board + - '/ec.bin 0x08000000', - 'reset halt'] - - self.openocdCmd(th_flash_cmds, self.th_board) - self.openocdCmd(dut_flash_cmds, self.dut_board) - self.openocdCmd(['hla_serial ' + self.th_hla, - 'init', - 'reset init', - 'resume'], - self.th_board) - self.openocdCmd(['hla_serial ' + self.dut_hla, - 'init', - 'reset init', - 'resume'], - self.dut_board) + Precondition: The DUT and TH must both be connected, and th.hla_serial + must hold the correct value (the th's serial #) + """ + if self.hla_serial != None: + return # serial was already set ('' is a valid serial) + serials = Cts.getSerialNumbers() + dut = [s for s in serials if self.th.hla_serial != s] + if len(dut) == 1: + self.hla_serial = dut[0] + return # Found your other st-link device serial! + else: + raise RuntimeError('Your TH serial number is incorrect, or your have' + ' too many st-link devices attached.') + # If len(dut) is 0 then your dut doesn't use an st-link device, so we + # don't have to worry about its serial number - def updateSerials(self): - """Updates serial #s for th and dut""" - try: - with open(self.th_ser_path) as th_f: - self.th_hla = th_f.read() - except IOError: - msg = ('Your th hla_serial may not have been saved.\n' - 'Connect only your th and run ./cts --setup, then try again.') - raise RuntimeError(msg) - self.saveDutSerial() +class Cts(object): + """Class that represents a CTS testing setup and provides + interface to boards (building, flashing, etc.) - def resetBoards(self): - """Resets the boards and allows them to run tests""" - self.updateSerials() - self.openocdCmd(['hla_serial ' + self.dut_hla, - 'init', 'reset init'], self.dut_board) - self.openocdCmd(['hla_serial ' + self.th_hla, - 'init', 'reset init'], self.th_board) - self.openocdCmd(['hla_serial ' + self.th_hla, - 'init', 'resume'], self.th_board) - self.openocdCmd(['hla_serial ' + self.dut_hla, - 'init', 'resume'], self.dut_board) - - def readAvailableBytes(self, fd): - """Read info from a serial port described by a file descriptor + Attributes: + dut: DeviceUnderTest object representing dut + th: TestHarness object representing th + module: Name of module to build/run tests for + ec_directory: String containing path to EC top level directory + test_names: List of strings of test names contained in given module + test_results: Dictionary of results of each test from module, with + keys being test name strings and values being test result integers + return_codes: List of strings of return codes, with a code's integer + value being the index for the corresponding string representation + """ + + def __init__(self, ec_dir, dut='nucleo-f072rb', module='gpio'): + """Initializes cts class object with given arguments. Args: - fd: file descriptor for device ttyACM file + dut: Name of Device Under Test (DUT) board + ec_dir: String path to ec directory + module: Name of module to build/run tests for """ - buf = [] - while True: - if select.select([fd], [], [], 1)[0]: - buf.append(os.read(fd, 1)) - else: - break - result = ''.join(buf) - return result + self.results_dir = '/tmp/cts_results' + self.ec_directory = ec_dir + self.th = TestHarness() + self.dut = DeviceUnderTest(dut, self.th) # DUT constructor needs TH - def getDevFileDescriptor(self, path): - """Read available bytes from device dev path + th_ser_path = os.path.join( + self.ec_directory, + 'build', + self.th.board, + 'th_hla_serial') + + self.module = module + + testlist_path = os.path.join( + self.ec_directory, + 'cts', + self.module, + 'cts.testlist') + + self.test_names = Cts._getMacroArgs(testlist_path, 'CTS_TEST') + + self.th.serial_path = th_ser_path + + return_codes_path = os.path.join(self.ec_directory, + 'cts', + 'common', + 'cts.rc') + + self.return_codes = Cts._getMacroArgs( + return_codes_path, 'CTS_RC_') + + self.test_results = collections.OrderedDict() + + def set_module(self, mod): + """Sets the module instance variable. Also sets test_names, + since that depends directly on the module we are using Args: - path: The serial device file path to read from + mod: String of module name + """ + self.module = mod - Return: the file descriptor for the open serial device file + + def make(self): + self.dut.make(self.module, self.ec_directory) + self.th.make(self.module, self.ec_directory) + + def flashBoards(self): + """Flashes th and dut boards with their most recently build ec.bin""" + self.updateSerials() + self.th.flash() + self.dut.flash() + + def setup(self): + """Saves th serial number if th only is connected. + + Return: + Serial number that was saved """ - fd = os.open(path, os.O_RDONLY) - flag = fcntl.fcntl(fd, fcntl.F_GETFL) - fcntl.fcntl(fd, fcntl.F_SETFL, flag | os.O_NONBLOCK) - return fd + return self.th.saveSerial() - def getDevFilenames(self): - """Read available bytes from device dev path + def updateSerials(self): + """Updates serials of both th and dut, in that order (order matters)""" + self.th.updateSerial() + self.dut.updateSerial() - Args: - path: The serial device file path to read from + def resetBoards(self): + """Resets the boards and allows them to run tests + Due to current (7/27/16) version of sync function, + both boards must be rest and halted, with the th + resuming first, in order for the test suite to run + in sync + """ + self.updateSerials() + self.th.sendOpenOcdCommands(['init', 'reset halt']) + self.dut.sendOpenOcdCommands(['init', 'reset halt']) + self.th.sendOpenOcdCommands(['init', 'resume']) + self.dut.sendOpenOcdCommands(['init', 'resume']) - Return: the file descriptor for the open serial device file + @staticmethod + def getSerialNumbers(): + """Gets serial numbers of all st-link v2.1 board attached to host + + Returns: + List of serials """ - com_files = [f for f in os.listdir('/dev/') if f.startswith('ttyACM')] - if len(com_files) < 2: - raise RuntimeError('The device dev paths could not be found') - elif len(com_files) > 2: - raise RuntimeError('Too many serial devices connected to host') - else: - return ('/dev/' + com_files[0], '/dev/' + com_files[1]) + usb_args = ['lsusb', '-v', '-d', '0x0483:0x374b'] + usb_process = sp.Popen(usb_args, stdout=sp.PIPE, shell=False) + st_link_info = usb_process.communicate()[0] + st_serials = [] + for line in st_link_info.split('\n'): + if 'iSerial' in line: + st_serials.append(line.split()[2].strip()) + return st_serials - def getMacroArgs(self, filepath, macro): + @staticmethod + def _getMacroArgs(filepath, macro): """Get list of args of a certain macro in a file when macro is used by itself on a line @@ -314,10 +419,10 @@ class Cts(object): for ln in [ln for ln in fl.readlines( ) if ln.strip().startswith(macro)]: ln = ln.strip()[len(macro):] - args.append(ln.strip('()').replace(',','')) + args.append(ln.strip('()').replace(',', '')) return args - def parseOutput(self, r1, r2): + def _parseOutput(self, r1, r2): """Parse the outputs of the DUT and TH together Args; @@ -331,42 +436,59 @@ class Cts(object): tokens = ln.split() if len(tokens) != 2: continue - elif tokens[0].strip() not in self.test_names: + print 'Tokens are: ' + str(tokens) + test = tokens[0].strip() + try: + return_code = int(tokens[1]) + except ValueError: # Second token is not an int continue - elif tokens[0] in self.test_results.keys(): - if self.test_results[tokens[0]] != int(tokens[1]): - if self.test_results[tokens[0]] == CTS_SUCCESS_CODE: - self.test_results[tokens[0]] = int(tokens[1]) - elif int(tokens[1]) == CTS_SUCCESS_CODE: - continue - else: - self.test_results[tokens[0]] = CTS_CONFLICTING_CODE - else: - continue - else: - self.test_results[tokens[0]] = int(tokens[1]) + if test not in self.test_names: + continue + elif self.test_results.get( + test, + CTS_SUCCESS_CODE) == CTS_SUCCESS_CODE: + self.test_results[test] = return_code + print 'Is ' + str(return_code) + ' the same as ' + str(self.test_results[test]) + elif return_code != self.test_results[test]: + print 'Setting ' + test + ' to CTS_CONFLICTING_CODE' + self.test_results[test] = CTS_CONFLICTING_CODE + + def _resultsAsString(self): + """Takes saved results and returns a duplicate of their dictionary + with the return codes replaces with their string representation + Returns: + dictionary with test name strings as keys and test result strings + as values + """ + result = deepcopy(self.test_results) # Convert codes to strings - for test, code in self.test_results.items(): + for test, code in result.items(): if code == CTS_CONFLICTING_CODE: - self.test_results[test] = 'RESULTS CONFLICT' - self.test_results[test] = self.return_codes[code] + result[test] = 'RESULTS CONFLICT' + else: + result[test] = self.return_codes[code] for tn in self.test_names: - if tn not in self.test_results.keys(): - self.test_results[tn] = 'NO RESULT RETURNED' # Exceptional case + if tn not in result: + # Exceptional case + result[tn] = 'NO RESULT RETURNED' - def resultsAsString(self): + return result + + def prettyResults(self): """Takes saved results and returns a string representation of them - Return: Saved string that contains results + Return: Dictionary similar to self.test_results, but with strings + instead of error codes """ - t_long = max(len(s) for s in self.test_results.keys()) - e_max_len = max(len(s) for s in self.test_results.values()) + res = self._resultsAsString() + t_long = max(len(s) for s in res.keys()) + e_max_len = max(len(s) for s in res.values()) pretty_results = 'CTS Test Results for ' + self.module + ' module:\n' - for test, code in self.test_results.items(): + for test, code in res.items(): align_str = '\n{0:<' + str(t_long) + \ '} {1:>' + str(e_max_len) + '}' pretty_results += align_str.format(test, code) @@ -375,42 +497,27 @@ class Cts(object): def resetAndRecord(self): """Resets boards, records test results in results dir""" + self.updateSerials() + self.dut.setupForOutput() + self.th.setupForOutput() + self.dut.readAvailableBytes() # clear buffer + self.th.readAvailableBytes() self.resetBoards() - # Doesn't matter which is dut or th because we combine their results - d1, d2 = self.getDevFilenames() - try: - fd1 = self.getDevFileDescriptor(d1) - fd2 = self.getDevFileDescriptor(d2) - except: # If board was just connected, must be reset to be read from - for i in range(3): - self.resetBoards() - time.sleep(10) - try: - fd1 = self.getDevFileDescriptor(d1) - fd2 = self.getDevFileDescriptor(d2) - break - except: - continue + time.sleep(MAX_SUITE_TIME_SEC) - self.readAvailableBytes(fd1) # clear any junk from buffer - self.readAvailableBytes(fd2) - self.resetBoards() - time.sleep(3) - res1 = self.readAvailableBytes(fd1) - res2 = self.readAvailableBytes(fd2) - if len(res1) == 0 or len(res2) == 0: + dut_results = self.dut.readAvailableBytes() + th_results = self.th.readAvailableBytes() + if not dut_results or not th_results: raise ValueError('Output missing from boards.\n' - 'If you are running cat on a ttyACMx file,\n' - 'please kill that process and try again') - self.parseOutput(res1, res2) - pretty_results = self.resultsAsString() - - dest = os.path.join( - self.results_dir, - self.dut_board, - self.module + '.txt') + 'If you are running cat on a ttyACMx file,\n' + 'please kill that process and try again') + + self._parseOutput(dut_results, th_results) + pretty_results = self.prettyResults() + + dest = os.path.join(self.results_dir, self.dut.board, self.module + '.txt') if not os.path.exists(os.path.dirname(dest)): os.makedirs(os.path.dirname(dest)) @@ -424,7 +531,6 @@ def main(): ec_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..') os.chdir(ec_dir) - cts_suite = Cts(ec_dir) dut_board = 'nucleo-f072rb' # nucleo by default module = 'gpio' # gpio by default @@ -446,31 +552,27 @@ def main(): parser.add_argument('-f', '--flash', action='store_true', - help='Flash boards with last image built for them') + help='Flash boards with most recent image and record results') parser.add_argument('-r', '--reset', action='store_true', - help='Reset boards and save test results') + help='Reset boards and save test results (no flashing)') args = parser.parse_args() if args.module: module = args.module - cts_suite.set_module(module) if args.dut: dut_board = args.dut - cts_suite.set_dut_board(dut_board) + + cts_suite = Cts(ec_dir, module=module, dut=dut_board) if args.setup: - serial = cts_suite.saveThSerial() - if(serial is not None): - print 'Your th hla_serial # has been saved as: ' + serial - else: - print 'Unable to save serial' - return + serial = cts_suite.setup() + print 'Your th hla_serial # has been saved as: ' + serial - if args.reset: + elif args.reset: cts_suite.resetAndRecord() elif args.build: |