diff options
Diffstat (limited to 'cts')
37 files changed, 1196 insertions, 839 deletions
diff --git a/cts/build.mk b/cts/build.mk index 817b69b25c..44db306f40 100644 --- a/cts/build.mk +++ b/cts/build.mk @@ -1,5 +1,5 @@ # -*- makefile -*- -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. diff --git a/cts/common/board.py b/cts/common/board.py index d2c8e02b04..3f92ff50ad 100644 --- a/cts/common/board.py +++ b/cts/common/board.py @@ -1,388 +1,421 @@ -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes # Note: This is a py2/3 compatible file. from __future__ import print_function -from abc import ABCMeta -from abc import abstractmethod import os import shutil import subprocess as sp -import serial +from abc import ABCMeta, abstractmethod +import serial # pylint:disable=import-error import six - -OCD_SCRIPT_DIR = '/usr/share/openocd/scripts' +OCD_SCRIPT_DIR = "/usr/share/openocd/scripts" OPENOCD_CONFIGS = { - 'stm32l476g-eval': 'board/stm32l4discovery.cfg', - 'nucleo-f072rb': 'board/st_nucleo_f0.cfg', - 'nucleo-f411re': 'board/st_nucleo_f4.cfg', + "stm32l476g-eval": "board/stm32l4discovery.cfg", + "nucleo-f072rb": "board/st_nucleo_f0.cfg", + "nucleo-f411re": "board/st_nucleo_f4.cfg", } FLASH_OFFSETS = { - 'stm32l476g-eval': '0x08000000', - 'nucleo-f072rb': '0x08000000', - 'nucleo-f411re': '0x08000000', + "stm32l476g-eval": "0x08000000", + "nucleo-f072rb": "0x08000000", + "nucleo-f411re": "0x08000000", } -REBOOT_MARKER = 'UART initialized after reboot' +REBOOT_MARKER = "UART initialized after reboot" def get_subprocess_args(): - if six.PY3: - return {'encoding': 'utf-8'} - return {} + if six.PY3: + return {"encoding": "utf-8"} + return {} class Board(six.with_metaclass(ABCMeta, object)): - """Class representing a single board connected to a host machine. - - Attributes: - 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: String of file descriptor for tty_port - """ - - def __init__(self, board, module, hla_serial=None): - """Initializes a board object with given attributes. - - Args: - board: String containing board name - module: String of the test module you are building, - i.e. gpio, timer, etc. - hla_serial: Serial number if board's adaptor is an HLA - - Raises: - RuntimeError: Board is not supported - """ - if board not in OPENOCD_CONFIGS: - msg = 'OpenOcd configuration not found for ' + board - raise RuntimeError(msg) - if board not in FLASH_OFFSETS: - msg = 'Flash offset not found for ' + board - raise RuntimeError(msg) - self.board = board - self.flash_offset = FLASH_OFFSETS[self.board] - self.openocd_config = OPENOCD_CONFIGS[self.board] - self.module = module - self.hla_serial = hla_serial - self.tty_port = None - self.tty = None - - def reset_log_dir(self): - """Reset log directory.""" - if os.path.isdir(self.log_dir): - shutil.rmtree(self.log_dir) - os.makedirs(self.log_dir) - - @staticmethod - def get_stlink_serials(): - """Gets serial numbers of all st-link v2.1 board attached to host. - - Returns: - List of serials + """Class representing a single board connected to a host machine. + + Attributes: + 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: String of file descriptor for tty_port """ - usb_args = ['sudo', 'lsusb', '-v', '-d', '0x0483:0x374b'] - st_link_info = sp.check_output(usb_args, **get_subprocess_args()) - st_serials = [] - for line in st_link_info.split('\n'): - if 'iSerial' not in line: - continue - words = line.split() - if len(words) <= 2: - continue - st_serials.append(words[2].strip()) - return st_serials - - @abstractmethod - def get_serial(self): - """Subclass should implement this.""" - pass - - def send_openocd_commands(self, commands): - """Send a command to the board via openocd. - - Args: - commands: A list of commands to send - - Returns: - True if execution is successful or False otherwise. - """ - args = ['sudo', 'openocd', '-s', OCD_SCRIPT_DIR, - '-f', self.openocd_config, '-c', 'hla_serial ' + self.hla_serial] - - for cmd in commands: - args += ['-c', cmd] - args += ['-c', 'shutdown'] - - rv = 1 - with open(self.openocd_log, 'a') as output: - rv = sp.call(args, stdout=output, stderr=sp.STDOUT) - - if rv != 0: - self.dump_openocd_log() - - return rv == 0 - def dump_openocd_log(self): - with open(self.openocd_log) as log: - print(log.read()) - - def build(self, ec_dir): - """Builds test suite module for board. - - Args: - ec_dir: String of the ec directory path - - Returns: - True if build is successful or False otherwise. - """ - cmds = ['make', - '--directory=' + ec_dir, - 'BOARD=' + self.board, - 'CTS_MODULE=' + self.module, - '-j'] - - rv = 1 - with open(self.build_log, 'a') as output: - rv = sp.call(cmds, stdout=output, stderr=sp.STDOUT) - - if rv != 0: - self.dump_build_log() - - return rv == 0 - - def dump_build_log(self): - with open(self.build_log) as log: - print(log.read()) - - def flash(self, image_path): - """Flashes board with most recent build ec.bin.""" - cmd = ['reset_config connect_assert_srst', - 'init', - 'reset init', - 'flash write_image erase %s %s' % (image_path, self.flash_offset)] - return self.send_openocd_commands(cmd) - - def to_string(self): - s = ('Type: Board\n' - 'board: ' + self.board + '\n' - 'hla_serial: ' + self.hla_serial + '\n' - 'openocd_config: ' + self.openocd_config + '\n' - 'tty_port: ' + self.tty_port + '\n' - 'tty: ' + str(self.tty) + '\n') - return s - - def reset_halt(self): - """Reset then halt board.""" - return self.send_openocd_commands(['init', 'reset halt']) - - def resume(self): - """Resume halting board.""" - return self.send_openocd_commands(['init', 'resume']) - - def setup_tty(self): - """Call this before calling read_tty for the first time. - - This is not in the initialization because caller only should call - this function after serial numbers are setup - """ - self.get_serial() - self.reset_halt() - self.identify_tty_port() - - tty = None - try: - tty = serial.Serial(self.tty_port, 115200, timeout=1) - except serial.SerialException: - raise ValueError('Failed to open ' + self.tty_port + ' of ' + self.board + - '. Please make sure the port is available and you have' + - ' permission to read it. Create dialout group and run:' + - ' sudo usermod -a -G dialout <username>.') - self.tty = tty - - def read_tty(self, max_boot_count=1): - """Read info from a serial port described by a file descriptor. - - Args: - max_boot_count: Stop reading if boot count exceeds this number - - Returns: - result: characters read from tty - boot: boot counts - """ - buf = [] - line = [] - boot = 0 - while True: - c = self.tty.read().decode('utf-8') - if not c: - break - line.append(c) - if c == '\n': - l = ''.join(line) - buf.append(l) - if REBOOT_MARKER in l: - boot += 1 + def __init__(self, board, module, hla_serial=None): + """Initializes a board object with given attributes. + + Args: + board: String containing board name + module: String of the test module you are building, + i.e. gpio, timer, etc. + hla_serial: Serial number if board's adaptor is an HLA + + Raises: + RuntimeError: Board is not supported + """ + if board not in OPENOCD_CONFIGS: + msg = "OpenOcd configuration not found for " + board + raise RuntimeError(msg) + if board not in FLASH_OFFSETS: + msg = "Flash offset not found for " + board + raise RuntimeError(msg) + self.board = board + self.flash_offset = FLASH_OFFSETS[self.board] + self.openocd_config = OPENOCD_CONFIGS[self.board] + self.module = module + self.hla_serial = hla_serial + self.tty_port = None + self.tty = None + self.log_dir = None + self.openocd_log = os.devnull + self.build_log = os.devnull + + def reset_log_dir(self): + """Reset log directory.""" + if self.log_dir: + if os.path.isdir(self.log_dir): + shutil.rmtree(self.log_dir) + os.makedirs(self.log_dir) + + @staticmethod + def get_stlink_serials(): + """Gets serial numbers of all st-link v2.1 board attached to host. + + Returns: + List of serials + """ + usb_args = ["sudo", "lsusb", "-v", "-d", "0x0483:0x374b"] + st_link_info = sp.check_output(usb_args, **get_subprocess_args()) + st_serials = [] + for line in st_link_info.split("\n"): + if "iSerial" not in line: + continue + words = line.split() + if len(words) <= 2: + continue + st_serials.append(words[2].strip()) + return st_serials + + @abstractmethod + def get_serial(self): + """Subclass should implement this.""" + pass + + def send_openocd_commands(self, commands): + """Send a command to the board via openocd. + + Args: + commands: A list of commands to send + + Returns: + True if execution is successful or False otherwise. + """ + args = [ + "sudo", + "openocd", + "-s", + OCD_SCRIPT_DIR, + "-f", + self.openocd_config, + "-c", + "hla_serial " + self.hla_serial, + ] + + for cmd in commands: + args += ["-c", cmd] + args += ["-c", "shutdown"] + + rv = 1 + with open(self.openocd_log, "a") as output: + rv = sp.call(args, stdout=output, stderr=sp.STDOUT) + + if rv != 0: + self.dump_openocd_log() + + return rv == 0 + + def dump_openocd_log(self): + with open(self.openocd_log) as log: + print(log.read()) + + def build(self, ec_dir): + """Builds test suite module for board. + + Args: + ec_dir: String of the ec directory path + + Returns: + True if build is successful or False otherwise. + """ + cmds = [ + "make", + "--directory=" + ec_dir, + "BOARD=" + self.board, + "CTS_MODULE=" + self.module, + "-j", + ] + + rv = 1 + with open(self.build_log, "a") as output: + rv = sp.call(cmds, stdout=output, stderr=sp.STDOUT) + + if rv != 0: + self.dump_build_log() + + return rv == 0 + + def dump_build_log(self): + with open(self.build_log) as log: + print(log.read()) + + def flash(self, image_path): + """Flashes board with most recent build ec.bin.""" + cmd = [ + "reset_config connect_assert_srst", + "init", + "reset init", + "flash write_image erase %s %s" % (image_path, self.flash_offset), + ] + return self.send_openocd_commands(cmd) + + def to_string(self): + s = ( + "Type: Board\n" + "board: " + self.board + "\n" + "hla_serial: " + self.hla_serial + "\n" + "openocd_config: " + self.openocd_config + "\n" + "tty_port: " + self.tty_port + "\n" + "tty: " + str(self.tty) + "\n" + ) + return s + + def reset_halt(self): + """Reset then halt board.""" + return self.send_openocd_commands(["init", "reset halt"]) + + def resume(self): + """Resume halting board.""" + return self.send_openocd_commands(["init", "resume"]) + + def setup_tty(self): + """Call this before calling read_tty for the first time. + + This is not in the initialization because caller only should call + this function after serial numbers are setup + """ + self.get_serial() + self.reset_halt() + self.identify_tty_port() + + tty = None + try: + tty = serial.Serial(self.tty_port, 115200, timeout=1) + except serial.SerialException: + raise ValueError( + "Failed to open " + + self.tty_port + + " of " + + self.board + + ". Please make sure the port is available and you have" + + " permission to read it. Create dialout group and run:" + + " sudo usermod -a -G dialout <username>." + ) + self.tty = tty + + def read_tty(self, max_boot_count=1): + """Read info from a serial port described by a file descriptor. + + Args: + max_boot_count: Stop reading if boot count exceeds this number + + Returns: + result: characters read from tty + boot: boot counts + """ + buf = [] line = [] - if boot > max_boot_count: - break - - l = ''.join(line) - buf.append(l) - result = ''.join(buf) - - return result, boot - - def identify_tty_port(self): - """Saves this board's serial port.""" - dev_dir = '/dev' - id_prefix = 'ID_SERIAL_SHORT=' - com_devices = [f for f in os.listdir(dev_dir) if f.startswith('ttyACM')] - - 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'], - **get_subprocess_args()) - 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 we get here without returning, something is wrong - raise RuntimeError('The device dev path could not be found') - - def close_tty(self): - """Close tty.""" - self.tty.close() + boot = 0 + while True: + c = self.tty.read().decode("utf-8") + if not c: + break + line.append(c) + if c == "\n": + l = "".join(line) + buf.append(l) + if REBOOT_MARKER in l: + boot += 1 + line = [] + if boot > max_boot_count: + break + + l = "".join(line) + buf.append(l) + result = "".join(buf) + + return result, boot + + def identify_tty_port(self): + """Saves this board's serial port.""" + dev_dir = "/dev" + id_prefix = "ID_SERIAL_SHORT=" + com_devices = [f for f in os.listdir(dev_dir) if f.startswith("ttyACM")] + + 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", + ], + **get_subprocess_args() + ) + 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 we get here without returning, something is wrong + raise RuntimeError("The device dev path could not be found") + + def close_tty(self): + """Close tty.""" + self.tty.close() class TestHarness(Board): - """Subclass of Board representing a Test Harness. + """Subclass of Board representing a Test Harness. - Attributes: - serial_path: Path to file containing serial number - """ - - def __init__(self, board, module, log_dir, serial_path): - """Initializes a board object with given attributes. - - Args: - board: board name - module: module name - log_dir: Directory where log file is stored + Attributes: serial_path: Path to file containing serial number """ - Board.__init__(self, board, module) - self.log_dir = log_dir - self.openocd_log = os.path.join(log_dir, 'openocd_th.log') - self.build_log = os.path.join(log_dir, 'build_th.log') - self.serial_path = serial_path - self.reset_log_dir() - - def get_serial(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 f: - s = f.read() - self.hla_serial = s.strip() + + def __init__(self, board, module, log_dir, serial_path): + """Initializes a board object with given attributes. + + Args: + board: board name + module: module name + log_dir: Directory where log file is stored + serial_path: Path to file containing serial number + """ + Board.__init__(self, board, module) + self.log_dir = log_dir + self.openocd_log = os.path.join(log_dir, "openocd_th.log") + self.build_log = os.path.join(log_dir, "build_th.log") + self.serial_path = serial_path + self.reset_log_dir() + + def get_serial(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 f: + s = f.read() + self.hla_serial = s.strip() + return + except IOError: + msg = ( + "Your TH board has not been identified.\n" + "Connect only TH and run the script --setup, then try again." + ) + raise RuntimeError(msg) + + def save_serial(self): + """Saves the TH serial number to a file.""" + serials = Board.get_stlink_serials() + if len(serials) > 1: + msg = ( + "There are more than one test board connected to the host." + "\nConnect only the test harness and remove other boards." + ) + raise RuntimeError(msg) + if len(serials) < 1: + msg = "No test boards were found.\n" "Check boards are connected." + raise RuntimeError(msg) + + s = serials[0] + serial_dir = os.path.dirname(self.serial_path) + if not os.path.exists(serial_dir): + os.makedirs(serial_dir) + with open(self.serial_path, mode="w") as f: + f.write(s) + self.hla_serial = s + + print("Your TH serial", s, "has been saved as", self.serial_path) return - except IOError: - msg = ('Your TH board has not been identified.\n' - 'Connect only TH and run the script --setup, then try again.') - raise RuntimeError(msg) - - def save_serial(self): - """Saves the TH serial number to a file.""" - serials = Board.get_stlink_serials() - if len(serials) > 1: - msg = ('There are more than one test board connected to the host.' - '\nConnect only the test harness and remove other boards.') - raise RuntimeError(msg) - if len(serials) < 1: - msg = ('No test boards were found.\n' - 'Check boards are connected.') - raise RuntimeError(msg) - - s = serials[0] - serial_dir = os.path.dirname(self.serial_path) - if not os.path.exists(serial_dir): - os.makedirs(serial_dir) - with open(self.serial_path, mode='w') as f: - f.write(s) - self.hla_serial = s - - print('Your TH serial', s, 'has been saved as', self.serial_path) - return class DeviceUnderTest(Board): - """Subclass of Board representing a DUT board. + """Subclass of Board representing a DUT board. - Attributes: - th: Reference to test harness board to which this DUT is attached - """ - - def __init__(self, board, th, module, log_dir, hla_ser=None): - """Initializes a DUT object. - - Args: - board: String containing board name + Attributes: th: Reference to test harness board to which this DUT is attached - module: module name - log_dir: Directory where log file is stored - hla_ser: Serial number if board uses an HLA adaptor """ - Board.__init__(self, board, module, hla_serial=hla_ser) - self.th = th - self.log_dir = log_dir - self.openocd_log = os.path.join(log_dir, 'openocd_dut.log') - self.build_log = os.path.join(log_dir, 'build_dut.log') - self.reset_log_dir() - - def get_serial(self): - """Get serial number. - Precondition: The DUT and TH must both be connected, and th.hla_serial - must hold the correct value (the th's serial #) + def __init__(self, board, th, module, log_dir, hla_ser=None): + """Initializes a DUT object. + + Args: + board: String containing board name + th: Reference to test harness board to which this DUT is attached + module: module name + log_dir: Directory where log file is stored + hla_ser: Serial number if board uses an HLA adaptor + """ + Board.__init__(self, board, module, hla_serial=hla_ser) + self.th = th + self.log_dir = log_dir + self.openocd_log = os.path.join(log_dir, "openocd_dut.log") + self.build_log = os.path.join(log_dir, "build_dut.log") + self.reset_log_dir() + + def get_serial(self): + """Get serial number. + + Precondition: The DUT and TH must both be connected, and th.hla_serial + must hold the correct value (the th's serial #) + + Raises: + RuntimeError: DUT isn't found or multiple DUTs are found. + """ + if self.hla_serial is not None: + # serial was already set ('' is a valid serial) + return - Raises: - RuntimeError: DUT isn't found or multiple DUTs are found. - """ - if self.hla_serial is not None: - # serial was already set ('' is a valid serial) - return - - serials = Board.get_stlink_serials() - dut = [s for s in serials if self.th.hla_serial != s] - - # 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 - if not dut: - msg = ('Failed to find serial for DUT.\n' - 'Is ' + self.board + ' connected?') - raise RuntimeError(msg) - if len(dut) > 1: - msg = ('Found multiple DUTs.\n' - 'You can connect only one DUT at a time. This may be caused by\n' - 'an incorrect TH serial. Check if ' + self.th.serial_path + '\n' - 'contains a correct serial.') - raise RuntimeError(msg) - - # Found your other st-link device serial! - self.hla_serial = dut[0] - return + serials = Board.get_stlink_serials() + dut = [s for s in serials if self.th.hla_serial != s] + + # 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 + if not dut: + msg = ( + "Failed to find serial for DUT.\nIs " + + self.board + + " connected?" + ) + raise RuntimeError(msg) + if len(dut) > 1: + msg = ( + "Found multiple DUTs.\n" + "You can connect only one DUT at a time. This may be caused by\n" + "an incorrect TH serial. Check if " + self.th.serial_path + "\n" + "contains a correct serial." + ) + raise RuntimeError(msg) + + # Found your other st-link device serial! + self.hla_serial = dut[0] + return diff --git a/cts/common/cts.rc b/cts/common/cts.rc index 264b982655..fe27b2c308 100644 --- a/cts/common/cts.rc +++ b/cts/common/cts.rc @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/common/cts_common.c b/cts/common/cts_common.c index 8975636655..4b56456a3c 100644 --- a/cts/common/cts_common.c +++ b/cts/common/cts_common.c @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -11,7 +11,7 @@ __attribute__((weak)) void clean_state(void) /* Each test overrides as needed */ } -void cts_main_loop(const struct cts_test* tests, const char *name) +void cts_main_loop(const struct cts_test *tests, const char *name) { enum cts_rc rc; int i; diff --git a/cts/common/cts_common.h b/cts/common/cts_common.h index 13a435e655..8fd9073c62 100644 --- a/cts/common/cts_common.h +++ b/cts/common/cts_common.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -10,16 +10,16 @@ /* Console output macros */ #define CPUTS(outstr) cputs(CC_SYSTEM, outstr) -#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ## args) -#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ## args) -#define CPRINTL(format, args...) CPRINTS("%s:%d: "format, \ - __func__, __LINE__, ## args) +#define CPRINTF(format, args...) cprintf(CC_SYSTEM, format, ##args) +#define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) +#define CPRINTL(format, args...) \ + CPRINTS("%s:%d: " format, __func__, __LINE__, ##args) -#define READ_WAIT_TIME_MS 100 -#define CTS_INTERRUPT_TRIGGER_DELAY_US (250 * MSEC) +#define READ_WAIT_TIME_MS 100 +#define CTS_INTERRUPT_TRIGGER_DELAY_US (250 * MSEC) enum cts_rc { - #include "cts.rc" +#include "cts.rc" }; struct cts_test { @@ -38,7 +38,7 @@ extern const int cts_test_count; * @test: List of tests to run * @name: Name of the test to be printed on EC console */ -void cts_main_loop(const struct cts_test* tests, const char *name); +void cts_main_loop(const struct cts_test *tests, const char *name); /** * Callback function called at the beginning of the main loop diff --git a/cts/common/cts_testlist.h b/cts/common/cts_testlist.h index 1586c1348e..ee3ea58d39 100644 --- a/cts/common/cts_testlist.h +++ b/cts/common/cts_testlist.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -22,7 +22,7 @@ #undef CTS_TEST #define CTS_TEST(test, th_rc, th_string, dut_rc, dut_string) \ - {test, STRINGIFY(test)}, + { test, STRINGIFY(test) }, struct cts_test tests[] = { #include "cts.testlist" }; diff --git a/cts/common/dut_common.c b/cts/common/dut_common.c index c9644b66e8..aa68436d41 100644 --- a/cts/common/dut_common.c +++ b/cts/common/dut_common.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/common/th_common.c b/cts/common/th_common.c index 1d692b7843..3084579b99 100644 --- a/cts/common/th_common.c +++ b/cts/common/th_common.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/cts.py b/cts/cts.py index c3e0335cab..f61de47398 100755 --- a/cts/cts.py +++ b/cts/cts.py @@ -1,12 +1,8 @@ #!/usr/bin/env python # -# Copyright 2016 The Chromium OS Authors. All rights reserved. +# Copyright 2016 The ChromiumOS Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# -# Ignore indention messages, since legacy scripts use 2 spaces instead of 4. -# pylint: disable=bad-indentation,docstring-section-indent -# pylint: disable=docstring-trailing-quotes # A script which builds, flashes, and runs EC CTS # @@ -28,416 +24,443 @@ import argparse import os import shutil import time -import common.board as board +import common.board as board -CTS_RC_PREFIX = 'CTS_RC_' -DEFAULT_TH = 'stm32l476g-eval' -DEFAULT_DUT = 'nucleo-f072rb' +CTS_RC_PREFIX = "CTS_RC_" +DEFAULT_TH = "stm32l476g-eval" +DEFAULT_DUT = "nucleo-f072rb" MAX_SUITE_TIME_SEC = 5 -CTS_TEST_RESULT_DIR = '/tmp/ects' +CTS_TEST_RESULT_DIR = "/tmp/ects" # Host only return codes. Make sure they match values in cts.rc -CTS_RC_DID_NOT_START = -1 # test did not run. -CTS_RC_DID_NOT_END = -2 # test did not run. -CTS_RC_DUPLICATE_RUN = -3 # test was run multiple times. -CTS_RC_INVALID_RETURN_CODE = -4 # failed to parse return code +CTS_RC_DID_NOT_START = -1 # test did not run. +CTS_RC_DID_NOT_END = -2 # test did not run. +CTS_RC_DUPLICATE_RUN = -3 # test was run multiple times. +CTS_RC_INVALID_RETURN_CODE = -4 # failed to parse return code class Cts(object): - """Class that represents a eCTS run. - - Attributes: - dut: DeviceUnderTest object representing DUT - th: TestHarness object representing a test harness - module: Name of module to build/run tests for - testlist: List of strings of test names contained in given module - return_codes: Dict of strings of return codes, with a code's integer - value being the index for the corresponding string representation - """ - - def __init__(self, ec_dir, th, dut, module): - """Initializes cts class object with given arguments. - - Args: - ec_dir: Path to ec directory - th: Name of the test harness board - dut: Name of the device under test board - module: Name of module to build/run tests for (e.g. gpio, interrupt) - """ - self.results_dir = os.path.join(CTS_TEST_RESULT_DIR, dut, module) - if os.path.isdir(self.results_dir): - shutil.rmtree(self.results_dir) - else: - os.makedirs(self.results_dir) - self.ec_dir = ec_dir - self.module = module - serial_path = os.path.join(CTS_TEST_RESULT_DIR, 'th_serial') - self.th = board.TestHarness(th, module, self.results_dir, serial_path) - self.dut = board.DeviceUnderTest(dut, self.th, module, self.results_dir) - cts_dir = os.path.join(self.ec_dir, 'cts') - testlist_path = os.path.join(cts_dir, self.module, 'cts.testlist') - return_codes_path = os.path.join(cts_dir, 'common', 'cts.rc') - self.get_return_codes(return_codes_path) - self.testlist = self.get_macro_args(testlist_path, 'CTS_TEST') - - def build(self): - """Build images for DUT and TH.""" - print('Building DUT image...') - if not self.dut.build(self.ec_dir): - raise RuntimeError('Building module %s for DUT failed' % (self.module)) - print('Building TH image...') - if not self.th.build(self.ec_dir): - raise RuntimeError('Building module %s for TH failed' % (self.module)) - - def flash_boards(self): - """Flashes TH and DUT with their most recently built ec.bin.""" - cts_module = 'cts_' + self.module - image_path = os.path.join('build', self.th.board, cts_module, 'ec.bin') - self.identify_boards() - print('Flashing TH with', image_path) - if not self.th.flash(image_path): - raise RuntimeError('Flashing TH failed') - image_path = os.path.join('build', self.dut.board, cts_module, 'ec.bin') - print('Flashing DUT with', image_path) - if not self.dut.flash(image_path): - raise RuntimeError('Flashing DUT failed') - - def setup(self): - """Setup boards.""" - self.th.save_serial() - - def identify_boards(self): - """Updates serials of TH and DUT in that order (order matters).""" - self.th.get_serial() - self.dut.get_serial() - - def get_macro_args(self, filepath, macro): - """Get list of args of a macro in a file when macro. - - Args: - filepath: String containing absolute path to the file - macro: String containing text of macro to get args of - - Returns: - List of dictionaries where each entry is: - 'name': Test name, - 'th_string': Expected string from TH, - 'dut_string': Expected string from DUT, + """Class that represents a eCTS run. + + Attributes: + dut: DeviceUnderTest object representing DUT + th: TestHarness object representing a test harness + module: Name of module to build/run tests for + testlist: List of strings of test names contained in given module + return_codes: Dict of strings of return codes, with a code's integer + value being the index for the corresponding string representation """ - tests = [] - with open(filepath, 'r') as f: - lines = f.readlines() - joined = ''.join(lines).replace('\\\n', '').splitlines() - for l in joined: - if not l.strip().startswith(macro): - continue - d = {} - l = l.strip()[len(macro):] - l = l.strip('()').split(',') - d['name'] = l[0].strip() - d['th_rc'] = self.get_return_code_value(l[1].strip().strip('"')) - d['th_string'] = l[2].strip().strip('"') - d['dut_rc'] = self.get_return_code_value(l[3].strip().strip('"')) - d['dut_string'] = l[4].strip().strip('"') - tests.append(d) - return tests - - def get_return_codes(self, filepath): - """Read return code names from the return code definition file.""" - self.return_codes = {} - val = 0 - with open(filepath, 'r') as f: - for line in f: - line = line.strip() - if not line.startswith(CTS_RC_PREFIX): - continue - line = line.split(',')[0] - if '=' in line: - tokens = line.split('=') - line = tokens[0].strip() - val = int(tokens[1].strip()) - self.return_codes[line] = val - val += 1 - - def parse_output(self, output): - """Parse console output from DUT or TH. - - Args: - output: String containing consoule output - - Returns: - List of dictionaries where each key and value are: - name = 'ects_test_x', - started = True/False, - ended = True/False, - rc = CTS_RC_*, - output = All text between 'ects_test_x start' and 'ects_test_x end' - """ - results = [] - i = 0 - for test in self.testlist: - results.append({}) - results[i]['name'] = test['name'] - results[i]['started'] = False - results[i]['rc'] = CTS_RC_DID_NOT_START - results[i]['string'] = False - results[i]['output'] = [] - i += 1 - - i = 0 - for ln in [ln.strip() for ln in output.split('\n')]: - if i + 1 > len(results): - break - tokens = ln.split() - if len(tokens) >= 2: - if tokens[0].strip() == results[i]['name']: - if tokens[1].strip() == 'start': - # start line found - if results[i]['started']: # Already started - results[i]['rc'] = CTS_RC_DUPLICATE_RUN - else: - results[i]['rc'] = CTS_RC_DID_NOT_END - results[i]['started'] = True - continue - elif results[i]['started'] and tokens[1].strip() == 'end': - # end line found - results[i]['rc'] = CTS_RC_INVALID_RETURN_CODE - if len(tokens) == 3: - try: - results[i]['rc'] = int(tokens[2].strip()) - except ValueError: - pass - # Since index is incremented when 'end' is encountered, we don't - # need to check duplicate 'end'. - i += 1 - continue - if results[i]['started']: - results[i]['output'].append(ln) - - return results - - def get_return_code_name(self, code, strip_prefix=False): - name = '' - for k, v in self.return_codes.items(): - if v == code: - if strip_prefix: - name = k[len(CTS_RC_PREFIX):] - else: - name = k - return name - - def get_return_code_value(self, name): - if name: - return self.return_codes[name] - return 0 - - def evaluate_run(self, dut_output, th_output): - """Parse outputs to derive test results. - Args: - dut_output: String output of DUT - th_output: String output of TH - - Returns: - th_results: list of test results for TH - dut_results: list of test results for DUT - """ - th_results = self.parse_output(th_output) - dut_results = self.parse_output(dut_output) - - # Search for expected string in each output - for i, v in enumerate(self.testlist): - if v['th_string'] in th_results[i]['output'] or not v['th_string']: - th_results[i]['string'] = True - if v['dut_string'] in dut_results[i]['output'] or not v['dut_string']: - dut_results[i]['string'] = True + def __init__(self, ec_dir, th, dut, module): + """Initializes cts class object with given arguments. + + Args: + ec_dir: Path to ec directory + th: Name of the test harness board + dut: Name of the device under test board + module: Name of module to build/run tests for (e.g. gpio, interrupt) + """ + self.results_dir = os.path.join(CTS_TEST_RESULT_DIR, dut, module) + if os.path.isdir(self.results_dir): + shutil.rmtree(self.results_dir) + else: + os.makedirs(self.results_dir) + self.ec_dir = ec_dir + self.module = module + serial_path = os.path.join(CTS_TEST_RESULT_DIR, "th_serial") + self.th = board.TestHarness(th, module, self.results_dir, serial_path) + self.dut = board.DeviceUnderTest(dut, self.th, module, self.results_dir) + cts_dir = os.path.join(self.ec_dir, "cts") + testlist_path = os.path.join(cts_dir, self.module, "cts.testlist") + return_codes_path = os.path.join(cts_dir, "common", "cts.rc") + self.get_return_codes(return_codes_path) + self.testlist = self.get_macro_args(testlist_path, "CTS_TEST") + + def build(self): + """Build images for DUT and TH.""" + print("Building DUT image...") + if not self.dut.build(self.ec_dir): + raise RuntimeError( + "Building module %s for DUT failed" % (self.module) + ) + print("Building TH image...") + if not self.th.build(self.ec_dir): + raise RuntimeError( + "Building module %s for TH failed" % (self.module) + ) + + def flash_boards(self): + """Flashes TH and DUT with their most recently built ec.bin.""" + cts_module = "cts_" + self.module + image_path = os.path.join("build", self.th.board, cts_module, "ec.bin") + self.identify_boards() + print("Flashing TH with", image_path) + if not self.th.flash(image_path): + raise RuntimeError("Flashing TH failed") + image_path = os.path.join("build", self.dut.board, cts_module, "ec.bin") + print("Flashing DUT with", image_path) + if not self.dut.flash(image_path): + raise RuntimeError("Flashing DUT failed") + + def setup(self): + """Setup boards.""" + self.th.save_serial() + + def identify_boards(self): + """Updates serials of TH and DUT in that order (order matters).""" + self.th.get_serial() + self.dut.get_serial() + + def get_macro_args(self, filepath, macro): + """Get list of args of a macro in a file when macro. + + Args: + filepath: String containing absolute path to the file + macro: String containing text of macro to get args of + + Returns: + List of dictionaries where each entry is: + 'name': Test name, + 'th_string': Expected string from TH, + 'dut_string': Expected string from DUT, + """ + tests = [] + with open(filepath, "r") as f: + lines = f.readlines() + joined = "".join(lines).replace("\\\n", "").splitlines() + for l in joined: + if not l.strip().startswith(macro): + continue + d = {} + l = l.strip()[len(macro) :] + l = l.strip("()").split(",") + d["name"] = l[0].strip() + d["th_rc"] = self.get_return_code_value(l[1].strip().strip('"')) + d["th_string"] = l[2].strip().strip('"') + d["dut_rc"] = self.get_return_code_value( + l[3].strip().strip('"') + ) + d["dut_string"] = l[4].strip().strip('"') + tests.append(d) + return tests + + def get_return_codes(self, filepath): + """Read return code names from the return code definition file.""" + self.return_codes = {} + val = 0 + with open(filepath, "r") as f: + for line in f: + line = line.strip() + if not line.startswith(CTS_RC_PREFIX): + continue + line = line.split(",")[0] + if "=" in line: + tokens = line.split("=") + line = tokens[0].strip() + val = int(tokens[1].strip()) + self.return_codes[line] = val + val += 1 + + def parse_output(self, output): + """Parse console output from DUT or TH. + + Args: + output: String containing consoule output + + Returns: + List of dictionaries where each key and value are: + name = 'ects_test_x', + started = True/False, + ended = True/False, + rc = CTS_RC_*, + output = All text between 'ects_test_x start' and 'ects_test_x end' + """ + results = [] + i = 0 + for test in self.testlist: + results.append({}) + results[i]["name"] = test["name"] + results[i]["started"] = False + results[i]["rc"] = CTS_RC_DID_NOT_START + results[i]["string"] = False + results[i]["output"] = [] + i += 1 - return th_results, dut_results + i = 0 + for ln in [ln.strip() for ln in output.split("\n")]: + if i + 1 > len(results): + break + tokens = ln.split() + if len(tokens) >= 2: + if tokens[0].strip() == results[i]["name"]: + if tokens[1].strip() == "start": + # start line found + if results[i]["started"]: # Already started + results[i]["rc"] = CTS_RC_DUPLICATE_RUN + else: + results[i]["rc"] = CTS_RC_DID_NOT_END + results[i]["started"] = True + continue + elif results[i]["started"] and tokens[1].strip() == "end": + # end line found + results[i]["rc"] = CTS_RC_INVALID_RETURN_CODE + if len(tokens) == 3: + try: + results[i]["rc"] = int(tokens[2].strip()) + except ValueError: + pass + # Since index is incremented when 'end' is encountered, we don't + # need to check duplicate 'end'. + i += 1 + continue + if results[i]["started"]: + results[i]["output"].append(ln) + + return results + + def get_return_code_name(self, code, strip_prefix=False): + name = "" + for k, v in self.return_codes.items(): + if v == code: + if strip_prefix: + name = k[len(CTS_RC_PREFIX) :] + else: + name = k + return name + + def get_return_code_value(self, name): + if name: + return self.return_codes[name] + return 0 + + def evaluate_run(self, dut_output, th_output): + """Parse outputs to derive test results. + + Args: + dut_output: String output of DUT + th_output: String output of TH + + Returns: + th_results: list of test results for TH + dut_results: list of test results for DUT + """ + th_results = self.parse_output(th_output) + dut_results = self.parse_output(dut_output) + + # Search for expected string in each output + for i, v in enumerate(self.testlist): + if v["th_string"] in th_results[i]["output"] or not v["th_string"]: + th_results[i]["string"] = True + if ( + v["dut_string"] in dut_results[i]["output"] + or not v["dut_string"] + ): + dut_results[i]["string"] = True + + return th_results, dut_results + + def print_result(self, th_results, dut_results): + """Print results to the screen. + + Args: + th_results: list of test results for TH + dut_results: list of test results for DUT + """ + len_test_name = max(len(s["name"]) for s in self.testlist) + len_code_name = max( + len(self.get_return_code_name(v, True)) + for v in self.return_codes.values() + ) + + head = "{:^" + str(len_test_name) + "} " + head += "{:^" + str(len_code_name) + "} " + head += "{:^" + str(len_code_name) + "}" + head += "{:^" + str(len(" TH_STR")) + "}" + head += "{:^" + str(len(" DUT_STR")) + "}" + head += "{:^" + str(len(" RESULT")) + "}\n" + fmt = "{:" + str(len_test_name) + "} " + fmt += "{:>" + str(len_code_name) + "} " + fmt += "{:>" + str(len_code_name) + "}" + fmt += "{:>" + str(len(" TH_STR")) + "}" + fmt += "{:>" + str(len(" DUT_STR")) + "}" + fmt += "{:>" + str(len(" RESULT")) + "}\n" + + self.formatted_results = head.format( + "TEST NAME", "TH_RC", "DUT_RC", " TH_STR", " DUT_STR", " RESULT" + ) + for i, d in enumerate(dut_results): + th_cn = self.get_return_code_name(th_results[i]["rc"], True) + dut_cn = self.get_return_code_name(dut_results[i]["rc"], True) + th_res = self.evaluate_result( + th_results[i], + self.testlist[i]["th_rc"], + self.testlist[i]["th_string"], + ) + dut_res = self.evaluate_result( + dut_results[i], + self.testlist[i]["dut_rc"], + self.testlist[i]["dut_string"], + ) + self.formatted_results += fmt.format( + d["name"], + th_cn, + dut_cn, + "YES" if th_results[i]["string"] else "NO", + "YES" if dut_results[i]["string"] else "NO", + "PASS" if th_res and dut_res else "FAIL", + ) + + def evaluate_result(self, result, expected_rc, expected_string): + if result["rc"] != expected_rc: + return False + if expected_string and expected_string not in result["output"]: + return False + return True + + def run(self): + """Resets boards, records test results in results dir.""" + print("Reading serials...") + self.identify_boards() + print("Opening DUT tty...") + self.dut.setup_tty() + print("Opening TH tty...") + self.th.setup_tty() + + # Boards might be still writing to tty. Wait a few seconds before flashing. + time.sleep(3) + + # clear buffers + print("Clearing DUT tty...") + self.dut.read_tty() + print("Clearing TH tty...") + self.th.read_tty() + + # 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 + print("Halting TH...") + if not self.th.reset_halt(): + raise RuntimeError("Failed to halt TH") + print("Halting DUT...") + if not self.dut.reset_halt(): + raise RuntimeError("Failed to halt DUT") + print("Resuming TH...") + if not self.th.resume(): + raise RuntimeError("Failed to resume TH") + print("Resuming DUT...") + if not self.dut.resume(): + raise RuntimeError("Failed to resume DUT") + + time.sleep(MAX_SUITE_TIME_SEC) + + print("Reading DUT tty...") + dut_output, _ = self.dut.read_tty() + self.dut.close_tty() + print("Reading TH tty...") + th_output, _ = self.th.read_tty() + self.th.close_tty() + + print("Halting TH...") + if not self.th.reset_halt(): + raise RuntimeError("Failed to halt TH") + print("Halting DUT...") + if not self.dut.reset_halt(): + raise RuntimeError("Failed to halt DUT") + + if not dut_output or not th_output: + raise ValueError( + "Output missing from boards. If you have a process " + "reading ttyACMx, please kill that process and try " + "again." + ) + + print("Pursing results...") + th_results, dut_results = self.evaluate_run(dut_output, th_output) + + # Print out results + self.print_result(th_results, dut_results) + + # Write results + dest = os.path.join(self.results_dir, "results.log") + with open(dest, "w") as fl: + fl.write(self.formatted_results) + + # Write UART outputs + dest = os.path.join(self.results_dir, "uart_th.log") + with open(dest, "w") as fl: + fl.write(th_output) + dest = os.path.join(self.results_dir, "uart_dut.log") + with open(dest, "w") as fl: + fl.write(dut_output) + + print(self.formatted_results) + + # TODO(chromium:735652): Should set exit code for the shell - def print_result(self, th_results, dut_results): - """Print results to the screen. - Args: - th_results: list of test results for TH - dut_results: list of test results for DUT - """ - len_test_name = max(len(s['name']) for s in self.testlist) - len_code_name = max(len(self.get_return_code_name(v, True)) - for v in self.return_codes.values()) - - head = '{:^' + str(len_test_name) + '} ' - head += '{:^' + str(len_code_name) + '} ' - head += '{:^' + str(len_code_name) + '}' - head += '{:^' + str(len(' TH_STR')) + '}' - head += '{:^' + str(len(' DUT_STR')) + '}' - head += '{:^' + str(len(' RESULT')) + '}\n' - fmt = '{:' + str(len_test_name) + '} ' - fmt += '{:>' + str(len_code_name) + '} ' - fmt += '{:>' + str(len_code_name) + '}' - fmt += '{:>' + str(len(' TH_STR')) + '}' - fmt += '{:>' + str(len(' DUT_STR')) + '}' - fmt += '{:>' + str(len(' RESULT')) + '}\n' - - self.formatted_results = head.format( - 'TEST NAME', 'TH_RC', 'DUT_RC', - ' TH_STR', ' DUT_STR', ' RESULT') - for i, d in enumerate(dut_results): - th_cn = self.get_return_code_name(th_results[i]['rc'], True) - dut_cn = self.get_return_code_name(dut_results[i]['rc'], True) - th_res = self.evaluate_result(th_results[i], - self.testlist[i]['th_rc'], - self.testlist[i]['th_string']) - dut_res = self.evaluate_result(dut_results[i], - self.testlist[i]['dut_rc'], - self.testlist[i]['dut_string']) - self.formatted_results += fmt.format( - d['name'], th_cn, dut_cn, - 'YES' if th_results[i]['string'] else 'NO', - 'YES' if dut_results[i]['string'] else 'NO', - 'PASS' if th_res and dut_res else 'FAIL') - - def evaluate_result(self, result, expected_rc, expected_string): - if result['rc'] != expected_rc: - return False - if expected_string and expected_string not in result['output']: - return False - return True - - def run(self): - """Resets boards, records test results in results dir.""" - print('Reading serials...') - self.identify_boards() - print('Opening DUT tty...') - self.dut.setup_tty() - print('Opening TH tty...') - self.th.setup_tty() - - # Boards might be still writing to tty. Wait a few seconds before flashing. - time.sleep(3) - - # clear buffers - print('Clearing DUT tty...') - self.dut.read_tty() - print('Clearing TH tty...') - self.th.read_tty() - - # 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 - print('Halting TH...') - if not self.th.reset_halt(): - raise RuntimeError('Failed to halt TH') - print('Halting DUT...') - if not self.dut.reset_halt(): - raise RuntimeError('Failed to halt DUT') - print('Resuming TH...') - if not self.th.resume(): - raise RuntimeError('Failed to resume TH') - print('Resuming DUT...') - if not self.dut.resume(): - raise RuntimeError('Failed to resume DUT') - - time.sleep(MAX_SUITE_TIME_SEC) - - print('Reading DUT tty...') - dut_output, _ = self.dut.read_tty() - self.dut.close_tty() - print('Reading TH tty...') - th_output, _ = self.th.read_tty() - self.th.close_tty() - - print('Halting TH...') - if not self.th.reset_halt(): - raise RuntimeError('Failed to halt TH') - print('Halting DUT...') - if not self.dut.reset_halt(): - raise RuntimeError('Failed to halt DUT') - - if not dut_output or not th_output: - raise ValueError('Output missing from boards. If you have a process ' - 'reading ttyACMx, please kill that process and try ' - 'again.') - - print('Pursing results...') - th_results, dut_results = self.evaluate_run(dut_output, th_output) - - # Print out results - self.print_result(th_results, dut_results) - - # Write results - dest = os.path.join(self.results_dir, 'results.log') - with open(dest, 'w') as fl: - fl.write(self.formatted_results) - - # Write UART outputs - dest = os.path.join(self.results_dir, 'uart_th.log') - with open(dest, 'w') as fl: - fl.write(th_output) - dest = os.path.join(self.results_dir, 'uart_dut.log') - with open(dest, 'w') as fl: - fl.write(dut_output) - - print(self.formatted_results) - - # TODO(chromium:735652): Should set exit code for the shell +def main(): + ec_dir = os.path.realpath( + os.path.join(os.path.dirname(os.path.abspath(__file__)), "..") + ) + os.chdir(ec_dir) + + dut = DEFAULT_DUT + module = "meta" + + parser = argparse.ArgumentParser(description="Used to build/flash boards") + parser.add_argument( + "-d", "--dut", help="Specify DUT you want to build/flash" + ) + parser.add_argument( + "-m", "--module", help="Specify module you want to build/flash" + ) + parser.add_argument( + "-s", + "--setup", + action="store_true", + help="Connect only the TH to save its serial", + ) + parser.add_argument( + "-b", + "--build", + action="store_true", + help="Build test suite (no flashing)", + ) + parser.add_argument( + "-f", + "--flash", + action="store_true", + help="Flash boards with most recent images", + ) + parser.add_argument( + "-r", "--run", action="store_true", help="Run tests without flashing" + ) + + args = parser.parse_args() + + if args.module: + module = args.module + + if args.dut: + dut = args.dut + + cts = Cts(ec_dir, DEFAULT_TH, dut=dut, module=module) + + if args.setup: + cts.setup() + elif args.build: + cts.build() + elif args.flash: + cts.flash_boards() + elif args.run: + cts.run() + else: + cts.build() + cts.flash_boards() + cts.run() -def main(): - ec_dir = os.path.realpath(os.path.join( - os.path.dirname(os.path.abspath(__file__)), '..')) - os.chdir(ec_dir) - - dut = DEFAULT_DUT - module = 'meta' - - parser = argparse.ArgumentParser(description='Used to build/flash boards') - parser.add_argument('-d', - '--dut', - help='Specify DUT you want to build/flash') - parser.add_argument('-m', - '--module', - help='Specify module you want to build/flash') - parser.add_argument('-s', - '--setup', - action='store_true', - help='Connect only the TH to save its serial') - parser.add_argument('-b', - '--build', - action='store_true', - help='Build test suite (no flashing)') - parser.add_argument('-f', - '--flash', - action='store_true', - help='Flash boards with most recent images') - parser.add_argument('-r', - '--run', - action='store_true', - help='Run tests without flashing') - - args = parser.parse_args() - - if args.module: - module = args.module - - if args.dut: - dut = args.dut - - cts = Cts(ec_dir, DEFAULT_TH, dut=dut, module=module) - - if args.setup: - cts.setup() - elif args.build: - cts.build() - elif args.flash: - cts.flash_boards() - elif args.run: - cts.run() - else: - cts.build() - cts.flash_boards() - cts.run() - -if __name__ == '__main__': - main() +if __name__ == "__main__": + main() diff --git a/cts/cts.tasklist b/cts/cts.tasklist index 152b0d02b2..40dfb21e10 100644 --- a/cts/cts.tasklist +++ b/cts/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/gpio/cts.testlist b/cts/gpio/cts.testlist index 113d2b405f..a5b7482675 100644 --- a/cts/gpio/cts.testlist +++ b/cts/gpio/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/gpio/dut.c b/cts/gpio/dut.c index 7ed613911c..92ae893a48 100644 --- a/cts/gpio/dut.c +++ b/cts/gpio/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -21,7 +21,7 @@ enum cts_rc set_high_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 1); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } @@ -29,7 +29,7 @@ enum cts_rc set_low_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 0); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } diff --git a/cts/gpio/th.c b/cts/gpio/th.c index 30f33b21bf..98fc232d1c 100644 --- a/cts/gpio/th.c +++ b/cts/gpio/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -47,7 +47,7 @@ enum cts_rc read_high_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 1); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } @@ -55,14 +55,14 @@ enum cts_rc read_low_test(void) { gpio_set_flags(GPIO_OUTPUT_TEST, GPIO_ODR_LOW); gpio_set_level(GPIO_OUTPUT_TEST, 0); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } enum cts_rc od_read_high_test(void) { gpio_set_flags(GPIO_INPUT_TEST, GPIO_OUTPUT | GPIO_ODR_LOW); - msleep(READ_WAIT_TIME_MS*2); + msleep(READ_WAIT_TIME_MS * 2); return CTS_RC_SUCCESS; } diff --git a/cts/hook/cts.testlist b/cts/hook/cts.testlist index 97b25575d4..75e1a11324 100644 --- a/cts/hook/cts.testlist +++ b/cts/hook/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2017 The Chromium OS Authors. All rights reserved. +/* Copyright 2017 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/hook/dut.c b/cts/hook/dut.c index f3a52ddaf4..fc6187cade 100644 --- a/cts/hook/dut.c +++ b/cts/hook/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -88,8 +88,7 @@ static enum cts_rc test_ticks(void) msleep(1300); interval = tick_time[1].val - tick_time[0].val; - error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / - HOOK_TICK_INTERVAL; + error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / HOOK_TICK_INTERVAL; if (error_pct < -10 || 10 < error_pct) { CPRINTS("tick error=%d%% interval=%lld", error_pct, interval); return CTS_RC_FAILURE; @@ -142,8 +141,8 @@ static enum cts_rc test_deferred(void) /* Invalid deferred function */ deferred_call_count = 0; - if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) - == EC_SUCCESS) { + if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) == + EC_SUCCESS) { CPRINTL("non_deferred_func_data"); return CTS_RC_FAILURE; } diff --git a/cts/hook/th.c b/cts/hook/th.c index 41eab28462..fc6187cade 120000..100644 --- a/cts/hook/th.c +++ b/cts/hook/th.c @@ -1 +1,164 @@ -dut.c
\ No newline at end of file +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test hooks. + */ + +#include "common.h" +#include "console.h" +#include "cts_common.h" +#include "hooks.h" +#include "task.h" +#include "timer.h" +#include "util.h" +#include "watchdog.h" + +static int init_hook_count; +static int tick_hook_count; +static int tick2_hook_count; +static int tick_count_seen_by_tick2; +static timestamp_t tick_time[2]; +static int second_hook_count; +static timestamp_t second_time[2]; +static int deferred_call_count; + +static void init_hook(void) +{ + init_hook_count++; +} +DECLARE_HOOK(HOOK_INIT, init_hook, HOOK_PRIO_DEFAULT); + +static void tick_hook(void) +{ + tick_hook_count++; + tick_time[0] = tick_time[1]; + tick_time[1] = get_time(); +} +DECLARE_HOOK(HOOK_TICK, tick_hook, HOOK_PRIO_DEFAULT); + +static void tick2_hook(void) +{ + tick2_hook_count++; + tick_count_seen_by_tick2 = tick_hook_count; +} +/* tick2_hook() prio means it should be called after tick_hook() */ +DECLARE_HOOK(HOOK_TICK, tick2_hook, HOOK_PRIO_DEFAULT + 1); + +static void second_hook(void) +{ + second_hook_count++; + second_time[0] = second_time[1]; + second_time[1] = get_time(); +} +DECLARE_HOOK(HOOK_SECOND, second_hook, HOOK_PRIO_DEFAULT); + +static void deferred_func(void) +{ + deferred_call_count++; +} +DECLARE_DEFERRED(deferred_func); + +static void invalid_deferred_func(void) +{ + deferred_call_count++; +} + +static const struct deferred_data invalid_deferred_func_data = { + invalid_deferred_func +}; + +static enum cts_rc test_init_hook(void) +{ + if (init_hook_count != 1) + return CTS_RC_FAILURE; + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_ticks(void) +{ + int64_t interval; + int error_pct; + + /* + * HOOK_SECOND must have been fired at least once when HOOK + * task starts. We only need to wait for just more than a second + * to allow it fires for the second time. + */ + msleep(1300); + + interval = tick_time[1].val - tick_time[0].val; + error_pct = (interval - HOOK_TICK_INTERVAL) * 100 / HOOK_TICK_INTERVAL; + if (error_pct < -10 || 10 < error_pct) { + CPRINTS("tick error=%d%% interval=%lld", error_pct, interval); + return CTS_RC_FAILURE; + } + + interval = second_time[1].val - second_time[0].val; + error_pct = (interval - SECOND) * 100 / SECOND; + if (error_pct < -10 || 10 < error_pct) { + CPRINTS("second error=%d%% interval=%lld", error_pct, interval); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_priority(void) +{ + usleep(HOOK_TICK_INTERVAL); + if (tick_hook_count != tick2_hook_count) + return CTS_RC_FAILURE; + if (tick_hook_count != tick_count_seen_by_tick2) + return CTS_RC_FAILURE; + return CTS_RC_SUCCESS; +} + +static enum cts_rc test_deferred(void) +{ + deferred_call_count = 0; + hook_call_deferred(&deferred_func_data, 50 * MSEC); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + msleep(100); + if (deferred_call_count != 1) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + /* Test cancellation */ + deferred_call_count = 0; + hook_call_deferred(&deferred_func_data, 50 * MSEC); + msleep(25); + hook_call_deferred(&deferred_func_data, -1); + msleep(75); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + /* Invalid deferred function */ + deferred_call_count = 0; + if (hook_call_deferred(&invalid_deferred_func_data, 50 * MSEC) == + EC_SUCCESS) { + CPRINTL("non_deferred_func_data"); + return CTS_RC_FAILURE; + } + msleep(100); + if (deferred_call_count != 0) { + CPRINTL("deferred_call_count=%d", deferred_call_count); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +#include "cts_testlist.h" + +void cts_task(void) +{ + cts_main_loop(tests, "Hook"); + task_wait_event(-1); +} diff --git a/cts/i2c/cts.testlist b/cts/i2c/cts.testlist index 7b6461e84d..b52e247680 100644 --- a/cts/i2c/cts.testlist +++ b/cts/i2c/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/i2c/cts_i2c.h b/cts/i2c/cts_i2c.h index 2914d92a99..ae4aab9878 100644 --- a/cts/i2c/cts_i2c.h +++ b/cts/i2c/cts_i2c.h @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -12,9 +12,9 @@ enum cts_i2c_packets { READ32_OFF, }; -#define WRITE8_DATA 0x42 -#define WRITE16_DATA 0x1234 -#define WRITE32_DATA 0xDEADBEEF -#define READ8_DATA 0x23 -#define READ16_DATA 0xACED -#define READ32_DATA 0x01ABCDEF +#define WRITE8_DATA 0x42 +#define WRITE16_DATA 0x1234 +#define WRITE32_DATA 0xDEADBEEF +#define READ8_DATA 0x23 +#define READ16_DATA 0xACED +#define READ32_DATA 0x01ABCDEF diff --git a/cts/i2c/dut.c b/cts/i2c/dut.c index c7a3f9fccf..d2d721fdd6 100644 --- a/cts/i2c/dut.c +++ b/cts/i2c/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ @@ -17,24 +17,24 @@ enum cts_rc write8_test(void) { - if (i2c_write8(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE8_OFF, WRITE8_DATA)) + if (i2c_write8(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE8_OFF, + WRITE8_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } enum cts_rc write16_test(void) { - if (i2c_write16(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE16_OFF, WRITE16_DATA)) + if (i2c_write16(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE16_OFF, + WRITE16_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } enum cts_rc write32_test(void) { - if (i2c_write32(i2c_ports[0].port, TH_ADDR_FLAGS, - WRITE32_OFF, WRITE32_DATA)) + if (i2c_write32(i2c_ports[0].port, TH_ADDR_FLAGS, WRITE32_OFF, + WRITE32_DATA)) return CTS_RC_FAILURE; return CTS_RC_SUCCESS; } @@ -43,8 +43,7 @@ enum cts_rc read8_test(void) { int data; - if (i2c_read8(i2c_ports[0].port, TH_ADDR_FLAGS, - READ8_OFF, &data)) + if (i2c_read8(i2c_ports[0].port, TH_ADDR_FLAGS, READ8_OFF, &data)) return CTS_RC_FAILURE; if (data != READ8_DATA) { CPRINTL("Expecting 0x%x but read 0x%x", READ8_DATA, data); @@ -58,8 +57,7 @@ enum cts_rc read16_test(void) { int data; - if (i2c_read16(i2c_ports[0].port, TH_ADDR_FLAGS, - READ16_OFF, &data)) + if (i2c_read16(i2c_ports[0].port, TH_ADDR_FLAGS, READ16_OFF, &data)) return CTS_RC_FAILURE; if (data != READ16_DATA) { CPRINTL("Expecting 0x%x but read 0x%x", READ16_DATA, data); @@ -73,8 +71,7 @@ enum cts_rc read32_test(void) { int data; - if (i2c_read32(i2c_ports[0].port, TH_ADDR_FLAGS, - READ32_OFF, &data)) + if (i2c_read32(i2c_ports[0].port, TH_ADDR_FLAGS, READ32_OFF, &data)) return CTS_RC_FAILURE; if (data != READ32_DATA) { CPRINTL("Read 0x%x expecting 0x%x", data, READ32_DATA); @@ -84,7 +81,6 @@ enum cts_rc read32_test(void) return CTS_RC_SUCCESS; } - #include "cts_testlist.h" void cts_task(void) diff --git a/cts/i2c/th.c b/cts/i2c/th.c index 78035cb1b2..ef57f6300c 100644 --- a/cts/i2c/th.c +++ b/cts/i2c/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/interrupt/cts.testlist b/cts/interrupt/cts.testlist index 0fdaf6fca2..e48208d900 100644 --- a/cts/interrupt/cts.testlist +++ b/cts/interrupt/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/interrupt/dut.c b/cts/interrupt/dut.c index a479918c5f..c2e0af0f81 100644 --- a/cts/interrupt/dut.c +++ b/cts/interrupt/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/interrupt/th.c b/cts/interrupt/th.c index 1639a1868c..ff9a3b303b 100644 --- a/cts/interrupt/th.c +++ b/cts/interrupt/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/cts.testlist b/cts/meta/cts.testlist index 28ac7e325f..2d41848737 100644 --- a/cts/meta/cts.testlist +++ b/cts/meta/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/dut.c b/cts/meta/dut.c index c321676aec..8880c7ba13 100644 --- a/cts/meta/dut.c +++ b/cts/meta/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/meta/th.c b/cts/meta/th.c index 57b2f492bd..ec7f061793 100644 --- a/cts/meta/th.c +++ b/cts/meta/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/cts.tasklist b/cts/mutex/cts.tasklist index 3387e1de09..ad0c75c601 100644 --- a/cts/mutex/cts.tasklist +++ b/cts/mutex/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/cts.testlist b/cts/mutex/cts.testlist index 5b1cdb1dae..5cea62c079 100644 --- a/cts/mutex/cts.testlist +++ b/cts/mutex/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/mutex/dut.c b/cts/mutex/dut.c index 9cbbd8badb..c48dfcaa64 100644 --- a/cts/mutex/dut.c +++ b/cts/mutex/dut.c @@ -1,7 +1,7 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - * Copyright 2011 Google Inc. + * Copyright 2011 Google LLC * * Tasks for mutexes basic tests. */ @@ -23,7 +23,7 @@ static struct mutex mtx; int mutex_random_task(void *unused) { - char letter = 'A'+(TASK_ID_MTX3A - task_get_current()); + char letter = 'A' + (TASK_ID_MTX3A - task_get_current()); /* wait to be activated */ while (1) { diff --git a/cts/mutex/th.c b/cts/mutex/th.c index 9cbbd8badb..c48dfcaa64 100644 --- a/cts/mutex/th.c +++ b/cts/mutex/th.c @@ -1,7 +1,7 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. - * Copyright 2011 Google Inc. + * Copyright 2011 Google LLC * * Tasks for mutexes basic tests. */ @@ -23,7 +23,7 @@ static struct mutex mtx; int mutex_random_task(void *unused) { - char letter = 'A'+(TASK_ID_MTX3A - task_get_current()); + char letter = 'A' + (TASK_ID_MTX3A - task_get_current()); /* wait to be activated */ while (1) { diff --git a/cts/task/cts.tasklist b/cts/task/cts.tasklist index 6477d74c2c..1adbf211ec 100644 --- a/cts/task/cts.tasklist +++ b/cts/task/cts.tasklist @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/task/cts.testlist b/cts/task/cts.testlist index c4b7bc3231..3ad8e33928 100644 --- a/cts/task/cts.testlist +++ b/cts/task/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/task/dut.c b/cts/task/dut.c index 71fe4050ec..257809b4b8 100644 --- a/cts/task/dut.c +++ b/cts/task/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2013 The Chromium OS Authors. All rights reserved. +/* Copyright 2013 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. * @@ -70,15 +70,15 @@ enum cts_rc test_task_switch(void) } if (wake_count[0] != repeat_count || wake_count[1] != repeat_count) { - CPRINTS("Unexpected counter values: %d %d %d", - wake_count[0], wake_count[1], wake_count[2]); + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); return CTS_RC_FAILURE; } /* TODO: Verify no tasks are ready, no events are pending. */ - if (*task_get_event_bitmap(TASK_ID_A) - || *task_get_event_bitmap(TASK_ID_B) - || *task_get_event_bitmap(TASK_ID_C)) { + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { CPRINTS("Events are pending"); return CTS_RC_FAILURE; } @@ -102,17 +102,17 @@ enum cts_rc test_task_priority(void) return CTS_RC_FAILURE; } - if (wake_count[0] != repeat_count - 1 - || wake_count[1] != repeat_count - 1) { - CPRINTS("Unexpected counter values: %d %d %d", - wake_count[0], wake_count[1], wake_count[2]); + if (wake_count[0] != repeat_count - 1 || + wake_count[1] != repeat_count - 1) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); return CTS_RC_FAILURE; } /* TODO: Verify no tasks are ready, no events are pending. */ - if (*task_get_event_bitmap(TASK_ID_A) - || *task_get_event_bitmap(TASK_ID_B) - || *task_get_event_bitmap(TASK_ID_C)) { + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { CPRINTS("Events are pending"); return CTS_RC_FAILURE; } diff --git a/cts/task/th.c b/cts/task/th.c index 41eab28462..257809b4b8 120000..100644 --- a/cts/task/th.c +++ b/cts/task/th.c @@ -1 +1,144 @@ -dut.c
\ No newline at end of file +/* Copyright 2013 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Tasks for scheduling test. + */ + +#include "common.h" +#include "cts_common.h" +#include "task.h" +#include "timer.h" + +static int repeat_count; +static int wake_count[3]; + +void clean_state(void) +{ + wake_count[0] = wake_count[1] = wake_count[2] = 0; +} + +void task_abc(void *data) +{ + int task_id = task_get_current(); + int id = task_id - TASK_ID_A; + task_id_t next = task_id + 1; + + if (next > TASK_ID_C) + next = TASK_ID_A; + + task_wait_event(-1); + + CPRINTS("%c Starting", 'A' + id); + cflush(); + + while (1) { + wake_count[id]++; + if (id == 2 && wake_count[id] == repeat_count) { + task_set_event(TASK_ID_CTS, TASK_EVENT_WAKE); + task_wait_event(0); + } else { + task_set_event(next, TASK_EVENT_WAKE); + task_wait_event(0); + } + } +} + +void task_tick(void *data) +{ + task_wait_event(-1); + ccprintf("\n[starting Task T]\n"); + + /* Wake up every tick */ + while (1) + /* Wait for timer interrupt message */ + usleep(3000); +} + +enum cts_rc test_task_switch(void) +{ + uint32_t event; + + repeat_count = 3000; + + task_wake(TASK_ID_A); + event = task_wait_event(5 * SECOND); + + if (event != TASK_EVENT_WAKE) { + CPRINTS("Woken up by unexpected event: 0x%08x", event); + return CTS_RC_FAILURE; + } + + if (wake_count[0] != repeat_count || wake_count[1] != repeat_count) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); + return CTS_RC_FAILURE; + } + + /* TODO: Verify no tasks are ready, no events are pending. */ + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { + CPRINTS("Events are pending"); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +enum cts_rc test_task_priority(void) +{ + uint32_t event; + + repeat_count = 2; + + task_wake(TASK_ID_A); + task_wake(TASK_ID_C); + + event = task_wait_event(5 * SECOND); + + if (event != TASK_EVENT_WAKE) { + CPRINTS("Woken up by unexpected event: 0x%08x", event); + return CTS_RC_FAILURE; + } + + if (wake_count[0] != repeat_count - 1 || + wake_count[1] != repeat_count - 1) { + CPRINTS("Unexpected counter values: %d %d %d", wake_count[0], + wake_count[1], wake_count[2]); + return CTS_RC_FAILURE; + } + + /* TODO: Verify no tasks are ready, no events are pending. */ + if (*task_get_event_bitmap(TASK_ID_A) || + *task_get_event_bitmap(TASK_ID_B) || + *task_get_event_bitmap(TASK_ID_C)) { + CPRINTS("Events are pending"); + return CTS_RC_FAILURE; + } + + return CTS_RC_SUCCESS; +} + +static void recurse(int x) +{ + CPRINTS("+%d", x); + msleep(1); + recurse(x + 1); + CPRINTS("-%d", x); +} + +enum cts_rc test_stack_overflow(void) +{ + recurse(0); + return CTS_RC_FAILURE; +} + +#include "cts_testlist.h" + +void cts_task(void) +{ + task_wake(TASK_ID_TICK); + cts_main_loop(tests, "Task"); + task_wait_event(-1); +} diff --git a/cts/timer/cts.testlist b/cts/timer/cts.testlist index 9b5da0d6c9..6567757ced 100644 --- a/cts/timer/cts.testlist +++ b/cts/timer/cts.testlist @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/timer/dut.c b/cts/timer/dut.c index 96d7c5a3cf..9f94b9a398 100644 --- a/cts/timer/dut.c +++ b/cts/timer/dut.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ diff --git a/cts/timer/th.c b/cts/timer/th.c index e82cac71ab..e301ce0e38 100644 --- a/cts/timer/th.c +++ b/cts/timer/th.c @@ -1,4 +1,4 @@ -/* Copyright 2016 The Chromium OS Authors. All rights reserved. +/* Copyright 2016 The ChromiumOS Authors * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ |