summaryrefslogtreecommitdiff
path: root/cts
diff options
context:
space:
mode:
Diffstat (limited to 'cts')
-rw-r--r--cts/common/board.py86
-rw-r--r--cts/common/cts.rc18
-rw-r--r--cts/common/cts_testlist.h11
-rwxr-xr-xcts/cts.py254
-rw-r--r--cts/gpio/cts.testlist17
-rw-r--r--cts/gpio/dut.c3
-rw-r--r--cts/gpio/th.c3
-rw-r--r--cts/i2c/cts.testlist12
-rw-r--r--cts/interrupt/cts.testlist12
-rw-r--r--cts/interrupt/dut.c3
-rw-r--r--cts/interrupt/th.c3
-rw-r--r--cts/meta/cts.testlist28
-rw-r--r--cts/meta/dut.c17
-rw-r--r--cts/meta/th.c16
-rw-r--r--cts/task/cts.testlist9
-rw-r--r--cts/task/dut.c12
-rw-r--r--cts/timer/cts.testlist2
-rw-r--r--cts/timer/dut.c3
-rw-r--r--cts/timer/th.c3
19 files changed, 313 insertions, 199 deletions
diff --git a/cts/common/board.py b/cts/common/board.py
index d478b1fca8..d3db78b792 100644
--- a/cts/common/board.py
+++ b/cts/common/board.py
@@ -2,13 +2,13 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-from abc import ABCMeta, abstractmethod
+from abc import ABCMeta
+from abc import abstractmethod
import fcntl
import os
import select
import shutil
import subprocess as sp
-import time
OCD_SCRIPT_DIR = '/usr/local/share/openocd/scripts'
@@ -26,7 +26,7 @@ REBOOT_MARKER = 'UART initialized after reboot'
class Board(object):
- """Class representing a single board connected to a host machine
+ """Class representing a single board connected to a host machine.
Attributes:
board: String containing actual type of board, i.e. nucleo-f072rb
@@ -40,19 +40,23 @@ class Board(object):
"""
__metaclass__ = ABCMeta # This is an Abstract Base Class (ABC)
+
def __init__(self, board, module, hla_serial=None):
- """Initializes a board object with given attributes
+ """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 not board in OPENOCD_CONFIGS:
+ if board not in OPENOCD_CONFIGS:
msg = 'OpenOcd configuration not found for ' + board
raise RuntimeError(msg)
- if not board in FLASH_OFFSETS:
+ if board not in FLASH_OFFSETS:
msg = 'Flash offset not found for ' + board
raise RuntimeError(msg)
self.board = board
@@ -64,14 +68,14 @@ class Board(object):
self.tty = None
def reset_log_dir(self):
- """Reset log directory"""
+ """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
+ """Gets serial numbers of all st-link v2.1 board attached to host.
Returns:
List of serials
@@ -81,7 +85,7 @@ class Board(object):
st_link_info = usb_process.communicate()[0]
st_serials = []
for line in st_link_info.split('\n'):
- if not 'iSerial' in line:
+ if 'iSerial' not in line:
continue
words = line.split()
if len(words) <= 2:
@@ -91,14 +95,17 @@ class Board(object):
@abstractmethod
def get_serial(self):
- """Subclass should implement this"""
+ """Subclass should implement this."""
pass
def send_open_ocd_commands(self, commands):
- """Send a command to the board via openocd
+ """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 = ['openocd', '-s', OCD_SCRIPT_DIR,
'-f', self.openocd_config, '-c', 'hla_serial ' + self.hla_serial]
@@ -120,11 +127,14 @@ class Board(object):
with open(self.openocd_log) as log:
print log.read()
- def build(self, module, ec_dir):
- """Builds test suite module for board
+ 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,
@@ -146,7 +156,7 @@ class Board(object):
print log.read()
def flash(self, image_path):
- """Flashes board with most recent build ec.bin"""
+ """Flashes board with most recent build ec.bin."""
cmd = ['reset_config connect_assert_srst',
'init',
'reset init',
@@ -163,11 +173,12 @@ class Board(object):
return s
def reset(self):
- """Reset then halt board """
+ """Reset then halt board."""
return self.send_open_ocd_commands(['init', 'reset halt'])
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
"""
@@ -185,12 +196,12 @@ class Board(object):
self.tty = tty
def read_tty(self, max_boot_count=1):
- """Read info from a serial port described by a file descriptor
+ """Read info from a serial port described by a file descriptor.
Args:
max_boot_count: Stop reading if boot count exceeds this number
- Return:
+ Returns:
result: characters read from tty
boot: boot counts
"""
@@ -219,19 +230,15 @@ class Board(object):
return result, boot
def identify_tty_port(self):
- """Saves this board's serial port"""
+ """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'])
+ 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):]:
@@ -241,7 +248,7 @@ class Board(object):
raise RuntimeError('The device dev path could not be found')
def open_tty(self):
- """Read available bytes from device dev path"""
+ """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)
@@ -249,18 +256,19 @@ class Board(object):
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
+ """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)
@@ -271,9 +279,9 @@ class TestHarness(Board):
self.reset_log_dir()
def get_serial(self):
- """Loads serial number from saved location"""
+ """Loads serial number from saved location."""
if self.hla_serial:
- return # serial was already loaded
+ return # serial was already loaded
try:
with open(self.serial_path, mode='r') as ser_f:
self.hla_serial = ser_f.read()
@@ -284,7 +292,7 @@ class TestHarness(Board):
raise RuntimeError(msg)
def save_serial(self):
- """Saves the TH serial number to a file"""
+ """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.'
@@ -296,9 +304,9 @@ class TestHarness(Board):
raise RuntimeError(msg)
serial = serials[0]
- dir = os.path.dirname(self.serial_path)
- if not os.path.exists(dir):
- os.makedirs(dir)
+ 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 ser_f:
ser_f.write(serial)
self.hla_serial = serial
@@ -308,20 +316,21 @@ class TestHarness(Board):
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 Device Under Test object with given attributes
+ """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
- hla_serial: Serial number if board uses an HLA adaptor
+ 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
@@ -335,8 +344,11 @@ class DeviceUnderTest(Board):
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 != None:
+ if self.hla_serial is not None:
# serial was already set ('' is a valid serial)
return
diff --git a/cts/common/cts.rc b/cts/common/cts.rc
index 8d66a8af4e..264b982655 100644
--- a/cts/common/cts.rc
+++ b/cts/common/cts.rc
@@ -14,11 +14,21 @@
* where <NAME> will be printed on the result screen.
*/
-/* Host only codes. Should not be needed by th.c or dut.c. */
-CTS_RC_DUPLICATE_RUN = -2,
-CTS_RC_NO_RESULT = -1,
+/*
+ * Host only return codes. Should not be needed by th.c or dut.c.
+ */
+/* Test didn't run */
+CTS_RC_DID_NOT_START = -1,
+/* Test didn't end */
+CTS_RC_DID_NOT_END = -2,
+/* Results were reported twice or more */
+CTS_RC_DUPLICATE_RUN = -3,
+/* Error in parsing return code. Probably it was null or not an integer. */
+CTS_RC_INVALID_RC = -4,
-/* Regular codes */
+/*
+ * Regular return codes. Used by DUT and TH.
+ */
CTS_RC_SUCCESS = 0,
CTS_RC_FAILURE,
CTS_RC_BAD_SYNC,
diff --git a/cts/common/cts_testlist.h b/cts/common/cts_testlist.h
index a9a53c56f6..9e18c7f8eb 100644
--- a/cts/common/cts_testlist.h
+++ b/cts/common/cts_testlist.h
@@ -3,18 +3,25 @@
* found in the LICENSE file.
*/
+/*
+ * CTS_TEST macro is used by dut.c, th.c, and cts.py. Currently, the 2nd
+ * and 3rd arguments are only used by cts.py. They specify the expected
+ * strings output by TH and DUT, respectively.
+ */
+
struct cts_test {
enum cts_rc (*run)(void);
char *name;
};
-#define CTS_TEST(test) {test, STRINGIFY(test)},
+#define CTS_TEST(test, th_rc, th_string, dut_rc, dut_string) \
+ {test, STRINGIFY(test)},
struct cts_test tests[] = {
#include "cts.testlist"
};
#undef CTS_TEST
-#define CTS_TEST(test) CTS_TEST_ID_##test,
+#define CTS_TEST(test, th_rc, th_string, dut_rc, dut_string) CTS_TEST_ID_##test,
enum {
#include "cts.testlist"
CTS_TEST_ID_COUNT,
diff --git a/cts/cts.py b/cts/cts.py
index b046bc4ca5..ed0889698d 100755
--- a/cts/cts.py
+++ b/cts/cts.py
@@ -1,4 +1,5 @@
-#!/usr/bin/python2
+#!/usr/bin/python
+#
# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
@@ -17,32 +18,33 @@
import argparse
-from collections import defaultdict
-import common.board as board
import os
import shutil
import time
+import common.board as board
-# Host only return codes. Make sure they match values in cts.rc
-CTS_RC_DUPLICATE_RUN = -2 # The test was run multiple times.
-CTS_RC_NO_RESULT = -1 # The test did not run.
-
+CTS_RC_PREFIX = 'CTS_RC_'
DEFAULT_TH = 'stm32l476g-eval'
DEFAULT_DUT = 'nucleo-f072rb'
MAX_SUITE_TIME_SEC = 5
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
+
class Cts(object):
- """Class that represents a CTS testing setup and provides
- interface to boards (building, flashing, etc.)
+ """Class that represents a eCTS run.
Attributes:
- dut: DeviceUnderTest object representing dut
- th: TestHarness object representing th
+ dut: DeviceUnderTest object representing DUT
+ th: TestHarness object representing a test harness
module: Name of module to build/run tests for
- test_names: List of strings of test names contained in given module
+ 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
"""
@@ -68,22 +70,21 @@ class Cts(object):
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')
- self.test_names = Cts.get_macro_args(testlist_path, 'CTS_TEST')
-
return_codes_path = os.path.join(cts_dir, 'common', 'cts.rc')
- self.get_return_codes(return_codes_path, '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"""
+ """Build images for DUT and TH."""
print 'Building DUT image...'
- if not self.dut.build(self.module, self.ec_dir):
+ 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.module, self.ec_dir):
+ 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 boards with their most recently build ec.bin"""
+ """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()
@@ -96,102 +97,207 @@ class Cts(object):
raise RuntimeError('Flashing DUT failed')
def setup(self):
- """Setup boards"""
+ """Setup boards."""
self.th.save_serial()
def identify_boards(self):
- """Updates serials of both th and dut, in that order (order matters)"""
+ """Updates serials of TH and DUT in that order (order matters)."""
self.th.get_serial()
self.dut.get_serial()
- @staticmethod
- def get_macro_args(filepath, macro):
- """Get list of args of a certain macro in a file when macro is used
- by itself on a line
+ 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,
"""
- args = []
+ tests = []
with open(filepath, 'r') as f:
- for l in f.readlines():
+ 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):]
- args.append(l.strip('()').replace(',', ''))
- return args
-
- def get_return_codes(self, file, prefix):
- """Extract return code names from the definition file (cts.rc)"""
+ 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(file, 'r') as f:
- for line in f.readlines():
+ with open(filepath, 'r') as f:
+ for line in f:
line = line.strip()
- if not line.startswith(prefix):
+ if not line.startswith(CTS_RC_PREFIX):
continue
- line = line[len(prefix):]
line = line.split(',')[0]
if '=' in line:
tokens = line.split('=')
line = tokens[0].strip()
val = int(tokens[1].strip())
- self.return_codes[val] = line
+ self.return_codes[line] = val
val += 1
def parse_output(self, output):
- results = defaultdict(lambda: CTS_RC_NO_RESULT)
+ """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:
- continue
- test_name = tokens[0].strip()
- if test_name not in self.test_names:
- continue
- try:
- return_code = int(tokens[1])
- except ValueError: # Second token is not an int
- continue
- if test_name in results:
- results[test_name] = CTS_RC_DUPLICATE_RUN
- else:
- results[test_name] = return_code
+ 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):
- return self.return_codes.get(code, '%d' % code)
+ def get_return_code_name(self, code, strip_prefix=False):
+ name = ''
+ for k, v in self.return_codes.iteritems():
+ 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
+ """Parse outputs to derive test results.
- Args;
+ 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
"""
- dut_results = self.parse_output(dut_output)
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
- len_test_name = max(len(s) for s in self.test_names)
- len_code_name = max(len(s) for s in self.return_codes.values())
+ 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) + '}\n'
+ 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) + '}\n'
-
- self.formatted_results = head.format('test name', 'TH', 'DUT')
- for test_name in self.test_names:
- th_cn = self.get_return_code_name(th_results[test_name])
- dut_cn = self.get_return_code_name(dut_results[test_name])
- self.formatted_results += fmt.format(test_name, th_cn, dut_cn)
+ 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_RETURN_CODE', 'DUT_RETURN_CODE',
+ ' 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,
+ th_results[i]['string'], dut_results[i]['string'],
+ '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"""
+ """Resets boards, records test results in results dir."""
print 'Reading serials...'
self.identify_boards()
print 'Opening DUT tty...'
@@ -228,9 +334,9 @@ class Cts(object):
time.sleep(MAX_SUITE_TIME_SEC)
print 'Reading DUT tty...'
- dut_output, dut_boot = self.dut.read_tty()
+ dut_output, _ = self.dut.read_tty()
print 'Reading TH tty...'
- th_output, th_boot = self.th.read_tty()
+ th_output, _ = self.th.read_tty()
print 'Halting TH...'
if not self.th.send_open_ocd_commands(['init', 'reset halt']):
@@ -245,7 +351,10 @@ class Cts(object):
'again.')
print 'Pursing results...'
- self.evaluate_run(dut_output, th_output)
+ 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')
@@ -262,11 +371,10 @@ class Cts(object):
print self.formatted_results
- # TODO: Should set exit code for the shell
+ # TODO(chromium:735652): Should set exit code for the shell
def main():
- """Main entry point for CTS script from command line"""
ec_dir = os.path.realpath(os.path.join(
os.path.dirname(os.path.abspath(__file__)), '..'))
os.chdir(ec_dir)
@@ -321,5 +429,5 @@ def main():
cts.flash_boards()
cts.run()
-if __name__ == "__main__":
+if __name__ == '__main__':
main()
diff --git a/cts/gpio/cts.testlist b/cts/gpio/cts.testlist
index e59be1c7ce..be303067a3 100644
--- a/cts/gpio/cts.testlist
+++ b/cts/gpio/cts.testlist
@@ -6,15 +6,20 @@
/* Currently tests will execute in the order they are listed here */
/* Test whether sync completes successfully */
-CTS_TEST(sync_test)
+CTS_TEST(sync_test,,,,)
+
/* Check if the dut can set a line low */
-CTS_TEST(set_low_test)
+CTS_TEST(set_low_test,,,,)
+
/* Check if the dut can set a line high */
-CTS_TEST(set_high_test)
+CTS_TEST(set_high_test,,,,)
+
/* Check if the dut can read a line that is low */
-CTS_TEST(read_high_test)
+CTS_TEST(read_high_test,,,,)
+
/* Check if the dut can read a line that is high */
-CTS_TEST(read_low_test)
+CTS_TEST(read_low_test,,,,)
+
/* Check if the dut reads its true pin level (success)
or its register level when configured as a low open drain output pin */
-CTS_TEST(od_read_high_test)
+CTS_TEST(od_read_high_test,,,,)
diff --git a/cts/gpio/dut.c b/cts/gpio/dut.c
index 22694b8c4f..c5b6bf813f 100644
--- a/cts/gpio/dut.c
+++ b/cts/gpio/dut.c
@@ -81,8 +81,9 @@ void cts_task(void)
uart_flush_output();
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
result = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, result);
+ CPRINTF("\n%s end %d\n", tests[i].name, result);
uart_flush_output();
}
diff --git a/cts/gpio/th.c b/cts/gpio/th.c
index 7350ff0e55..d18c1c367a 100644
--- a/cts/gpio/th.c
+++ b/cts/gpio/th.c
@@ -75,8 +75,9 @@ void cts_task(void)
uart_flush_output();
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
result = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, result);
+ CPRINTF("\n%s end %d\n", tests[i].name, result);
uart_flush_output();
}
diff --git a/cts/i2c/cts.testlist b/cts/i2c/cts.testlist
index 79732dc65b..809daaa322 100644
--- a/cts/i2c/cts.testlist
+++ b/cts/i2c/cts.testlist
@@ -6,9 +6,9 @@
/* Currently tests will execute in the order they are listed here */
/* Test whether sync completes successfully */
-CTS_TEST(write8_test)
-CTS_TEST(write16_test)
-CTS_TEST(write32_test)
-CTS_TEST(read8_test)
-CTS_TEST(read16_test)
-CTS_TEST(read32_test) \ No newline at end of file
+CTS_TEST(write8_test,,,,)
+CTS_TEST(write16_test,,,,)
+CTS_TEST(write32_test,,,,)
+CTS_TEST(read8_test,,,,)
+CTS_TEST(read16_test,,,,)
+CTS_TEST(read32_test,,,,) \ No newline at end of file
diff --git a/cts/interrupt/cts.testlist b/cts/interrupt/cts.testlist
index 6e0265ed60..0fdaf6fca2 100644
--- a/cts/interrupt/cts.testlist
+++ b/cts/interrupt/cts.testlist
@@ -4,14 +4,14 @@
*/
/* Test interrupt_enable/disable */
-CTS_TEST(test_interrupt_enable)
-CTS_TEST(test_interrupt_disable)
+CTS_TEST(test_interrupt_enable,,,,)
+CTS_TEST(test_interrupt_disable,,,,)
/* Test task_wait_for_event */
-CTS_TEST(test_task_wait_event)
+CTS_TEST(test_task_wait_event,,,,)
/* Test task_disable_irq */
-CTS_TEST(test_task_disable_irq)
+CTS_TEST(test_task_disable_irq,,,,)
/* Test nested interrupt. Lower priority IRQ is fired, followed by
* higher priority IRQ. Handler executions should be nested.
@@ -23,7 +23,7 @@ CTS_TEST(test_task_disable_irq)
* task_cts ----* *----
* A B C D
*/
-CTS_TEST(test_nested_interrupt_low_high)
+CTS_TEST(test_nested_interrupt_low_high,,,,)
/* Test nested interrupt. Higher priority IRQ is fired, followed by
* lower priority IRQ. Handlers should be executed sequentially.
@@ -35,7 +35,7 @@ CTS_TEST(test_nested_interrupt_low_high)
* task_cts ----* *----
* B C A D
*/
-CTS_TEST(test_nested_interrupt_high_low)
+CTS_TEST(test_nested_interrupt_high_low,,,,)
/*
* Other ideas
diff --git a/cts/interrupt/dut.c b/cts/interrupt/dut.c
index a04d5659d5..35b47001ca 100644
--- a/cts/interrupt/dut.c
+++ b/cts/interrupt/dut.c
@@ -185,9 +185,10 @@ void cts_task(void)
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
clear_state();
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
rc = tests[i].run();
interrupt_enable();
- CPRINTF("\n%s %d\n", tests[i].name, rc);
+ CPRINTF("\n%s end %d\n", tests[i].name, rc);
cflush();
}
diff --git a/cts/interrupt/th.c b/cts/interrupt/th.c
index 0949faa8b2..b409fbd8ef 100644
--- a/cts/interrupt/th.c
+++ b/cts/interrupt/th.c
@@ -74,8 +74,9 @@ void cts_task(void)
gpio_set_level(GPIO_OUTPUT_TEST, 1);
gpio_set_level(GPIO_CTS_IRQ2, 1);
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
rc = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, rc);
+ CPRINTF("\n%s end %d\n", tests[i].name, rc);
cflush();
}
diff --git a/cts/meta/cts.testlist b/cts/meta/cts.testlist
index 778b0f62cc..d453d33e51 100644
--- a/cts/meta/cts.testlist
+++ b/cts/meta/cts.testlist
@@ -12,53 +12,41 @@
* 3
* 4
*/
-CTS_TEST(debug_test)
+CTS_TEST(debug_test,,,,)
/* Test should succeed if both report success
* (expected result: success)
*/
-CTS_TEST(success_test)
+CTS_TEST(success_test,,,,)
/* Test should fail if one reports success and
* (one reports failure (expected result: failure)
*/
-CTS_TEST(fail_dut_test)
+CTS_TEST(fail_dut_test,,, CTS_RC_FAILURE,)
/* Test should fail if one reports success and
* (one reports failure (expected result: failure)
*/
-CTS_TEST(fail_th_test)
+CTS_TEST(fail_th_test, CTS_RC_FAILURE,,,)
/* Test should fail when both boards report failure
* (expected result: failure)
*/
-CTS_TEST(fail_both_test)
+CTS_TEST(fail_both_test, CTS_RC_FAILURE,, CTS_RC_FAILURE,)
/* Test should fail with bad sync if one reports bad
* sync and the other reports success (expected result:
* bad_sync)
*/
-CTS_TEST(bad_sync_and_success_test)
+CTS_TEST(bad_sync_and_success_test, CTS_RC_BAD_SYNC,,,)
/* Test should fail with bad sync if both boards report
* bad sync (expected result: bad_sync)
*/
-CTS_TEST(bad_sync_both_test)
-
-/* Test should report conflict if one reports bad sync
- * and the other reports failure
- * (expected result: conflict)
- */
-CTS_TEST(bad_sync_failure_test)
+CTS_TEST(bad_sync_both_test, CTS_RC_BAD_SYNC,, CTS_RC_BAD_SYNC,)
/* Test should be listed as corrupted if one test hangs,
* regardless of what the other test outputs
* (expected result: corrupted)
*/
-CTS_TEST(hang_test)
-
-/* Test should be corrupted if it follows a corrupted
- * test, regardless of what the actual result was
- * reported as
- */
-CTS_TEST(post_corruption_success) \ No newline at end of file
+CTS_TEST(hang_test, CTS_RC_SUCCESS,, CTS_RC_DID_NOT_END,)
diff --git a/cts/meta/dut.c b/cts/meta/dut.c
index ad772bc10b..b80628449b 100644
--- a/cts/meta/dut.c
+++ b/cts/meta/dut.c
@@ -37,7 +37,7 @@ enum cts_rc fail_both_test(void)
enum cts_rc bad_sync_and_success_test(void)
{
- return CTS_RC_BAD_SYNC;
+ return CTS_RC_SUCCESS;
}
enum cts_rc bad_sync_both_test(void)
@@ -45,11 +45,6 @@ enum cts_rc bad_sync_both_test(void)
return CTS_RC_BAD_SYNC;
}
-enum cts_rc bad_sync_failure_test(void)
-{
- return CTS_RC_BAD_SYNC;
-}
-
enum cts_rc hang_test(void)
{
while (1) {
@@ -60,11 +55,6 @@ enum cts_rc hang_test(void)
return CTS_RC_SUCCESS;
}
-enum cts_rc post_corruption_success(void)
-{
- return CTS_RC_SUCCESS;
-}
-
#include "cts_testlist.h"
void cts_task(void)
@@ -75,12 +65,13 @@ void cts_task(void)
cflush();
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
result = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, result);
+ CPRINTF("\n%s end %d\n", tests[i].name, result);
cflush();
}
- CPRINTS("GPIO test suite finished");
+ CPRINTS("Meta test finished");
cflush();
while (1) {
watchdog_reload();
diff --git a/cts/meta/th.c b/cts/meta/th.c
index bdab9ce6f1..c1331ff2a7 100644
--- a/cts/meta/th.c
+++ b/cts/meta/th.c
@@ -55,23 +55,12 @@ enum cts_rc bad_sync_both_test(void)
return CTS_RC_BAD_SYNC;
}
-enum cts_rc bad_sync_failure_test(void)
-{
- CTS_DEBUG_PRINTF("Expect: Conflict");
- return CTS_RC_FAILURE;
-}
-
enum cts_rc hang_test(void)
{
CTS_DEBUG_PRINTF("This and next, expect: Corrupted");
return CTS_RC_SUCCESS;
}
-enum cts_rc post_corruption_success(void)
-{
- return CTS_RC_SUCCESS;
-}
-
#include "cts_testlist.h"
void cts_task(void)
@@ -82,12 +71,13 @@ void cts_task(void)
cflush();
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
result = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, result);
+ CPRINTF("\n%s end %d\n", tests[i].name, result);
cflush();
}
- CPRINTS("GPIO test suite finished");
+ CPRINTS("Meta test finished");
cflush();
while (1) {
watchdog_reload();
diff --git a/cts/task/cts.testlist b/cts/task/cts.testlist
index 25dbcc313a..c4b7bc3231 100644
--- a/cts/task/cts.testlist
+++ b/cts/task/cts.testlist
@@ -9,18 +9,19 @@
* repeated TEST_COUNT times. It's expected all tasks to run exactly
* TEST_COUNT times. Tick task runs to inject some irregularity.
*/
-CTS_TEST(test_task_switch)
+CTS_TEST(test_task_switch,,,,)
/*
* Test task priority. CTS task wakes up A and C then goes to sleep. Since C
* has a higher priority, C should run first. This should result in C running
* one more time than A (or B).
*/
-CTS_TEST(test_task_priority)
+CTS_TEST(test_task_priority,,,,)
/*
* Test stack overflow. CTS task overflows the stack and it should be detected
* when task switch happens. Reboot is expected.
- * TODO: Verify stack overflow detection and reboot.
*/
-CTS_TEST(test_stack_overflow) \ No newline at end of file
+CTS_TEST(test_stack_overflow,\
+ CTS_RC_DID_NOT_END, "Stack overflow in CTS task!",\
+ CTS_RC_DID_NOT_END, "Stack overflow in CTS task!")
diff --git a/cts/task/dut.c b/cts/task/dut.c
index e34dd0babb..4cc6e3e4a4 100644
--- a/cts/task/dut.c
+++ b/cts/task/dut.c
@@ -125,19 +125,14 @@ static void recurse(int x)
CPRINTS("-%d", x);
}
-enum cts_rc test_stack_overflow(void);
-
-#include "cts_testlist.h"
-
enum cts_rc test_stack_overflow(void)
{
- /* recurse() is expected to overflow the stack, which leads to reboot.
- * So, we print output proactively. */
- CPRINTF("\n%s %d\n", tests[CTS_TEST_ID_COUNT - 1].name, CTS_RC_SUCCESS);
recurse(0);
return CTS_RC_FAILURE;
}
+#include "cts_testlist.h"
+
void cts_task(void)
{
enum cts_rc rc;
@@ -147,8 +142,9 @@ void cts_task(void)
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
clear_state();
+ CPRINTF("\n%s start\n", tests[i].name);
rc = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, rc);
+ CPRINTF("\n%s end %d\n", tests[i].name, rc);
cflush();
}
diff --git a/cts/timer/cts.testlist b/cts/timer/cts.testlist
index d4cb3c30b3..9b5da0d6c9 100644
--- a/cts/timer/cts.testlist
+++ b/cts/timer/cts.testlist
@@ -16,4 +16,4 @@
* - GPIO_OUTPUT connection for sending notification from DUT
* - Calibrated TH timer
*/
-CTS_TEST(timer_calibration_test)
+CTS_TEST(timer_calibration_test,,,,)
diff --git a/cts/timer/dut.c b/cts/timer/dut.c
index 29003f36af..4089964791 100644
--- a/cts/timer/dut.c
+++ b/cts/timer/dut.c
@@ -29,8 +29,9 @@ void cts_task(void)
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
rc = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, rc);
+ CPRINTF("\n%s end %d\n", tests[i].name, rc);
cflush();
}
diff --git a/cts/timer/th.c b/cts/timer/th.c
index a6e9d575b1..4c9912fdda 100644
--- a/cts/timer/th.c
+++ b/cts/timer/th.c
@@ -62,8 +62,9 @@ void cts_task(void)
for (i = 0; i < CTS_TEST_ID_COUNT; i++) {
sync();
+ CPRINTF("\n%s start\n", tests[i].name);
rc = tests[i].run();
- CPRINTF("\n%s %d\n", tests[i].name, rc);
+ CPRINTF("\n%s end %d\n", tests[i].name, rc);
cflush();
}