Merge "Added serials to the raised AndroidDeviceErrors"
diff --git a/acts/framework/acts/controllers/android_device.py b/acts/framework/acts/controllers/android_device.py
index c809f5d..2f72d65 100755
--- a/acts/framework/acts/controllers/android_device.py
+++ b/acts/framework/acts/controllers/android_device.py
@@ -64,15 +64,17 @@
RELEASE_ID_REGEXES = [re.compile(r'\w+\.\d+\.\d+'), re.compile(r'N\w+')]
+class AndroidDeviceConfigError(Exception):
+ """Raised when AndroidDevice configs are malformatted."""
+
+
class AndroidDeviceError(error.ActsError):
- """Raised when there is an error in AndroidDevice
- """
- pass
+ """Raised when there is an error in AndroidDevice."""
class DoesNotExistError(AndroidDeviceError):
- """Raised when something that does not exist is referenced.
- """
+ """Raised when something that does not exist is referenced."""
+
def create(configs):
@@ -86,11 +88,11 @@
A list of AndroidDevice objects.
"""
if not configs:
- raise AndroidDeviceError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
+ raise AndroidDeviceConfigError(ANDROID_DEVICE_EMPTY_CONFIG_MSG)
elif configs == ANDROID_DEVICE_PICK_ALL_TOKEN:
ads = get_all_instances()
elif not isinstance(configs, list):
- raise AndroidDeviceError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
+ raise AndroidDeviceConfigError(ANDROID_DEVICE_NOT_LIST_CONFIG_MSG)
elif isinstance(configs[0], str):
# Configs is a list of serials.
ads = get_instances(configs)
@@ -103,7 +105,8 @@
for ad in ads:
if not ad.is_connected():
raise DoesNotExistError(("Android device %s is specified in config"
- " but is not attached.") % ad.serial)
+ " but is not attached.") % ad.serial,
+ serial=ad.serial)
_start_services_on_ads(ads)
return ads
@@ -163,17 +166,19 @@
for ad in ads:
running_ads.append(ad)
if not ad.ensure_screen_on():
- ad.log.error("User window cannot come up")
+ ad.log.error('User window cannot come up')
destroy(running_ads)
- raise AndroidDeviceError("User window cannot come up")
+ raise AndroidDeviceError('User window cannot come up',
+ serial=ad.serial)
if not ad.skip_sl4a and not ad.is_sl4a_installed():
- ad.log.error("sl4a.apk is not installed")
+ ad.log.error('sl4a.apk is not installed')
destroy(running_ads)
- raise AndroidDeviceError("The required sl4a.apk is not installed")
+ raise AndroidDeviceError('The required sl4a.apk is not installed',
+ serial=ad.serial)
try:
ad.start_services(skip_sl4a=ad.skip_sl4a)
except:
- ad.log.exception("Failed to start some services, abort!")
+ ad.log.exception('Failed to start some services, abort!')
destroy(running_ads)
raise
@@ -244,12 +249,12 @@
results = []
for c in configs:
try:
- serial = c.pop("serial")
+ serial = c.pop('serial')
except KeyError:
- raise AndroidDeviceError(
+ raise AndroidDeviceConfigError(
"Required value 'serial' is missing in AndroidDevice config %s."
% c)
- ssh_config = c.pop("ssh_config", None)
+ ssh_config = c.pop('ssh_config', None)
ssh_connection = None
if ssh_config is not None:
ssh_settings = settings.from_config(ssh_config)
@@ -325,14 +330,14 @@
filtered = filter_devices(ads, _get_device_filter)
if not filtered:
- raise AndroidDeviceError(
+ raise ValueError(
"Could not find a target device that matches condition: %s." %
kwargs)
elif len(filtered) == 1:
return filtered[0]
else:
serials = [ad.serial for ad in filtered]
- raise AndroidDeviceError("More than one device matched: %s" % serials)
+ raise ValueError("More than one device matched: %s" % serials)
def take_bug_reports(ads, test_name, begin_time):
@@ -619,7 +624,7 @@
if hasattr(self, k) and k != "skip_sl4a":
raise AndroidDeviceError(
"Attempting to set existing attribute %s on %s" %
- (k, self.serial))
+ (k, self.serial), serial=self.serial)
setattr(self, k, v)
def root_adb(self):
@@ -773,9 +778,10 @@
logcat is no longer running.
"""
if self.is_adb_logcat_on:
- raise AndroidDeviceError(("Android device {} already has an adb "
- "logcat thread going on. Cannot start "
- "another one.").format(self.serial))
+ raise AndroidDeviceError(
+ 'Android device %s already has a running adb logcat thread. '
+ 'Cannot start another one.' % self.serial,
+ serial=self.serial)
# Disable adb log spam filter. Have to stop and clear settings first
# because 'start' doesn't support --clear option before Android N.
self.adb.shell("logpersist.stop --clear")
@@ -807,8 +813,9 @@
"""
if not self.is_adb_logcat_on:
raise AndroidDeviceError(
- "Android device %s does not have an ongoing adb logcat "
- "collection." % self.serial)
+ 'Android device %s does not have an ongoing adb logcat '
+ 'collection.' % self.serial,
+ serial=self.serial)
# Set the last timestamp to the current timestamp. This may cause
# a race condition that allows the same line to be logged twice,
# but it does not pose a problem for our logging purposes.
@@ -938,7 +945,8 @@
out = self.adb.shell("bugreportz", timeout=BUG_REPORT_TIMEOUT)
if not out.startswith("OK"):
raise AndroidDeviceError(
- "Failed to take bugreport on %s: %s" % (self.serial, out))
+ 'Failed to take bugreport on %s: %s' % (self.serial, out),
+ serial=self.serial)
br_out_path = out.split(':')[1].strip().split()[0]
self.adb.pull("%s %s" % (br_out_path, full_out_path))
else:
@@ -1147,7 +1155,8 @@
pass
time.sleep(5)
raise AndroidDeviceError(
- "Device %s booting process timed out." % self.serial)
+ 'Device %s booting process timed out.' % self.serial,
+ serial=self.serial)
def reboot(self, stop_at_lock_screen=False):
"""Reboots the device.
@@ -1195,7 +1204,8 @@
return
if not self.ensure_screen_on():
self.log.error("User window cannot come up")
- raise AndroidDeviceError("User window cannot come up")
+ raise AndroidDeviceError("User window cannot come up",
+ serial=self.serial)
self.start_services(self.skip_sl4a)
def restart_runtime(self):
@@ -1212,7 +1222,8 @@
self.root_adb()
if not self.ensure_screen_on():
self.log.error("User window cannot come up")
- raise AndroidDeviceError("User window cannot come up")
+ raise AndroidDeviceError('User window cannot come up',
+ serial=self.serial)
self.start_services(self.skip_sl4a)
def search_logcat(self, matching_string, begin_time=None):
diff --git a/acts/framework/acts/error.py b/acts/framework/acts/error.py
index f11e337..8e89499 100644
--- a/acts/framework/acts/error.py
+++ b/acts/framework/acts/error.py
@@ -10,7 +10,9 @@
class_name = self.__class__.__name__
self.message = self.__class__.__doc__
self.error_code = getattr(ActsErrorCode, class_name)
- self.extra = args
+ self.extra = kwargs
+ if len(args) > 0:
+ self.extra['details'] = args
def json_str(self):
"""Converts this error to a string in json format.
diff --git a/acts/framework/tests/acts_android_device_test.py b/acts/framework/tests/acts_android_device_test.py
index 17220c4..efbb115 100755
--- a/acts/framework/tests/acts_android_device_test.py
+++ b/acts/framework/tests/acts_android_device_test.py
@@ -182,13 +182,13 @@
def test_create_with_empty_config(self):
expected_msg = android_device.ANDROID_DEVICE_EMPTY_CONFIG_MSG
- with self.assertRaisesRegex(android_device.AndroidDeviceError,
+ with self.assertRaisesRegex(android_device.AndroidDeviceConfigError,
expected_msg):
android_device.create([])
def test_create_with_not_list_config(self):
expected_msg = android_device.ANDROID_DEVICE_NOT_LIST_CONFIG_MSG
- with self.assertRaisesRegex(android_device.AndroidDeviceError,
+ with self.assertRaisesRegex(android_device.AndroidDeviceConfigError,
expected_msg):
android_device.create("HAHA")
@@ -212,16 +212,14 @@
ads = get_mock_ads(5)
expected_msg = ("Could not find a target device that matches condition"
": {'serial': 5}.")
- with self.assertRaisesRegex(android_device.AndroidDeviceError,
- expected_msg):
+ with self.assertRaisesRegex(ValueError, expected_msg):
ad = android_device.get_device(ads, serial=len(ads))
def test_get_device_too_many_matches(self):
ads = get_mock_ads(5)
target_serial = ads[1].serial = ads[0].serial
expected_msg = "More than one device matched: \[0, 0\]"
- with self.assertRaisesRegex(android_device.AndroidDeviceError,
- expected_msg):
+ with self.assertRaisesRegex(ValueError, expected_msg):
ad = android_device.get_device(ads, serial=target_serial)
def test_start_services_on_ads(self):
@@ -402,8 +400,8 @@
start_proc_mock.assert_called_with(
adb_cmd % (ad.serial, expected_log_path))
self.assertEqual(ad.adb_logcat_file_path, expected_log_path)
- expected_msg = ("Android device .* already has an adb logcat thread "
- "going on. Cannot start another one.")
+ expected_msg = ('Android device .* already has a running adb logcat '
+ 'thread. Cannot start another one.')
# Expect error if start is called back to back.
with self.assertRaisesRegex(android_device.AndroidDeviceError,
expected_msg):
diff --git a/acts/framework/tests/acts_error_test.py b/acts/framework/tests/acts_error_test.py
index 2527b54..e19ad07 100755
--- a/acts/framework/tests/acts_error_test.py
+++ b/acts/framework/tests/acts_error_test.py
@@ -19,18 +19,28 @@
class ActsErrorTest(unittest.TestCase):
- def test_error_without_args(self):
+
+ def test_assert_key_pulled_from_acts_error_code(self):
e = error.ActsError()
self.assertEqual(e.error_code, 100)
+
+ def test_assert_description_pulled_from_docstring(self):
+ e = error.ActsError()
self.assertEqual(e.message, 'Base Acts Error')
- self.assertEqual(e.extra, ())
+
+ def test_error_without_args(self):
+ e = error.ActsError()
+ self.assertEqual(e.extra['details'], ())
def test_error_with_args(self):
- args = 'hello'
- e = error.ActsError(args)
- self.assertEqual(e.error_code, 100)
- self.assertEqual(e.message, 'Base Acts Error')
- self.assertEqual(e.extra, ('hello',))
+ args = ['hello']
+ e = error.ActsError(*args)
+ self.assertEqual(e.extra['details'], args)
+
+ def test_error_with_kwargs(self):
+ e = error.ActsError(key='value')
+ self.assertTrue('key' in e.extra.keys())
+ self.assertTrue('value' in e.extra['key'])
if __name__ == '__main__':