dbus_send: Fixed a bug with _build_arg_string()
The function would incorrectly error when a numeric dbus.* type object
was passed in (e.g. dbus.Int16) due to a 'continue' statement within a
nested loop. This was bypassed by refactoring the loop body.
BUG=chromium:726432
TEST=dbus_send_unittest.py
Change-Id: Ic8028746fe2e4cc5ae459c91bea28208d675bacf
Reviewed-on: https://chromium-review.googlesource.com/514409
Commit-Ready: Alexander Curtiss <curtissa@google.com>
Tested-by: Kirtika Ruchandani <kirtika@chromium.org>
Tested-by: Alexander Curtiss <curtissa@google.com>
Reviewed-by: Eric Caruso <ejcaruso@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/client/common_lib/cros/dbus_send.py b/client/common_lib/cros/dbus_send.py
index 1b9c924..36d7e09 100644
--- a/client/common_lib/cros/dbus_send.py
+++ b/client/common_lib/cros/dbus_send.py
@@ -116,9 +116,9 @@
# For backward compatibility, match old dbus-send output too.
# TODO: drop this when dbus is upgraded to 1.10.12+.
if match is None:
- match = re.match(r'method return sender=(%s) -> dest=(%s) '
- r'reply_serial=\d+' %
- (dbus_address_pattern, dbus_address_pattern), header)
+ match = re.match(r'method return sender=(%s) -> dest=(%s) '
+ r'reply_serial=\d+' %
+ (dbus_address_pattern, dbus_address_pattern), header)
if match is None:
raise error.TestError('Could not parse dbus-send header: %s' % header)
@@ -132,14 +132,13 @@
return DBusSendResult(sender=sender, responder=responder, response=ret_val)
-def _build_arg_string(raw_args):
- """Construct a string of arguments to a DBus method as dbus-send expects.
+def _dbus2string(raw_arg):
+ """Turn a dbus.* type object into a string that dbus-send expects.
- @param raw_args list of dbus.* type objects to seriallize.
+ @param raw_dbus dbus.* type object to stringify.
@return string suitable for dbus-send.
"""
- dbus.Boolean
int_map = {
dbus.Int16: 'int16:',
dbus.Int32: 'int32:',
@@ -150,25 +149,31 @@
dbus.Double: 'double:',
dbus.Byte: 'byte:',
}
- arg_list = []
- for arg in raw_args:
- if isinstance(arg, dbus.String):
- arg_list.append(pipes.quote('string:%s' %
- arg.replace('"', r'\"')))
- continue
- if isinstance(arg, dbus.Boolean):
- if arg:
- arg_list.append('boolean:true')
- else:
- arg_list.append('boolean:false')
- continue
- for prim_type, prefix in int_map.iteritems():
- if isinstance(arg, prim_type):
- arg_list.append(prefix + str(arg))
- continue
- raise error.TestError('No support for serializing %r' % arg)
- return ' '.join(arg_list)
+ if isinstance(raw_arg, dbus.String):
+ return pipes.quote('string:%s' % raw_arg.replace('"', r'\"'))
+
+ if isinstance(raw_arg, dbus.Boolean):
+ if raw_arg:
+ return 'boolean:true'
+ else:
+ return 'boolean:false'
+
+ for prim_type, prefix in int_map.iteritems():
+ if isinstance(raw_arg, prim_type):
+ return prefix + str(raw_arg)
+
+ raise error.TestError('No support for serializing %r' % raw_arg)
+
+
+def _build_arg_string(raw_args):
+ """Construct a string of arguments to a DBus method as dbus-send expects.
+
+ @param raw_args list of dbus.* type objects to seriallize.
+ @return string suitable for dbus-send.
+
+ """
+ return ' '.join([_dbus2string(arg) for arg in raw_args])
def dbus_send(bus_name, interface, object_path, method_name, args=None,
diff --git a/client/common_lib/cros/dbus_send_unittest.py b/client/common_lib/cros/dbus_send_unittest.py
index 79e0ffa..0f8991e 100755
--- a/client/common_lib/cros/dbus_send_unittest.py
+++ b/client/common_lib/cros/dbus_send_unittest.py
@@ -7,6 +7,7 @@
import unittest
import common
+import dbus
from autotest_lib.client.common_lib.cros import dbus_send
EXAMPLE_SHILL_GET_PROPERTIES_OUTPUT = \
@@ -210,6 +211,18 @@
assert len(result.response) == 0, (
'Got extra response: %r' % result.response)
+ def testBuildArgString(self):
+ """Test that we correctly form argument strings from dbus.* types."""
+ self.assertEquals(dbus_send._build_arg_string(
+ [dbus.Int16(42)]),
+ 'int16:42')
+ self.assertEquals(dbus_send._build_arg_string(
+ [dbus.Int16(42), dbus.Boolean(True)]),
+ 'int16:42 boolean:true')
+ self.assertEquals(dbus_send._build_arg_string(
+ [dbus.Int16(42), dbus.Boolean(True), dbus.String("foo")]),
+ 'int16:42 boolean:true string:foo')
+
if __name__ == "__main__":
unittest.main()