autotest: servo: Produce more meaningful exception messages from servod.
The underlying exception in servod is masked currently by the
xmlrpclib.Fault exception. This CL changes that relatively
meaningless message like:
<Fault 1: "<type 'exceptions.AttributeError'>:'tca6416' object has no
attribute 'hw_driver'">
To something more meaningful like:
FAIL: Setting 'lid_open' to 'no' :: No control named lid_open
BUG=chrome-os-partner:10908
TEST=./run_remote_tests.sh --remote=<host> --servo platform_CloseOpenLid --board=<board>
Tested by modifying servod's xml files to remove lid_open control to
see failure.
Change-Id: I594dc13f8fff4c43e35f0e020da9473c11c7453c
Reviewed-on: https://gerrit.chromium.org/gerrit/27243
Tested-by: Todd Broch <tbroch@chromium.org>
Reviewed-by: Vic Yang <victoryang@chromium.org>
Commit-Ready: Todd Broch <tbroch@chromium.org>
diff --git a/server/cros/servo.py b/server/cros/servo.py
index 2a852ec..5969321 100644
--- a/server/cros/servo.py
+++ b/server/cros/servo.py
@@ -5,7 +5,7 @@
# Expects to be run in an environment with sudo and no interactive password
# prompt, such as within the Chromium OS development chroot.
-import logging, os, select, subprocess, sys, time, xmlrpclib
+import logging, os, re, select, subprocess, sys, time, xmlrpclib
from autotest_lib.client.bin import utils as client_utils
from autotest_lib.client.common_lib import error
from autotest_lib.server import utils
@@ -304,10 +304,36 @@
self.set('warm_reset', 'off')
+ def _get_xmlrpclib_exception(self, xmlexc):
+ """Get meaningful exception string from xmlrpc.
+
+ Args:
+ xmlexc: xmlrpclib.Fault object
+
+ xmlrpclib.Fault.faultString has the following format:
+
+ <type 'exception type'>:'actual error message'
+
+ Parse and return the real exception from the servod side instead of the
+ less meaningful one like,
+ <Fault 1: "<type 'exceptions.AttributeError'>:'tca6416' object has no
+ attribute 'hw_driver'">
+
+ Returns:
+ string of underlying exception raised in servod.
+ """
+ return re.sub('^.*>:', '', xmlexc.faultString)
+
+
def get(self, gpio_name):
"""Get the value of a gpio from Servod."""
assert gpio_name
- return self._server.get(gpio_name)
+ try:
+ return self._server.get(gpio_name)
+ except xmlrpclib.Fault as e:
+ err_msg = "Getting '%s' :: %s" % \
+ (gpio_name, self._get_xmlrpclib_exception(e))
+ raise error.TestFail(err_msg)
def set(self, gpio_name, gpio_value):
@@ -328,7 +354,12 @@
"""Set the value of a gpio using Servod."""
assert gpio_name and gpio_value
logging.info('Setting %s to %s', gpio_name, gpio_value)
- self._server.set(gpio_name, gpio_value)
+ try:
+ self._server.set(gpio_name, gpio_value)
+ except xmlrpclib.Fault as e:
+ err_msg = "Setting '%s' to '%s' :: %s" % \
+ (gpio_name, gpio_value, self._get_xmlrpclib_exception(e))
+ raise error.TestFail(err_msg)
# TODO(waihong) It may fail if multiple servo's are connected to the same