aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnric Balletbo i Serra <enric.balletbo@collabora.com>2019-10-23 17:17:39 +0200
committerEnric Balletbo i Serra <enric.balletbo@collabora.com>2019-12-06 00:06:23 +0100
commit22a70bd6a1116a6edccd1a53b24aa5120ecfbce5 (patch)
treed3a2cd356eb272cff9482a816b860e70b00c8149
downloadcros-ec-tests-22a70bd6a1116a6edccd1a53b24aa5120ecfbce5.tar.gz
Add basic tests for CrOS EC
This is a basic script test written in python to test basic functionality on CrOS EC. The purpose is use this script as a base for a more complex tests. Signed-off-by: Enric Balletbo i Serra <enric.balletbo@collabora.com>
-rwxr-xr-xtest-cros-ec.py235
1 files changed, 235 insertions, 0 deletions
diff --git a/test-cros-ec.py b/test-cros-ec.py
new file mode 100755
index 0000000..900bb9c
--- /dev/null
+++ b/test-cros-ec.py
@@ -0,0 +1,235 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+from ctypes import *
+import errno
+import fcntl
+import os
+import sys
+import unittest
+
+EC_CMD_PROTO_VERSION = 0x0000
+EC_CMD_HELLO = 0x0001
+EC_CMD_GET_VERSION = 0x0002
+EC_CMD_GET_FEATURES = 0x000D
+
+EC_HOST_PARAM_SIZE = 0xfc
+
+EC_DEV_IOCXCMD = 0xc014ec00 # _IOWR(EC_DEV_IOC, 0, struct cros_ec_command)
+
+ECFEATURES = -1
+# Supported features
+EC_FEATURE_LIMITED = 0
+EC_FEATURE_FLASH = 1
+EC_FEATURE_PWM_FAN = 2
+EC_FEATURE_PWM_KEYB = 3
+EC_FEATURE_LIGHTBAR = 4
+EC_FEATURE_LED = 5
+EC_FEATURE_MOTION_SENSE = 6
+EC_FEATURE_KEYB = 7
+EC_FEATURE_PSTORE = 8
+EC_FEATURE_PORT80 = 9
+EC_FEATURE_THERMAL = 10
+EC_FEATURE_BKLIGHT_SWITCH = 11
+EC_FEATURE_WIFI_SWITCH = 12
+EC_FEATURE_HOST_EVENTS = 13
+EC_FEATURE_GPIO = 14
+EC_FEATURE_I2C = 15
+EC_FEATURE_CHARGER = 16
+EC_FEATURE_BATTERY = 17
+EC_FEATURE_SMART_BATTERY = 18
+EC_FEATURE_HANG_DETECT = 19
+EC_FEATURE_PMU = 20
+EC_FEATURE_SUB_MCU = 21
+EC_FEATURE_USB_PD = 22
+EC_FEATURE_USB_MUX = 23
+EC_FEATURE_MOTION_SENSE_FIFO = 24
+EC_FEATURE_VSTORE = 25
+EC_FEATURE_USBC_SS_MUX_VIRTUAL = 26
+EC_FEATURE_RTC = 27
+EC_FEATURE_FINGERPRINT = 28
+EC_FEATURE_TOUCHPAD = 29
+EC_FEATURE_RWSIG = 30
+EC_FEATURE_DEVICE_EVENT = 31
+EC_FEATURE_UNIFIED_WAKE_MASKS = 32
+EC_FEATURE_HOST_EVENT64 = 33
+EC_FEATURE_EXEC_IN_RAM = 34
+EC_FEATURE_CEC = 35
+EC_FEATURE_MOTION_SENSE_TIGHT_TIMESTAMPS = 36
+EC_FEATURE_REFINED_TABLET_MODE_HYSTERESIS = 37
+EC_FEATURE_SCP = 39
+EC_FEATURE_ISH = 40
+
+class cros_ec_command(Structure):
+ _fields_ = [
+ ('version', c_uint),
+ ('command', c_uint),
+ ('outsize', c_uint),
+ ('insize', c_uint),
+ ('result', c_uint),
+ ('data', c_ubyte * EC_HOST_PARAM_SIZE)
+ ]
+
+class ec_params_hello(Structure):
+ _fields_ = [
+ ('in_data', c_uint)
+ ]
+
+class ec_response_hello(Structure):
+ _fields_ = [
+ ('out_data', c_uint)
+ ]
+
+class ec_params_get_features(Structure):
+ _fields_ = [
+ ('in_data', c_ulong)
+ ]
+
+class ec_response_get_features(Structure):
+ _fields_ = [
+ ('out_data', c_ulong)
+ ]
+
+def EC_FEATURE_MASK_0(event_code):
+ return (1 << (event_code % 32))
+
+def EC_FEATURE_MASK_1(event_code):
+ return (1 << (event_code - 32))
+
+def is_feature_supported(feature):
+ global ECFEATURES
+
+ if ECFEATURES == -1:
+ fd = open("/dev/cros_ec", 'r')
+
+ param = ec_params_get_features()
+ response = ec_response_get_features()
+
+ cmd = cros_ec_command()
+ cmd.version = 0
+ cmd.command = EC_CMD_GET_FEATURES
+ cmd.insize = sizeof(param)
+ cmd.outsize = sizeof(response)
+
+ memmove(addressof(cmd.data), addressof(param), cmd.outsize)
+ fcntl.ioctl(fd, EC_DEV_IOCXCMD, cmd)
+ memmove(addressof(response), addressof(cmd.data), cmd.outsize)
+
+ fd.close()
+
+ if cmd.result == 0:
+ ECFEATURES = response.out_data
+ else:
+ return False
+
+ return (ECFEATURES & EC_FEATURE_MASK_0(feature)) > 0
+
+###############################################################################
+# TEST RUNNERS
+###############################################################################
+
+class LavaTextTestResult(unittest.TestResult):
+
+ def __init__(self, runner):
+ unittest.TestResult.__init__(self)
+ self.runner = runner
+
+ def addSuccess(self, test):
+ unittest.TestResult.addSuccess(self, test)
+ self.runner.writeUpdate("<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=%s RESULT=pass>\n" % test.id())
+
+ def addError(self, test, err):
+ unittest.TestResult.addError(self, test, err)
+ self.runner.writeUpdate("<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=%s RESULT=unknown>\n" % test.id())
+
+ def addFailure(self, test, err):
+ unittest.TestResult.addFailure(self, test, err)
+ self.runner.writeUpdate("<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=%s RESULT=fail>\n" % test.id())
+
+ def addSkip(self, test, reason):
+ unittest.TestResult.addSkip(self, test, reason)
+ self.runner.writeUpdate("<LAVA_SIGNAL_TESTCASE TEST_CASE_ID=%s RESULT=skip>\n" % test.id())
+
+class LavaTestRunner:
+
+ def __init__(self, stream=sys.stderr, verbosity=0):
+ self.stream = stream
+ self.verbosity = verbosity
+
+ def writeUpdate(self, message):
+ self.stream.write(message)
+
+ def run(self, test):
+ result = LavaTextTestResult(self)
+ test(result)
+ result.testsRun
+ return result
+
+###############################################################################
+# TEST SUITES
+###############################################################################
+
+class TestCrosEC(unittest.TestCase):
+
+ def test_cros_ec_chardev(self):
+ self.assertEqual(os.path.exists("/dev/cros_ec"), 1)
+
+ # Hello. This is a simple command to test the EC is responsive to commands
+ def test_cros_ec_hello(self):
+ fd = open("/dev/cros_ec", 'r')
+ param = ec_params_hello()
+ param.in_data = 0xa0b0c0d0 # magic number that the EC expects on HELLO
+
+ response = ec_response_hello()
+
+ cmd = cros_ec_command()
+ cmd.version = 0
+ cmd.command = EC_CMD_HELLO
+ cmd.insize = sizeof(param)
+ cmd.outsize = sizeof(response)
+
+ memmove(addressof(cmd.data), addressof(param), cmd.outsize)
+ fcntl.ioctl(fd, EC_DEV_IOCXCMD, cmd)
+ memmove(addressof(response), addressof(cmd.data), cmd.insize)
+
+ fd.close()
+
+ self.assertEqual(cmd.result, 0)
+ # magic number that the EC answers on HELLO
+ self.assertEqual(response.out_data, 0xa1b2c3d4)
+
+ # EC_FEATURE_BATTERY: Battery cutoff at-shutdown
+ def test_cros_ec_battery_cutoff_at_shutdown(self):
+ self.skipTest("demonstrating skipping")
+ fd = open("/sys/class/chromeos/cros_ec/" + "battery_cutoff", 'w')
+ fd.write("at-shutdown")
+ fd.close()
+
+ fd = open("/sys/class/chromeos/cros_ec/" + "battery_cutoff", 'w')
+ fd.write("at-shutdown\n")
+ fd.close()
+
+ with self.assertRaises(IOError) as cm:
+ fd = open("/sys/class/chromeos/cros_ec/" + "battery_cutoff", 'w')
+ fd.write("at-shutdown-")
+ fd.close()
+ self.assertEqual(cm.exception.error_code, 22)
+
+ with self.assertRaises(IOError) as cm:
+ fd = open("/sys/class/chromeos/cros_ec/" + "battery_cutoff", 'w')
+ fd.write("at-shutdow-")
+ fd.close()
+ self.assertEqual(cm.exception.error_code, 22)
+
+ with self.assertRaises(IOError) as cm:
+ fd = open("/sys/class/chromeos/cros_ec/" + "battery_cutoff", 'w')
+ fd.write("at-shutdow")
+ fd.close()
+ self.assertEqual(cm.exception.error_code, 22)
+
+if __name__ == '__main__':
+ unittest.main(testRunner=LavaTestRunner(),
+ # these make sure that some options that are not applicable
+ # remain hidden from the help menu.
+ failfast=False, buffer=False, catchbreak=False)
+