aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZiwei Zhang <zhangxh@google.com>2024-04-09 11:56:25 +0800
committerZiwei Zhang <zhangxh@google.com>2024-04-09 05:00:25 +0000
commit51b0b7394aa1bbf4812fb4e8f734a2b5f0939494 (patch)
treef8869eb48e3de9e7c345310bc19cce3ce968b527
parenta529b98b550f5d2cdb797699d6528ca5454759a6 (diff)
parent161ff47b51c5fa836bf7a14fbdc69587682018b3 (diff)
downloadmobly-main.tar.gz
Upgrade mobly to 161ff47b51c5fa836bf7a14fbdc69587682018b3HEADmastermain
This project was upgraded with external_updater. Usage: tools/external_updater/updater.sh update external/python/mobly For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md Test: TreeHugger Bug: 331669033 Change-Id: I17cf03d6bec68fb3b9e84b0475543edc000d174f
-rw-r--r--.github/workflows/ci.yml9
-rw-r--r--.gitignore1
-rw-r--r--.style.yapf5
-rw-r--r--CHANGELOG.md20
-rw-r--r--CONTRIBUTING.md8
-rw-r--r--METADATA28
-rw-r--r--README.md19
-rw-r--r--docs/conf.py48
-rw-r--r--mobly/asserts.py226
-rw-r--r--mobly/base_instrumentation_test.py145
-rw-r--r--mobly/base_suite.py1
-rw-r--r--mobly/base_test.py220
-rw-r--r--mobly/config_parser.py25
-rw-r--r--mobly/controller_manager.py66
-rw-r--r--mobly/controllers/android_device.py135
-rw-r--r--mobly/controllers/android_device_lib/adb.py175
-rw-r--r--mobly/controllers/android_device_lib/callback_handler.py23
-rw-r--r--mobly/controllers/android_device_lib/callback_handler_v2.py15
-rw-r--r--mobly/controllers/android_device_lib/errors.py1
-rw-r--r--mobly/controllers/android_device_lib/event_dispatcher.py92
-rw-r--r--mobly/controllers/android_device_lib/fastboot.py18
-rw-r--r--mobly/controllers/android_device_lib/jsonrpc_client_base.py51
-rwxr-xr-xmobly/controllers/android_device_lib/jsonrpc_shell_base.py7
-rw-r--r--mobly/controllers/android_device_lib/service_manager.py44
-rw-r--r--mobly/controllers/android_device_lib/services/base_service.py1
-rw-r--r--mobly/controllers/android_device_lib/services/logcat.py55
-rw-r--r--mobly/controllers/android_device_lib/services/snippet_management_service.py28
-rw-r--r--mobly/controllers/android_device_lib/sl4a_client.py29
-rw-r--r--mobly/controllers/android_device_lib/snippet_client.py100
-rw-r--r--mobly/controllers/android_device_lib/snippet_client_v2.py180
-rw-r--r--mobly/controllers/android_device_lib/snippet_event.py24
-rw-r--r--mobly/controllers/attenuator.py74
-rw-r--r--mobly/controllers/attenuator_lib/minicircuits.py106
-rw-r--r--mobly/controllers/attenuator_lib/telnet_scpi_client.py16
-rw-r--r--mobly/controllers/iperf_server.py61
-rw-r--r--mobly/controllers/sniffer.py335
-rw-r--r--mobly/controllers/sniffer_lib/local/local_base.py103
-rw-r--r--mobly/controllers/sniffer_lib/local/tcpdump.py27
-rw-r--r--mobly/controllers/sniffer_lib/local/tshark.py35
-rw-r--r--mobly/expects.py5
-rw-r--r--mobly/keys.py1
-rw-r--r--mobly/logger.py48
-rw-r--r--mobly/records.py81
-rw-r--r--mobly/runtime_test_info.py3
-rw-r--r--mobly/signals.py11
-rw-r--r--mobly/snippet/callback_event.py13
-rw-r--r--mobly/snippet/callback_handler_base.py34
-rw-r--r--mobly/snippet/client_base.py52
-rw-r--r--mobly/snippet/errors.py6
-rw-r--r--mobly/suite_runner.py85
-rw-r--r--mobly/test_runner.py162
-rw-r--r--mobly/utils.py169
-rw-r--r--pyproject.toml44
-rw-r--r--setup.cfg6
-rwxr-xr-xsetup.py70
-rwxr-xr-xtests/lib/integration_test.py9
-rwxr-xr-xtests/lib/jsonrpc_client_test_base.py19
-rwxr-xr-xtests/lib/mock_android_device.py53
-rw-r--r--tests/lib/mock_instrumentation_test.py10
-rw-r--r--tests/lib/mock_second_controller.py2
-rw-r--r--tests/lib/utils.py5
-rwxr-xr-xtests/mobly/asserts_test.py106
-rwxr-xr-xtests/mobly/base_instrumentation_test_test.py230
-rwxr-xr-xtests/mobly/base_test_test.py928
-rw-r--r--tests/mobly/config_parser_test.py33
-rwxr-xr-xtests/mobly/controller_manager_test.py99
-rwxr-xr-xtests/mobly/controllers/android_device_lib/adb_test.py669
-rwxr-xr-xtests/mobly/controllers/android_device_lib/callback_handler_test.py109
-rw-r--r--tests/mobly/controllers/android_device_lib/callback_handler_v2_test.py83
-rwxr-xr-xtests/mobly/controllers/android_device_lib/errors_test.py11
-rw-r--r--tests/mobly/controllers/android_device_lib/fastboot_test.py13
-rwxr-xr-xtests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py56
-rwxr-xr-xtests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py25
-rwxr-xr-xtests/mobly/controllers/android_device_lib/service_manager_test.py56
-rwxr-xr-xtests/mobly/controllers/android_device_lib/services/logcat_test.py390
-rwxr-xr-xtests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py70
-rwxr-xr-xtests/mobly/controllers/android_device_lib/sl4a_client_test.py70
-rwxr-xr-xtests/mobly/controllers/android_device_lib/snippet_client_test.py472
-rw-r--r--tests/mobly/controllers/android_device_lib/snippet_client_v2_test.py1132
-rwxr-xr-xtests/mobly/controllers/android_device_lib/snippet_event_test.py13
-rwxr-xr-xtests/mobly/controllers/android_device_test.py1565
-rwxr-xr-xtests/mobly/logger_test.py84
-rwxr-xr-xtests/mobly/output_test.py143
-rwxr-xr-xtests/mobly/records_test.py270
-rwxr-xr-xtests/mobly/snippet/callback_event_test.py10
-rw-r--r--tests/mobly/snippet/callback_handler_base_test.py105
-rwxr-xr-xtests/mobly/snippet/client_base_test.py138
-rwxr-xr-xtests/mobly/suite_runner_test.py68
-rwxr-xr-xtests/mobly/test_runner_test.py223
-rwxr-xr-xtests/mobly/test_suite_test.py9
-rwxr-xr-xtests/mobly/utils_test.py444
-rwxr-xr-xtools/sl4a_shell.py11
-rwxr-xr-xtools/snippet_shell.py32
93 files changed, 6637 insertions, 4474 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b788662..a24efc3 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,4 +1,4 @@
-name: CI tests for google/mobly
+name: CI
on: [push, pull_request]
@@ -8,7 +8,7 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
- python-version: [3.7, 3.8]
+ python-version: ["3.11", "3.12"]
steps:
- name: Checkout repo
uses: actions/checkout@v2
@@ -27,3 +27,8 @@ jobs:
run: |
tox
+ - name: Check formatting
+ run: |
+ python -m pip install pyink
+ pyink --check .
+
diff --git a/.gitignore b/.gitignore
index 9c7984a..06591ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -12,3 +12,4 @@ Gemfile.lock
.sass-cache
_site
.tox/
+venv/
diff --git a/.style.yapf b/.style.yapf
deleted file mode 100644
index 38ecc35..0000000
--- a/.style.yapf
+++ /dev/null
@@ -1,5 +0,0 @@
-[style]
-based_on_style = google
-indent_width: 2
-spaces_before_comment = 2
-
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42c8df7..424dc64 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,26 @@
# Mobly Release History
+## Mobly Release 1.12.3: Proper Repeat and Retry Reporting
+Bumping min Python version requirement to 3.11.
+Modernized the repo's packaging mechanism.
+Removed legacy code and dependencies.
+
+### New
+* Support am instrument options in snippet client.
+* Support adb reverse in `AdbProxy`.
+* Improved mechanism for tracking repeat and retry records in test report.
+
+### Breaking Changes
+* [Deprecation] `get_available_host_port` is now deprecated and will be removed
+ in the next major release. Please rely on the OS to allocate ports.
+
+### Fixes
+* Eliminated redundant `fastboot` calls.
+
+[Full list of changes](https://github.com/google/mobly/milestone/30?closed=1)
+
+
## Mobly Release 1.12.2: Improve Support for Custom Suites
Bug fixes and improvements to better support users who construct their own
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index d9bdd95..bca38c3 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -43,16 +43,16 @@ mobly $ tox
```
### Code style
-Before pushing your changes, you need to lint the code style via `yapf`
+Before pushing your changes, you need to lint the code style via `pyink`
-To install `yapf`:
+To install `pyink`:
```sh
-$ pip3 install yapf
+$ pip3 install pyink
```
To lint the code:
```sh
-mobly $ yapf -i {files you modified}
+mobly $ pyink .
```
diff --git a/METADATA b/METADATA
index 2d088a5..57b7b7e 100644
--- a/METADATA
+++ b/METADATA
@@ -1,20 +1,20 @@
-name: "mobly"
-description:
- "Mobly is a Python-based test framework that specializes in supporting test "
- "cases that require multiple devices, complex environments, or custom "
- "hardware setups."
+# This project was upgraded with external_updater.
+# Usage: tools/external_updater/updater.sh update external/python/mobly
+# For more info, check https://cs.android.com/android/platform/superproject/+/main:tools/external_updater/README.md
+name: "mobly"
+description: "Mobly is a Python-based test framework that specializes in supporting test cases that require multiple devices, complex environments, or custom hardware setups."
third_party {
- url {
- type: HOMEPAGE
- value: "https://github.com/google/mobly"
+ license_type: NOTICE
+ last_upgrade_date {
+ year: 2024
+ month: 4
+ day: 9
}
- url {
- type: GIT
+ homepage: "https://github.com/google/mobly"
+ identifier {
+ type: "Git"
value: "https://github.com/google/mobly"
+ version: "161ff47b51c5fa836bf7a14fbdc69587682018b3"
}
- version: "1.11"
- last_upgrade_date { year: 2021 month: 12 day: 16 }
- license_type: NOTICE
}
-
diff --git a/README.md b/README.md
index 290a5b1..a9cd38f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
# Welcome to Mobly
+[![Latest release](https://img.shields.io/github/release/google/mobly.svg)](https://github.com/google/mobly/releases/latest)
+[![Build Status](https://github.com/google/mobly/actions/workflows/ci.yml/badge.svg?branch=master)](https://github.com/google/mobly/actions)
+
**Mobly** is a Python-based test framework that specializes in supporting test
cases that require multiple devices, complex environments, or custom hardware
setups.
@@ -21,24 +24,16 @@ While developed by Googlers, Mobly is not an official Google product.
## Compatibility
-Mobly requires *python 3.6* or newer.
+Mobly requires *python 3.11* or newer.
Mobly tests could run on the following platforms:
- Ubuntu 14.04+
- MacOS 10.6+
- Windows 7+
-| Platform | Build Status |
-|----------|--------------|
-| Linux | [![Linux Build Status](https://travis-ci.org/google/mobly.svg?branch=master)](https://travis-ci.org/google/mobly) |
-| Windows | [![Windows Build Status](https://storage.googleapis.com/mobly-kokoro-build-badges/mobly-windows.svg)](https://fusion.corp.google.com/projectanalysis/current/KOKORO/prod%3Amobly%2Fgcp_windows%2Fcontinuous) |
-
## System dependencies
- adb (1.0.40+ recommended)
- - python3.7+
- - python-setuptools
-
-*To use Python3, use `pip3` and `python3` (or python3.x) accordingly.*
+ - python3.11+
## Installation
You can install the released package from pip
@@ -47,12 +42,12 @@ You can install the released package from pip
pip install mobly
```
-or download the source then run `setup.py` to use the bleeding edge:
+or install from the source to use the bleeding edge:
```sh
git clone https://github.com/google/mobly.git
cd mobly
-python setup.py install
+pip install -e .
```
You may need `sudo` for the above commands if your system has certain permission
diff --git a/docs/conf.py b/docs/conf.py
index d08be89..2a7e6a9 100644
--- a/docs/conf.py
+++ b/docs/conf.py
@@ -18,6 +18,7 @@
#
import os
import sys
+
sys.path.insert(0, os.path.abspath(os.path.pardir))
# -- General configuration ------------------------------------------------
@@ -30,8 +31,10 @@ sys.path.insert(0, os.path.abspath(os.path.pardir))
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
- 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', 'sphinx.ext.todo',
- 'sphinx.ext.viewcode'
+ 'sphinx.ext.autodoc',
+ 'sphinx.ext.napoleon',
+ 'sphinx.ext.todo',
+ 'sphinx.ext.viewcode',
]
# Add any paths that contain templates here, relative to this directory.
@@ -54,18 +57,18 @@ source_suffix = ['.rst', '.md']
master_doc = 'index'
# General information about the project.
-project = u'Mobly'
-copyright = u'Copyright 2016 Google Inc.'
-author = u'Ang Li'
+project = 'Mobly'
+copyright = 'Copyright 2016 Google Inc.'
+author = 'Ang Li'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
-version = u''
+version = ''
# The full version, including alpha/beta/rc tags.
-release = u''
+release = ''
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
@@ -78,8 +81,12 @@ language = 'en'
# directories to ignore when looking for source files.
# This patterns also effect to html_static_path and html_extra_path
exclude_patterns = [
- '_build', 'Thumbs.db', '.DS_Store', 'tutorial.md',
- 'instrumentation_tutorial.md', 'android_device_service.md'
+ '_build',
+ 'Thumbs.db',
+ '.DS_Store',
+ 'tutorial.md',
+ 'instrumentation_tutorial.md',
+ 'android_device_service.md',
]
# The name of the Pygments (syntax highlighting) style to use.
@@ -117,15 +124,12 @@ latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
-
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
-
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
-
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
@@ -135,14 +139,14 @@ latex_elements = {
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
- (master_doc, 'Mobly.tex', u'Mobly Documentation', u'Ang Li', 'manual'),
+ (master_doc, 'Mobly.tex', 'Mobly Documentation', 'Ang Li', 'manual'),
]
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
-man_pages = [(master_doc, 'mobly', u'Mobly Documentation', [author], 1)]
+man_pages = [(master_doc, 'mobly', 'Mobly Documentation', [author], 1)]
# -- Options for Texinfo output -------------------------------------------
@@ -150,9 +154,19 @@ man_pages = [(master_doc, 'mobly', u'Mobly Documentation', [author], 1)]
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
- (master_doc, 'Mobly', u'Mobly Documentation', author, 'Mobly',
- 'Mobly is a Python-based test framework that specializes in supporting tests that require multiple devices, complex environments, or custom hardware setups.',
- 'Miscellaneous'),
+ (
+ master_doc,
+ 'Mobly',
+ 'Mobly Documentation',
+ author,
+ 'Mobly',
+ (
+ 'Mobly is a Python-based test framework that specializes in'
+ ' supporting tests that require multiple devices, complex'
+ ' environments, or custom hardware setups.'
+ ),
+ 'Miscellaneous',
+ ),
]
# -- Options for Epub output ----------------------------------------------
diff --git a/mobly/asserts.py b/mobly/asserts.py
index 70e1256..e877e05 100644
--- a/mobly/asserts.py
+++ b/mobly/asserts.py
@@ -23,11 +23,9 @@ _pyunit_proxy = unittest.TestCase()
_pyunit_proxy.maxDiff = None
-def _call_unittest_assertion(assertion_method,
- *args,
- msg=None,
- extras=None,
- **kwargs):
+def _call_unittest_assertion(
+ assertion_method, *args, msg=None, extras=None, **kwargs
+):
"""Wrapper for converting a unittest assertion into a Mobly one.
Args:
@@ -65,28 +63,21 @@ def assert_equal(first, second, msg=None, extras=None):
extras: An optional field for extra information to be included in
test result.
"""
- _call_unittest_assertion(_pyunit_proxy.assertEqual,
- first,
- second,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertEqual, first, second, msg=msg, extras=extras
+ )
def assert_not_equal(first, second, msg=None, extras=None):
"""Asserts that first is not equal (!=) to second."""
- _call_unittest_assertion(_pyunit_proxy.assertNotEqual,
- first,
- second,
- msg=msg,
- extras=extras)
-
-
-def assert_almost_equal(first,
- second,
- places=None,
- msg=None,
- delta=None,
- extras=None):
+ _call_unittest_assertion(
+ _pyunit_proxy.assertNotEqual, first, second, msg=msg, extras=extras
+ )
+
+
+def assert_almost_equal(
+ first, second, places=None, msg=None, delta=None, extras=None
+):
"""Asserts that first is almost equal to second.
Fails if the two objects are unequal as determined by their difference
@@ -107,21 +98,20 @@ def assert_almost_equal(first,
extras: An optional field for extra information to be included in
test result.
"""
- _call_unittest_assertion(_pyunit_proxy.assertAlmostEqual,
- first,
- second,
- places=places,
- msg=msg,
- delta=delta,
- extras=extras)
-
-
-def assert_not_almost_equal(first,
- second,
- places=None,
- msg=None,
- delta=None,
- extras=None):
+ _call_unittest_assertion(
+ _pyunit_proxy.assertAlmostEqual,
+ first,
+ second,
+ places=places,
+ msg=msg,
+ delta=delta,
+ extras=extras,
+ )
+
+
+def assert_not_almost_equal(
+ first, second, places=None, msg=None, delta=None, extras=None
+):
"""Asserts that first is not almost equal to second.
Args:
@@ -135,49 +125,43 @@ def assert_not_almost_equal(first,
extras: An optional field for extra information to be included in
test result.
"""
- _call_unittest_assertion(_pyunit_proxy.assertNotAlmostEqual,
- first,
- second,
- places=places,
- msg=msg,
- delta=delta,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertNotAlmostEqual,
+ first,
+ second,
+ places=places,
+ msg=msg,
+ delta=delta,
+ extras=extras,
+ )
def assert_in(member, container, msg=None, extras=None):
"""Asserts that member is in container."""
- _call_unittest_assertion(_pyunit_proxy.assertIn,
- member,
- container,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIn, member, container, msg=msg, extras=extras
+ )
def assert_not_in(member, container, msg=None, extras=None):
"""Asserts that member is not in container."""
- _call_unittest_assertion(_pyunit_proxy.assertNotIn,
- member,
- container,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertNotIn, member, container, msg=msg, extras=extras
+ )
def assert_is(expr1, expr2, msg=None, extras=None):
"""Asserts that expr1 is expr2."""
- _call_unittest_assertion(_pyunit_proxy.assertIs,
- expr1,
- expr2,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIs, expr1, expr2, msg=msg, extras=extras
+ )
def assert_is_not(expr1, expr2, msg=None, extras=None):
"""Asserts that expr1 is not expr2."""
- _call_unittest_assertion(_pyunit_proxy.assertIsNot,
- expr1,
- expr2,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIsNot, expr1, expr2, msg=msg, extras=extras
+ )
def assert_count_equal(first, second, msg=None, extras=None):
@@ -197,99 +181,83 @@ def assert_count_equal(first, second, msg=None, extras=None):
assert_count_equal([0, 1, 1], [1, 0, 1]) passes the assertion.
assert_count_equal([0, 0, 1], [0, 1]) raises an assertion error.
"""
- _call_unittest_assertion(_pyunit_proxy.assertCountEqual,
- first,
- second,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertCountEqual, first, second, msg=msg, extras=extras
+ )
def assert_less(a, b, msg=None, extras=None):
"""Asserts that a < b."""
- _call_unittest_assertion(_pyunit_proxy.assertLess,
- a,
- b,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertLess, a, b, msg=msg, extras=extras
+ )
def assert_less_equal(a, b, msg=None, extras=None):
"""Asserts that a <= b."""
- _call_unittest_assertion(_pyunit_proxy.assertLessEqual,
- a,
- b,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertLessEqual, a, b, msg=msg, extras=extras
+ )
def assert_greater(a, b, msg=None, extras=None):
"""Asserts that a > b."""
- _call_unittest_assertion(_pyunit_proxy.assertGreater,
- a,
- b,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertGreater, a, b, msg=msg, extras=extras
+ )
def assert_greater_equal(a, b, msg=None, extras=None):
"""Asserts that a >= b."""
- _call_unittest_assertion(_pyunit_proxy.assertGreaterEqual,
- a,
- b,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertGreaterEqual, a, b, msg=msg, extras=extras
+ )
def assert_is_none(obj, msg=None, extras=None):
"""Asserts that obj is None."""
- _call_unittest_assertion(_pyunit_proxy.assertIsNone,
- obj,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIsNone, obj, msg=msg, extras=extras
+ )
def assert_is_not_none(obj, msg=None, extras=None):
"""Asserts that obj is not None."""
- _call_unittest_assertion(_pyunit_proxy.assertIsNotNone,
- obj,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIsNotNone, obj, msg=msg, extras=extras
+ )
def assert_is_instance(obj, cls, msg=None, extras=None):
"""Asserts that obj is an instance of cls."""
- _call_unittest_assertion(_pyunit_proxy.assertIsInstance,
- obj,
- cls,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertIsInstance, obj, cls, msg=msg, extras=extras
+ )
def assert_not_is_instance(obj, cls, msg=None, extras=None):
"""Asserts that obj is not an instance of cls."""
- _call_unittest_assertion(_pyunit_proxy.assertNotIsInstance,
- obj,
- cls,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertNotIsInstance, obj, cls, msg=msg, extras=extras
+ )
def assert_regex(text, expected_regex, msg=None, extras=None):
"""Fails the test unless the text matches the regular expression."""
- _call_unittest_assertion(_pyunit_proxy.assertRegex,
- text,
- expected_regex,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertRegex, text, expected_regex, msg=msg, extras=extras
+ )
def assert_not_regex(text, unexpected_regex, msg=None, extras=None):
"""Fails the test if the text matches the regular expression."""
- _call_unittest_assertion(_pyunit_proxy.assertNotRegex,
- text,
- unexpected_regex,
- msg=msg,
- extras=extras)
+ _call_unittest_assertion(
+ _pyunit_proxy.assertNotRegex,
+ text,
+ unexpected_regex,
+ msg=msg,
+ extras=extras,
+ )
def assert_raises(expected_exception, extras=None, *args, **kwargs):
@@ -312,11 +280,9 @@ def assert_raises(expected_exception, extras=None, *args, **kwargs):
return context
-def assert_raises_regex(expected_exception,
- expected_regex,
- extras=None,
- *args,
- **kwargs):
+def assert_raises_regex(
+ expected_exception, expected_regex, extras=None, *args, **kwargs
+):
"""Assert that an exception is raised when a function is called.
If no exception is raised, test fail. If an exception is raised but not
@@ -334,9 +300,9 @@ def assert_raises_regex(expected_exception,
extras: An optional field for extra information to be included in
test result.
"""
- context = _AssertRaisesContext(expected_exception,
- expected_regex,
- extras=extras)
+ context = _AssertRaisesContext(
+ expected_exception, expected_regex, extras=extras
+ )
return context
@@ -526,7 +492,9 @@ class _AssertRaisesContext:
if isinstance(expected_regexp, str):
expected_regexp = re.compile(expected_regexp)
if not expected_regexp.search(str(exc_value)):
- raise signals.TestFailure('"%s" does not match "%s"' %
- (expected_regexp.pattern, str(exc_value)),
- extras=self.extras)
+ raise signals.TestFailure(
+ '"%s" does not match "%s"'
+ % (expected_regexp.pattern, str(exc_value)),
+ extras=self.extras,
+ )
return True
diff --git a/mobly/base_instrumentation_test.py b/mobly/base_instrumentation_test.py
index 9c24386..f41a500 100644
--- a/mobly/base_instrumentation_test.py
+++ b/mobly/base_instrumentation_test.py
@@ -302,10 +302,12 @@ class _InstrumentationBlock:
unknown_keys: dict, arbitrary keys that are handled generically.
"""
- def __init__(self,
- state=_InstrumentationBlockStates.UNKNOWN,
- prefix=None,
- previous_instrumentation_block=None):
+ def __init__(
+ self,
+ state=_InstrumentationBlockStates.UNKNOWN,
+ prefix=None,
+ previous_instrumentation_block=None,
+ ):
self.state = state
self.prefix = prefix
self.previous_instrumentation_block = previous_instrumentation_block
@@ -369,7 +371,7 @@ class _InstrumentationBlock:
A string containing a key value pair descripting some property
of the current instrumentation test method.
"""
- return line[len(prefix):].strip()
+ return line[len(prefix) :].strip()
def set_status_code(self, status_code_line):
"""Sets the status code for the instrumentation test method, used in
@@ -480,10 +482,12 @@ class _InstrumentationBlockFormatter:
self._unknown_keys = {}
for key, value in instrumentation_block.known_keys.items():
self._known_keys[key] = '\n'.join(
- instrumentation_block.known_keys[key]).rstrip()
+ instrumentation_block.known_keys[key]
+ ).rstrip()
for key, value in instrumentation_block.unknown_keys.items():
self._unknown_keys[key] = '\n'.join(
- instrumentation_block.unknown_keys[key]).rstrip()
+ instrumentation_block.unknown_keys[key]
+ ).rstrip()
self._begin_time = instrumentation_block.begin_time
def _get_name(self):
@@ -510,7 +514,8 @@ class _InstrumentationBlockFormatter:
name.
"""
class_parts = [
- self._prefix, self._known_keys[_InstrumentationKnownStatusKeys.CLASS]
+ self._prefix,
+ self._known_keys[_InstrumentationKnownStatusKeys.CLASS],
]
return '.'.join(filter(None, class_parts))
@@ -549,16 +554,20 @@ class _InstrumentationBlockFormatter:
extra_parts.append(self._known_keys[_InstrumentationKnownStatusKeys.STREAM])
extra_parts.append(
- self._known_keys[_InstrumentationKnownResultKeys.SHORTMSG])
+ self._known_keys[_InstrumentationKnownResultKeys.SHORTMSG]
+ )
extra_parts.append(
- self._known_keys[_InstrumentationKnownResultKeys.LONGMSG])
+ self._known_keys[_InstrumentationKnownResultKeys.LONGMSG]
+ )
extra_parts.append(self._known_keys[_InstrumentationKnownStatusKeys.ERROR])
- if self._known_keys[
- _InstrumentationKnownStatusKeys.STACK] not in self._known_keys[
- _InstrumentationKnownStatusKeys.STREAM]:
+ if (
+ self._known_keys[_InstrumentationKnownStatusKeys.STACK]
+ not in self._known_keys[_InstrumentationKnownStatusKeys.STREAM]
+ ):
extra_parts.append(
- self._known_keys[_InstrumentationKnownStatusKeys.STACK])
+ self._known_keys[_InstrumentationKnownStatusKeys.STACK]
+ )
return '\n'.join(filter(None, extra_parts))
@@ -574,8 +583,10 @@ class _InstrumentationBlockFormatter:
"""
if self._status_code in _InstrumentationStatusCodeCategories.FAIL:
return True
- elif (self._known_keys[_InstrumentationKnownStatusKeys.STACK] and
- self._status_code != _InstrumentationStatusCodes.ASSUMPTION_FAILURE):
+ elif (
+ self._known_keys[_InstrumentationKnownStatusKeys.STACK]
+ and self._status_code != _InstrumentationStatusCodes.ASSUMPTION_FAILURE
+ ):
return True
elif self._known_keys[_InstrumentationKnownStatusKeys.ERROR]:
return True
@@ -616,14 +627,16 @@ class _InstrumentationBlockFormatter:
elif self._status_code in _InstrumentationStatusCodeCategories.TIMING:
if self._error_message:
tr_record.test_error(
- e=signals.TestError(details=details, extras=extras))
+ e=signals.TestError(details=details, extras=extras)
+ )
else:
tr_record = None
else:
tr_record.test_error(e=signals.TestError(details=details, extras=extras))
if self._known_keys[_InstrumentationKnownStatusKeys.STACK]:
tr_record.termination_signal.stacktrace = self._known_keys[
- _InstrumentationKnownStatusKeys.STACK]
+ _InstrumentationKnownStatusKeys.STACK
+ ]
return tr_record
def has_completed_result_block_format(self, error_message):
@@ -669,11 +682,13 @@ class InstrumentationTestMixin:
"""
DEFAULT_INSTRUMENTATION_OPTION_PREFIX = 'instrumentation_option_'
- DEFAULT_INSTRUMENTATION_ERROR_MESSAGE = ('instrumentation run exited '
- 'unexpectedly')
+ DEFAULT_INSTRUMENTATION_ERROR_MESSAGE = (
+ 'instrumentation run exited unexpectedly'
+ )
- def _previous_block_never_completed(self, current_block, previous_block,
- new_state):
+ def _previous_block_never_completed(
+ self, current_block, previous_block, new_state
+ ):
"""Checks if the previous instrumentation method block completed.
Args:
@@ -691,11 +706,14 @@ class InstrumentationTestMixin:
completed executing.
"""
if previous_block:
- previously_timing_block = (previous_block.status_code
- in _InstrumentationStatusCodeCategories.TIMING)
- currently_new_block = (current_block.status_code
- == _InstrumentationStatusCodes.START or
- new_state == _InstrumentationBlockStates.RESULT)
+ previously_timing_block = (
+ previous_block.status_code
+ in _InstrumentationStatusCodeCategories.TIMING
+ )
+ currently_new_block = (
+ current_block.status_code == _InstrumentationStatusCodes.START
+ or new_state == _InstrumentationBlockStates.RESULT
+ )
return all([previously_timing_block, currently_new_block])
else:
return False
@@ -718,21 +736,24 @@ class InstrumentationTestMixin:
if self._previous_block_never_completed(
current_block=instrumentation_block,
previous_block=instrumentation_block.previous_instrumentation_block,
- new_state=new_state):
+ new_state=new_state,
+ ):
instrumentation_block.previous_instrumentation_block.set_error_message(
- self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE)
+ self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE
+ )
formatters.append(
_InstrumentationBlockFormatter(
- instrumentation_block.previous_instrumentation_block))
+ instrumentation_block.previous_instrumentation_block
+ )
+ )
if not instrumentation_block.is_empty:
formatters.append(_InstrumentationBlockFormatter(instrumentation_block))
return formatters
def _transition_instrumentation_block(
- self,
- instrumentation_block,
- new_state=_InstrumentationBlockStates.UNKNOWN):
+ self, instrumentation_block, new_state=_InstrumentationBlockStates.UNKNOWN
+ ):
"""Transitions and finishes the current instrumentation block.
Args:
@@ -750,8 +771,9 @@ class InstrumentationTestMixin:
test_record = formatter.create_test_record(self.TAG)
if test_record:
self.results.add_record(test_record)
- self.summary_writer.dump(test_record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ test_record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
return instrumentation_block.transition_state(new_state=new_state)
def _parse_method_block_line(self, instrumentation_block, line):
@@ -767,16 +789,18 @@ class InstrumentationTestMixin:
parsing instrumentation output.
"""
if line.startswith(_InstrumentationStructurePrefixes.STATUS):
- instrumentation_block.set_key(_InstrumentationStructurePrefixes.STATUS,
- line)
+ instrumentation_block.set_key(
+ _InstrumentationStructurePrefixes.STATUS, line
+ )
return instrumentation_block
elif line.startswith(_InstrumentationStructurePrefixes.STATUS_CODE):
instrumentation_block.set_status_code(line)
return self._transition_instrumentation_block(instrumentation_block)
elif line.startswith(_InstrumentationStructurePrefixes.RESULT):
# Unexpected transition from method block -> result block
- instrumentation_block.set_key(_InstrumentationStructurePrefixes.RESULT,
- line)
+ instrumentation_block.set_key(
+ _InstrumentationStructurePrefixes.RESULT, line
+ )
return self._parse_result_line(
self._transition_instrumentation_block(
instrumentation_block,
@@ -828,8 +852,10 @@ class InstrumentationTestMixin:
),
line,
)
- elif (line.startswith(_InstrumentationStructurePrefixes.RESULT) or
- _InstrumentationStructurePrefixes.FAILED in line):
+ elif (
+ line.startswith(_InstrumentationStructurePrefixes.RESULT)
+ or _InstrumentationStructurePrefixes.FAILED in line
+ ):
return self._parse_result_block_line(
self._transition_instrumentation_block(
instrumentation_block,
@@ -882,7 +908,8 @@ class InstrumentationTestMixin:
"""
formatter = _InstrumentationBlockFormatter(instrumentation_block)
return formatter.has_completed_result_block_format(
- self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE)
+ self.DEFAULT_INSTRUMENTATION_ERROR_MESSAGE
+ )
def parse_instrumentation_options(self, parameters=None):
"""Returns the options for the instrumentation test from user_params.
@@ -904,17 +931,15 @@ class InstrumentationTestMixin:
filtered_parameters = {}
for parameter_key, parameter_value in parameters.items():
if parameter_key.startswith(self.DEFAULT_INSTRUMENTATION_OPTION_PREFIX):
- option_key = parameter_key[len(self.
- DEFAULT_INSTRUMENTATION_OPTION_PREFIX):]
+ option_key = parameter_key[
+ len(self.DEFAULT_INSTRUMENTATION_OPTION_PREFIX) :
+ ]
filtered_parameters[option_key] = parameter_value
return filtered_parameters
- def run_instrumentation_test(self,
- device,
- package,
- options=None,
- prefix=None,
- runner=None):
+ def run_instrumentation_test(
+ self, device, package, options=None, prefix=None, runner=None
+ ):
"""Runs instrumentation tests on a device and creates test records.
Args:
@@ -942,19 +967,23 @@ class InstrumentationTestMixin:
def parse_instrumentation(raw_line):
line = raw_line.rstrip().decode('utf-8')
logging.info(line)
- instrumentation_block[0] = self._parse_line(instrumentation_block[0],
- line)
+ instrumentation_block[0] = self._parse_line(
+ instrumentation_block[0], line
+ )
- device.adb.instrument(package=package,
- options=options,
- runner=runner,
- handler=parse_instrumentation)
+ device.adb.instrument(
+ package=package,
+ options=options,
+ runner=runner,
+ handler=parse_instrumentation,
+ )
return self._finish_parsing(instrumentation_block[0])
-class BaseInstrumentationTestClass(InstrumentationTestMixin,
- base_test.BaseTestClass):
+class BaseInstrumentationTestClass(
+ InstrumentationTestMixin, base_test.BaseTestClass
+):
"""Base class for all instrumentation test classes to inherit from.
This class extends the BaseTestClass to add functionality to run and parse
diff --git a/mobly/base_suite.py b/mobly/base_suite.py
index 6febcd8..06cdeed 100644
--- a/mobly/base_suite.py
+++ b/mobly/base_suite.py
@@ -14,6 +14,7 @@
import abc
+
class BaseSuite(abc.ABC):
"""Class used to define a Mobly suite.
diff --git a/mobly/base_test.py b/mobly/base_test.py
index 9bf4fcc..e5060af 100644
--- a/mobly/base_test.py
+++ b/mobly/base_test.py
@@ -78,12 +78,14 @@ def repeat(count, max_consecutive_error=None):
"""
if count <= 1:
raise ValueError(
- f'The `count` for `repeat` must be larger than 1, got "{count}".')
+ f'The `count` for `repeat` must be larger than 1, got "{count}".'
+ )
if max_consecutive_error is not None and max_consecutive_error > count:
raise ValueError(
f'The `max_consecutive_error` ({max_consecutive_error}) for `repeat` '
- f'must be smaller than `count` ({count}).')
+ f'must be smaller than `count` ({count}).'
+ )
def _outer_decorator(func):
setattr(func, ATTR_REPEAT_CNT, count)
@@ -192,8 +194,10 @@ class BaseTestClass:
self.tests = []
class_identifier = self.__class__.__name__
if configs.test_class_name_suffix:
- class_identifier = '%s_%s' % (class_identifier,
- configs.test_class_name_suffix)
+ class_identifier = '%s_%s' % (
+ class_identifier,
+ configs.test_class_name_suffix,
+ )
if self.TAG is None:
self.TAG = class_identifier
# Set params.
@@ -208,13 +212,13 @@ class BaseTestClass:
self.summary_writer = configs.summary_writer
self._generated_test_table = collections.OrderedDict()
self._controller_manager = controller_manager.ControllerManager(
- class_name=self.TAG, controller_configs=configs.controller_configs)
+ class_name=self.TAG, controller_configs=configs.controller_configs
+ )
self.controller_configs = self._controller_manager.controller_configs
- def unpack_userparams(self,
- req_param_names=None,
- opt_param_names=None,
- **kwargs):
+ def unpack_userparams(
+ self, req_param_names=None, opt_param_names=None, **kwargs
+ ):
"""An optional function that unpacks user defined parameters into
individual variables.
@@ -251,8 +255,9 @@ class BaseTestClass:
if hasattr(self, name):
continue
if name not in self.user_params:
- raise Error('Missing required user param "%s" in test '
- 'configuration.' % name)
+ raise Error(
+ 'Missing required user param "%s" in test configuration.' % name
+ )
setattr(self, name, self.user_params[name])
for name in opt_param_names:
if hasattr(self, name):
@@ -261,8 +266,8 @@ class BaseTestClass:
setattr(self, name, self.user_params[name])
else:
logging.warning(
- 'Missing optional user param "%s" in '
- 'configuration, continue.', name)
+ 'Missing optional user param "%s" in configuration, continue.', name
+ )
def register_controller(self, module, required=True, min_number=1):
"""Loads a controller module and returns its loaded devices.
@@ -337,15 +342,17 @@ class BaseTestClass:
* `required` is True and no corresponding config can be found.
* Any other error occurred in the registration process.
"""
- return self._controller_manager.register_controller(module, required,
- min_number)
+ return self._controller_manager.register_controller(
+ module, required, min_number
+ )
def _record_controller_info(self):
# Collect controller information and write to test result.
for record in self._controller_manager.get_controller_info_records():
self.results.add_controller_info_record(record)
- self.summary_writer.dump(record.to_dict(),
- records.TestSummaryEntryType.CONTROLLER_INFO)
+ self.summary_writer.dump(
+ record.to_dict(), records.TestSummaryEntryType.CONTROLLER_INFO
+ )
def _pre_run(self):
"""Proxy function to guarantee the base implementation of `pre_run` is
@@ -358,7 +365,8 @@ class BaseTestClass:
record = records.TestResultRecord(stage_name, self.TAG)
record.test_begin()
self.current_test_info = runtime_test_info.RuntimeTestInfo(
- stage_name, self.log_path, record)
+ stage_name, self.log_path, record
+ )
try:
with self._log_test_stage(stage_name):
self.pre_run()
@@ -371,8 +379,9 @@ class BaseTestClass:
logging.exception('%s failed for %s.', stage_name, self.TAG)
record.test_error(e)
self.results.add_class_error(record)
- self.summary_writer.dump(record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
return False
def pre_run(self):
@@ -411,7 +420,8 @@ class BaseTestClass:
class_record = records.TestResultRecord(STAGE_NAME_SETUP_CLASS, self.TAG)
class_record.test_begin()
self.current_test_info = runtime_test_info.RuntimeTestInfo(
- STAGE_NAME_SETUP_CLASS, self.log_path, class_record)
+ STAGE_NAME_SETUP_CLASS, self.log_path, class_record
+ )
expects.recorder.reset_internal_states(class_record)
try:
with self._log_test_stage(STAGE_NAME_SETUP_CLASS):
@@ -427,16 +437,18 @@ class BaseTestClass:
self.results.add_class_error(class_record)
self._exec_procedure_func(self._on_fail, class_record)
class_record.update_record()
- self.summary_writer.dump(class_record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ class_record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
self._skip_remaining_tests(e)
return self.results
if expects.recorder.has_error:
self._exec_procedure_func(self._on_fail, class_record)
class_record.test_error()
class_record.update_record()
- self.summary_writer.dump(class_record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ class_record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
self.results.add_class_error(class_record)
self._skip_remaining_tests(class_record.termination_signal.exception)
return self.results
@@ -460,7 +472,8 @@ class BaseTestClass:
record = records.TestResultRecord(stage_name, self.TAG)
record.test_begin()
self.current_test_info = runtime_test_info.RuntimeTestInfo(
- stage_name, self.log_path, record)
+ stage_name, self.log_path, record
+ )
expects.recorder.reset_internal_states(record)
try:
with self._log_test_stage(stage_name):
@@ -473,15 +486,17 @@ class BaseTestClass:
record.test_error(e)
record.update_record()
self.results.add_class_error(record)
- self.summary_writer.dump(record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
else:
if expects.recorder.has_error:
record.test_error()
record.update_record()
self.results.add_class_error(record)
- self.summary_writer.dump(record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
finally:
self._clean_up()
@@ -511,14 +526,18 @@ class BaseTestClass:
if parent_token == stage_name:
parent_token = self.TAG
logging.debug(
- TEST_STAGE_BEGIN_LOG_TEMPLATE.format(parent_token=parent_token,
- child_token=stage_name))
+ TEST_STAGE_BEGIN_LOG_TEMPLATE.format(
+ parent_token=parent_token, child_token=stage_name
+ )
+ )
try:
yield
finally:
logging.debug(
- TEST_STAGE_END_LOG_TEMPLATE.format(parent_token=parent_token,
- child_token=stage_name))
+ TEST_STAGE_END_LOG_TEMPLATE.format(
+ parent_token=parent_token, child_token=stage_name
+ )
+ )
def _setup_test(self, test_name):
"""Proxy function to guarantee the base implementation of setup_test is
@@ -647,8 +666,11 @@ class BaseTestClass:
except signals.TestAbortSignal:
raise
except Exception as e:
- logging.exception('Exception happened when executing %s for %s.',
- procedure_name, self.current_test_info.name)
+ logging.exception(
+ 'Exception happened when executing %s for %s.',
+ procedure_name,
+ self.current_test_info.name,
+ )
tr_record.add_error(procedure_name, e)
def record_data(self, content):
@@ -698,12 +720,14 @@ class BaseTestClass:
retry_name = f'{test_name}_retry_{i+1}'
new_record = records.TestResultRecord(retry_name, self.TAG)
new_record.retry_parent = previous_record
+ new_record.parent = (previous_record, records.TestParentType.RETRY)
previous_record = self.exec_one_test(retry_name, test_method, new_record)
if not should_retry(previous_record):
break
- def _exec_one_test_with_repeat(self, test_name, test_method, repeat_count,
- max_consecutive_error):
+ def _exec_one_test_with_repeat(
+ self, test_name, test_method, repeat_count, max_consecutive_error
+ ):
"""Repeatedly execute a test case.
This method performs the action defined by the `repeat` decorator.
@@ -726,21 +750,31 @@ class BaseTestClass:
if max_consecutive_error == 0:
max_consecutive_error = repeat_count
+ previous_record = None
for i in range(repeat_count):
new_test_name = f'{test_name}_{i}'
- record = self.exec_one_test(new_test_name, test_method)
- if record.result in [
+ new_record = records.TestResultRecord(new_test_name, self.TAG)
+ if i > 0:
+ new_record.parent = (previous_record, records.TestParentType.REPEAT)
+ previous_record = self.exec_one_test(
+ new_test_name, test_method, new_record
+ )
+ if previous_record.result in [
records.TestResultEnums.TEST_RESULT_FAIL,
records.TestResultEnums.TEST_RESULT_ERROR,
]:
consecutive_error_count += 1
else:
consecutive_error_count = 0
+
if consecutive_error_count == max_consecutive_error:
logging.error(
'Repeated test case "%s" has consecutively failed %d iterations, '
- 'aborting the remaining %d iterations.', test_name,
- consecutive_error_count, repeat_count - 1 - i)
+ 'aborting the remaining %d iterations.',
+ test_name,
+ consecutive_error_count,
+ repeat_count - 1 - i,
+ )
return
def exec_one_test(self, test_name, test_method, record=None):
@@ -768,7 +802,8 @@ class BaseTestClass:
tr_record.uid = getattr(test_method, 'uid', None)
tr_record.test_begin()
self.current_test_info = runtime_test_info.RuntimeTestInfo(
- test_name, self.log_path, tr_record)
+ test_name, self.log_path, tr_record
+ )
expects.recorder.reset_internal_states(tr_record)
logging.info('%s %s', TEST_CASE_TOKEN, test_name)
# Did teardown_test throw an error.
@@ -784,8 +819,9 @@ class BaseTestClass:
except (signals.TestPass, signals.TestAbortSignal, signals.TestSkip):
raise
except Exception:
- logging.exception('Exception occurred in %s.',
- self.current_test_info.name)
+ logging.exception(
+ 'Exception occurred in %s.', self.current_test_info.name
+ )
raise
finally:
before_count = expects.recorder.error_count
@@ -794,9 +830,11 @@ class BaseTestClass:
except signals.TestAbortSignal:
raise
except Exception as e:
- logging.exception('Exception occurred in %s of %s.',
- STAGE_NAME_TEARDOWN_TEST,
- self.current_test_info.name)
+ logging.exception(
+ 'Exception occurred in %s of %s.',
+ STAGE_NAME_TEARDOWN_TEST,
+ self.current_test_info.name,
+ )
tr_record.test_error()
tr_record.add_error(STAGE_NAME_TEARDOWN_TEST, e)
teardown_test_failed = True
@@ -831,32 +869,37 @@ class BaseTestClass:
finally:
tr_record.update_record()
try:
- if tr_record.result in (records.TestResultEnums.TEST_RESULT_ERROR,
- records.TestResultEnums.TEST_RESULT_FAIL):
+ if tr_record.result in (
+ records.TestResultEnums.TEST_RESULT_ERROR,
+ records.TestResultEnums.TEST_RESULT_FAIL,
+ ):
self._exec_procedure_func(self._on_fail, tr_record)
elif tr_record.result == records.TestResultEnums.TEST_RESULT_PASS:
self._exec_procedure_func(self._on_pass, tr_record)
elif tr_record.result == records.TestResultEnums.TEST_RESULT_SKIP:
self._exec_procedure_func(self._on_skip, tr_record)
finally:
- logging.info(RESULT_LINE_TEMPLATE, tr_record.test_name,
- tr_record.result)
+ logging.info(
+ RESULT_LINE_TEMPLATE, tr_record.test_name, tr_record.result
+ )
self.results.add_record(tr_record)
- self.summary_writer.dump(tr_record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ tr_record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
self.current_test_info = None
return tr_record
def _assert_function_names_in_stack(self, expected_func_names):
- """Asserts that the current stack contains any of the given function names.
- """
+ """Asserts that the current stack contains any of the given function names."""
current_frame = inspect.currentframe()
caller_frames = inspect.getouterframes(current_frame, 2)
for caller_frame in caller_frames[2:]:
if caller_frame[3] in expected_func_names:
return
- raise Error(f"'{caller_frames[1][3]}' cannot be called outside of the "
- f"following functions: {expected_func_names}.")
+ raise Error(
+ f"'{caller_frames[1][3]}' cannot be called outside of the "
+ f'following functions: {expected_func_names}.'
+ )
def generate_tests(self, test_logic, name_func, arg_sets, uid_func=None):
"""Generates tests in the test class.
@@ -884,20 +927,26 @@ class BaseTestClass:
is the corresponding UID.
"""
self._assert_function_names_in_stack(
- [STAGE_NAME_PRE_RUN, STAGE_NAME_SETUP_GENERATED_TESTS])
+ [STAGE_NAME_PRE_RUN, STAGE_NAME_SETUP_GENERATED_TESTS]
+ )
root_msg = 'During test generation of "%s":' % test_logic.__name__
for args in arg_sets:
test_name = name_func(*args)
if test_name in self.get_existing_test_names():
- raise Error('%s Test name "%s" already exists, cannot be duplicated!' %
- (root_msg, test_name))
+ raise Error(
+ '%s Test name "%s" already exists, cannot be duplicated!'
+ % (root_msg, test_name)
+ )
test_func = functools.partial(test_logic, *args)
# If the `test_logic` method is decorated by `retry` or `repeat`
# decorators, copy the attributes added by the decorators to the
# generated test methods as well, so the generated test methods
# also have the retry/repeat behavior.
- for attr_name in (ATTR_MAX_RETRY_CNT, ATTR_MAX_CONSEC_ERROR,
- ATTR_REPEAT_CNT):
+ for attr_name in (
+ ATTR_MAX_RETRY_CNT,
+ ATTR_MAX_CONSEC_ERROR,
+ ATTR_REPEAT_CNT,
+ ):
attr = getattr(test_logic, attr_name, None)
if attr is not None:
setattr(test_func, attr_name, attr)
@@ -927,8 +976,9 @@ class BaseTestClass:
except signals.TestAbortAll:
raise
except Exception:
- logging.exception('Exception happened when executing %s in %s.',
- func.__name__, self.TAG)
+ logging.exception(
+ 'Exception happened when executing %s in %s.', func.__name__, self.TAG
+ )
def get_existing_test_names(self):
"""Gets the names of existing tests in the class.
@@ -966,8 +1016,10 @@ class BaseTestClass:
test_methods = []
for test_name in test_names:
if not test_name.startswith('test_'):
- raise Error('Test method name %s does not follow naming '
- 'convention test_*, abort.' % test_name)
+ raise Error(
+ 'Test method name %s does not follow naming '
+ 'convention test_*, abort.' % test_name
+ )
if hasattr(self, test_name):
test_method = getattr(self, test_name)
elif test_name in self._generated_test_table:
@@ -992,8 +1044,9 @@ class BaseTestClass:
test_record = records.TestResultRecord(test_name, self.TAG)
test_record.test_skip(exception)
self.results.add_record(test_record)
- self.summary_writer.dump(test_record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ test_record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
def run(self, test_names=None):
"""Runs tests within a test class.
@@ -1029,8 +1082,10 @@ class BaseTestClass:
# No test method specified by user, execute all in test class.
test_names = self.get_existing_test_names()
self.results.requested = test_names
- self.summary_writer.dump(self.results.requested_test_names_dict(),
- records.TestSummaryEntryType.TEST_NAME_LIST)
+ self.summary_writer.dump(
+ self.results.requested_test_names_dict(),
+ records.TestSummaryEntryType.TEST_NAME_LIST,
+ )
tests = self._get_test_methods(test_names)
try:
setup_class_result = self._setup_class()
@@ -1042,11 +1097,13 @@ class BaseTestClass:
repeat_count = getattr(test_method, ATTR_REPEAT_CNT, 0)
max_retry_count = getattr(test_method, ATTR_MAX_RETRY_CNT, 0)
if max_retry_count:
- self._exec_one_test_with_retry(test_name, test_method,
- max_retry_count)
+ self._exec_one_test_with_retry(
+ test_name, test_method, max_retry_count
+ )
elif repeat_count:
- self._exec_one_test_with_repeat(test_name, test_method, repeat_count,
- max_consecutive_error)
+ self._exec_one_test_with_repeat(
+ test_name, test_method, repeat_count, max_consecutive_error
+ )
else:
self.exec_one_test(test_name, test_method)
return self.results
@@ -1063,8 +1120,9 @@ class BaseTestClass:
raise e
finally:
self._teardown_class()
- logging.info('Summary for test class %s: %s', self.TAG,
- self.results.summary_str())
+ logging.info(
+ 'Summary for test class %s: %s', self.TAG, self.results.summary_str()
+ )
def _clean_up(self):
"""The final stage of a test class execution."""
@@ -1072,7 +1130,8 @@ class BaseTestClass:
record = records.TestResultRecord(stage_name, self.TAG)
record.test_begin()
self.current_test_info = runtime_test_info.RuntimeTestInfo(
- stage_name, self.log_path, record)
+ stage_name, self.log_path, record
+ )
expects.recorder.reset_internal_states(record)
with self._log_test_stage(stage_name):
# Write controller info and summary to summary file.
@@ -1082,5 +1141,6 @@ class BaseTestClass:
record.test_error()
record.update_record()
self.results.add_class_error(record)
- self.summary_writer.dump(record.to_dict(),
- records.TestSummaryEntryType.RECORD)
+ self.summary_writer.dump(
+ record.to_dict(), records.TestSummaryEntryType.RECORD
+ )
diff --git a/mobly/config_parser.py b/mobly/config_parser.py
index 2f2da91..a9aae59 100644
--- a/mobly/config_parser.py
+++ b/mobly/config_parser.py
@@ -39,8 +39,9 @@ def _validate_test_config(test_config):
"""
required_key = keys.Config.key_testbed.value
if required_key not in test_config:
- raise MoblyConfigError('Required key %s missing in test config.' %
- required_key)
+ raise MoblyConfigError(
+ 'Required key %s missing in test config.' % required_key
+ )
def _validate_testbed_name(name):
@@ -60,8 +61,9 @@ def _validate_testbed_name(name):
name = str(name)
for char in name:
if char not in utils.valid_filename_chars:
- raise MoblyConfigError('Char "%s" is not allowed in test bed names.' %
- char)
+ raise MoblyConfigError(
+ 'Char "%s" is not allowed in test bed names.' % char
+ )
def _validate_testbed_configs(testbed_configs):
@@ -111,7 +113,8 @@ def load_test_config_file(test_config_path, tb_filters=None):
if len(tbs) != len(tb_filters):
raise MoblyConfigError(
'Expect to find %d test bed configs, found %d. Check if'
- ' you have the correct test bed names.' % (len(tb_filters), len(tbs)))
+ ' you have the correct test bed names.' % (len(tb_filters), len(tbs))
+ )
configs[keys.Config.key_testbed.value] = tbs
mobly_params = configs.get(keys.Config.key_mobly_params.value, {})
# Decide log path.
@@ -127,14 +130,17 @@ def load_test_config_file(test_config_path, tb_filters=None):
for original_bed_config in configs[keys.Config.key_testbed.value]:
test_run_config = TestRunConfig()
test_run_config.testbed_name = original_bed_config[
- keys.Config.key_testbed_name.value]
+ keys.Config.key_testbed_name.value
+ ]
# Deprecated, use testbed_name
test_run_config.test_bed_name = test_run_config.testbed_name
test_run_config.log_path = log_path
test_run_config.controller_configs = original_bed_config.get(
- keys.Config.key_testbed_controllers.value, {})
+ keys.Config.key_testbed_controllers.value, {}
+ )
test_run_config.user_params = original_bed_config.get(
- keys.Config.key_testbed_test_params.value, {})
+ keys.Config.key_testbed_test_params.value, {}
+ )
test_configs.append(test_run_config)
return test_configs
@@ -186,8 +192,7 @@ class TestRunConfig:
self.test_class_name_suffix = None
def copy(self):
- """Returns a deep copy of the current config.
- """
+ """Returns a deep copy of the current config."""
return copy.deepcopy(self)
def __str__(self):
diff --git a/mobly/controller_manager.py b/mobly/controller_manager.py
index f19da27..c4633e7 100644
--- a/mobly/controller_manager.py
+++ b/mobly/controller_manager.py
@@ -11,7 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-""" Module for Mobly controller management."""
+"""Module for Mobly controller management."""
import collections
import copy
import logging
@@ -41,12 +41,14 @@ def verify_controller_module(module):
for attr in required_attributes:
if not hasattr(module, attr):
raise signals.ControllerError(
- 'Module %s missing required controller module attribute'
- ' %s.' % (module.__name__, attr))
+ 'Module %s missing required controller module attribute %s.'
+ % (module.__name__, attr)
+ )
if not getattr(module, attr):
raise signals.ControllerError(
- 'Controller interface %s in %s cannot be null.' %
- (attr, module.__name__))
+ 'Controller interface %s in %s cannot be null.'
+ % (attr, module.__name__)
+ )
class ControllerManager:
@@ -62,7 +64,8 @@ class ControllerManager:
def __init__(self, class_name, controller_configs):
# Controller object management.
- self._controller_objects = collections.OrderedDict(
+ self._controller_objects = (
+ collections.OrderedDict()
) # controller_name: objects
self._controller_modules = {} # controller_name: module
self._class_name = class_name
@@ -102,16 +105,19 @@ class ControllerManager:
if module_ref_name in self._controller_objects:
raise signals.ControllerError(
'Controller module %s has already been registered. It cannot '
- 'be registered again.' % module_ref_name)
+ 'be registered again.' % module_ref_name
+ )
# Create controller objects.
module_config_name = module.MOBLY_CONTROLLER_CONFIG_NAME
if module_config_name not in self.controller_configs:
if required:
- raise signals.ControllerError('No corresponding config found for %s' %
- module_config_name)
+ raise signals.ControllerError(
+ 'No corresponding config found for %s' % module_config_name
+ )
logging.warning(
'No corresponding config found for optional controller %s',
- module_config_name)
+ module_config_name,
+ )
return None
try:
# Make a deep copy of the config to pass to the controller module,
@@ -122,24 +128,28 @@ class ControllerManager:
except Exception:
logging.exception(
'Failed to initialize objects for controller %s, abort!',
- module_config_name)
+ module_config_name,
+ )
raise
if not isinstance(objects, list):
raise signals.ControllerError(
- 'Controller module %s did not return a list of objects, abort.' %
- module_ref_name)
+ 'Controller module %s did not return a list of objects, abort.'
+ % module_ref_name
+ )
# Check we got enough controller objects to continue.
actual_number = len(objects)
if actual_number < min_number:
module.destroy(objects)
raise signals.ControllerError(
- 'Expected to get at least %d controller objects, got %d.' %
- (min_number, actual_number))
+ 'Expected to get at least %d controller objects, got %d.'
+ % (min_number, actual_number)
+ )
# Save a shallow copy of the list for internal usage, so tests can't
# affect internal registry by manipulating the object list.
self._controller_objects[module_ref_name] = copy.copy(objects)
- logging.debug('Found %d objects for controller %s', len(objects),
- module_config_name)
+ logging.debug(
+ 'Found %d objects for controller %s', len(objects), module_config_name
+ )
self._controller_modules[module_ref_name] = module
return objects
@@ -174,22 +184,27 @@ class ControllerManager:
controller_info = None
try:
controller_info = module.get_info(
- copy.copy(self._controller_objects[controller_module_name]))
+ copy.copy(self._controller_objects[controller_module_name])
+ )
except AttributeError:
logging.warning(
'No optional debug info found for controller '
- '%s. To provide it, implement `get_info`.', controller_module_name)
+ '%s. To provide it, implement `get_info`.',
+ controller_module_name,
+ )
try:
yaml.dump(controller_info)
except TypeError:
logging.warning(
'The info of controller %s in class "%s" is not '
- 'YAML serializable! Coercing it to string.', controller_module_name,
- self._class_name)
+ 'YAML serializable! Coercing it to string.',
+ controller_module_name,
+ self._class_name,
+ )
controller_info = str(controller_info)
- return records.ControllerInfoRecord(self._class_name,
- module.MOBLY_CONTROLLER_CONFIG_NAME,
- controller_info)
+ return records.ControllerInfoRecord(
+ self._class_name, module.MOBLY_CONTROLLER_CONFIG_NAME, controller_info
+ )
def get_controller_info_records(self):
"""Get the info records for all the controller objects in the manager.
@@ -204,7 +219,8 @@ class ControllerManager:
info_records = []
for controller_module_name in self._controller_objects.keys():
with expects.expect_no_raises(
- 'Failed to collect controller info from %s' % controller_module_name):
+ 'Failed to collect controller info from %s' % controller_module_name
+ ):
record = self._create_controller_info_record(controller_module_name)
if record:
info_records.append(record)
diff --git a/mobly/controllers/android_device.py b/mobly/controllers/android_device.py
index c093e3c..20c5762 100644
--- a/mobly/controllers/android_device.py
+++ b/mobly/controllers/android_device.py
@@ -14,6 +14,7 @@
import contextlib
import enum
+import functools
import logging
import os
import re
@@ -149,12 +150,17 @@ def _validate_device_existence(serials):
serials: list of strings, the serials of all the devices that are expected
to exist.
"""
- valid_ad_identifiers = (list_adb_devices() + list_adb_devices_by_usb_id() +
- list_fastboot_devices())
+ valid_ad_identifiers = (
+ list_adb_devices()
+ + list_adb_devices_by_usb_id()
+ + list_fastboot_devices()
+ )
for serial in serials:
if serial not in valid_ad_identifiers:
- raise Error(f'Android device serial "{serial}" is specified in '
- 'config but is not reachable.')
+ raise Error(
+ f'Android device serial "{serial}" is specified in '
+ 'config but is not reachable.'
+ )
def _start_services_on_ads(ads):
@@ -172,15 +178,18 @@ def _start_services_on_ads(ads):
if start_logcat:
ad.services.logcat.start()
except Exception:
- is_required = getattr(ad, KEY_DEVICE_REQUIRED,
- DEFAULT_VALUE_DEVICE_REQUIRED)
+ is_required = getattr(
+ ad, KEY_DEVICE_REQUIRED, DEFAULT_VALUE_DEVICE_REQUIRED
+ )
if is_required:
ad.log.exception('Failed to start some services, abort!')
destroy(ads)
raise
else:
- ad.log.exception('Skipping this optional device because some '
- 'services failed to start.')
+ ad.log.exception(
+ 'Skipping this optional device because some '
+ 'services failed to start.'
+ )
def parse_device_list(device_list_str, key=None):
@@ -201,7 +210,7 @@ def parse_device_list(device_list_str, key=None):
try:
clean_lines = str(device_list_str, 'utf-8').strip().split('\n')
except UnicodeDecodeError:
- logging.warning("unicode decode error, origin str: %s", device_list_str)
+ logging.warning('unicode decode error, origin str: %s', device_list_str)
raise
results = []
for line in clean_lines:
@@ -291,7 +300,8 @@ def get_instances_with_configs(configs):
serials.append(c['serial'])
except KeyError:
raise Error(
- 'Required value "serial" is missing in AndroidDevice config %s.' % c)
+ 'Required value "serial" is missing in AndroidDevice config %s.' % c
+ )
_validate_device_existence(serials)
results = []
for c in configs:
@@ -373,8 +383,9 @@ def get_devices(ads, **kwargs):
filtered = filter_devices(ads, _get_device_filter)
if not filtered:
- raise Error('Could not find a target device that matches condition: %s.' %
- kwargs)
+ raise Error(
+ 'Could not find a target device that matches condition: %s.' % kwargs
+ )
else:
return filtered
@@ -429,9 +440,9 @@ def take_bug_reports(ads, test_name=None, begin_time=None, destination=None):
begin_time = mobly_logger.sanitize_filename(str(begin_time))
def take_br(test_name, begin_time, ad, destination):
- ad.take_bug_report(test_name=test_name,
- begin_time=begin_time,
- destination=destination)
+ ad.take_bug_report(
+ test_name=test_name, begin_time=begin_time, destination=destination
+ )
args = [(test_name, begin_time, ad, destination) for ad in ads]
utils.concurrent_exec(take_br, args)
@@ -450,7 +461,10 @@ class BuildInfoConstants(enum.Enum):
BUILD_TYPE = 'build_type', 'ro.build.type'
BUILD_FINGERPRINT = 'build_fingerprint', 'ro.build.fingerprint'
BUILD_VERSION_CODENAME = 'build_version_codename', 'ro.build.version.codename'
- BUILD_VERSION_INCREMENTAL = 'build_version_incremental', 'ro.build.version.incremental'
+ BUILD_VERSION_INCREMENTAL = (
+ 'build_version_incremental',
+ 'ro.build.version.incremental',
+ )
BUILD_VERSION_SDK = 'build_version_sdk', 'ro.build.version.sdk'
BUILD_PRODUCT = 'build_product', 'ro.build.product'
BUILD_CHARACTERISTICS = 'build_characteristics', 'ro.build.characteristics'
@@ -494,11 +508,13 @@ class AndroidDevice:
self._serial = str(serial)
# logging.log_path only exists when this is used in an Mobly test run.
_log_path_base = utils.abs_path(getattr(logging, 'log_path', '/tmp/logs'))
- self._log_path = os.path.join(_log_path_base,
- 'AndroidDevice%s' % self._normalized_serial)
+ self._log_path = os.path.join(
+ _log_path_base, 'AndroidDevice%s' % self._normalized_serial
+ )
self._debug_tag = self._serial
- self.log = AndroidDeviceLoggerAdapter(logging.getLogger(),
- {'tag': self.debug_tag})
+ self.log = AndroidDeviceLoggerAdapter(
+ logging.getLogger(), {'tag': self.debug_tag}
+ )
self._build_info = None
self._is_rebooting = False
self.adb = adb.AdbProxy(serial)
@@ -506,11 +522,12 @@ class AndroidDevice:
if self.is_rootable:
self.root_adb()
self.services = service_manager.ServiceManager(self)
- self.services.register(SERVICE_NAME_LOGCAT,
- logcat.Logcat,
- start_service=False)
- self.services.register('snippets',
- snippet_management_service.SnippetManagementService)
+ self.services.register(
+ SERVICE_NAME_LOGCAT, logcat.Logcat, start_service=False
+ )
+ self.services.register(
+ 'snippets', snippet_management_service.SnippetManagementService
+ )
# Device info cache.
self._user_added_device_info = {}
@@ -544,7 +561,7 @@ class AndroidDevice:
'serial': self.serial,
'model': self.model,
'build_info': self.build_info,
- 'user_added_info': self._user_added_device_info
+ 'user_added_info': self._user_added_device_info,
}
return info
@@ -621,8 +638,7 @@ class AndroidDevice:
@property
def log_path(self):
- """A string that is the path for all logs collected from this device.
- """
+ """A string that is the path for all logs collected from this device."""
if not os.path.exists(self._log_path):
utils.create_dir(self._log_path)
return self._log_path
@@ -632,13 +648,15 @@ class AndroidDevice:
"""Setter for `log_path`, use with caution."""
if self.has_active_service:
raise DeviceError(
- self, 'Cannot change `log_path` when there is service running.')
+ self, 'Cannot change `log_path` when there is service running.'
+ )
old_path = self._log_path
if new_path == old_path:
return
if os.listdir(new_path):
- raise DeviceError(self,
- 'Logs already exist at %s, cannot override.' % new_path)
+ raise DeviceError(
+ self, 'Logs already exist at %s, cannot override.' % new_path
+ )
if os.path.exists(old_path):
# Remove new path so copytree doesn't complain.
shutil.rmtree(new_path, ignore_errors=True)
@@ -682,7 +700,8 @@ class AndroidDevice:
if self.has_active_service:
raise DeviceError(
self,
- 'Cannot change device serial number when there is service running.')
+ 'Cannot change device serial number when there is service running.',
+ )
if self._debug_tag == self.serial:
self._debug_tag = new_serial
self._serial = new_serial
@@ -802,21 +821,20 @@ class AndroidDevice:
build_info = self.adb.getprops(CACHED_SYSTEM_PROPS)
for build_info_constant in BuildInfoConstants:
info[build_info_constant.build_info_key] = build_info.get(
- build_info_constant.system_prop_key, '')
+ build_info_constant.system_prop_key, ''
+ )
self._build_info = info
return info
return self._build_info
@property
def is_bootloader(self):
- """True if the device is in bootloader mode.
- """
+ """True if the device is in bootloader mode."""
return self.serial in list_fastboot_devices()
@property
def is_adb_root(self):
- """True if adb is running as root for this device.
- """
+ """True if adb is running as root for this device."""
try:
return '0' == self.adb.shell('id -u').decode('utf-8').strip()
except adb.AdbError:
@@ -828,10 +846,9 @@ class AndroidDevice:
def is_rootable(self):
return not self.is_bootloader and self.build_info['debuggable'] == '1'
- @property
+ @functools.cached_property
def model(self):
- """The Android code name for the device.
- """
+ """The Android code name for the device."""
# If device is in bootloader mode, get mode name from fastboot.
if self.is_bootloader:
out = self.fastboot.getvar('product').strip()
@@ -886,8 +903,10 @@ class AndroidDevice:
for k, v in config.items():
if hasattr(self, k) and k not in _ANDROID_DEVICE_SETTABLE_PROPS:
raise DeviceError(
- self, ('Attribute %s already exists with value %s, cannot set '
- 'again.') % (k, getattr(self, k)))
+ self,
+ 'Attribute %s already exists with value %s, cannot set again.'
+ % (k, getattr(self, k)),
+ )
setattr(self, k, v)
def root_adb(self):
@@ -928,10 +947,9 @@ class AndroidDevice:
if hasattr(self, name):
raise SnippetError(
self,
- 'Attribute "%s" already exists, please use a different name.' % name)
- self.services.snippets.add_snippet_client(
- name, package, config=config
- )
+ 'Attribute "%s" already exists, please use a different name.' % name,
+ )
+ self.services.snippets.add_snippet_client(name, package, config=config)
def unload_snippet(self, name):
"""Stops a snippet apk.
@@ -944,10 +962,9 @@ class AndroidDevice:
"""
self.services.snippets.remove_snippet_client(name)
- def generate_filename(self,
- file_type,
- time_identifier=None,
- extension_name=None):
+ def generate_filename(
+ self, file_type, time_identifier=None, extension_name=None
+ ):
"""Generates a name for an output file related to this device.
The name follows the pattern:
@@ -984,11 +1001,9 @@ class AndroidDevice:
self.log.debug('Generated filename: %s', filename_str)
return filename_str
- def take_bug_report(self,
- test_name=None,
- begin_time=None,
- timeout=300,
- destination=None):
+ def take_bug_report(
+ self, test_name=None, begin_time=None, timeout=300, destination=None
+ ):
"""Takes a bug report on the device and stores it in a file.
Args:
@@ -1056,8 +1071,9 @@ class AndroidDevice:
"""
filename = self.generate_filename(prefix, extension_name='png')
device_path = os.path.join('/storage/emulated/0/', filename)
- self.adb.shell(['screencap', '-p', device_path],
- timeout=TAKE_SCREENSHOT_TIMEOUT_SECOND)
+ self.adb.shell(
+ ['screencap', '-p', device_path], timeout=TAKE_SCREENSHOT_TIMEOUT_SECOND
+ )
utils.create_dir(destination)
self.adb.pull([device_path, destination])
pic_path = os.path.join(destination, filename)
@@ -1086,8 +1102,9 @@ class AndroidDevice:
return False, clean_out
return True, clean_out
- def wait_for_boot_completion(self,
- timeout=DEFAULT_TIMEOUT_BOOT_COMPLETION_SECOND):
+ def wait_for_boot_completion(
+ self, timeout=DEFAULT_TIMEOUT_BOOT_COMPLETION_SECOND
+ ):
"""Waits for Android framework to broadcast ACTION_BOOT_COMPLETED.
This function times out after 15 minutes.
diff --git a/mobly/controllers/android_device_lib/adb.py b/mobly/controllers/android_device_lib/adb.py
index 8b55b65..721dcc7 100644
--- a/mobly/controllers/android_device_lib/adb.py
+++ b/mobly/controllers/android_device_lib/adb.py
@@ -33,7 +33,9 @@ ADB_ROOT_RETRY_ATTEMPTS = 3
ADB_ROOT_RETRY_ATTEMPT_INTERVAL_SEC = 10
# Qualified class name of the default instrumentation test runner.
-DEFAULT_INSTRUMENTATION_RUNNER = 'com.android.common.support.test.runner.AndroidJUnitRunner'
+DEFAULT_INSTRUMENTATION_RUNNER = (
+ 'com.android.common.support.test.runner.AndroidJUnitRunner'
+)
# `adb shell getprop` can take surprisingly long, when the device is a
# networked virtual device.
@@ -43,7 +45,8 @@ DEFAULT_GETPROPS_RETRY_SLEEP_SEC = 1
# The regex pattern indicating the `adb connect` command did not fail.
PATTERN_ADB_CONNECT_SUCCESS = re.compile(
- r'^connected to .*|^already connected to .*')
+ r'^connected to .*|^already connected to .*'
+)
class Error(Exception):
@@ -72,9 +75,12 @@ class AdbError(Error):
self.serial = serial
def __str__(self):
- return ('Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s') % (
- utils.cli_cmd_to_string(
- self.cmd), self.ret_code, self.stdout, self.stderr)
+ return 'Error executing adb cmd "%s". ret: %d, stdout: %s, stderr: %s' % (
+ utils.cli_cmd_to_string(self.cmd),
+ self.ret_code,
+ self.stdout,
+ self.stderr,
+ )
class AdbTimeoutError(Error):
@@ -96,7 +102,9 @@ class AdbTimeoutError(Error):
def __str__(self):
return 'Timed out executing command "%s" after %ss.' % (
- utils.cli_cmd_to_string(self.cmd), self.timeout)
+ utils.cli_cmd_to_string(self.cmd),
+ self.timeout,
+ )
def is_adb_available():
@@ -190,16 +198,19 @@ class AdbProxy:
if stderr:
stderr.write(err)
- logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
- utils.cli_cmd_to_string(args), out, err, ret)
+ logging.debug(
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ utils.cli_cmd_to_string(args),
+ out,
+ err,
+ ret,
+ )
if ret == 0:
return out
else:
- raise AdbError(cmd=args,
- stdout=out,
- stderr=err,
- ret_code=ret,
- serial=self.serial)
+ raise AdbError(
+ cmd=args, stdout=out, stderr=err, ret_code=ret, serial=self.serial
+ )
def _execute_and_process_stdout(self, args, shell, handler) -> bytes:
"""Executes adb commands and processes the stdout with a handler.
@@ -217,11 +228,13 @@ class AdbProxy:
Raises:
AdbError: The adb command exit code is not 0.
"""
- proc = subprocess.Popen(args,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=shell,
- bufsize=1)
+ proc = subprocess.Popen(
+ args,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=shell,
+ bufsize=1,
+ )
out = '[elided, processed via handler]'
try:
# Even if the process dies, stdout.readline still works
@@ -241,8 +254,13 @@ class AdbProxy:
handler(line)
ret = proc.returncode
- logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
- utils.cli_cmd_to_string(args), out, err, ret)
+ logging.debug(
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ utils.cli_cmd_to_string(args),
+ out,
+ err,
+ ret,
+ )
if ret == 0:
return err
else:
@@ -291,12 +309,13 @@ class AdbProxy:
out = self._exec_cmd(adb_cmd, shell=shell, timeout=timeout, stderr=stderr)
return out
- def _execute_adb_and_process_stdout(self, name, args, shell,
- handler) -> bytes:
+ def _execute_adb_and_process_stdout(
+ self, name, args, shell, handler
+ ) -> bytes:
adb_cmd = self._construct_adb_cmd(name, args, shell=shell)
- err = self._execute_and_process_stdout(adb_cmd,
- shell=shell,
- handler=handler)
+ err = self._execute_and_process_stdout(
+ adb_cmd, shell=shell, handler=handler
+ )
return err
def _parse_getprop_output(self, output):
@@ -357,16 +376,13 @@ class AdbProxy:
Raises:
AdbError: if the connection failed.
"""
- stdout = self._exec_adb_cmd('connect',
- address,
- shell=False,
- timeout=None,
- stderr=None)
+ stdout = self._exec_adb_cmd(
+ 'connect', address, shell=False, timeout=None, stderr=None
+ )
if PATTERN_ADB_CONNECT_SUCCESS.match(stdout.decode('utf-8')) is None:
- raise AdbError(cmd=f'connect {address}',
- stdout=stdout,
- stderr='',
- ret_code=0)
+ raise AdbError(
+ cmd=f'connect {address}', stdout=stdout, stderr='', ret_code=0
+ )
return stdout
def getprop(self, prop_name, timeout=DEFAULT_GETPROP_TIMEOUT_SEC):
@@ -383,8 +399,11 @@ class AdbProxy:
A string that is the value of the property, or None if the property
doesn't exist.
"""
- return self.shell(['getprop', prop_name],
- timeout=timeout).decode('utf-8').strip()
+ return (
+ self.shell(['getprop', prop_name], timeout=timeout)
+ .decode('utf-8')
+ .strip()
+ )
def getprops(self, prop_names):
"""Get multiple properties of the device.
@@ -436,17 +455,19 @@ class AdbProxy:
def forward(self, args=None, shell=False) -> bytes:
with ADB_PORT_LOCK:
- return self._exec_adb_cmd('forward',
- args,
- shell,
- timeout=None,
- stderr=None)
-
- def instrument(self,
- package,
- options=None,
- runner=None,
- handler=None) -> bytes:
+ return self._exec_adb_cmd(
+ 'forward', args, shell, timeout=None, stderr=None
+ )
+
+ def reverse(self, args=None, shell=False) -> bytes:
+ with ADB_PORT_LOCK:
+ return self._exec_adb_cmd(
+ 'reverse', args, shell, timeout=None, stderr=None
+ )
+
+ def instrument(
+ self, package, options=None, runner=None, handler=None
+ ) -> bytes:
"""Runs an instrumentation command on the device.
This is a convenience wrapper to avoid parameter formatting.
@@ -487,21 +508,28 @@ class AdbProxy:
options_list.append('-e %s %s' % (option_key, option_value))
options_string = ' '.join(options_list)
- instrumentation_command = 'am instrument -r -w %s %s/%s' % (options_string,
- package, runner)
- logging.info('AndroidDevice|%s: Executing adb shell %s', self.serial,
- instrumentation_command)
+ instrumentation_command = 'am instrument -r -w %s %s/%s' % (
+ options_string,
+ package,
+ runner,
+ )
+ logging.info(
+ 'AndroidDevice|%s: Executing adb shell %s',
+ self.serial,
+ instrumentation_command,
+ )
if handler is None:
- return self._exec_adb_cmd('shell',
- instrumentation_command,
- shell=False,
- timeout=None,
- stderr=None)
+ return self._exec_adb_cmd(
+ 'shell',
+ instrumentation_command,
+ shell=False,
+ timeout=None,
+ stderr=None,
+ )
else:
- return self._execute_adb_and_process_stdout('shell',
- instrumentation_command,
- shell=False,
- handler=handler)
+ return self._execute_adb_and_process_stdout(
+ 'shell', instrumentation_command, shell=False, handler=handler
+ )
def root(self) -> bytes:
"""Enables ADB root mode on the device.
@@ -520,16 +548,18 @@ class AdbProxy:
retry_interval = ADB_ROOT_RETRY_ATTEMPT_INTERVAL_SEC
for attempt in range(ADB_ROOT_RETRY_ATTEMPTS):
try:
- return self._exec_adb_cmd('root',
- args=None,
- shell=False,
- timeout=None,
- stderr=None)
+ return self._exec_adb_cmd(
+ 'root', args=None, shell=False, timeout=None, stderr=None
+ )
except AdbError as e:
if attempt + 1 < ADB_ROOT_RETRY_ATTEMPTS:
- logging.debug('Retry the command "%s" since Error "%s" occurred.' %
- (utils.cli_cmd_to_string(
- e.cmd), e.stderr.decode('utf-8').strip()))
+ logging.debug(
+ 'Retry the command "%s" since Error "%s" occurred.'
+ % (
+ utils.cli_cmd_to_string(e.cmd),
+ e.stderr.decode('utf-8').strip(),
+ )
+ )
# Buffer between "adb root" commands.
time.sleep(retry_interval)
retry_interval *= 2
@@ -537,7 +567,6 @@ class AdbProxy:
raise e
def __getattr__(self, name):
-
def adb_call(args=None, shell=False, timeout=None, stderr=None) -> bytes:
"""Wrapper for an ADB command.
@@ -554,10 +583,8 @@ class AdbProxy:
Returns:
The output of the adb command run if exit code is 0.
"""
- return self._exec_adb_cmd(name,
- args,
- shell=shell,
- timeout=timeout,
- stderr=stderr)
+ return self._exec_adb_cmd(
+ name, args, shell=shell, timeout=timeout, stderr=stderr
+ )
return adb_call
diff --git a/mobly/controllers/android_device_lib/callback_handler.py b/mobly/controllers/android_device_lib/callback_handler.py
index c783b71..711c92a 100644
--- a/mobly/controllers/android_device_lib/callback_handler.py
+++ b/mobly/controllers/android_device_lib/callback_handler.py
@@ -21,7 +21,8 @@ from mobly.snippet import errors
logging.warning(
'The module mobly.controllers.android_device_lib.callback_handler is '
'deprecated and will be removed in a future version. Use module '
- 'mobly.controllers.android_device_lib.callback_handler_v2 instead.')
+ 'mobly.controllers.android_device_lib.callback_handler_v2 instead.'
+)
# The max timeout cannot be larger than the max time the socket waits for a
# response message. Otherwise, the socket would timeout before the Rpc call
@@ -91,8 +92,9 @@ class CallbackHandler:
"""
# Convert to milliseconds for Java side.
timeout_ms = int(timeout * 1000)
- return self._event_client.eventWaitAndGet(callback_id, event_name,
- timeout_ms)
+ return self._event_client.eventWaitAndGet(
+ callback_id, event_name, timeout_ms
+ )
def _callEventGetAll(self, callback_id, event_name):
"""Calls snippet lib's eventGetAll.
@@ -128,15 +130,19 @@ class CallbackHandler:
if timeout:
if timeout > MAX_TIMEOUT:
raise Error(
- self._ad, 'Specified timeout %s is longer than max timeout %s.' %
- (timeout, MAX_TIMEOUT))
+ self._ad,
+ 'Specified timeout %s is longer than max timeout %s.'
+ % (timeout, MAX_TIMEOUT),
+ )
try:
raw_event = self._callEventWaitAndGet(self._id, event_name, timeout)
except Exception as e:
if 'EventSnippetException: timeout.' in str(e):
raise TimeoutError(
- self._ad, 'Timed out after waiting %ss for event "%s" triggered by'
- ' %s (%s).' % (timeout, event_name, self._method_name, self._id))
+ self._ad,
+ 'Timed out after waiting %ss for event "%s" triggered by %s (%s).'
+ % (timeout, event_name, self._method_name, self._id),
+ )
raise
return snippet_event.from_dict(raw_event)
@@ -186,7 +192,8 @@ class CallbackHandler:
raise TimeoutError(
self._ad,
'Timed out after %ss waiting for an "%s" event that satisfies the '
- 'predicate "%s".' % (timeout, event_name, predicate.__name__))
+ 'predicate "%s".' % (timeout, event_name, predicate.__name__),
+ )
def getAll(self, event_name):
"""Gets all the events of a certain name that have been received so
diff --git a/mobly/controllers/android_device_lib/callback_handler_v2.py b/mobly/controllers/android_device_lib/callback_handler_v2.py
index 5675f7a..d1f9e8f 100644
--- a/mobly/controllers/android_device_lib/callback_handler_v2.py
+++ b/mobly/controllers/android_device_lib/callback_handler_v2.py
@@ -42,14 +42,19 @@ class CallbackHandlerV2(callback_handler_base.CallbackHandlerBase):
"""
timeout_ms = int(timeout_sec * 1000)
try:
- return self._event_client.eventWaitAndGet(callback_id, event_name,
- timeout_ms)
+ return self._event_client.eventWaitAndGet(
+ callback_id, event_name, timeout_ms
+ )
except Exception as e:
if TIMEOUT_ERROR_MESSAGE in str(e):
raise errors.CallbackHandlerTimeoutError(
- self._device, (f'Timed out after waiting {timeout_sec}s for event '
- f'"{event_name}" triggered by {self._method_name} '
- f'({self.callback_id}).')) from e
+ self._device,
+ (
+ f'Timed out after waiting {timeout_sec}s for event '
+ f'"{event_name}" triggered by {self._method_name} '
+ f'({self.callback_id}).'
+ ),
+ ) from e
raise
def callEventGetAllRpc(self, callback_id, event_name):
diff --git a/mobly/controllers/android_device_lib/errors.py b/mobly/controllers/android_device_lib/errors.py
index 9434cbc..1f9156e 100644
--- a/mobly/controllers/android_device_lib/errors.py
+++ b/mobly/controllers/android_device_lib/errors.py
@@ -42,6 +42,7 @@ class ServiceError(DeviceError):
A service is inherently associated with a device instance, so the service
error type is a subtype of `DeviceError`.
"""
+
SERVICE_TYPE = None
def __init__(self, device, msg):
diff --git a/mobly/controllers/android_device_lib/event_dispatcher.py b/mobly/controllers/android_device_lib/event_dispatcher.py
index 26db911..80610ef 100644
--- a/mobly/controllers/android_device_lib/event_dispatcher.py
+++ b/mobly/controllers/android_device_lib/event_dispatcher.py
@@ -25,18 +25,15 @@ class EventDispatcherError(Exception):
class IllegalStateError(EventDispatcherError):
- """Raise when user tries to put event_dispatcher into an illegal state.
- """
+ """Raise when user tries to put event_dispatcher into an illegal state."""
class DuplicateError(EventDispatcherError):
- """Raise when a duplicate is being created and it shouldn't.
- """
+ """Raise when a duplicate is being created and it shouldn't."""
class EventDispatcher:
- """Class managing events for an sl4a connection.
- """
+ """Class managing events for an sl4a connection."""
DEFAULT_TIMEOUT = 60
@@ -69,11 +66,11 @@ class EventDispatcher:
raise
if not event_obj:
continue
- elif 'name' not in event_obj:
+ elif "name" not in event_obj:
print("Received Malformed event {}".format(event_obj))
continue
else:
- event_name = event_obj['name']
+ event_name = event_obj["name"]
# if handler registered, process event
if event_name in self.handlers:
self.handle_subscribed_event(event_obj, event_name)
@@ -107,13 +104,13 @@ class EventDispatcher:
handler for one type of event.
"""
if self.started:
- raise IllegalStateError(("Can't register service after polling is"
- " started"))
+ raise IllegalStateError("Can't register service after polling is started")
self.lock.acquire()
try:
if event_name in self.handlers:
raise DuplicateError(
- 'A handler for {} already exists'.format(event_name))
+ "A handler for {} already exists".format(event_name)
+ )
self.handlers[event_name] = (handler, args)
finally:
self.lock.release()
@@ -194,15 +191,13 @@ class EventDispatcher:
# Block forever on event wait
return e_queue.get(True)
except queue.Empty:
- raise queue.Empty('Timeout after {}s waiting for event: {}'.format(
- timeout, event_name))
-
- def wait_for_event(self,
- event_name,
- predicate,
- timeout=DEFAULT_TIMEOUT,
- *args,
- **kwargs):
+ raise queue.Empty(
+ "Timeout after {}s waiting for event: {}".format(timeout, event_name)
+ )
+
+ def wait_for_event(
+ self, event_name, predicate, timeout=DEFAULT_TIMEOUT, *args, **kwargs
+ ):
"""Wait for an event that satisfies a predicate to appear.
Continuously pop events of a particular name and check against the
@@ -238,8 +233,11 @@ class EventDispatcher:
return event
if time.perf_counter() > deadline:
- raise queue.Empty('Timeout after {}s waiting for event: {}'.format(
- timeout, event_name))
+ raise queue.Empty(
+ "Timeout after {}s waiting for event: {}".format(
+ timeout, event_name
+ )
+ )
def pop_events(self, regex_pattern, timeout):
"""Pop events whose names match a regex pattern.
@@ -275,10 +273,13 @@ class EventDispatcher:
break
time.sleep(1)
if len(results) == 0:
- raise queue.Empty('Timeout after {}s waiting for event: {}'.format(
- timeout, regex_pattern))
+ raise queue.Empty(
+ "Timeout after {}s waiting for event: {}".format(
+ timeout, regex_pattern
+ )
+ )
- return sorted(results, key=lambda event: event['time'])
+ return sorted(results, key=lambda event: event["time"])
def _match_and_pop(self, regex_pattern):
"""Pop one event from each of the event queues whose names
@@ -331,8 +332,15 @@ class EventDispatcher:
handler, args = self.handlers[event_name]
self.executor.submit(handler, event_obj, *args)
- def _handle(self, event_handler, event_name, user_args, event_timeout, cond,
- cond_timeout):
+ def _handle(
+ self,
+ event_handler,
+ event_name,
+ user_args,
+ event_timeout,
+ cond,
+ cond_timeout,
+ ):
"""Pop an event of specified type and calls its handler on it. If
condition is not None, block until condition is met or timeout.
"""
@@ -341,13 +349,15 @@ class EventDispatcher:
event = self.pop_event(event_name, event_timeout)
return event_handler(event, *user_args)
- def handle_event(self,
- event_handler,
- event_name,
- user_args,
- event_timeout=None,
- cond=None,
- cond_timeout=None):
+ def handle_event(
+ self,
+ event_handler,
+ event_name,
+ user_args,
+ event_timeout=None,
+ cond=None,
+ cond_timeout=None,
+ ):
"""Handle events that don't have registered handlers
In a new thread, poll one event of specified type from its queue and
@@ -371,8 +381,15 @@ class EventDispatcher:
If blocking call worker.result() is triggered, the handler
needs to return something to unblock.
"""
- worker = self.executor.submit(self._handle, event_handler, event_name,
- user_args, event_timeout, cond, cond_timeout)
+ worker = self.executor.submit(
+ self._handle,
+ event_handler,
+ event_name,
+ user_args,
+ event_timeout,
+ cond,
+ cond_timeout,
+ )
return worker
def pop_all(self, event_name):
@@ -392,8 +409,7 @@ class EventDispatcher:
starts polling.
"""
if not self.started:
- raise IllegalStateError(("Dispatcher needs to be started before "
- "popping."))
+ raise IllegalStateError("Dispatcher needs to be started before popping.")
results = []
try:
self.lock.acquire()
diff --git a/mobly/controllers/android_device_lib/fastboot.py b/mobly/controllers/android_device_lib/fastboot.py
index 1ef4969..cac08f1 100644
--- a/mobly/controllers/android_device_lib/fastboot.py
+++ b/mobly/controllers/android_device_lib/fastboot.py
@@ -37,14 +37,19 @@ def exe_cmd(*cmds):
proc = Popen(cmd, stdout=PIPE, stderr=PIPE, shell=True)
(out, err) = proc.communicate()
ret = proc.returncode
- logging.debug('cmd: %s, stdout: %s, stderr: %s, ret: %s',
- utils.cli_cmd_to_string(cmds), out, err, ret)
+ logging.debug(
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ utils.cli_cmd_to_string(cmds),
+ out,
+ err,
+ ret,
+ )
if not err:
return out
return err
-class FastbootProxy():
+class FastbootProxy:
"""Proxy class for fastboot.
For syntactic reasons, the '-' in fastboot commands need to be replaced
@@ -53,12 +58,12 @@ class FastbootProxy():
>> fb.devices() # will return the console output of "fastboot devices".
"""
- def __init__(self, serial=""):
+ def __init__(self, serial=''):
self.serial = serial
if serial:
- self.fastboot_str = "fastboot -s {}".format(serial)
+ self.fastboot_str = 'fastboot -s {}'.format(serial)
else:
- self.fastboot_str = "fastboot"
+ self.fastboot_str = 'fastboot'
def _exec_fastboot_cmd(self, name, arg_str):
return exe_cmd(' '.join((self.fastboot_str, name, arg_str)))
@@ -67,7 +72,6 @@ class FastbootProxy():
return exe_cmd(' '.join((self.fastboot_str,) + args))
def __getattr__(self, name):
-
def fastboot_call(*args):
clean_name = name.replace('_', '-')
arg_str = ' '.join(str(elem) for elem in args)
diff --git a/mobly/controllers/android_device_lib/jsonrpc_client_base.py b/mobly/controllers/android_device_lib/jsonrpc_client_base.py
index 7f27fa5..d272782 100644
--- a/mobly/controllers/android_device_lib/jsonrpc_client_base.py
+++ b/mobly/controllers/android_device_lib/jsonrpc_client_base.py
@@ -86,6 +86,7 @@ class JsonRpcCommand:
INIT: Initializes a new session.
CONTINUE: Creates a connection.
"""
+
INIT = 'initiate'
CONTINUE = 'continue'
@@ -203,16 +204,20 @@ class JsonRpcClientBase(abc.ABC):
"""
self._counter = self._id_counter()
try:
- self._conn = socket.create_connection(('localhost', self.host_port),
- _SOCKET_CONNECTION_TIMEOUT)
+ self._conn = socket.create_connection(
+ ('localhost', self.host_port), _SOCKET_CONNECTION_TIMEOUT
+ )
except ConnectionRefusedError as err:
# Retry using '127.0.0.1' for IPv4 enabled machines that only resolve
# 'localhost' to '[::1]'.
self.log.debug(
'Failed to connect to localhost, trying 127.0.0.1: {}'.format(
- str(err)))
- self._conn = socket.create_connection(('127.0.0.1', self.host_port),
- _SOCKET_CONNECTION_TIMEOUT)
+ str(err)
+ )
+ )
+ self._conn = socket.create_connection(
+ ('127.0.0.1', self.host_port), _SOCKET_CONNECTION_TIMEOUT
+ )
self._conn.settimeout(_SOCKET_READ_TIMEOUT)
self._client = self._conn.makefile(mode='brw')
@@ -248,8 +253,7 @@ class JsonRpcClientBase(abc.ABC):
self._conn = None
def clear_host_port(self):
- """Stops the adb port forwarding of the host port used by this client.
- """
+ """Stops the adb port forwarding of the host port used by this client."""
if self.host_port:
self._ad.adb.forward(['--remove', 'tcp:%d' % self.host_port])
self.host_port = None
@@ -264,13 +268,14 @@ class JsonRpcClientBase(abc.ABC):
Error: a socket error occurred during the send.
"""
try:
- self._client.write(msg.encode("utf8") + b'\n')
+ self._client.write(msg.encode('utf8') + b'\n')
self._client.flush()
self.log.debug('Snippet sent %s.', msg)
except socket.error as e:
raise Error(
self._ad,
- 'Encountered socket error "%s" sending RPC message "%s"' % (e, msg))
+ 'Encountered socket error "%s" sending RPC message "%s"' % (e, msg),
+ )
def _client_receive(self):
"""Receives the server's response of an Rpc message.
@@ -289,13 +294,16 @@ class JsonRpcClientBase(abc.ABC):
if _MAX_RPC_RESP_LOGGING_LENGTH >= len(response):
self.log.debug('Snippet received: %s', response)
else:
- self.log.debug('Snippet received: %s... %d chars are truncated',
- response[:_MAX_RPC_RESP_LOGGING_LENGTH],
- len(response) - _MAX_RPC_RESP_LOGGING_LENGTH)
+ self.log.debug(
+ 'Snippet received: %s... %d chars are truncated',
+ response[:_MAX_RPC_RESP_LOGGING_LENGTH],
+ len(response) - _MAX_RPC_RESP_LOGGING_LENGTH,
+ )
return response
except socket.error as e:
- raise Error(self._ad,
- 'Encountered socket error reading RPC response "%s"' % e)
+ raise Error(
+ self._ad, 'Encountered socket error reading RPC response "%s"' % e
+ )
def _cmd(self, command, uid=None):
"""Send a command to the server.
@@ -342,11 +350,13 @@ class JsonRpcClientBase(abc.ABC):
if result.get('callback') is not None:
if self._event_client is None:
self._event_client = self._start_event_client()
- return callback_handler.CallbackHandler(callback_id=result['callback'],
- event_client=self._event_client,
- ret_value=result['result'],
- method_name=method,
- ad=self._ad)
+ return callback_handler.CallbackHandler(
+ callback_id=result['callback'],
+ event_client=self._event_client,
+ ret_value=result['result'],
+ method_name=method,
+ ad=self._ad,
+ )
return result['result']
def disable_hidden_api_blacklist(self):
@@ -357,7 +367,8 @@ class JsonRpcClientBase(abc.ABC):
# in development report sdk_version 27, but still enforce the blacklist.
if self._ad.is_rootable and (sdk_version >= 28 or version_codename == 'P'):
self._ad.adb.shell(
- 'settings put global hidden_api_blacklist_exemptions "*"')
+ 'settings put global hidden_api_blacklist_exemptions "*"'
+ )
def __getattr__(self, name):
"""Wrapper for python magic to turn method calls into RPC calls."""
diff --git a/mobly/controllers/android_device_lib/jsonrpc_shell_base.py b/mobly/controllers/android_device_lib/jsonrpc_shell_base.py
index 3129f59..c6d395b 100755
--- a/mobly/controllers/android_device_lib/jsonrpc_shell_base.py
+++ b/mobly/controllers/android_device_lib/jsonrpc_shell_base.py
@@ -59,8 +59,11 @@ class JsonRpcShellBase:
elif len(serials) == 1:
serial = serials[0]
else:
- raise Error('Expected one phone, but %d found. Use the -s flag or '
- 'specify ANDROID_SERIAL.' % len(serials))
+ raise Error(
+ 'Expected one phone, but %d found. Use the -s flag or '
+ 'specify ANDROID_SERIAL.'
+ % len(serials)
+ )
if serial not in serials:
raise Error('Device "%s" is not found by adb.' % serial)
ads = android_device.get_instances([serial])
diff --git a/mobly/controllers/android_device_lib/service_manager.py b/mobly/controllers/android_device_lib/service_manager.py
index 983cff7..17d5a1f 100644
--- a/mobly/controllers/android_device_lib/service_manager.py
+++ b/mobly/controllers/android_device_lib/service_manager.py
@@ -74,11 +74,15 @@ class ServiceManager:
if not inspect.isclass(service_class):
raise Error(self._device, '"%s" is not a class!' % service_class)
if not issubclass(service_class, base_service.BaseService):
- raise Error(self._device,
- 'Class %s is not a subclass of BaseService!' % service_class)
+ raise Error(
+ self._device,
+ 'Class %s is not a subclass of BaseService!' % service_class,
+ )
if alias in self._service_objects:
- raise Error(self._device,
- 'A service is already registered with alias "%s".' % alias)
+ raise Error(
+ self._device,
+ 'A service is already registered with alias "%s".' % alias,
+ )
service_obj = service_class(self._device, configs)
service_obj.alias = alias
if start_service:
@@ -94,12 +98,14 @@ class ServiceManager:
alias: string, the alias of the service instance to unregister.
"""
if alias not in self._service_objects:
- raise Error(self._device,
- 'No service is registered with alias "%s".' % alias)
+ raise Error(
+ self._device, 'No service is registered with alias "%s".' % alias
+ )
service_obj = self._service_objects.pop(alias)
if service_obj.is_alive:
- with expects.expect_no_raises('Failed to stop service instance "%s".' %
- alias):
+ with expects.expect_no_raises(
+ 'Failed to stop service instance "%s".' % alias
+ ):
service_obj.stop()
def for_each(self, func):
@@ -111,8 +117,9 @@ class ServiceManager:
"""
aliases = list(self._service_objects.keys())
for alias in aliases:
- with expects.expect_no_raises('Failed to execute "%s" for service "%s".' %
- (func.__name__, alias)):
+ with expects.expect_no_raises(
+ 'Failed to execute "%s" for service "%s".' % (func.__name__, alias)
+ ):
func(self._service_objects[alias])
def list_live_services(self):
@@ -125,8 +132,11 @@ class ServiceManager:
list of strings, the aliases of the services that are running.
"""
aliases = []
- self.for_each(lambda service: aliases.append(service.alias)
- if service.is_alive else None)
+ self.for_each(
+ lambda service: aliases.append(service.alias)
+ if service.is_alive
+ else None
+ )
return aliases
def create_output_excerpts_all(self, test_info):
@@ -185,8 +195,9 @@ class ServiceManager:
if name not in self._service_objects:
raise Error(
self._device,
- 'No service is registered under the name "%s", cannot start.' %
- name)
+ 'No service is registered under the name "%s", cannot start.'
+ % name,
+ )
service = self._service_objects[name]
if not service.is_alive:
service.start()
@@ -235,8 +246,9 @@ class ServiceManager:
if name not in self._service_objects:
raise Error(
self._device,
- 'No service is registered under the name "%s", cannot resume.' %
- name)
+ 'No service is registered under the name "%s", cannot resume.'
+ % name,
+ )
service = self._service_objects[name]
service.resume()
diff --git a/mobly/controllers/android_device_lib/services/base_service.py b/mobly/controllers/android_device_lib/services/base_service.py
index 4739797..8706bf0 100644
--- a/mobly/controllers/android_device_lib/services/base_service.py
+++ b/mobly/controllers/android_device_lib/services/base_service.py
@@ -21,6 +21,7 @@ class BaseService(abc.ABC):
This class defines the interface for Mobly's AndroidDevice service.
"""
+
_alias = None
def __init__(self, device, configs=None):
diff --git a/mobly/controllers/android_device_lib/services/logcat.py b/mobly/controllers/android_device_lib/services/logcat.py
index 37a8454..04dcf9d 100644
--- a/mobly/controllers/android_device_lib/services/logcat.py
+++ b/mobly/controllers/android_device_lib/services/logcat.py
@@ -27,6 +27,7 @@ CREATE_LOGCAT_FILE_TIMEOUT_SEC = 5
class Error(errors.ServiceError):
"""Root error type for logcat service."""
+
SERVICE_TYPE = 'Logcat'
@@ -54,6 +55,7 @@ class Logcat(base_service.BaseService):
adb_logcat_file_path: string, path to the file that the service writes
adb logcat to by default.
"""
+
OUTPUT_FILE_TYPE = 'logcat'
def __init__(self, android_device, configs=None):
@@ -73,8 +75,10 @@ class Logcat(base_service.BaseService):
if not self._ad.is_rootable:
return
- logpersist_warning = ('%s encountered an error enabling persistent'
- ' logs, logs may not get saved.')
+ logpersist_warning = (
+ '%s encountered an error enabling persistent'
+ ' logs, logs may not get saved.'
+ )
# Android L and older versions do not have logpersist installed,
# so check that the logpersist scripts exists before trying to use
# them.
@@ -113,11 +117,13 @@ class Logcat(base_service.BaseService):
"""
dest_path = test_info.output_path
utils.create_dir(dest_path)
- filename = self._ad.generate_filename(self.OUTPUT_FILE_TYPE, test_info,
- 'txt')
+ filename = self._ad.generate_filename(
+ self.OUTPUT_FILE_TYPE, test_info, 'txt'
+ )
excerpt_file_path = os.path.join(dest_path, filename)
- with io.open(excerpt_file_path, 'w', encoding='utf-8',
- errors='replace') as out:
+ with io.open(
+ excerpt_file_path, 'w', encoding='utf-8', errors='replace'
+ ) as out:
# Devices may accidentally go offline during test,
# check not None before readline().
while self._adb_logcat_file_obj:
@@ -153,7 +159,8 @@ class Logcat(base_service.BaseService):
if self.is_alive:
raise Error(
self._ad,
- 'Logcat thread is already running, cannot start another one.')
+ 'Logcat thread is already running, cannot start another one.',
+ )
def update_config(self, new_config):
"""Updates the configuration for the service.
@@ -168,8 +175,11 @@ class Logcat(base_service.BaseService):
new_config: Config, the new config to use.
"""
self._assert_not_running()
- self._ad.log.info('[LogcatService] Changing config from %s to %s',
- self._config, new_config)
+ self._ad.log.info(
+ '[LogcatService] Changing config from %s to %s',
+ self._config,
+ new_config,
+ )
self._config = new_config
def _open_logcat_file(self):
@@ -181,13 +191,13 @@ class Logcat(base_service.BaseService):
deadline = time.perf_counter() + CREATE_LOGCAT_FILE_TIMEOUT_SEC
while not os.path.exists(self.adb_logcat_file_path):
if time.perf_counter() > deadline:
- raise Error(self._ad,
- 'Timeout while waiting for logcat file to be created.')
+ raise Error(
+ self._ad, 'Timeout while waiting for logcat file to be created.'
+ )
time.sleep(1)
- self._adb_logcat_file_obj = io.open(self.adb_logcat_file_path,
- 'r',
- encoding='utf-8',
- errors='replace')
+ self._adb_logcat_file_obj = io.open(
+ self.adb_logcat_file_path, 'r', encoding='utf-8', errors='replace'
+ )
self._adb_logcat_file_obj.seek(0, os.SEEK_END)
def _close_logcat_file(self):
@@ -203,7 +213,8 @@ class Logcat(base_service.BaseService):
"""
if self._ad.is_bootloader:
self._ad.log.warning(
- 'Skip starting logcat because the device is in fastboot mode.')
+ 'Skip starting logcat because the device is in fastboot mode.'
+ )
return
self._assert_not_running()
if self._config.clear_log:
@@ -218,8 +229,9 @@ class Logcat(base_service.BaseService):
self._close_logcat_file()
self.adb_logcat_file_path = self._config.output_file_path
if not self.adb_logcat_file_path:
- f_name = self._ad.generate_filename(self.OUTPUT_FILE_TYPE,
- extension_name='txt')
+ f_name = self._ad.generate_filename(
+ self.OUTPUT_FILE_TYPE, extension_name='txt'
+ )
logcat_file_path = os.path.join(self._ad.log_path, f_name)
self.adb_logcat_file_path = logcat_file_path
utils.create_dir(os.path.dirname(self.adb_logcat_file_path))
@@ -227,8 +239,11 @@ class Logcat(base_service.BaseService):
# double quotes in args if starting and ending with it.
# Add spaces at beginning and at last to fix this issue.
cmd = ' "%s" -s %s logcat -v threadtime -T 1 %s >> "%s" ' % (
- adb.ADB, self._ad.serial, self._config.logcat_params,
- self.adb_logcat_file_path)
+ adb.ADB,
+ self._ad.serial,
+ self._config.logcat_params,
+ self.adb_logcat_file_path,
+ )
process = utils.start_standing_subprocess(cmd, shell=True)
self._adb_logcat_process = process
diff --git a/mobly/controllers/android_device_lib/services/snippet_management_service.py b/mobly/controllers/android_device_lib/services/snippet_management_service.py
index 05e8cda..7da1b23 100644
--- a/mobly/controllers/android_device_lib/services/snippet_management_service.py
+++ b/mobly/controllers/android_device_lib/services/snippet_management_service.py
@@ -21,6 +21,7 @@ MISSING_SNIPPET_CLIENT_MSG = 'No snippet client is registered with name "%s".'
class Error(errors.ServiceError):
"""Root error type for snippet management service."""
+
SERVICE_TYPE = 'SnippetManagementService'
@@ -73,17 +74,23 @@ class SnippetManagementService(base_service.BaseService):
# Should not load snippet with the same name more than once.
if name in self._snippet_clients:
raise Error(
- self, 'Name "%s" is already registered with package "%s", it cannot '
- 'be used again.' % (name, self._snippet_clients[name].client.package))
+ self,
+ 'Name "%s" is already registered with package "%s", it cannot '
+ 'be used again.' % (name, self._snippet_clients[name].client.package),
+ )
# Should not load the same snippet package more than once.
for snippet_name, client in self._snippet_clients.items():
if package == client.package:
raise Error(
- self, 'Snippet package "%s" has already been loaded under name'
- ' "%s".' % (package, snippet_name))
+ self,
+ 'Snippet package "%s" has already been loaded under name "%s".'
+ % (package, snippet_name),
+ )
client = snippet_client_v2.SnippetClientV2(
- package=package, ad=self._device, config=config,
+ package=package,
+ ad=self._device,
+ config=config,
)
client.initialize()
self._snippet_clients[name] = client
@@ -111,7 +118,8 @@ class SnippetManagementService(base_service.BaseService):
else:
self._device.log.debug(
'Not startng SnippetClient<%s> because it is already alive.',
- client.package)
+ client.package,
+ )
def stop(self):
"""Stops all the snippet clients under management."""
@@ -122,7 +130,8 @@ class SnippetManagementService(base_service.BaseService):
else:
self._device.log.debug(
'Not stopping SnippetClient<%s> because it is not alive.',
- client.package)
+ client.package,
+ )
def pause(self):
"""Pauses all the snippet clients under management.
@@ -141,8 +150,9 @@ class SnippetManagementService(base_service.BaseService):
self._device.log.debug('Resuming SnippetClient<%s>.', client.package)
client.restore_server_connection()
else:
- self._device.log.debug('Not resuming SnippetClient<%s>.',
- client.package)
+ self._device.log.debug(
+ 'Not resuming SnippetClient<%s>.', client.package
+ )
def __getattr__(self, name):
client = self.get_snippet_client(name)
diff --git a/mobly/controllers/android_device_lib/sl4a_client.py b/mobly/controllers/android_device_lib/sl4a_client.py
index 725a61c..ac59f5b 100644
--- a/mobly/controllers/android_device_lib/sl4a_client.py
+++ b/mobly/controllers/android_device_lib/sl4a_client.py
@@ -24,7 +24,8 @@ _DEVICE_SIDE_PORT = 8080
_LAUNCH_CMD = (
'am start -a com.googlecode.android_scripting.action.LAUNCH_SERVER '
'--ei com.googlecode.android_scripting.extra.USE_SERVICE_PORT %s '
- 'com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher')
+ 'com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher'
+)
# Maximum time to wait for the app to start on the device (10 minutes).
# TODO: This timeout is set high in order to allow for retries in
# start_app_and_connect. Decrease it when the call to connect() has the option
@@ -59,7 +60,8 @@ class Sl4aClient(jsonrpc_client_base.JsonRpcClientBase):
out = self._adb.shell('pm list package')
if not utils.grep('com.googlecode.android_scripting', out):
raise jsonrpc_client_base.AppStartError(
- self._ad, '%s is not installed on %s' % (_APP_NAME, self._adb.serial))
+ self._ad, '%s is not installed on %s' % (_APP_NAME, self._adb.serial)
+ )
self.disable_hidden_api_blacklist()
# sl4a has problems connecting after disconnection, so kill the apk and
@@ -108,8 +110,9 @@ class Sl4aClient(jsonrpc_client_base.JsonRpcClientBase):
try:
self.closeSl4aSession()
except Exception:
- self.log.exception('Failed to gracefully shut down %s.',
- self.app_name)
+ self.log.exception(
+ 'Failed to gracefully shut down %s.', self.app_name
+ )
# Close the socket connection.
self.disconnect()
@@ -141,23 +144,25 @@ class Sl4aClient(jsonrpc_client_base.JsonRpcClientBase):
started = True
break
except Exception:
- self.log.debug('%s is not yet running, retrying',
- self.app_name,
- exc_info=True)
+ self.log.debug(
+ '%s is not yet running, retrying', self.app_name, exc_info=True
+ )
time.sleep(1)
if not started:
raise jsonrpc_client_base.AppRestoreConnectionError(
- self._ad, '%s failed to connect for %s at host port %s, '
- 'device port %s' %
- (self.app_name, self._adb.serial, self.host_port, self.device_port))
+ self._ad,
+ '%s failed to connect for %s at host port %s, device port %s'
+ % (self.app_name, self._adb.serial, self.host_port, self.device_port),
+ )
def _start_event_client(self):
# Start an EventDispatcher for the current sl4a session
event_client = Sl4aClient(self._ad)
event_client.host_port = self.host_port
event_client.device_port = self.device_port
- event_client.connect(uid=self.uid,
- cmd=jsonrpc_client_base.JsonRpcCommand.CONTINUE)
+ event_client.connect(
+ uid=self.uid, cmd=jsonrpc_client_base.JsonRpcCommand.CONTINUE
+ )
ed = event_dispatcher.EventDispatcher(event_client)
ed.start()
return ed
diff --git a/mobly/controllers/android_device_lib/snippet_client.py b/mobly/controllers/android_device_lib/snippet_client.py
index 42ae122..099f9c7 100644
--- a/mobly/controllers/android_device_lib/snippet_client.py
+++ b/mobly/controllers/android_device_lib/snippet_client.py
@@ -23,13 +23,16 @@ from mobly.controllers.android_device_lib import errors
from mobly.controllers.android_device_lib import jsonrpc_client_base
from mobly.snippet import errors as snippet_errors
-logging.warning('The module mobly.controllers.android_device_lib.snippet_client'
- ' is deprecated and will be removed in a future version. Use'
- ' module mobly.controllers.android_device_lib.snippet_client_v2'
- ' instead.')
+logging.warning(
+ 'The module mobly.controllers.android_device_lib.snippet_client'
+ ' is deprecated and will be removed in a future version. Use'
+ ' module mobly.controllers.android_device_lib.snippet_client_v2'
+ ' instead.'
+)
_INSTRUMENTATION_RUNNER_PACKAGE = (
- 'com.google.android.mobly.snippet.SnippetRunner')
+ 'com.google.android.mobly.snippet.SnippetRunner'
+)
# Major version of the launch and communication protocol being used by this
# client.
@@ -45,11 +48,14 @@ _PROTOCOL_MAJOR_VERSION = 1
_PROTOCOL_MINOR_VERSION = 0
_LAUNCH_CMD = (
- '{shell_cmd} am instrument {user} -w -e action start {snippet_package}/' +
- _INSTRUMENTATION_RUNNER_PACKAGE)
+ '{shell_cmd} am instrument {user} -w -e action start {snippet_package}/'
+ + _INSTRUMENTATION_RUNNER_PACKAGE
+)
-_STOP_CMD = ('am instrument {user} -w -e action stop {snippet_package}/' +
- _INSTRUMENTATION_RUNNER_PACKAGE)
+_STOP_CMD = (
+ 'am instrument {user} -w -e action stop {snippet_package}/'
+ + _INSTRUMENTATION_RUNNER_PACKAGE
+)
# Test that uses UiAutomation requires the shell session to be maintained while
# test is in progress. However, this requirement does not hold for the test that
@@ -154,7 +160,8 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
self.stop_app()
except Exception:
self._ad.log.exception(
- 'Failed to stop app after failure to start and connect.')
+ 'Failed to stop app after failure to start and connect.'
+ )
# Explicitly raise the original error from starting app.
raise e
@@ -177,11 +184,17 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
# process. Starting snippets can be slow, especially if there are
# multiple, and this avoids the perception that the framework is hanging
# for a long time doing nothing.
- self.log.info('Launching snippet apk %s with protocol %d.%d', self.package,
- _PROTOCOL_MAJOR_VERSION, _PROTOCOL_MINOR_VERSION)
- cmd = _LAUNCH_CMD.format(shell_cmd=persists_shell_cmd,
- user=self._get_user_command_string(),
- snippet_package=self.package)
+ self.log.info(
+ 'Launching snippet apk %s with protocol %d.%d',
+ self.package,
+ _PROTOCOL_MAJOR_VERSION,
+ _PROTOCOL_MINOR_VERSION,
+ )
+ cmd = _LAUNCH_CMD.format(
+ shell_cmd=persists_shell_cmd,
+ user=self._get_user_command_string(),
+ snippet_package=self.package,
+ )
start_time = time.perf_counter()
self._proc = self._do_start_app(cmd)
@@ -203,9 +216,12 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
self.connect()
# Yaaay! We're done!
- self.log.debug('Snippet %s started after %.1fs on host port %s',
- self.package,
- time.perf_counter() - start_time, self.host_port)
+ self.log.debug(
+ 'Snippet %s started after %.1fs on host port %s',
+ self.package,
+ time.perf_counter() - start_time,
+ self.host_port,
+ )
def restore_app_connection(self, port=None):
"""Restores the app after device got reconnected.
@@ -232,8 +248,12 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
self.log.exception('Failed to re-connect to app.')
raise jsonrpc_client_base.AppRestoreConnectionError(
self._ad,
- ('Failed to restore app connection for %s at host port %s, '
- 'device port %s') % (self.package, self.host_port, self.device_port))
+ (
+ 'Failed to restore app connection for %s at host port %s, '
+ 'device port %s'
+ )
+ % (self.package, self.host_port, self.device_port),
+ )
# Because the previous connection was lost, update self._proc
self._proc = None
@@ -252,11 +272,14 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
utils.stop_standing_subprocess(self._proc)
self._proc = None
out = self._adb.shell(
- _STOP_CMD.format(snippet_package=self.package,
- user=self._get_user_command_string())).decode('utf-8')
+ _STOP_CMD.format(
+ snippet_package=self.package, user=self._get_user_command_string()
+ )
+ ).decode('utf-8')
if 'OK (0 tests)' not in out:
raise errors.DeviceError(
- self._ad, 'Failed to stop existing apk. Unexpected output: %s' % out)
+ self._ad, 'Failed to stop existing apk. Unexpected output: %s' % out
+ )
self._stop_event_client()
@@ -293,17 +316,21 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
out = self._adb.shell(f'pm list package --user {self.user_id}')
if not utils.grep('^package:%s$' % self.package, out):
raise AppStartPreCheckError(
- self._ad, f'{self.package} is not installed for user {self.user_id}.')
+ self._ad, f'{self.package} is not installed for user {self.user_id}.'
+ )
# Check that the app is instrumented.
out = self._adb.shell('pm list instrumentation')
matched_out = utils.grep(
f'^instrumentation:{self.package}/{_INSTRUMENTATION_RUNNER_PACKAGE}',
- out)
+ out,
+ )
if not matched_out:
raise AppStartPreCheckError(
- self._ad, f'{self.package} is installed, but it is not instrumented.')
- match = re.search(r'^instrumentation:(.*)\/(.*) \(target=(.*)\)$',
- matched_out[0])
+ self._ad, f'{self.package} is installed, but it is not instrumented.'
+ )
+ match = re.search(
+ r'^instrumentation:(.*)\/(.*) \(target=(.*)\)$', matched_out[0]
+ )
target_name = match.group(3)
# Check that the instrumentation target is installed if it's not the
# same as the snippet package.
@@ -313,7 +340,8 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
raise AppStartPreCheckError(
self._ad,
f'Instrumentation target {target_name} is not installed for user '
- f'{self.user_id}.')
+ f'{self.user_id}.',
+ )
def _do_start_app(self, launch_cmd):
adb_cmd = [adb.ADB]
@@ -339,14 +367,16 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
line = self._proc.stdout.readline().decode('utf-8')
if not line:
raise jsonrpc_client_base.AppStartError(
- self._ad, 'Unexpected EOF waiting for app to start')
+ self._ad, 'Unexpected EOF waiting for app to start'
+ )
# readline() uses an empty string to mark EOF, and a single newline
# to mark regular empty lines in the output. Don't move the strip()
# call above the truthiness check, or this method will start
# considering any blank output line to be EOF.
line = line.strip()
- if (line.startswith('INSTRUMENTATION_RESULT:') or
- line.startswith('SNIPPET ')):
+ if line.startswith('INSTRUMENTATION_RESULT:') or line.startswith(
+ 'SNIPPET '
+ ):
self.log.debug('Accepted line from instrumentation output: "%s"', line)
return line
self.log.debug('Discarded line from instrumentation output: "%s"', line)
@@ -362,8 +392,10 @@ class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
self.log.warning(
'No %s and %s commands available to launch instrument '
'persistently, tests that depend on UiAutomator and '
- 'at the same time performs USB disconnection may fail', _SETSID_COMMAND,
- _NOHUP_COMMAND)
+ 'at the same time performs USB disconnection may fail',
+ _SETSID_COMMAND,
+ _NOHUP_COMMAND,
+ )
return ''
def help(self, print_output=True):
diff --git a/mobly/controllers/android_device_lib/snippet_client_v2.py b/mobly/controllers/android_device_lib/snippet_client_v2.py
index f7494c2..41376fb 100644
--- a/mobly/controllers/android_device_lib/snippet_client_v2.py
+++ b/mobly/controllers/android_device_lib/snippet_client_v2.py
@@ -18,7 +18,7 @@ import enum
import json
import re
import socket
-from typing import Dict
+from typing import Dict, Union
from mobly import utils
from mobly.controllers.android_device_lib import adb
@@ -28,16 +28,22 @@ from mobly.snippet import client_base
from mobly.snippet import errors
# The package of the instrumentation runner used for mobly snippet
-_INSTRUMENTATION_RUNNER_PACKAGE = 'com.google.android.mobly.snippet.SnippetRunner'
+_INSTRUMENTATION_RUNNER_PACKAGE = (
+ 'com.google.android.mobly.snippet.SnippetRunner'
+)
# The command template to start the snippet server
_LAUNCH_CMD = (
- '{shell_cmd} am instrument {user} -w -e action start {instrument_options} '
- f'{{snippet_package}}/{_INSTRUMENTATION_RUNNER_PACKAGE}')
+ '{shell_cmd} am instrument {user} -w -e action start'
+ ' {instrument_options}'
+ f' {{snippet_package}}/{_INSTRUMENTATION_RUNNER_PACKAGE}'
+)
# The command template to stop the snippet server
-_STOP_CMD = ('am instrument {user} -w -e action stop {snippet_package}/'
- f'{_INSTRUMENTATION_RUNNER_PACKAGE}')
+_STOP_CMD = (
+ 'am instrument {user} -w -e action stop {snippet_package}/'
+ f'{_INSTRUMENTATION_RUNNER_PACKAGE}'
+)
# Major version of the launch and communication protocol being used by this
# client.
@@ -89,10 +95,13 @@ class Config:
other purposes may not take effect and you should use snippet RPCs. This
is because Mobly snippet runner changes the subsequent instrumentation
process.
+ user_id: The user id under which to launch the snippet process.
"""
am_instrument_options: Dict[str, str] = dataclasses.field(
- default_factory=dict)
+ default_factory=dict
+ )
+ user_id: Union[int, None] = None
class ConnectionHandshakeCommand(enum.Enum):
@@ -106,6 +115,7 @@ class ConnectionHandshakeCommand(enum.Enum):
INIT: Initiates a new session and makes a connection with this session.
CONTINUE: Makes a connection with the current session.
"""
+
INIT = 'initiate'
CONTINUE = 'continue'
@@ -142,7 +152,7 @@ class SnippetClientV2(client_base.ClientBase):
self.device_port = None
self.uid = UNKNOWN_UID
self._adb = ad.adb
- self._user_id = None
+ self._user_id = None if config is None else config.user_id
self._proc = None
self._client = None # keep it to prevent close errors on connect failure
self._conn = None
@@ -205,19 +215,23 @@ class SnippetClientV2(client_base.ClientBase):
if not utils.grep(f'^package:{self.package}$', out):
raise errors.ServerStartPreCheckError(
self._device,
- f'{self.package} is not installed for user {self.user_id}.')
+ f'{self.package} is not installed for user {self.user_id}.',
+ )
# Validate that the app is instrumented.
out = self._adb.shell('pm list instrumentation')
matched_out = utils.grep(
f'^instrumentation:{self.package}/{_INSTRUMENTATION_RUNNER_PACKAGE}',
- out)
+ out,
+ )
if not matched_out:
raise errors.ServerStartPreCheckError(
self._device,
- f'{self.package} is installed, but it is not instrumented.')
- match = re.search(r'^instrumentation:(.*)\/(.*) \(target=(.*)\)$',
- matched_out[0])
+ f'{self.package} is installed, but it is not instrumented.',
+ )
+ match = re.search(
+ r'^instrumentation:(.*)\/(.*) \(target=(.*)\)$', matched_out[0]
+ )
target_name = match.group(3)
# Validate that the instrumentation target is installed if it's not the
# same as the snippet package.
@@ -227,14 +241,16 @@ class SnippetClientV2(client_base.ClientBase):
raise errors.ServerStartPreCheckError(
self._device,
f'Instrumentation target {target_name} is not installed for user '
- f'{self.user_id}.')
+ f'{self.user_id}.',
+ )
def _disable_hidden_api_blocklist(self):
"""If necessary and possible, disables hidden api blocklist."""
sdk_version = int(self._device.build_info['build_version_sdk'])
if self._device.is_rootable and sdk_version >= 28:
self._device.adb.shell(
- 'settings put global hidden_api_blacklist_exemptions "*"')
+ 'settings put global hidden_api_blacklist_exemptions "*"'
+ )
def start_server(self):
"""Starts the server on the remote device.
@@ -250,14 +266,19 @@ class SnippetClientV2(client_base.ClientBase):
server output.
"""
persists_shell_cmd = self._get_persisting_command()
- self.log.debug('Snippet server for package %s is using protocol %d.%d',
- self.package, _PROTOCOL_MAJOR_VERSION,
- _PROTOCOL_MINOR_VERSION)
+ self.log.debug(
+ 'Snippet server for package %s is using protocol %d.%d',
+ self.package,
+ _PROTOCOL_MAJOR_VERSION,
+ _PROTOCOL_MINOR_VERSION,
+ )
option_str = self._get_instrument_options_str()
- cmd = _LAUNCH_CMD.format(shell_cmd=persists_shell_cmd,
- user=self._get_user_command_string(),
- snippet_package=self.package,
- instrument_options=option_str)
+ cmd = _LAUNCH_CMD.format(
+ shell_cmd=persists_shell_cmd,
+ user=self._get_user_command_string(),
+ snippet_package=self.package,
+ instrument_options=option_str,
+ )
self._proc = self._run_adb_cmd(cmd)
# Check protocol version and get the device port
@@ -293,7 +314,9 @@ class SnippetClientV2(client_base.ClientBase):
'No %s and %s commands available to launch instrument '
'persistently, tests that depend on UiAutomator and '
'at the same time perform USB disconnections may fail.',
- _SETSID_COMMAND, _NOHUP_COMMAND)
+ _SETSID_COMMAND,
+ _NOHUP_COMMAND,
+ )
return ''
def _get_instrument_options_str(self):
@@ -343,15 +366,17 @@ class SnippetClientV2(client_base.ClientBase):
line = self._proc.stdout.readline().decode('utf-8')
if not line:
raise errors.ServerStartError(
- self._device, 'Unexpected EOF when waiting for server to start.')
+ self._device, 'Unexpected EOF when waiting for server to start.'
+ )
# readline() uses an empty string to mark EOF, and a single newline
# to mark regular empty lines in the output. Don't move the strip()
# call above the truthiness check, or this method will start
# considering any blank output line to be EOF.
line = line.strip()
- if (line.startswith('INSTRUMENTATION_RESULT:') or
- line.startswith('SNIPPET ')):
+ if line.startswith('INSTRUMENTATION_RESULT:') or line.startswith(
+ 'SNIPPET '
+ ):
self.log.debug('Accepted line from instrumentation output: "%s"', line)
return line
@@ -378,9 +403,17 @@ class SnippetClientV2(client_base.ClientBase):
def _forward_device_port(self):
"""Forwards the device port to a host port."""
- if not self.host_port:
- self.host_port = utils.get_available_host_port()
- self._adb.forward([f'tcp:{self.host_port}', f'tcp:{self.device_port}'])
+ if self.host_port and self.host_port in adb.list_occupied_adb_ports():
+ raise errors.Error(
+ self._device,
+ f'Cannot forward to host port {self.host_port} because adb has'
+ ' forwarded another device port to it.',
+ )
+
+ host_port = self.host_port or 0
+ # Example stdout: b'12345\n'
+ stdout = self._adb.forward([f'tcp:{host_port}', f'tcp:{self.device_port}'])
+ self.host_port = int(stdout.strip())
def create_socket_connection(self):
"""Creates a socket connection to the server.
@@ -397,23 +430,29 @@ class SnippetClientV2(client_base.ClientBase):
try:
self.log.debug(
'Snippet client is creating socket connection to the snippet server '
- 'of %s through host port %d.', self.package, self.host_port)
- self._conn = socket.create_connection(('localhost', self.host_port),
- _SOCKET_CONNECTION_TIMEOUT)
+ 'of %s through host port %d.',
+ self.package,
+ self.host_port,
+ )
+ self._conn = socket.create_connection(
+ ('localhost', self.host_port), _SOCKET_CONNECTION_TIMEOUT
+ )
except ConnectionRefusedError as err:
# Retry using '127.0.0.1' for IPv4 enabled machines that only resolve
# 'localhost' to '[::1]'.
- self.log.debug('Failed to connect to localhost, trying 127.0.0.1: %s',
- str(err))
- self._conn = socket.create_connection(('127.0.0.1', self.host_port),
- _SOCKET_CONNECTION_TIMEOUT)
+ self.log.debug(
+ 'Failed to connect to localhost, trying 127.0.0.1: %s', str(err)
+ )
+ self._conn = socket.create_connection(
+ ('127.0.0.1', self.host_port), _SOCKET_CONNECTION_TIMEOUT
+ )
self._conn.settimeout(_SOCKET_READ_TIMEOUT)
self._client = self._conn.makefile(mode='brw')
- def send_handshake_request(self,
- uid=UNKNOWN_UID,
- cmd=ConnectionHandshakeCommand.INIT):
+ def send_handshake_request(
+ self, uid=UNKNOWN_UID, cmd=ConnectionHandshakeCommand.INIT
+ ):
"""Sends a handshake request to the server to prepare for the communication.
Through the handshake response, this function checks whether the server
@@ -438,7 +477,8 @@ class SnippetClientV2(client_base.ClientBase):
if not response:
raise errors.ProtocolError(
- self._device, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE)
+ self._device, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE
+ )
response = self._decode_socket_response_bytes(response)
@@ -471,8 +511,9 @@ class SnippetClientV2(client_base.ClientBase):
self._client_send(request)
response = self._client_receive()
if not response:
- raise errors.ProtocolError(self._device,
- errors.ProtocolError.NO_RESPONSE_FROM_SERVER)
+ raise errors.ProtocolError(
+ self._device, errors.ProtocolError.NO_RESPONSE_FROM_SERVER
+ )
return self._decode_socket_response_bytes(response)
def _client_send(self, message):
@@ -490,7 +531,7 @@ class SnippetClientV2(client_base.ClientBase):
except socket.error as e:
raise errors.Error(
self._device,
- f'Encountered socket error "{e}" sending RPC message "{message}"'
+ f'Encountered socket error "{e}" sending RPC message "{message}"',
) from e
def _client_receive(self):
@@ -506,8 +547,8 @@ class SnippetClientV2(client_base.ClientBase):
return self._client.readline()
except socket.error as e:
raise errors.Error(
- self._device,
- f'Encountered socket error "{e}" reading RPC response') from e
+ self._device, f'Encountered socket error "{e}" reading RPC response'
+ ) from e
def _decode_socket_response_bytes(self, response):
"""Returns a string decoded from the socket response bytes.
@@ -525,8 +566,9 @@ class SnippetClientV2(client_base.ClientBase):
return str(response, encoding='utf8')
except UnicodeError:
self.log.error(
- 'Failed to decode socket response bytes using encoding '
- 'utf8: %s', response)
+ 'Failed to decode socket response bytes using encoding utf8: %s',
+ response,
+ )
raise
def handle_callback(self, callback_id, ret_value, rpc_func_name):
@@ -552,7 +594,8 @@ class SnippetClientV2(client_base.ClientBase):
method_name=rpc_func_name,
device=self._device,
rpc_max_timeout_sec=_SOCKET_READ_TIMEOUT,
- default_timeout_sec=_CALLBACK_DEFAULT_TIMEOUT_SEC)
+ default_timeout_sec=_CALLBACK_DEFAULT_TIMEOUT_SEC,
+ )
def _create_event_client(self):
"""Creates a separate client to the same session for propagating events.
@@ -563,14 +606,19 @@ class SnippetClientV2(client_base.ClientBase):
"""
self._event_client = SnippetClientV2(package=self.package, ad=self._device)
self._event_client.make_connection_with_forwarded_port(
- self.host_port, self.device_port, self.uid,
- ConnectionHandshakeCommand.CONTINUE)
-
- def make_connection_with_forwarded_port(self,
- host_port,
- device_port,
- uid=UNKNOWN_UID,
- cmd=ConnectionHandshakeCommand.INIT):
+ self.host_port,
+ self.device_port,
+ self.uid,
+ ConnectionHandshakeCommand.CONTINUE,
+ )
+
+ def make_connection_with_forwarded_port(
+ self,
+ host_port,
+ device_port,
+ uid=UNKNOWN_UID,
+ cmd=ConnectionHandshakeCommand.INIT,
+ ):
"""Makes a connection to the server with the given forwarded port.
This process assumes that a device port has already been forwarded to a
@@ -653,13 +701,16 @@ class SnippetClientV2(client_base.ClientBase):
# Send the stop signal to the server running on the device side.
out = self._adb.shell(
- _STOP_CMD.format(snippet_package=self.package,
- user=self._get_user_command_string())).decode('utf-8')
+ _STOP_CMD.format(
+ snippet_package=self.package, user=self._get_user_command_string()
+ )
+ ).decode('utf-8')
if 'OK (0 tests)' not in out:
raise android_device_lib_errors.DeviceError(
self._device,
- f'Failed to stop existing apk. Unexpected output: {out}.')
+ f'Failed to stop existing apk. Unexpected output: {out}.',
+ )
def _destroy_event_client(self):
"""Releases all the resources acquired in `_create_event_client`."""
@@ -699,9 +750,11 @@ class SnippetClientV2(client_base.ClientBase):
self.log.error('Failed to re-connect to the server.')
raise errors.ServerRestoreConnectionError(
self._device,
- (f'Failed to restore server connection for {self.package} at '
- f'host port {self.host_port}, device port {self.device_port}.'
- )) from e
+ (
+ f'Failed to restore server connection for {self.package} at '
+ f'host port {self.host_port}, device port {self.device_port}.'
+ ),
+ ) from e
# Because the previous connection was lost, update self._proc
self._proc = None
@@ -719,7 +772,8 @@ class SnippetClientV2(client_base.ClientBase):
"""
if self._event_client:
self._event_client.make_connection_with_forwarded_port(
- self.host_port, self.device_port)
+ self.host_port, self.device_port
+ )
def help(self, print_output=True):
"""Calls the help RPC, which returns the list of RPC calls available.
diff --git a/mobly/controllers/android_device_lib/snippet_event.py b/mobly/controllers/android_device_lib/snippet_event.py
index 7ef75c1..860335b 100644
--- a/mobly/controllers/android_device_lib/snippet_event.py
+++ b/mobly/controllers/android_device_lib/snippet_event.py
@@ -13,9 +13,11 @@
# limitations under the License.
import logging
-logging.warning('The module mobly.controllers.android_device_lib.snippet_event '
- 'is deprecated and will be removed in a future version. Use '
- 'module mobly.snippet.callback_event instead.')
+logging.warning(
+ 'The module mobly.controllers.android_device_lib.snippet_event '
+ 'is deprecated and will be removed in a future version. Use '
+ 'module mobly.snippet.callback_event instead.'
+)
def from_dict(event_dict):
@@ -29,10 +31,12 @@ def from_dict(event_dict):
Returns:
A SnippetEvent object.
"""
- return SnippetEvent(callback_id=event_dict['callbackId'],
- name=event_dict['name'],
- creation_time=event_dict['time'],
- data=event_dict['data'])
+ return SnippetEvent(
+ callback_id=event_dict['callbackId'],
+ name=event_dict['name'],
+ creation_time=event_dict['time'],
+ data=event_dict['data'],
+ )
class SnippetEvent:
@@ -55,6 +59,6 @@ class SnippetEvent:
self.data = data
def __repr__(self):
- return ('SnippetEvent(callback_id: %s, name: %s, creation_time: %s, '
- 'data: %s)') % (self.callback_id, self.name, self.creation_time,
- self.data)
+ return (
+ 'SnippetEvent(callback_id: %s, name: %s, creation_time: %s, data: %s)'
+ ) % (self.callback_id, self.name, self.creation_time, self.data)
diff --git a/mobly/controllers/attenuator.py b/mobly/controllers/attenuator.py
index eebc0e4..70f1faa 100644
--- a/mobly/controllers/attenuator.py
+++ b/mobly/controllers/attenuator.py
@@ -33,7 +33,6 @@ Sample Config:
]
"""
import importlib
-import logging
MOBLY_CONTROLLER_CONFIG_NAME = "Attenuator"
# Keys used inside a config dict for attenuator.
@@ -62,7 +61,8 @@ def create(configs):
module = importlib.import_module(module_name)
# Create each
attenuation_device = module.AttenuatorDevice(
- path_count=len(config[KEY_PATHS]))
+ path_count=len(config[KEY_PATHS])
+ )
attenuation_device.model = attenuator_model
instances = attenuation_device.open(config[KEY_ADDRESS], config[KEY_PORT])
for idx, path_name in enumerate(config[KEY_PATHS]):
@@ -78,19 +78,19 @@ def destroy(objs):
class Error(Exception):
"""This is the Exception class defined for all errors generated by
- Attenuator-related modules.
- """
+ Attenuator-related modules.
+ """
def _validate_config(config):
"""Verifies that a config dict for an attenuator device is valid.
- Args:
- config: A dict that is the configuration for an attenuator device.
+ Args:
+ config: A dict that is the configuration for an attenuator device.
- Raises:
- attenuator.Error: A config is not valid.
- """
+ Raises:
+ attenuator.Error: A config is not valid.
+ """
required_keys = [KEY_ADDRESS, KEY_MODEL, KEY_PORT, KEY_PATHS]
for key in required_keys:
if key not in config:
@@ -99,62 +99,62 @@ def _validate_config(config):
class AttenuatorPath:
"""A convenience class that allows users to control each attenuator path
- separately as different objects, as opposed to passing in an index number
- to the functions of an attenuator device object.
+ separately as different objects, as opposed to passing in an index number
+ to the functions of an attenuator device object.
- This decouples the test code from the actual attenuator device used in the
- physical test bed.
+ This decouples the test code from the actual attenuator device used in the
+ physical test bed.
- For example, if a test needs to attenuate four signal paths, this allows the
- test to do:
+ For example, if a test needs to attenuate four signal paths, this allows the
+ test to do:
- .. code-block:: python
+ .. code-block:: python
- self.attenuation_paths[0].set_atten(50)
- self.attenuation_paths[1].set_atten(40)
+ self.attenuation_paths[0].set_atten(50)
+ self.attenuation_paths[1].set_atten(40)
- instead of:
+ instead of:
- .. code-block:: python
+ .. code-block:: python
- self.attenuators[0].set_atten(0, 50)
- self.attenuators[0].set_atten(1, 40)
+ self.attenuators[0].set_atten(0, 50)
+ self.attenuators[0].set_atten(1, 40)
- The benefit the former is that the physical test bed can use either four
- single-channel attenuators, or one four-channel attenuators. Whereas the
- latter forces the test bed to use a four-channel attenuator.
- """
+ The benefit the former is that the physical test bed can use either four
+ single-channel attenuators, or one four-channel attenuators. Whereas the
+ latter forces the test bed to use a four-channel attenuator.
+ """
def __init__(self, attenuation_device, idx=0, name=None):
self.model = attenuation_device.model
self.attenuation_device = attenuation_device
self.idx = idx
self.name = name
- if (self.idx >= attenuation_device.path_count):
+ if self.idx >= attenuation_device.path_count:
raise IndexError("Attenuator index out of range!")
def set_atten(self, value):
"""This function sets the attenuation of Attenuator.
- Args:
- value: This is a floating point value for nominal attenuation to be
- set. Unit is db.
- """
+ Args:
+ value: This is a floating point value for nominal attenuation to be
+ set. Unit is db.
+ """
self.attenuation_device.set_atten(self.idx, value)
def get_atten(self):
"""Gets the current attenuation setting of Attenuator.
- Returns:
- A float that is the current attenuation value. Unit is db.
- """
+ Returns:
+ A float that is the current attenuation value. Unit is db.
+ """
return self.attenuation_device.get_atten(self.idx)
def get_max_atten(self):
"""Gets the max attenuation supported by the Attenuator.
- Returns:
- A float that is the max attenuation value.
- """
+ Returns:
+ A float that is the max attenuation value.
+ """
return self.attenuation_device.max_atten
diff --git a/mobly/controllers/attenuator_lib/minicircuits.py b/mobly/controllers/attenuator_lib/minicircuits.py
index f33a5d1..7234015 100644
--- a/mobly/controllers/attenuator_lib/minicircuits.py
+++ b/mobly/controllers/attenuator_lib/minicircuits.py
@@ -24,75 +24,79 @@ from mobly.controllers.attenuator_lib import telnet_scpi_client
class AttenuatorDevice:
"""This provides a specific telnet-controlled implementation of
- AttenuatorDevice for Mini-Circuits RC-DAT attenuators.
+ AttenuatorDevice for Mini-Circuits RC-DAT attenuators.
- Attributes:
- path_count: The number of signal attenuation path this device has.
- """
+ Attributes:
+ path_count: The number of signal attenuation path this device has.
+ """
def __init__(self, path_count=1):
self.path_count = path_count
# The telnet client used to communicate with the attenuator device.
self._telnet_client = telnet_scpi_client.TelnetScpiClient(
- tx_cmd_separator="\r\n", rx_cmd_separator="\r\n", prompt="")
+ tx_cmd_separator="\r\n", rx_cmd_separator="\r\n", prompt=""
+ )
@property
def is_open(self):
"""This function returns the state of the telnet connection to the
- underlying AttenuatorDevice.
+ underlying AttenuatorDevice.
- Returns:
- True if there is a successfully open connection to the
- AttenuatorDevice.
- """
+ Returns:
+ True if there is a successfully open connection to the
+ AttenuatorDevice.
+ """
return bool(self._telnet_client.is_open)
def open(self, host, port=23):
"""Opens a telnet connection to the desired AttenuatorDevice and
- queries basic information.
+ queries basic information.
- Args:
- host: A valid hostname (IP address or DNS-resolvable name) to an
- MC-DAT attenuator instrument.
- port: An optional port number (defaults to telnet default 23)
- """
+ Args:
+ host: A valid hostname (IP address or DNS-resolvable name) to an
+ MC-DAT attenuator instrument.
+ port: An optional port number (defaults to telnet default 23)
+ """
self._telnet_client.open(host, port)
config_str = self._telnet_client.cmd("MN?")
if config_str.startswith("MN="):
- config_str = config_str[len("MN="):]
+ config_str = config_str[len("MN=") :]
self.properties = dict(
- zip(['model', 'max_freq', 'max_atten'], config_str.split("-", 2)))
- self.max_atten = float(self.properties['max_atten'])
+ zip(["model", "max_freq", "max_atten"], config_str.split("-", 2))
+ )
+ self.max_atten = float(self.properties["max_atten"])
def close(self):
"""Closes a telnet connection to the desired attenuator device.
- This should be called as part of any teardown procedure prior to the
- attenuator instrument leaving scope.
- """
+ This should be called as part of any teardown procedure prior to the
+ attenuator instrument leaving scope.
+ """
if self.is_open:
self._telnet_client.close()
def set_atten(self, idx, value):
"""Sets the attenuation value for a particular signal path.
- Args:
- idx: Zero-based index int which is the identifier for a particular
- signal path in an instrument. For instruments that only has one
- channel, this is ignored by the device.
- value: A float that is the attenuation value to set.
-
- Raises:
- Error: The underlying telnet connection to the instrument is not
- open.
- IndexError: The index of the attenuator is greater than the maximum
- index of the underlying instrument.
- ValueError: The requested set value is greater than the maximum
- attenuation value.
- """
+ Args:
+ idx: Zero-based index int which is the identifier for a particular
+ signal path in an instrument. For instruments that only has one
+ channel, this is ignored by the device.
+ value: A float that is the attenuation value to set.
+
+ Raises:
+ Error: The underlying telnet connection to the instrument is not
+ open.
+ IndexError: The index of the attenuator is greater than the maximum
+ index of the underlying instrument.
+ ValueError: The requested set value is greater than the maximum
+ attenuation value.
+ """
if not self.is_open:
- raise attenuator.Error("Connection to attenuator at %s is not open!" %
- self._telnet_client.host)
+ raise attenuator.Error(
+ "Connection to attenuator at %s is not open!"
+ % self._telnet_client.host
+ )
if idx + 1 > self.path_count:
raise IndexError("Attenuator index out of range!", self.path_count, idx)
if value > self.max_atten:
@@ -102,22 +106,24 @@ class AttenuatorDevice:
def get_atten(self, idx=0):
"""This function returns the current attenuation from an attenuator at a
- given index in the instrument.
+ given index in the instrument.
- Args:
- idx: This zero-based index is the identifier for a particular
- attenuator in an instrument.
+ Args:
+ idx: This zero-based index is the identifier for a particular
+ attenuator in an instrument.
- Raises:
- Error: The underlying telnet connection to the instrument is not
- open.
+ Raises:
+ Error: The underlying telnet connection to the instrument is not
+ open.
- Returns:
- A float that is the current attenuation value.
- """
+ Returns:
+ A float that is the current attenuation value.
+ """
if not self.is_open:
- raise attenuator.Error("Connection to attenuator at %s is not open!" %
- self._telnet_client.host)
+ raise attenuator.Error(
+ "Connection to attenuator at %s is not open!"
+ % self._telnet_client.host
+ )
if idx + 1 > self.path_count or idx < 0:
raise IndexError("Attenuator index out of range!", self.path_count, idx)
telnet_cmd = ":ATT?" if self.path_count == 1 else "CHAN:%s:ATT?" % (idx + 1)
diff --git a/mobly/controllers/attenuator_lib/telnet_scpi_client.py b/mobly/controllers/attenuator_lib/telnet_scpi_client.py
index 4dde387..98cccca 100644
--- a/mobly/controllers/attenuator_lib/telnet_scpi_client.py
+++ b/mobly/controllers/attenuator_lib/telnet_scpi_client.py
@@ -23,14 +23,14 @@ from mobly.controllers import attenuator
def _ascii_string(uc_string):
- return str(uc_string).encode('ASCII')
+ return str(uc_string).encode("ASCII")
class TelnetScpiClient:
"""This is an internal helper class for Telnet+SCPI command-based
- instruments. It should only be used by those implemention control libraries
- and not by any user code directly.
- """
+ instruments. It should only be used by those implemention control libraries
+ and not by any user code directly.
+ """
def __init__(self, tx_cmd_separator="\n", rx_cmd_separator="\n", prompt=""):
self._tn = None
@@ -70,13 +70,15 @@ class TelnetScpiClient:
return None
match_idx, match_val, ret_text = self._tn.expect(
- [_ascii_string("\S+" + self.rx_cmd_separator)], 1)
+ [_ascii_string("\S+" + self.rx_cmd_separator)], 1
+ )
if match_idx == -1:
raise attenuator.Error("Telnet command failed to return valid data")
ret_text = ret_text.decode()
- ret_text = ret_text.strip(self.tx_cmd_separator + self.rx_cmd_separator +
- self.prompt)
+ ret_text = ret_text.strip(
+ self.tx_cmd_separator + self.rx_cmd_separator + self.prompt
+ )
return ret_text
diff --git a/mobly/controllers/iperf_server.py b/mobly/controllers/iperf_server.py
index e4dcb81..e99b298 100644
--- a/mobly/controllers/iperf_server.py
+++ b/mobly/controllers/iperf_server.py
@@ -16,11 +16,10 @@ import io
import json
import logging
import os
-import subprocess
from mobly import utils
-MOBLY_CONTROLLER_CONFIG_NAME = "IPerfServer"
+MOBLY_CONTROLLER_CONFIG_NAME = 'IPerfServer'
def create(configs):
@@ -57,16 +56,16 @@ class IPerfResult:
def _has_data(self):
"""Checks if the iperf result has valid throughput data.
- Returns:
- True if the result contains throughput data. False otherwise.
- """
- return ('end' in self.result) and ('sum' in self.result["end"])
+ Returns:
+ True if the result contains throughput data. False otherwise.
+ """
+ return ('end' in self.result) and ('sum' in self.result['end'])
def get_json(self):
"""
- Returns:
- The raw json output from iPerf.
- """
+ Returns:
+ The raw json output from iPerf.
+ """
return self.result
@property
@@ -79,8 +78,8 @@ class IPerfResult:
def avg_rate(self):
"""Average receiving rate in MB/s over the entire run.
- If the result is not from a success run, this property is None.
- """
+ If the result is not from a success run, this property is None.
+ """
if not self._has_data or 'sum' not in self.result['end']:
return None
bps = self.result['end']['sum']['bits_per_second']
@@ -89,10 +88,10 @@ class IPerfResult:
@property
def avg_receive_rate(self):
"""Average receiving rate in MB/s over the entire run. This data may
- not exist if iperf was interrupted.
+ not exist if iperf was interrupted.
- If the result is not from a success run, this property is None.
- """
+ If the result is not from a success run, this property is None.
+ """
if not self._has_data or 'sum_received' not in self.result['end']:
return None
bps = self.result['end']['sum_received']['bits_per_second']
@@ -101,44 +100,44 @@ class IPerfResult:
@property
def avg_send_rate(self):
"""Average sending rate in MB/s over the entire run. This data may
- not exist if iperf was interrupted.
+ not exist if iperf was interrupted.
- If the result is not from a success run, this property is None.
- """
+ If the result is not from a success run, this property is None.
+ """
if not self._has_data or 'sum_sent' not in self.result['end']:
return None
bps = self.result['end']['sum_sent']['bits_per_second']
return bps / 8 / 1024 / 1024
-class IPerfServer():
- """Class that handles iperf3 operations.
- """
+class IPerfServer:
+ """Class that handles iperf3 operations."""
def __init__(self, port, log_path):
self.port = port
- self.log_path = os.path.join(log_path, "iPerf{}".format(self.port))
- self.iperf_str = "iperf3 -s -J -p {}".format(port)
+ self.log_path = os.path.join(log_path, 'iPerf{}'.format(self.port))
+ self.iperf_str = 'iperf3 -s -J -p {}'.format(port)
self.iperf_process = None
self.log_files = []
self.started = False
- def start(self, extra_args="", tag=""):
+ def start(self, extra_args='', tag=''):
"""Starts iperf server on specified port.
- Args:
- extra_args: A string representing extra arguments to start iperf
- server with.
- tag: Appended to log file name to identify logs from different
- iperf runs.
- """
+ Args:
+ extra_args: A string representing extra arguments to start iperf
+ server with.
+ tag: Appended to log file name to identify logs from different
+ iperf runs.
+ """
if self.started:
return
utils.create_dir(self.log_path)
if tag:
tag = tag + ','
- out_file_name = "IPerfServer,{},{}{}.log".format(self.port, tag,
- len(self.log_files))
+ out_file_name = 'IPerfServer,{},{}{}.log'.format(
+ self.port, tag, len(self.log_files)
+ )
full_out_path = os.path.join(self.log_path, out_file_name)
cmd = '%s %s > %s' % (self.iperf_str, extra_args, full_out_path)
self.iperf_process = utils.start_standing_subprocess(cmd, shell=True)
diff --git a/mobly/controllers/sniffer.py b/mobly/controllers/sniffer.py
index 91293b4..e1f3460 100644
--- a/mobly/controllers/sniffer.py
+++ b/mobly/controllers/sniffer.py
@@ -20,18 +20,18 @@ MOBLY_CONTROLLER_CONFIG_NAME = "Sniffer"
def create(configs):
"""Initializes the sniffer structures based on the JSON configuration. The
- expected keys are:
-
- * Type: A first-level type of sniffer. Planned to be 'local' for
- sniffers running on the local machine, or 'remote' for sniffers
- running remotely.
- * SubType: The specific sniffer type to be used.
- * Interface: The WLAN interface used to configure the sniffer.
- * BaseConfigs: A dictionary specifying baseline configurations of
- the sniffer. Configurations can be overridden when starting a
- capture. The keys must be one of the Sniffer.CONFIG_KEY_*
- values.
- """
+ expected keys are:
+
+ * Type: A first-level type of sniffer. Planned to be 'local' for
+ sniffers running on the local machine, or 'remote' for sniffers
+ running remotely.
+ * SubType: The specific sniffer type to be used.
+ * Interface: The WLAN interface used to configure the sniffer.
+ * BaseConfigs: A dictionary specifying baseline configurations of
+ the sniffer. Configurations can be overridden when starting a
+ capture. The keys must be one of the Sniffer.CONFIG_KEY_*
+ values.
+ """
objs = []
for c in configs:
sniffer_type = c["Type"]
@@ -39,18 +39,19 @@ def create(configs):
interface = c["Interface"]
base_configs = c["BaseConfigs"]
module_name = "mobly.controllers.sniffer_lib.{}.{}".format(
- sniffer_type, sniffer_subtype)
+ sniffer_type, sniffer_subtype
+ )
module = importlib.import_module(module_name)
objs.append(
- module.Sniffer(interface,
- logging.getLogger(),
- base_configs=base_configs))
+ module.Sniffer(
+ interface, logging.getLogger(), base_configs=base_configs
+ )
+ )
return objs
def destroy(objs):
- """Destroys the sniffers and terminates any ongoing capture sessions.
- """
+ """Destroys the sniffers and terminates any ongoing capture sessions."""
for sniffer in objs:
try:
sniffer.stop_capture()
@@ -60,221 +61,227 @@ def destroy(objs):
class SnifferError(Exception):
"""This is the Exception class defined for all errors generated by
- Sniffer-related modules.
- """
+ Sniffer-related modules.
+ """
+
pass
class InvalidDataError(Exception):
"""This exception is thrown when invalid configuration data is passed
- to a method.
- """
+ to a method.
+ """
+
pass
class ExecutionError(SnifferError):
"""This exception is thrown when trying to configure the capture device
- or when trying to execute the capture operation.
+ or when trying to execute the capture operation.
+
+ When this exception is seen, it is possible that the sniffer module is run
+ without sudo (for local sniffers) or keys are out-of-date (for remote
+ sniffers).
+ """
- When this exception is seen, it is possible that the sniffer module is run
- without sudo (for local sniffers) or keys are out-of-date (for remote
- sniffers).
- """
pass
class InvalidOperationError(SnifferError):
"""Certain methods may only be accessed when the instance upon which they
- are invoked is in a certain state. This indicates that the object is not
- in the correct state for a method to be called.
- """
+ are invoked is in a certain state. This indicates that the object is not
+ in the correct state for a method to be called.
+ """
+
pass
class Sniffer:
"""This class defines an object representing a sniffer.
- The object defines the generic behavior of sniffers - irrespective of how
- they are implemented, or where they are located: on the local machine or on
- the remote machine.
- """
+ The object defines the generic behavior of sniffers - irrespective of how
+ they are implemented, or where they are located: on the local machine or on
+ the remote machine.
+ """
CONFIG_KEY_CHANNEL = "channel"
def __init__(self, interface, logger, base_configs=None):
"""The constructor for the Sniffer. It constructs a sniffer and
- configures it to be ready for capture.
-
- Args:
- interface: A string specifying the interface used to configure the
- sniffer.
- logger: Mobly logger object.
- base_configs: A dictionary containing baseline configurations of the
- sniffer. These can be overridden when staring a capture. The
- keys are specified by Sniffer.CONFIG_KEY_*.
-
- Returns:
- self: A configured sniffer.
-
- Raises:
- InvalidDataError: if the config_path is invalid.
- NoPermissionError: if an error occurs while configuring the
- sniffer.
- """
+ configures it to be ready for capture.
+
+ Args:
+ interface: A string specifying the interface used to configure the
+ sniffer.
+ logger: Mobly logger object.
+ base_configs: A dictionary containing baseline configurations of the
+ sniffer. These can be overridden when staring a capture. The
+ keys are specified by Sniffer.CONFIG_KEY_*.
+
+ Returns:
+ self: A configured sniffer.
+
+ Raises:
+ InvalidDataError: if the config_path is invalid.
+ NoPermissionError: if an error occurs while configuring the
+ sniffer.
+ """
raise NotImplementedError("Base class should not be called directly!")
def get_descriptor(self):
"""This function returns a string describing the sniffer. The specific
- string (and its format) is up to each derived sniffer type.
+ string (and its format) is up to each derived sniffer type.
- Returns:
- A string describing the sniffer.
- """
+ Returns:
+ A string describing the sniffer.
+ """
raise NotImplementedError("Base class should not be called directly!")
def get_type(self):
"""This function returns the type of the sniffer.
- Returns:
- The type (string) of the sniffer. Corresponds to the 'Type' key of
- the sniffer configuration.
- """
+ Returns:
+ The type (string) of the sniffer. Corresponds to the 'Type' key of
+ the sniffer configuration.
+ """
raise NotImplementedError("Base class should not be called directly!")
def get_subtype(self):
"""This function returns the sub-type of the sniffer.
- Returns:
- The sub-type (string) of the sniffer. Corresponds to the 'SubType'
- key of the sniffer configuration.
- """
+ Returns:
+ The sub-type (string) of the sniffer. Corresponds to the 'SubType'
+ key of the sniffer configuration.
+ """
raise NotImplementedError("Base class should not be called directly!")
def get_interface(self):
"""This function returns The interface used to configure the sniffer,
- e.g. 'wlan0'.
+ e.g. 'wlan0'.
- Returns:
- The interface (string) used to configure the sniffer. Corresponds to
- the 'Interface' key of the sniffer configuration.
- """
+ Returns:
+ The interface (string) used to configure the sniffer. Corresponds to
+ the 'Interface' key of the sniffer configuration.
+ """
raise NotImplementedError("Base class should not be called directly!")
def get_capture_file(self):
"""The sniffer places a capture in the logger directory. This function
- enables the caller to obtain the path of that capture.
+ enables the caller to obtain the path of that capture.
- Returns:
- The full path of the current or last capture.
- """
+ Returns:
+ The full path of the current or last capture.
+ """
raise NotImplementedError("Base class should not be called directly!")
- def start_capture(self,
- override_configs=None,
- additional_args=None,
- duration=None,
- packet_count=None):
+ def start_capture(
+ self,
+ override_configs=None,
+ additional_args=None,
+ duration=None,
+ packet_count=None,
+ ):
"""This function starts a capture which is saved to the specified file
- path.
-
- Depending on the type/subtype and configuration of the sniffer the
- capture may terminate on its own or may require an explicit call to the
- stop_capture() function.
-
- This is a non-blocking function so a terminating function must be
- called either explicitly or implicitly:
-
- * Explicitly: call either stop_capture() or wait_for_capture()
- * Implicitly: use with a with clause. The wait_for_capture()
- function will be called if a duration is specified (i.e.
- is not None), otherwise a stop_capture() will be called.
-
- The capture is saved to a file in the log path of the logger. Use
- the get_capture_file() to get the full path to the current or most
- recent capture.
-
- Args:
- override_configs: A dictionary which is combined with the
- base_configs ("BaseConfigs" in the sniffer configuration). The
- keys (specified by Sniffer.CONFIG_KEY_*) determine the
- configuration of the sniffer for this specific capture.
- additional_args: A string specifying additional raw
- command-line arguments to pass to the underlying sniffer. The
- interpretation of these flags is sniffer-dependent.
- duration: An integer specifying the number of seconds over which to
- capture packets. The sniffer will be terminated after this
- duration. Used in implicit mode when using a 'with' clause. In
- explicit control cases may have to be performed using a
- sleep+stop or as the timeout argument to the wait function.
- packet_count: An integer specifying the number of packets to capture
- before terminating. Should be used with duration to guarantee
- that capture terminates at some point (even if did not capture
- the specified number of packets).
-
- Returns:
- An ActiveCaptureContext process which can be used with a 'with'
- clause.
-
- Raises:
- InvalidDataError: for invalid configurations
- NoPermissionError: if an error occurs while configuring and running
- the sniffer.
- """
+ path.
+
+ Depending on the type/subtype and configuration of the sniffer the
+ capture may terminate on its own or may require an explicit call to the
+ stop_capture() function.
+
+ This is a non-blocking function so a terminating function must be
+ called either explicitly or implicitly:
+
+ * Explicitly: call either stop_capture() or wait_for_capture()
+ * Implicitly: use with a with clause. The wait_for_capture()
+ function will be called if a duration is specified (i.e.
+ is not None), otherwise a stop_capture() will be called.
+
+ The capture is saved to a file in the log path of the logger. Use
+ the get_capture_file() to get the full path to the current or most
+ recent capture.
+
+ Args:
+ override_configs: A dictionary which is combined with the
+ base_configs ("BaseConfigs" in the sniffer configuration). The
+ keys (specified by Sniffer.CONFIG_KEY_*) determine the
+ configuration of the sniffer for this specific capture.
+ additional_args: A string specifying additional raw
+ command-line arguments to pass to the underlying sniffer. The
+ interpretation of these flags is sniffer-dependent.
+ duration: An integer specifying the number of seconds over which to
+ capture packets. The sniffer will be terminated after this
+ duration. Used in implicit mode when using a 'with' clause. In
+ explicit control cases may have to be performed using a
+ sleep+stop or as the timeout argument to the wait function.
+ packet_count: An integer specifying the number of packets to capture
+ before terminating. Should be used with duration to guarantee
+ that capture terminates at some point (even if did not capture
+ the specified number of packets).
+
+ Returns:
+ An ActiveCaptureContext process which can be used with a 'with'
+ clause.
+
+ Raises:
+ InvalidDataError: for invalid configurations
+ NoPermissionError: if an error occurs while configuring and running
+ the sniffer.
+ """
raise NotImplementedError("Base class should not be called directly!")
def stop_capture(self):
"""This function stops a capture and guarantees that the capture is
- saved to the capture file configured during the start_capture() method.
- Depending on the type of the sniffer the file may previously contain
- partial results (e.g. for a local sniffer) or may not exist until the
- stop_capture() method is executed (e.g. for a remote sniffer).
-
- Depending on the type/subtype and configuration of the sniffer the
- capture may terminate on its own without requiring a call to this
- function. In such a case it is still necessary to call either this
- function or the wait_for_capture() function to make sure that the
- capture file is moved to the correct location.
-
- Raises:
- NoPermissionError: No permission when trying to stop a capture
- and save the capture file.
- """
+ saved to the capture file configured during the start_capture() method.
+ Depending on the type of the sniffer the file may previously contain
+ partial results (e.g. for a local sniffer) or may not exist until the
+ stop_capture() method is executed (e.g. for a remote sniffer).
+
+ Depending on the type/subtype and configuration of the sniffer the
+ capture may terminate on its own without requiring a call to this
+ function. In such a case it is still necessary to call either this
+ function or the wait_for_capture() function to make sure that the
+ capture file is moved to the correct location.
+
+ Raises:
+ NoPermissionError: No permission when trying to stop a capture
+ and save the capture file.
+ """
raise NotImplementedError("Base class should not be called directly!")
def wait_for_capture(self, timeout=None):
"""This function waits for a capture to terminate and guarantees that
- the capture is saved to the capture file configured during the
- start_capture() method. Depending on the type of the sniffer the file
- may previously contain partial results (e.g. for a local sniffer) or
- may not exist until the stop_capture() method is executed (e.g. for a
- remote sniffer).
-
- Depending on the type/subtype and configuration of the sniffer the
- capture may terminate on its own without requiring a call to this
- function. In such a case it is still necessary to call either this
- function or the stop_capture() function to make sure that the capture
- file is moved to the correct location.
-
- Args:
- timeout: An integer specifying the number of seconds to wait for
- the capture to terminate on its own. On expiration of the
- timeout the sniffer is stopped explicitly using the
- stop_capture() function.
-
- Raises:
- NoPermissionError: No permission when trying to stop a capture and
- save the capture file.
- """
+ the capture is saved to the capture file configured during the
+ start_capture() method. Depending on the type of the sniffer the file
+ may previously contain partial results (e.g. for a local sniffer) or
+ may not exist until the stop_capture() method is executed (e.g. for a
+ remote sniffer).
+
+ Depending on the type/subtype and configuration of the sniffer the
+ capture may terminate on its own without requiring a call to this
+ function. In such a case it is still necessary to call either this
+ function or the stop_capture() function to make sure that the capture
+ file is moved to the correct location.
+
+ Args:
+ timeout: An integer specifying the number of seconds to wait for
+ the capture to terminate on its own. On expiration of the
+ timeout the sniffer is stopped explicitly using the
+ stop_capture() function.
+
+ Raises:
+ NoPermissionError: No permission when trying to stop a capture and
+ save the capture file.
+ """
raise NotImplementedError("Base class should not be called directly!")
class ActiveCaptureContext:
"""This class defines an object representing an active sniffer capture.
- The object is returned by a Sniffer.start_capture() command and terminates
- the capture when the 'with' clause exits. It is syntactic sugar for
- try/finally.
- """
+ The object is returned by a Sniffer.start_capture() command and terminates
+ the capture when the 'with' clause exits. It is syntactic sugar for
+ try/finally.
+ """
_sniffer = None
_timeout = None
diff --git a/mobly/controllers/sniffer_lib/local/local_base.py b/mobly/controllers/sniffer_lib/local/local_base.py
index a9fb673..c81b108 100644
--- a/mobly/controllers/sniffer_lib/local/local_base.py
+++ b/mobly/controllers/sniffer_lib/local/local_base.py
@@ -20,7 +20,6 @@ the actual capture (sniff) to sub-classes.
import os
import shutil
-import signal
import subprocess
import tempfile
from mobly import logger
@@ -30,15 +29,14 @@ from mobly.controllers import sniffer
class SnifferLocalBase(sniffer.Sniffer):
"""This class defines the common behaviors of WLAN sniffers running on
- WLAN interfaces of the local machine.
+ WLAN interfaces of the local machine.
- Specific mechanisms to capture packets over the local WLAN interfaces are
- implemented by sub-classes of this class - i.e. it is not a final class.
- """
+ Specific mechanisms to capture packets over the local WLAN interfaces are
+ implemented by sub-classes of this class - i.e. it is not a final class.
+ """
def __init__(self, interface, logger, base_configs=None):
- """See base class documentation
- """
+ """See base class documentation"""
self._base_configs = None
self._capture_file_path = ""
self._interface = ""
@@ -52,20 +50,18 @@ class SnifferLocalBase(sniffer.Sniffer):
self._base_configs = base_configs
try:
- subprocess.check_call(['ifconfig', self._interface, 'down'])
- subprocess.check_call(['iwconfig', self._interface, 'mode', 'monitor'])
- subprocess.check_call(['ifconfig', self._interface, 'up'])
+ subprocess.check_call(["ifconfig", self._interface, "down"])
+ subprocess.check_call(["iwconfig", self._interface, "mode", "monitor"])
+ subprocess.check_call(["ifconfig", self._interface, "up"])
except Exception as err:
raise sniffer.ExecutionError(err)
def get_interface(self):
- """See base class documentation
- """
+ """See base class documentation"""
return self._interface
def get_type(self):
- """See base class documentation
- """
+ """See base class documentation"""
return "local"
def get_capture_file(self):
@@ -73,10 +69,10 @@ class SnifferLocalBase(sniffer.Sniffer):
def _pre_capture_config(self, override_configs=None):
"""Utility function which configures the wireless interface per the
- specified configurations. Operation is performed before every capture
- start using baseline configurations (specified when sniffer initialized)
- and override configurations specified here.
- """
+ specified configurations. Operation is performed before every capture
+ start using baseline configurations (specified when sniffer initialized)
+ and override configurations specified here.
+ """
final_configs = {}
if self._base_configs:
final_configs.update(self._base_configs)
@@ -86,71 +82,78 @@ class SnifferLocalBase(sniffer.Sniffer):
if sniffer.Sniffer.CONFIG_KEY_CHANNEL in final_configs:
try:
subprocess.check_call([
- 'iwconfig', self._interface, 'channel',
- str(final_configs[sniffer.Sniffer.CONFIG_KEY_CHANNEL])
+ "iwconfig",
+ self._interface,
+ "channel",
+ str(final_configs[sniffer.Sniffer.CONFIG_KEY_CHANNEL]),
])
except Exception as err:
raise sniffer.ExecutionError(err)
- def _get_command_line(self,
- additional_args=None,
- duration=None,
- packet_count=None):
+ def _get_command_line(
+ self, additional_args=None, duration=None, packet_count=None
+ ):
"""Utility function to be implemented by every child class - which
- are the concrete sniffer classes. Each sniffer-specific class should
- derive the command line to execute its sniffer based on the specified
- arguments.
- """
+ are the concrete sniffer classes. Each sniffer-specific class should
+ derive the command line to execute its sniffer based on the specified
+ arguments.
+ """
raise NotImplementedError("Base class should not be called directly!")
def _post_process(self):
"""Utility function which is executed after a capture is done. It
- moves the capture file to the requested location.
- """
+ moves the capture file to the requested location.
+ """
self._process = None
shutil.move(self._temp_capture_file_path, self._capture_file_path)
- def start_capture(self,
- override_configs=None,
- additional_args=None,
- duration=None,
- packet_count=None):
- """See base class documentation
- """
+ def start_capture(
+ self,
+ override_configs=None,
+ additional_args=None,
+ duration=None,
+ packet_count=None,
+ ):
+ """See base class documentation"""
if self._process is not None:
raise sniffer.InvalidOperationError(
- "Trying to start a sniff while another is still running!")
- capture_dir = os.path.join(self._logger.log_path,
- "Sniffer-{}".format(self._interface))
+ "Trying to start a sniff while another is still running!"
+ )
+ capture_dir = os.path.join(
+ self._logger.log_path, "Sniffer-{}".format(self._interface)
+ )
os.makedirs(capture_dir, exist_ok=True)
self._capture_file_path = os.path.join(
- capture_dir, "capture_{}.pcap".format(logger.get_log_file_timestamp()))
+ capture_dir, "capture_{}.pcap".format(logger.get_log_file_timestamp())
+ )
self._pre_capture_config(override_configs)
_, self._temp_capture_file_path = tempfile.mkstemp(suffix=".pcap")
- cmd = self._get_command_line(additional_args=additional_args,
- duration=duration,
- packet_count=packet_count)
+ cmd = self._get_command_line(
+ additional_args=additional_args,
+ duration=duration,
+ packet_count=packet_count,
+ )
self._process = utils.start_standing_subprocess(cmd)
return sniffer.ActiveCaptureContext(self, duration)
def stop_capture(self):
- """See base class documentation
- """
+ """See base class documentation"""
if self._process is None:
raise sniffer.InvalidOperationError(
- "Trying to stop a non-started process")
+ "Trying to stop a non-started process"
+ )
utils.stop_standing_subprocess(self._process)
self._post_process()
def wait_for_capture(self, timeout=None):
- """See base class documentation
- """
+ """See base class documentation"""
if self._process is None:
raise sniffer.InvalidOperationError(
- "Trying to wait on a non-started process")
+ "Trying to wait on a non-started process"
+ )
try:
utils.wait_for_standing_subprocess(self._process, timeout)
self._post_process()
diff --git a/mobly/controllers/sniffer_lib/local/tcpdump.py b/mobly/controllers/sniffer_lib/local/tcpdump.py
index 053d4eb..4f54cdb 100644
--- a/mobly/controllers/sniffer_lib/local/tcpdump.py
+++ b/mobly/controllers/sniffer_lib/local/tcpdump.py
@@ -18,12 +18,10 @@ from mobly.controllers.sniffer_lib.local import local_base
class Sniffer(local_base.SnifferLocalBase):
- """This class defines a sniffer which uses tcpdump as its back-end
- """
+ """This class defines a sniffer which uses tcpdump as its back-end"""
def __init__(self, config_path, logger, base_configs=None):
- """See base class documentation
- """
+ """See base class documentation"""
self._executable_path = None
super().__init__(config_path, logger, base_configs=base_configs)
@@ -31,24 +29,23 @@ class Sniffer(local_base.SnifferLocalBase):
self._executable_path = shutil.which("tcpdump")
if self._executable_path is None:
raise sniffer.SnifferError(
- "Cannot find a path to the 'tcpdump' executable")
+ "Cannot find a path to the 'tcpdump' executable"
+ )
def get_descriptor(self):
- """See base class documentation
- """
+ """See base class documentation"""
return "local-tcpdump-{}".format(self._interface)
def get_subtype(self):
- """See base class documentation
- """
+ """See base class documentation"""
return "tcpdump"
- def _get_command_line(self,
- additional_args=None,
- duration=None,
- packet_count=None):
- cmd = "{} -i {} -w {}".format(self._executable_path, self._interface,
- self._temp_capture_file_path)
+ def _get_command_line(
+ self, additional_args=None, duration=None, packet_count=None
+ ):
+ cmd = "{} -i {} -w {}".format(
+ self._executable_path, self._interface, self._temp_capture_file_path
+ )
if packet_count is not None:
cmd = "{} -c {}".format(cmd, packet_count)
if additional_args is not None:
diff --git a/mobly/controllers/sniffer_lib/local/tshark.py b/mobly/controllers/sniffer_lib/local/tshark.py
index a22d5f0..e48b1c6 100644
--- a/mobly/controllers/sniffer_lib/local/tshark.py
+++ b/mobly/controllers/sniffer_lib/local/tshark.py
@@ -18,38 +18,37 @@ from mobly.controllers.sniffer_lib.local import local_base
class Sniffer(local_base.SnifferLocalBase):
- """This class defines a sniffer which uses tshark as its back-end
- """
+ """This class defines a sniffer which uses tshark as its back-end"""
def __init__(self, config_path, logger, base_configs=None):
- """See base class documentation
- """
+ """See base class documentation"""
self._executable_path = None
super().__init__(config_path, logger, base_configs=base_configs)
- self._executable_path = (shutil.which("tshark") or
- shutil.which("/usr/local/bin/tshark"))
+ self._executable_path = shutil.which("tshark") or shutil.which(
+ "/usr/local/bin/tshark"
+ )
if self._executable_path is None:
- raise sniffer.SnifferError("Cannot find a path to the 'tshark' "
- "executable (or to '/usr/local/bin/tshark')")
+ raise sniffer.SnifferError(
+ "Cannot find a path to the 'tshark' "
+ "executable (or to '/usr/local/bin/tshark')"
+ )
def get_descriptor(self):
- """See base class documentation
- """
+ """See base class documentation"""
return "local-tshark-{}-ch{}".format(self._interface)
def get_subtype(self):
- """See base class documentation
- """
+ """See base class documentation"""
return "tshark"
- def _get_command_line(self,
- additional_args=None,
- duration=None,
- packet_count=None):
- cmd = "{} -i {} -w {}".format(self._executable_path, self._interface,
- self._temp_capture_file_path)
+ def _get_command_line(
+ self, additional_args=None, duration=None, packet_count=None
+ ):
+ cmd = "{} -i {} -w {}".format(
+ self._executable_path, self._interface, self._temp_capture_file_path
+ )
if duration is not None:
cmd = "{} -a duration:{}".format(cmd, duration)
if packet_count is not None:
diff --git a/mobly/expects.py b/mobly/expects.py
index 9475758..ad7cb8a 100644
--- a/mobly/expects.py
+++ b/mobly/expects.py
@@ -129,8 +129,9 @@ def expect_equal(first, second, msg=None, extras=None):
try:
asserts.assert_equal(first, second, msg, extras)
except signals.TestSignal as e:
- logging.exception('Expected %s equals to %s, but they are not.', first,
- second)
+ logging.exception(
+ 'Expected %s equals to %s, but they are not.', first, second
+ )
recorder.add_error(e)
diff --git a/mobly/keys.py b/mobly/keys.py
index b561734..1987cdc 100644
--- a/mobly/keys.py
+++ b/mobly/keys.py
@@ -17,6 +17,7 @@ import enum
class Config(enum.Enum):
"""The reserved keywordss used in configurations."""
+
# Keywords for params consumed by Mobly itself.
key_mobly_params = 'MoblyParams'
key_log_path = 'LogPath'
diff --git a/mobly/logger.py b/mobly/logger.py
index ea1de12..b792cae 100644
--- a/mobly/logger.py
+++ b/mobly/logger.py
@@ -30,34 +30,25 @@ LINUX_MAX_FILENAME_LENGTH = 255
# length seems to be lower.
WINDOWS_MAX_FILENAME_LENGTH = 237
WINDOWS_RESERVED_CHARACTERS_REPLACEMENTS = {
- '<':
- '-',
- '>':
- '-',
- ':':
- '-',
- '"':
- '_',
- '/':
- '_',
- '\\':
- '_',
- '|':
- ',',
- '?':
- ',',
- '*':
- ',',
+ '<': '-',
+ '>': '-',
+ ':': '-',
+ '"': '_',
+ '/': '_',
+ '\\': '_',
+ '|': ',',
+ '?': ',',
+ '*': ',',
# Integer zero (i.e. NUL) is not a valid character.
# While integers 1-31 are also usually valid, they aren't sanitized because
# they are situationally valid.
- chr(0):
- '0',
+ chr(0): '0',
}
# Note, although the documentation does not specify as such, COM0 and LPT0 are
# also invalid/reserved filenames.
WINDOWS_RESERVED_FILENAME_REGEX = re.compile(
- r'^(CON|PRN|AUX|NUL|(COM|LPT)[0-9])(\.[^.]*)?$', re.IGNORECASE)
+ r'^(CON|PRN|AUX|NUL|(COM|LPT)[0-9])(\.[^.]*)?$', re.IGNORECASE
+)
WINDOWS_RESERVED_FILENAME_PREFIX = 'mobly_'
log_line_format = '%(asctime)s.%(msecs).03d %(levelname)s %(message)s'
@@ -201,11 +192,13 @@ def _setup_test_logger(log_path, console_level, prefix=None):
f_formatter = logging.Formatter(log_line_format, log_line_time_format)
# Write logger output to files
fh_info = logging.FileHandler(
- os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG))
+ os.path.join(log_path, records.OUTPUT_FILE_INFO_LOG)
+ )
fh_info.setFormatter(f_formatter)
fh_info.setLevel(logging.INFO)
fh_debug = logging.FileHandler(
- os.path.join(log_path, records.OUTPUT_FILE_DEBUG_LOG))
+ os.path.join(log_path, records.OUTPUT_FILE_DEBUG_LOG)
+ )
fh_debug.setFormatter(f_formatter)
fh_debug.setLevel(logging.DEBUG)
log.addHandler(ch)
@@ -241,10 +234,9 @@ def create_latest_log_alias(actual_path, alias):
utils.create_alias(actual_path, alias_path)
-def setup_test_logger(log_path,
- prefix=None,
- alias='latest',
- console_level=logging.INFO):
+def setup_test_logger(
+ log_path, prefix=None, alias='latest', console_level=logging.INFO
+):
"""Customizes the root logger for a test run.
In addition to configuring the Mobly logging handlers, this also sets two
@@ -294,7 +286,7 @@ def _truncate_filename(filename, max_length):
# This is kind of a degrenerate case where the extension is
# extremely long, in which case, just return the truncated filename.
return filename[:max_length]
- return '.'.join([filename[:max_length - len(extension) - 1], extension])
+ return '.'.join([filename[: max_length - len(extension) - 1], extension])
else:
return filename[:max_length]
diff --git a/mobly/records.py b/mobly/records.py
index 08ebe8e..10d3063 100644
--- a/mobly/records.py
+++ b/mobly/records.py
@@ -11,8 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-"""This module has classes for test result collection, and test result output.
-"""
+"""This module has classes for test result collection, and test result output."""
import collections
import copy
@@ -38,6 +37,13 @@ class Error(Exception):
"""Raised for errors in record module members."""
+class TestParentType(enum.Enum):
+ """The type of parent in a chain of executions of the same test."""
+
+ REPEAT = 'repeat'
+ RETRY = 'retry'
+
+
def uid(uid):
"""Decorator specifying the unique identifier (UID) of a test case.
@@ -56,7 +62,6 @@ def uid(uid):
raise ValueError('UID cannot be None.')
def decorate(test_func):
-
@functools.wraps(test_func)
def wrapper(*args, **kwargs):
return test_func(*args, **kwargs)
@@ -77,6 +82,7 @@ class TestSummaryEntryType(enum.Enum):
The idea is similar to how `TestResult.json_str` categorizes different
sections of a `TestResult` object in the serialized format.
"""
+
# A list of all the tests requested for a test run.
# This is dumped at the beginning of a summary file so we know what was
# requested in case the test is interrupted and the final summary is not
@@ -153,12 +159,14 @@ class TestSummaryWriter:
with io.open(self._path, 'a', encoding='utf-8') as f:
# Use safe_dump here to avoid language-specific tags in final
# output.
- yaml.safe_dump(new_content,
- f,
- explicit_start=True,
- explicit_end=True,
- allow_unicode=True,
- indent=4)
+ yaml.safe_dump(
+ new_content,
+ f,
+ explicit_start=True,
+ explicit_end=True,
+ allow_unicode=True,
+ indent=4,
+ )
class TestResultEnums:
@@ -181,6 +189,7 @@ class TestResultEnums:
RECORD_STACKTRACE = 'Stacktrace'
RECORD_SIGNATURE = 'Signature'
RECORD_RETRY_PARENT = 'Retry Parent'
+ RECORD_PARENT = 'Parent'
RECORD_POSITION = 'Position'
TEST_RESULT_PASS = 'PASS'
TEST_RESULT_FAIL = 'FAIL'
@@ -240,7 +249,8 @@ class ExceptionRecord:
exc_traceback = e.__traceback__
if exc_traceback:
self.stacktrace = ''.join(
- traceback.format_exception(e.__class__, e, exc_traceback))
+ traceback.format_exception(e.__class__, e, exc_traceback)
+ )
# Populate fields based on the type of the termination signal.
if self.is_test_signal:
self._set_details(e.details)
@@ -315,9 +325,10 @@ class TestResultRecord:
uid: User-defined unique identifier of the test.
signature: string, unique identifier of a test record, the value is
generated by Mobly.
- retry_parent: TestResultRecord, only set for retry iterations. This is the
- test result record of the previous retry iteration. Parsers can use this
- field to construct the chain of execution for each retried test.
+ retry_parent: [DEPRECATED] Use the `parent` field instead.
+ parent: tuple[TestResultRecord, TestParentType], set for multiple iterations
+ of a test. This is the test result record of the previous iteration.
+ Parsers can use this field to construct the chain of execution for each test.
termination_signal: ExceptionRecord, the main exception of the test.
extra_errors: OrderedDict, all exceptions occurred during the entire
test lifecycle. The order of occurrence is preserved.
@@ -332,6 +343,7 @@ class TestResultRecord:
self.uid = None
self.signature = None
self.retry_parent = None
+ self.parent = None
self.termination_signal = None
self.extra_errors = collections.OrderedDict()
self.result = None
@@ -358,8 +370,7 @@ class TestResultRecord:
@property
def stacktrace(self):
- """The stacktrace string for the exception that terminated the test.
- """
+ """The stacktrace string for the exception that terminated the test."""
if self.termination_signal:
return self.termination_signal.stacktrace
@@ -468,8 +479,10 @@ class TestResultRecord:
if self.result != TestResultEnums.TEST_RESULT_FAIL:
self.result = TestResultEnums.TEST_RESULT_ERROR
if position in self.extra_errors:
- raise Error('An exception is already recorded with position "%s",'
- ' cannot reuse.' % position)
+ raise Error(
+ 'An exception is already recorded with position "%s", cannot reuse.'
+ % position
+ )
if isinstance(e, ExceptionRecord):
self.extra_errors[position] = e
else:
@@ -500,12 +513,22 @@ class TestResultRecord:
d[TestResultEnums.RECORD_RESULT] = self.result
d[TestResultEnums.RECORD_UID] = self.uid
d[TestResultEnums.RECORD_SIGNATURE] = self.signature
- d[TestResultEnums.
- RECORD_RETRY_PARENT] = self.retry_parent.signature if self.retry_parent else None
+ d[TestResultEnums.RECORD_RETRY_PARENT] = (
+ self.retry_parent.signature if self.retry_parent else None
+ )
+ d[TestResultEnums.RECORD_PARENT] = (
+ {
+ 'parent': self.parent[0].signature,
+ 'type': self.parent[1].value,
+ }
+ if self.parent
+ else None
+ )
d[TestResultEnums.RECORD_EXTRAS] = self.extras
d[TestResultEnums.RECORD_DETAILS] = self.details
- d[TestResultEnums.
- RECORD_TERMINATION_SIGNAL_TYPE] = self.termination_signal_type
+ d[TestResultEnums.RECORD_TERMINATION_SIGNAL_TYPE] = (
+ self.termination_signal_type
+ )
d[TestResultEnums.RECORD_EXTRA_ERRORS] = {
key: value.to_dict() for (key, value) in self.extra_errors.items()
}
@@ -551,8 +574,9 @@ class TestResult:
A TestResult instance that's the sum of two TestResult instances.
"""
if not isinstance(r, TestResult):
- raise TypeError('Operand %s of type %s is not a TestResult.' %
- (r, type(r)))
+ raise TypeError(
+ 'Operand %s of type %s is not a TestResult.' % (r, type(r))
+ )
sum_result = TestResult()
for name in sum_result.__dict__:
r_value = getattr(r, name)
@@ -638,16 +662,19 @@ class TestResult:
count = 0
for record in self.passed:
r = record
- while r.retry_parent:
+ while r.parent is not None and r.parent[1] == TestParentType.RETRY:
count += 1
- r = r.retry_parent
+ r = r.parent[0]
return count
@property
def is_all_pass(self):
"""True if no tests failed or threw errors, False otherwise."""
- num_of_result_altering_errors = (len(self.failed) + len(self.error) -
- self._count_eventually_passing_retries())
+ num_of_result_altering_errors = (
+ len(self.failed)
+ + len(self.error)
+ - self._count_eventually_passing_retries()
+ )
if num_of_result_altering_errors == 0:
return True
return False
diff --git a/mobly/runtime_test_info.py b/mobly/runtime_test_info.py
index ed691bc..ca0eafd 100644
--- a/mobly/runtime_test_info.py
+++ b/mobly/runtime_test_info.py
@@ -40,7 +40,8 @@ class RuntimeTestInfo:
self._name = test_name
self._record = record
self._output_dir_path = utils.abs_path(
- os.path.join(log_path, self._record.signature))
+ os.path.join(log_path, self._record.signature)
+ )
@property
def name(self):
diff --git a/mobly/signals.py b/mobly/signals.py
index ef777d9..dc020f9 100644
--- a/mobly/signals.py
+++ b/mobly/signals.py
@@ -11,8 +11,7 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
-"""This module is where all the test signal classes and related utilities live.
-"""
+"""This module is where all the test signal classes and related utilities live."""
import json
@@ -38,8 +37,9 @@ class TestSignal(Exception):
json.dumps(extras)
self.extras = extras
except TypeError:
- raise TestSignalError('Extras must be json serializable. %s '
- 'is not.' % extras)
+ raise TestSignalError(
+ 'Extras must be json serializable. %s is not.' % extras
+ )
def __str__(self):
return 'Details=%s, Extras=%s' % (self.details, self.extras)
@@ -62,8 +62,7 @@ class TestSkip(TestSignal):
class TestAbortSignal(TestSignal):
- """Base class for abort signals.
- """
+ """Base class for abort signals."""
class TestAbortClass(TestAbortSignal):
diff --git a/mobly/snippet/callback_event.py b/mobly/snippet/callback_event.py
index 55471c7..ea8ee38 100644
--- a/mobly/snippet/callback_event.py
+++ b/mobly/snippet/callback_event.py
@@ -23,10 +23,12 @@ def from_dict(event_dict):
Returns:
A CallbackEvent object.
"""
- return CallbackEvent(callback_id=event_dict['callbackId'],
- name=event_dict['name'],
- creation_time=event_dict['time'],
- data=event_dict['data'])
+ return CallbackEvent(
+ callback_id=event_dict['callbackId'],
+ name=event_dict['name'],
+ creation_time=event_dict['time'],
+ data=event_dict['data'],
+ )
class CallbackEvent:
@@ -49,4 +51,5 @@ class CallbackEvent:
def __repr__(self):
return (
f'CallbackEvent(callback_id: {self.callback_id}, name: {self.name}, '
- f'creation_time: {self.creation_time}, data: {self.data})')
+ f'creation_time: {self.creation_time}, data: {self.data})'
+ )
diff --git a/mobly/snippet/callback_handler_base.py b/mobly/snippet/callback_handler_base.py
index 50465d1..95b5a4b 100644
--- a/mobly/snippet/callback_handler_base.py
+++ b/mobly/snippet/callback_handler_base.py
@@ -45,14 +45,16 @@ class CallbackHandlerBase(abc.ABC):
ret_value: any, the direct return value of the async RPC call.
"""
- def __init__(self,
- callback_id,
- event_client,
- ret_value,
- method_name,
- device,
- rpc_max_timeout_sec,
- default_timeout_sec=120):
+ def __init__(
+ self,
+ callback_id,
+ event_client,
+ ret_value,
+ method_name,
+ device,
+ rpc_max_timeout_sec,
+ default_timeout_sec=120,
+ ):
"""Initializes a callback handler base object.
Args:
@@ -74,10 +76,12 @@ class CallbackHandlerBase(abc.ABC):
self._method_name = method_name
if rpc_max_timeout_sec < default_timeout_sec:
- raise ValueError('The max timeout of a single RPC must be no smaller '
- 'than the default timeout of the callback handler. '
- f'Got rpc_max_timeout_sec={rpc_max_timeout_sec}, '
- f'default_timeout_sec={default_timeout_sec}.')
+ raise ValueError(
+ 'The max timeout of a single RPC must be no smaller '
+ 'than the default timeout of the callback handler. '
+ f'Got rpc_max_timeout_sec={rpc_max_timeout_sec}, '
+ f'default_timeout_sec={default_timeout_sec}.'
+ )
self._rpc_max_timeout_sec = rpc_max_timeout_sec
self._default_timeout_sec = default_timeout_sec
@@ -168,7 +172,8 @@ class CallbackHandlerBase(abc.ABC):
raise errors.CallbackHandlerBaseError(
self._device,
f'Specified timeout {timeout} is longer than max timeout '
- f'{self.rpc_max_timeout_sec}.')
+ f'{self.rpc_max_timeout_sec}.',
+ )
raw_event = self.callEventWaitAndGetRpc(self._id, event_name, timeout)
return callback_event.from_dict(raw_event)
@@ -223,7 +228,8 @@ class CallbackHandlerBase(abc.ABC):
raise errors.CallbackHandlerTimeoutError(
self._device,
f'Timed out after {timeout}s waiting for an "{event_name}" event that '
- f'satisfies the predicate "{predicate.__name__}".')
+ f'satisfies the predicate "{predicate.__name__}".',
+ )
def getAll(self, event_name):
"""Gets all existing events in the server with the specified identifier.
diff --git a/mobly/snippet/client_base.py b/mobly/snippet/client_base.py
index 3e046df..3a24a20 100644
--- a/mobly/snippet/client_base.py
+++ b/mobly/snippet/client_base.py
@@ -127,26 +127,34 @@ class ClientBase(abc.ABC):
self.log.debug('Starting the snippet server of %s.', self.package)
self.start_server()
- self.log.debug('Making a connection to the snippet server of %s.',
- self.package)
+ self.log.debug(
+ 'Making a connection to the snippet server of %s.', self.package
+ )
self._make_connection()
except Exception:
self.log.error(
'Error occurred trying to start and connect to the snippet server '
- 'of %s.', self.package)
+ 'of %s.',
+ self.package,
+ )
try:
self.stop()
except Exception: # pylint: disable=broad-except
# Only prints this exception and re-raises the original exception
self.log.exception(
'Failed to stop the snippet package %s after failure to start '
- 'and connect.', self.package)
+ 'and connect.',
+ self.package,
+ )
raise
- self.log.debug('Snippet package %s initialized after %.1fs.', self.package,
- time.perf_counter() - start_time)
+ self.log.debug(
+ 'Snippet package %s initialized after %.1fs.',
+ self.package,
+ time.perf_counter() - start_time,
+ )
@abc.abstractmethod
def before_starting_server(self):
@@ -271,7 +279,8 @@ class ClientBase(abc.ABC):
except Exception:
self.log.error(
'Server process running check failed, skip sending RPC method(%s).',
- rpc_func_name)
+ rpc_func_name,
+ )
raise
with self._lock:
@@ -285,12 +294,15 @@ class ClientBase(abc.ABC):
if self.verbose_logging or _MAX_RPC_RESP_LOGGING_LENGTH >= len(response):
self.log.debug('Snippet received: %s', response)
else:
- self.log.debug('Snippet received: %s... %d chars are truncated',
- response[:_MAX_RPC_RESP_LOGGING_LENGTH],
- len(response) - _MAX_RPC_RESP_LOGGING_LENGTH)
+ self.log.debug(
+ 'Snippet received: %s... %d chars are truncated',
+ response[:_MAX_RPC_RESP_LOGGING_LENGTH],
+ len(response) - _MAX_RPC_RESP_LOGGING_LENGTH,
+ )
response_decoded = self._decode_response_string_and_validate_format(
- rpc_id, response)
+ rpc_id, response
+ )
return self._handle_rpc_response(rpc_func_name, response_decoded)
@abc.abstractmethod
@@ -360,19 +372,22 @@ class ClientBase(abc.ABC):
errors.ProtocolError: if the response format is invalid.
"""
if not response:
- raise errors.ProtocolError(self._device,
- errors.ProtocolError.NO_RESPONSE_FROM_SERVER)
+ raise errors.ProtocolError(
+ self._device, errors.ProtocolError.NO_RESPONSE_FROM_SERVER
+ )
result = json.loads(response)
for field_name in RPC_RESPONSE_REQUIRED_FIELDS:
if field_name not in result:
raise errors.ProtocolError(
self._device,
- errors.ProtocolError.RESPONSE_MISSING_FIELD % field_name)
+ errors.ProtocolError.RESPONSE_MISSING_FIELD % field_name,
+ )
if result['id'] != rpc_id:
- raise errors.ProtocolError(self._device,
- errors.ProtocolError.MISMATCHED_API_ID)
+ raise errors.ProtocolError(
+ self._device, errors.ProtocolError.MISMATCHED_API_ID
+ )
return result
@@ -399,8 +414,9 @@ class ClientBase(abc.ABC):
if response['error']:
raise errors.ApiError(self._device, response['error'])
if response['callback'] is not None:
- return self.handle_callback(response['callback'], response['result'],
- rpc_func_name)
+ return self.handle_callback(
+ response['callback'], response['result'], rpc_func_name
+ )
return response['result']
@abc.abstractmethod
diff --git a/mobly/snippet/errors.py b/mobly/snippet/errors.py
index 4d41adb..6ca7197 100644
--- a/mobly/snippet/errors.py
+++ b/mobly/snippet/errors.py
@@ -51,9 +51,11 @@ class ApiError(Error):
class ProtocolError(Error):
"""Raised when there was an error in exchanging data with server."""
+
NO_RESPONSE_FROM_HANDSHAKE = 'No response from handshake.'
- NO_RESPONSE_FROM_SERVER = ('No response from server. '
- 'Check the device logcat for crashes.')
+ NO_RESPONSE_FROM_SERVER = (
+ 'No response from server. Check the device logcat for crashes.'
+ )
MISMATCHED_API_ID = 'RPC request-response ID mismatch.'
RESPONSE_MISSING_FIELD = 'Missing required field in the RPC response: %s.'
diff --git a/mobly/suite_runner.py b/mobly/suite_runner.py
index b2b2579..b0b064c 100644
--- a/mobly/suite_runner.py
+++ b/mobly/suite_runner.py
@@ -93,34 +93,45 @@ def _parse_cli_args(argv):
"""
parser = argparse.ArgumentParser(description='Mobly Suite Executable.')
group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('-c',
- '--config',
- type=str,
- metavar='<PATH>',
- help='Path to the test configuration file.')
+ group.add_argument(
+ '-c',
+ '--config',
+ type=str,
+ metavar='<PATH>',
+ help='Path to the test configuration file.',
+ )
group.add_argument(
'-l',
'--list_tests',
action='store_true',
- help='Print the names of the tests defined in a script without '
- 'executing them.')
- parser.add_argument('--tests',
- '--test_case',
- nargs='+',
- type=str,
- metavar='[ClassA[.test_a] ClassB[.test_b] ...]',
- help='A list of test classes and optional tests to execute.')
- parser.add_argument('-tb',
- '--test_bed',
- nargs='+',
- type=str,
- metavar='[<TEST BED NAME1> <TEST BED NAME2> ...]',
- help='Specify which test beds to run tests on.')
-
- parser.add_argument('-v',
- '--verbose',
- action='store_true',
- help='Set console logger level to DEBUG')
+ help=(
+ 'Print the names of the tests defined in a script without '
+ 'executing them.'
+ ),
+ )
+ parser.add_argument(
+ '--tests',
+ '--test_case',
+ nargs='+',
+ type=str,
+ metavar='[ClassA[.test_a] ClassB[.test_b] ...]',
+ help='A list of test classes and optional tests to execute.',
+ )
+ parser.add_argument(
+ '-tb',
+ '--test_bed',
+ nargs='+',
+ type=str,
+ metavar='[<TEST BED NAME1> <TEST BED NAME2> ...]',
+ help='Specify which test beds to run tests on.',
+ )
+
+ parser.add_argument(
+ '-v',
+ '--verbose',
+ action='store_true',
+ help='Set console logger level to DEBUG',
+ )
if not argv:
argv = sys.argv[1:]
return parser.parse_known_args(argv)[0]
@@ -142,8 +153,10 @@ def _find_suite_class():
if issubclass(module_member, base_suite.BaseSuite):
test_suites.append(module_member)
if len(test_suites) != 1:
- logging.error('Expected 1 test class per file, found %s.',
- [t.__name__ for t in test_suites])
+ logging.error(
+ 'Expected 1 test class per file, found %s.',
+ [t.__name__ for t in test_suites],
+ )
sys.exit(1)
return test_suites[0]
@@ -172,7 +185,7 @@ def _print_test_names(test_classes):
cls._clean_up()
print('==========> %s <==========' % cls.TAG)
for name in test_names:
- print(f"{cls.TAG}.{name}")
+ print(f'{cls.TAG}.{name}')
def run_suite_class(argv=None):
@@ -186,14 +199,16 @@ def run_suite_class(argv=None):
if cli_args.list_tests:
_print_test_names([suite_class])
sys.exit(0)
- test_configs = config_parser.load_test_config_file(cli_args.config,
- cli_args.test_bed)
+ test_configs = config_parser.load_test_config_file(
+ cli_args.config, cli_args.test_bed
+ )
config_count = len(test_configs)
if config_count != 1:
logging.error('Expect exactly one test config, found %d', config_count)
config = test_configs[0]
runner = test_runner.TestRunner(
- log_dir=config.log_path, testbed_name=config.testbed_name)
+ log_dir=config.log_path, testbed_name=config.testbed_name
+ )
suite = suite_class(runner, config)
console_level = logging.DEBUG if cli_args.verbose else logging.INFO
ok = False
@@ -229,8 +244,9 @@ def run_suite(test_classes, argv=None):
for test_class in test_classes:
if not issubclass(test_class, base_test.BaseTestClass):
logging.error(
- 'Test class %s does not extend '
- 'mobly.base_test.BaseTestClass', test_class)
+ 'Test class %s does not extend mobly.base_test.BaseTestClass',
+ test_class,
+ )
sys.exit(1)
if args.list_tests:
@@ -238,8 +254,7 @@ def run_suite(test_classes, argv=None):
sys.exit(0)
# Load test config file.
- test_configs = config_parser.load_test_config_file(args.config,
- args.test_bed)
+ test_configs = config_parser.load_test_config_file(args.config, args.test_bed)
# Find the full list of tests to execute
selected_tests = compute_selected_tests(test_classes, args.tests)
@@ -249,7 +264,7 @@ def run_suite(test_classes, argv=None):
for config in test_configs:
runner = test_runner.TestRunner(config.log_path, config.testbed_name)
with runner.mobly_logger(console_level=console_level):
- for (test_class, tests) in selected_tests.items():
+ for test_class, tests in selected_tests.items():
runner.add_test_class(config, test_class, tests)
try:
runner.run()
diff --git a/mobly/test_runner.py b/mobly/test_runner.py
index 529035f..5c97113 100644
--- a/mobly/test_runner.py
+++ b/mobly/test_runner.py
@@ -70,8 +70,9 @@ def main(argv=None):
# Execute the test class with configs.
ok = True
for config in test_configs:
- runner = TestRunner(log_dir=config.log_path,
- testbed_name=config.testbed_name)
+ runner = TestRunner(
+ log_dir=config.log_path, testbed_name=config.testbed_name
+ )
with runner.mobly_logger(console_level=console_level):
runner.add_test_class(config, test_class, tests)
try:
@@ -104,34 +105,45 @@ def parse_mobly_cli_args(argv):
"""
parser = argparse.ArgumentParser(description='Mobly Test Executable.')
group = parser.add_mutually_exclusive_group(required=True)
- group.add_argument('-c',
- '--config',
- type=str,
- metavar='<PATH>',
- help='Path to the test configuration file.')
+ group.add_argument(
+ '-c',
+ '--config',
+ type=str,
+ metavar='<PATH>',
+ help='Path to the test configuration file.',
+ )
group.add_argument(
'-l',
'--list_tests',
action='store_true',
- help='Print the names of the tests defined in a script without '
- 'executing them.')
- parser.add_argument('--tests',
- '--test_case',
- nargs='+',
- type=str,
- metavar='[test_a test_b...]',
- help='A list of tests in the test class to execute.')
- parser.add_argument('-tb',
- '--test_bed',
- nargs='+',
- type=str,
- metavar='[<TEST BED NAME1> <TEST BED NAME2> ...]',
- help='Specify which test beds to run tests on.')
-
- parser.add_argument('-v',
- '--verbose',
- action='store_true',
- help='Set console logger level to DEBUG')
+ help=(
+ 'Print the names of the tests defined in a script without '
+ 'executing them.'
+ ),
+ )
+ parser.add_argument(
+ '--tests',
+ '--test_case',
+ nargs='+',
+ type=str,
+ metavar='[test_a test_b...]',
+ help='A list of tests in the test class to execute.',
+ )
+ parser.add_argument(
+ '-tb',
+ '--test_bed',
+ nargs='+',
+ type=str,
+ metavar='[<TEST BED NAME1> <TEST BED NAME2> ...]',
+ help='Specify which test beds to run tests on.',
+ )
+
+ parser.add_argument(
+ '-v',
+ '--verbose',
+ action='store_true',
+ help='Set console logger level to DEBUG',
+ )
if not argv:
argv = sys.argv[1:]
return parser.parse_known_args(argv)[0]
@@ -150,11 +162,14 @@ def _find_test_class():
SystemExit: Raised if the number of test classes is not exactly one.
"""
try:
- return utils.find_subclass_in_module(base_test.BaseTestClass,
- sys.modules['__main__'])
+ return utils.find_subclass_in_module(
+ base_test.BaseTestClass, sys.modules['__main__']
+ )
except ValueError:
- logging.exception('Exactly one subclass of `base_test.BaseTestClass`'
- ' should be in the main file.')
+ logging.exception(
+ 'Exactly one subclass of `base_test.BaseTestClass`'
+ ' should be in the main file.'
+ )
sys.exit(1)
@@ -206,11 +221,9 @@ class TestRunner:
run it with.
"""
- def __init__(self,
- config,
- test_class,
- tests=None,
- test_class_name_suffix=None):
+ def __init__(
+ self, config, test_class, tests=None, test_class_name_suffix=None
+ ):
self.config = config
self.test_class = test_class
self.test_class_name_suffix = test_class_name_suffix
@@ -255,8 +268,9 @@ class TestRunner:
String, the generated log path.
"""
self._logger_start_time = logger.get_log_file_timestamp()
- self.root_output_path = os.path.join(self._log_dir, self._testbed_name,
- self._logger_start_time)
+ self.root_output_path = os.path.join(
+ self._log_dir, self._testbed_name, self._logger_start_time
+ )
return self.root_output_path
@property
@@ -323,10 +337,12 @@ class TestRunner:
"""
# Refresh the log path at the beginning of the logger context.
root_output_path = self._test_run_metadata.generate_test_run_log_path()
- logger.setup_test_logger(root_output_path,
- self._testbed_name,
- alias=alias,
- console_level=console_level)
+ logger.setup_test_logger(
+ root_output_path,
+ self._testbed_name,
+ alias=alias,
+ console_level=console_level,
+ )
try:
yield self._test_run_metadata.root_output_path
finally:
@@ -351,18 +367,25 @@ class TestRunner:
constructor.
"""
if self._log_dir != config.log_path:
- raise Error('TestRunner\'s log folder is "%s", but a test config with a '
- 'different log folder ("%s") was added.' %
- (self._log_dir, config.log_path))
+ raise Error(
+ 'TestRunner\'s log folder is "%s", but a test config with a '
+ 'different log folder ("%s") was added.'
+ % (self._log_dir, config.log_path)
+ )
if self._testbed_name != config.testbed_name:
- raise Error('TestRunner\'s test bed is "%s", but a test config with a '
- 'different test bed ("%s") was added.' %
- (self._testbed_name, config.testbed_name))
+ raise Error(
+ 'TestRunner\'s test bed is "%s", but a test config with a '
+ 'different test bed ("%s") was added.'
+ % (self._testbed_name, config.testbed_name)
+ )
self._test_run_infos.append(
- TestRunner._TestRunInfo(config=config,
- test_class=test_class,
- tests=tests,
- test_class_name_suffix=name_suffix))
+ TestRunner._TestRunInfo(
+ config=config,
+ test_class=test_class,
+ tests=tests,
+ test_class_name_suffix=name_suffix,
+ )
+ )
def _run_test_class(self, config, test_class, tests=None):
"""Instantiates and executes a test class.
@@ -377,8 +400,9 @@ class TestRunner:
tests: Optional list of test names within the class to execute.
"""
test_instance = test_class(config)
- logging.debug('Executing test class "%s" with config: %s',
- test_class.__name__, config)
+ logging.debug(
+ 'Executing test class "%s" with config: %s', test_class.__name__, config
+ )
try:
cls_result = test_instance.run(tests)
self.results += cls_result
@@ -412,7 +436,8 @@ class TestRunner:
utils.create_dir(self._test_run_metadata.root_output_path)
summary_writer = records.TestSummaryWriter(
- self._test_run_metadata.summary_file_path)
+ self._test_run_metadata.summary_file_path
+ )
# When a SIGTERM is received during the execution of a test, the Mobly test
# immediately terminates without executing any of the finally blocks. This
@@ -432,24 +457,35 @@ class TestRunner:
test_config = test_run_info.config.copy()
test_config.log_path = self._test_run_metadata.root_output_path
test_config.summary_writer = summary_writer
- test_config.test_class_name_suffix = test_run_info.test_class_name_suffix
+ test_config.test_class_name_suffix = (
+ test_run_info.test_class_name_suffix
+ )
try:
- self._run_test_class(config=test_config,
- test_class=test_run_info.test_class,
- tests=test_run_info.tests)
+ self._run_test_class(
+ config=test_config,
+ test_class=test_run_info.test_class,
+ tests=test_run_info.tests,
+ )
except signals.TestAbortAll as e:
logging.warning('Abort all subsequent test classes. Reason: %s', e)
raise
finally:
- summary_writer.dump(self.results.summary_dict(),
- records.TestSummaryEntryType.SUMMARY)
+ summary_writer.dump(
+ self.results.summary_dict(), records.TestSummaryEntryType.SUMMARY
+ )
self._test_run_metadata.set_end_point()
# Show the test run summary.
summary_lines = [
f'Summary for test run {self._test_run_metadata.run_id}:',
f'Total time elapsed {self._test_run_metadata.time_elapsed_sec}s',
- f'Artifacts are saved in "{self._test_run_metadata.root_output_path}"',
- f'Test summary saved in "{self._test_run_metadata.summary_file_path}"',
- f'Test results: {self.results.summary_str()}'
+ (
+ 'Artifacts are saved in'
+ f' "{self._test_run_metadata.root_output_path}"'
+ ),
+ (
+ 'Test summary saved in'
+ f' "{self._test_run_metadata.summary_file_path}"'
+ ),
+ f'Test results: {self.results.summary_str()}',
]
logging.info('\n'.join(summary_lines))
diff --git a/mobly/utils.py b/mobly/utils.py
index 7d26496..02125ed 100644
--- a/mobly/utils.py
+++ b/mobly/utils.py
@@ -20,27 +20,20 @@ import inspect
import io
import logging
import os
-import pipes
import platform
import random
import re
+import shlex
import signal
import string
import subprocess
import threading
import time
import traceback
-from typing import Tuple, overload
+from typing import Literal, Tuple, overload
import portpicker
-# TODO(#851): Remove this try/except statement and typing_extensions from
-# install_requires when Python 3.8 is the minimum version we support.
-try:
- from typing import Literal
-except ImportError:
- from typing_extensions import Literal
-
# File name length is limited to 255 chars on some OS, so we need to make sure
# the file names we output fits within the limit.
MAX_FILENAME_LEN = 255
@@ -75,7 +68,7 @@ GMT_to_olson = {
'GMT+12': 'Pacific/Fiji',
'GMT+13': 'Pacific/Tongatapu',
'GMT-11': 'Pacific/Midway',
- 'GMT-10': 'Pacific/Honolulu'
+ 'GMT-10': 'Pacific/Honolulu',
}
@@ -127,6 +120,7 @@ def create_alias(target_path, alias_path):
os.remove(alias_path)
if platform.system() == 'Windows':
from win32com import client
+
shell = client.Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(alias_path)
shortcut.Targetpath = target_path
@@ -280,19 +274,23 @@ def _collect_process_tree(starting_pid):
while stack:
pid = stack.pop()
try:
- ps_results = subprocess.check_output([
- 'ps',
- '-o',
- 'pid',
- '--ppid',
- str(pid),
- '--noheaders',
- ]).decode().strip()
+ ps_results = (
+ subprocess.check_output([
+ 'ps',
+ '-o',
+ 'pid',
+ '--ppid',
+ str(pid),
+ '--noheaders',
+ ])
+ .decode()
+ .strip()
+ )
except subprocess.CalledProcessError:
# Ignore if there is not child process.
continue
- children_pid_list = list(map(int, ps_results.split('\n ')))
+ children_pid_list = [int(p.strip()) for p in ps_results.split('\n')]
stack.extend(children_pid_list)
ret.extend(children_pid_list)
@@ -358,7 +356,8 @@ def concurrent_exec(func, param_list, max_workers=30, raise_on_exception=False):
`raise_on_exception` is True.
"""
with concurrent.futures.ThreadPoolExecutor(
- max_workers=max_workers) as executor:
+ max_workers=max_workers
+ ) as executor:
# Start the load operations and mark each future with its params
future_to_params = {executor.submit(func, *p): p for p in param_list}
return_vals = []
@@ -368,55 +367,64 @@ def concurrent_exec(func, param_list, max_workers=30, raise_on_exception=False):
try:
return_vals.append(future.result())
except Exception as exc: # pylint: disable=broad-except
- logging.exception('%s generated an exception: %s', params,
- traceback.format_exc())
+ logging.exception(
+ '%s generated an exception: %s', params, traceback.format_exc()
+ )
return_vals.append(exc)
exceptions.append(exc)
if raise_on_exception and exceptions:
error_messages = []
for exception in exceptions:
- error_messages.append(''.join(
- traceback.format_exception(exception.__class__, exception,
- exception.__traceback__)))
+ error_messages.append(
+ ''.join(
+ traceback.format_exception(
+ exception.__class__, exception, exception.__traceback__
+ )
+ )
+ )
raise RuntimeError('\n\n'.join(error_messages))
return return_vals
# Provide hint for pytype checker to avoid the Union[bytes, str] case.
@overload
-def run_command(cmd,
- stdout=...,
- stderr=...,
- shell=...,
- timeout=...,
- cwd=...,
- env=...,
- universal_newlines: Literal[False] = ...
- ) -> Tuple[int, bytes, bytes]:
+def run_command(
+ cmd,
+ stdout=...,
+ stderr=...,
+ shell=...,
+ timeout=...,
+ cwd=...,
+ env=...,
+ universal_newlines: Literal[False] = ...,
+) -> Tuple[int, bytes, bytes]:
...
@overload
-def run_command(cmd,
- stdout=...,
- stderr=...,
- shell=...,
- timeout=...,
- cwd=...,
- env=...,
- universal_newlines: Literal[True] = ...
- ) -> Tuple[int, str, str]:
+def run_command(
+ cmd,
+ stdout=...,
+ stderr=...,
+ shell=...,
+ timeout=...,
+ cwd=...,
+ env=...,
+ universal_newlines: Literal[True] = ...,
+) -> Tuple[int, str, str]:
...
-def run_command(cmd,
- stdout=None,
- stderr=None,
- shell=False,
- timeout=None,
- cwd=None,
- env=None,
- universal_newlines=False):
+def run_command(
+ cmd,
+ stdout=None,
+ stderr=None,
+ shell=False,
+ timeout=None,
+ cwd=None,
+ env=None,
+ universal_newlines=False,
+):
"""Runs a command in a subprocess.
This function is very similar to subprocess.check_output. The main
@@ -457,13 +465,15 @@ def run_command(cmd,
stdout = subprocess.PIPE
if stderr is None:
stderr = subprocess.PIPE
- process = subprocess.Popen(cmd,
- stdout=stdout,
- stderr=stderr,
- shell=shell,
- cwd=cwd,
- env=env,
- universal_newlines=universal_newlines)
+ process = subprocess.Popen(
+ cmd,
+ stdout=stdout,
+ stderr=stderr,
+ shell=shell,
+ cwd=cwd,
+ env=env,
+ universal_newlines=universal_newlines,
+ )
timer = None
timer_triggered = threading.Event()
if timeout and timeout > 0:
@@ -482,10 +492,9 @@ def run_command(cmd,
if timer is not None:
timer.cancel()
if timer_triggered.is_set():
- raise subprocess.TimeoutExpired(cmd=cmd,
- timeout=timeout,
- output=out,
- stderr=err)
+ raise subprocess.TimeoutExpired(
+ cmd=cmd, timeout=timeout, output=out, stderr=err
+ )
return process.returncode, out, err
@@ -510,12 +519,14 @@ def start_standing_subprocess(cmd, shell=False, env=None):
The subprocess that was started.
"""
logging.debug('Starting standing subprocess with: %s', cmd)
- proc = subprocess.Popen(cmd,
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- shell=shell,
- env=env)
+ proc = subprocess.Popen(
+ cmd,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ shell=shell,
+ env=env,
+ )
# Leaving stdin open causes problems for input, e.g. breaking the
# code.inspect() shell (http://stackoverflow.com/a/25512460/1612937), so
# explicitly close it assuming it is not needed for standing subprocesses.
@@ -585,6 +596,8 @@ def wait_for_standing_subprocess(proc, timeout=None):
def get_available_host_port():
"""Gets a host port number available for adb forward.
+ DEPRECATED: This method is unreliable. Pass `tcp:0` to adb forward instead.
+
Returns:
An integer representing a port number on the host available for adb
forward.
@@ -592,8 +605,14 @@ def get_available_host_port():
Raises:
Error: when no port is found after MAX_PORT_ALLOCATION_RETRY times.
"""
+ logging.warning(
+ 'The method mobly.utils.get_available_host_port is deprecated because it '
+ 'is unreliable. Pass "tcp:0" to adb forward instead.'
+ )
+
# Only import adb module if needed.
from mobly.controllers.android_device_lib import adb
+
port = portpicker.pick_unused_port()
if not adb.is_adb_available():
return port
@@ -603,8 +622,11 @@ def get_available_host_port():
if port not in adb.list_occupied_adb_ports():
return port
port = portpicker.pick_unused_port()
- raise Error('Failed to find available port after {} retries'.format(
- MAX_PORT_ALLOCATION_RETRY))
+ raise Error(
+ 'Failed to find available port after {} retries'.format(
+ MAX_PORT_ALLOCATION_RETRY
+ )
+ )
def grep(regex, output):
@@ -642,7 +664,7 @@ def cli_cmd_to_string(args):
if isinstance(args, str):
# Return directly if it's already a string.
return args
- return ' '.join([pipes.quote(arg) for arg in args])
+ return ' '.join([shlex.quote(arg) for arg in args])
def get_settable_properties(cls):
@@ -696,6 +718,7 @@ def find_subclass_in_module(base_class, module):
subclasses = find_subclasses_in_module([base_class], module)
if len(subclasses) != 1:
raise ValueError(
- 'Expected 1 subclass of %s per module, found %s.' %
- (base_class.__name__, [subclass.__name__ for subclass in subclasses]))
+ 'Expected 1 subclass of %s per module, found %s.'
+ % (base_class.__name__, [subclass.__name__ for subclass in subclasses])
+ )
return subclasses[0]
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..47bbbfc
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,44 @@
+[build-system]
+requires = [ "setuptools>=61.2",]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "mobly"
+version = "1.12.3"
+description = "Automation framework for special end-to-end test cases"
+requires-python = ">=3.11"
+dependencies = [ "portpicker", "pywin32; platform_system == \"Windows\"", "pyyaml",]
+
+[[project.maintainers]]
+name = "Ang Li"
+email = "mobly-github@googlegroups.com"
+
+[project.license]
+text = "Apache2.0"
+
+[project.urls]
+Homepage = "https://github.com/google/mobly"
+Download = "https://github.com/google/mobly/tarball/1.12.3"
+
+[project.optional-dependencies]
+testing = [ "mock", "pytest", "pytz",]
+
+[tool.setuptools]
+include-package-data = false
+script-files = [ "tools/sl4a_shell.py", "tools/snippet_shell.py",]
+
+[tool.pyink]
+line-length = 80
+preview = true
+pyink-indentation = 2
+pyink-use-majority-quotes = true
+extend-exclude = '.*\/venv/.*|.*\/\.tox\/.*'
+
+[tool.pytest.ini_options]
+python_classes = [ "*Test",]
+python_files = [ "*_test.py",]
+testpaths = [ "tests/mobly",]
+
+[tool.setuptools.packages.find]
+exclude = [ "tests",]
+namespaces = false
diff --git a/setup.cfg b/setup.cfg
deleted file mode 100644
index 3b9eef9..0000000
--- a/setup.cfg
+++ /dev/null
@@ -1,6 +0,0 @@
-[metadata]
-description_file = README.md
-[tool:pytest]
-python_classes = *Test
-python_files = *_test.py
-testpaths = tests/mobly
diff --git a/setup.py b/setup.py
deleted file mode 100755
index e99a054..0000000
--- a/setup.py
+++ /dev/null
@@ -1,70 +0,0 @@
-# Copyright 2016 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-import platform
-import setuptools
-from setuptools.command import test
-import sys
-
-install_requires = [
- 'portpicker',
- 'pyyaml',
- 'typing_extensions>=4.1.1; python_version<"3.8"',
-]
-
-if platform.system() == 'Windows':
- install_requires.append('pywin32')
-
-
-class PyTest(test.test):
- """Class used to execute unit tests using PyTest. This allows us to execute
- unit tests without having to install the package.
- """
-
- def finalize_options(self):
- test.test.finalize_options(self)
- self.test_args = ['-x', "tests/mobly"]
- self.test_suite = True
-
- def run_tests(self):
- import pytest
- errno = pytest.main(self.test_args)
- sys.exit(errno)
-
-
-def main():
- setuptools.setup(
- name='mobly',
- version='1.12.2',
- maintainer='Ang Li',
- maintainer_email='mobly-github@googlegroups.com',
- description='Automation framework for special end-to-end test cases',
- license='Apache2.0',
- url='https://github.com/google/mobly',
- download_url='https://github.com/google/mobly/tarball/1.12.2',
- packages=setuptools.find_packages(exclude=['tests']),
- include_package_data=False,
- scripts=['tools/sl4a_shell.py', 'tools/snippet_shell.py'],
- tests_require=[
- 'mock',
- 'pytest',
- 'pytz',
- ],
- install_requires=install_requires,
- cmdclass={'test': PyTest},
- )
-
-
-if __name__ == '__main__':
- main()
diff --git a/tests/lib/integration_test.py b/tests/lib/integration_test.py
index 0a1cf87..905caa6 100755
--- a/tests/lib/integration_test.py
+++ b/tests/lib/integration_test.py
@@ -28,13 +28,16 @@ class IntegrationTest(base_test.BaseTestClass):
def test_hello_world(self):
asserts.assert_equal(self.user_params['icecream'], 42)
asserts.assert_equal(self.user_params['extra_param'], 'haha')
- logging.info('This is a bare minimal test to make sure the basic MOBLY'
- ' test flow works.')
+ logging.info(
+ 'This is a bare minimal test to make sure the basic MOBLY'
+ ' test flow works.'
+ )
asserts.explicit_pass(
'Hello World',
# Use a unicode string here to make sure the full log pipeline
# works with unicode.
- extras=u'\u2022')
+ extras='\u2022',
+ )
if __name__ == '__main__':
diff --git a/tests/lib/jsonrpc_client_test_base.py b/tests/lib/jsonrpc_client_test_base.py
index 3124630..7ea0eeb 100755
--- a/tests/lib/jsonrpc_client_test_base.py
+++ b/tests/lib/jsonrpc_client_test_base.py
@@ -26,21 +26,26 @@ class JsonRpcClientTestBase(unittest.TestCase):
MOCK_RESP = (
b'{"id": 0, "result": 123, "error": null, "status": 1, "uid": 1, '
- b'"callback": null}')
+ b'"callback": null}'
+ )
MOCK_RESP_WITHOUT_CALLBACK = (
- b'{"id": 0, "result": 123, "error": null, "status": 1, "uid": 1}')
+ b'{"id": 0, "result": 123, "error": null, "status": 1, "uid": 1}'
+ )
MOCK_RESP_TEMPLATE = (
'{"id": %d, "result": 123, "error": null, "status": 1, "uid": 1, '
- '"callback": null}')
+ '"callback": null}'
+ )
MOCK_RESP_UNKNOWN_STATUS = (
- b'{"id": 0, "result": 123, "error": null, "status": 0, '
- b'"callback": null}')
+ b'{"id": 0, "result": 123, "error": null, "status": 0, "callback": null}'
+ )
MOCK_RESP_WITH_CALLBACK = (
b'{"id": 0, "result": 123, "error": null, "status": 1, "uid": 1, '
- b'"callback": "1-0"}')
+ b'"callback": "1-0"}'
+ )
MOCK_RESP_WITH_ERROR = b'{"id": 0, "error": 1, "status": 1, "uid": 1}'
MOCK_RESP_FLEXIABLE_RESULT_LENGTH = (
- '{"id": 0, "result": "%s", "error": null, "status": 0, "callback": null}')
+ '{"id": 0, "result": "%s", "error": null, "status": 0, "callback": null}'
+ )
class MockSocketFile:
diff --git a/tests/lib/mock_android_device.py b/tests/lib/mock_android_device.py
index 9d14991..cbc61f8 100755
--- a/tests/lib/mock_android_device.py
+++ b/tests/lib/mock_android_device.py
@@ -29,7 +29,7 @@ DEFAULT_MOCK_PROPERTIES = {
'ro.build.version.sdk': '28',
'ro.product.name': 'FakeModel',
'ro.debuggable': '1',
- 'sys.boot_completed': "1",
+ 'sys.boot_completed': '1',
'ro.build.characteristics': 'emulator,phone',
'ro.hardware': 'marlin',
}
@@ -50,7 +50,7 @@ def get_mock_ads(num):
"""
ads = []
for i in range(num):
- ad = mock.MagicMock(name="AndroidDevice", serial=str(i), h_port=None)
+ ad = mock.MagicMock(name='AndroidDevice', serial=str(i), h_port=None)
ad.skip_logcat = False
ads.append(ad)
return ads
@@ -63,7 +63,7 @@ def get_all_instances():
def get_instances(serials):
ads = []
for serial in serials:
- ad = mock.MagicMock(name="AndroidDevice", serial=serial, h_port=None)
+ ad = mock.MagicMock(name='AndroidDevice', serial=serial, h_port=None)
ads.append(ad)
return ads
@@ -79,13 +79,15 @@ def list_adb_devices():
class MockAdbProxy:
"""Mock class that swaps out calls to adb with mock calls."""
- def __init__(self,
- serial='',
- fail_br=False,
- fail_br_before_N=False,
- mock_properties=None,
- installed_packages=None,
- instrumented_packages=None):
+ def __init__(
+ self,
+ serial='',
+ fail_br=False,
+ fail_br_before_N=False,
+ mock_properties=None,
+ installed_packages=None,
+ instrumented_packages=None,
+ ):
self.serial = serial
self.fail_br = fail_br
self.fail_br_before_N = fail_br_before_N
@@ -103,28 +105,31 @@ class MockAdbProxy:
self.instrumented_packages = instrumented_packages
def shell(self, params, timeout=None):
- if params == "id -u":
- return b"root"
- elif params == "bugreportz":
+ if params == 'id -u':
+ return b'root'
+ elif params == 'bugreportz':
if self.fail_br:
- return b"OMG I died!\n"
+ return b'OMG I died!\n'
return b'OK:/path/bugreport.zip\n'
- elif params == "bugreportz -v":
+ elif params == 'bugreportz -v':
if self.fail_br_before_N:
- return b"/system/bin/sh: bugreportz: not found"
+ return b'/system/bin/sh: bugreportz: not found'
return b'1.1'
elif 'pm list package' in params:
packages = self.installed_packages + [
package for package, _, _ in self.instrumented_packages
]
- return bytes('\n'.join(['package:%s' % package for package in packages]),
- 'utf-8')
+ return bytes(
+ '\n'.join(['package:%s' % package for package in packages]), 'utf-8'
+ )
elif 'pm list instrumentation' in params:
return bytes(
'\n'.join([
'instrumentation:%s/%s (target=%s)' % (package, runner, target)
for package, runner, target in self.instrumented_packages
- ]), 'utf-8')
+ ]),
+ 'utf-8',
+ )
elif 'which' in params:
return b''
@@ -138,8 +143,11 @@ class MockAdbProxy:
def bugreport(self, args, shell=False, timeout=None):
expected = os.path.join(
- logging.log_path, 'AndroidDevice%s' % self.serial, 'BugReports',
- 'bugreport,test_something,%s,fakemodel,sometime' % self.serial)
+ logging.log_path,
+ 'AndroidDevice%s' % self.serial,
+ 'BugReports',
+ 'bugreport,test_something,%s,fakemodel,sometime' % self.serial,
+ )
if expected not in args:
raise Error('"Expected "%s", got "%s"' % (expected, args))
@@ -162,10 +170,9 @@ class MockFastbootProxy:
self.serial = serial
def devices(self):
- return b"xxxx device\nyyyy device"
+ return b'xxxx device\nyyyy device'
def __getattr__(self, name):
-
def fastboot_call(*args):
arg_str = ' '.join(str(elem) for elem in args)
return arg_str
diff --git a/tests/lib/mock_instrumentation_test.py b/tests/lib/mock_instrumentation_test.py
index be3d90e..ee1ee6a 100644
--- a/tests/lib/mock_instrumentation_test.py
+++ b/tests/lib/mock_instrumentation_test.py
@@ -24,7 +24,8 @@ MOCK_TEST_PACKAGE = 'com.my.package.test'
class MockInstrumentationTest(
- base_instrumentation_test.BaseInstrumentationTestClass):
+ base_instrumentation_test.BaseInstrumentationTestClass
+):
def __init__(self, tmp_dir, user_params={}):
mock_test_run_configs = config_parser.TestRunConfig()
@@ -35,7 +36,6 @@ class MockInstrumentationTest(
super().__init__(mock_test_run_configs)
def run_mock_instrumentation_test(self, instrumentation_output, prefix):
-
def fake_instrument(package, options=None, runner=None, handler=None):
for line in instrumentation_output.splitlines():
handler(line)
@@ -44,6 +44,6 @@ class MockInstrumentationTest(
mock_device = mock.Mock(spec=android_device.AndroidDevice)
mock_device.adb = mock.Mock(spec=adb.AdbProxy)
mock_device.adb.instrument = fake_instrument
- return self.run_instrumentation_test(mock_device,
- MOCK_TEST_PACKAGE,
- prefix=prefix)
+ return self.run_instrumentation_test(
+ mock_device, MOCK_TEST_PACKAGE, prefix=prefix
+ )
diff --git a/tests/lib/mock_second_controller.py b/tests/lib/mock_second_controller.py
index 3f32349..aef70b3 100644
--- a/tests/lib/mock_second_controller.py
+++ b/tests/lib/mock_second_controller.py
@@ -54,7 +54,7 @@ class AnotherMagicDevice:
return self.magic
def set_magic(self, extra_magic):
- self.magic['extra_magic'] = extra_magic
+ self.magic["extra_magic"] = extra_magic
def who_am_i(self):
return {"MyOtherMagic": self.magic}
diff --git a/tests/lib/utils.py b/tests/lib/utils.py
index 904459c..3bbe43c 100644
--- a/tests/lib/utils.py
+++ b/tests/lib/utils.py
@@ -34,5 +34,6 @@ def validate_test_result(result):
for bucket_list, expected_enum in buckets:
for record in bucket_list:
if record.result != expected_enum:
- raise AssertionError('Expected result %s, got %s.' %
- (expected_enum, record.result))
+ raise AssertionError(
+ 'Expected result %s, got %s.' % (expected_enum, record.result)
+ )
diff --git a/tests/mobly/asserts_test.py b/tests/mobly/asserts_test.py
index 662173f..3713185 100755
--- a/tests/mobly/asserts_test.py
+++ b/tests/mobly/asserts_test.py
@@ -58,11 +58,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_almost_equal_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
- asserts.assert_almost_equal(1,
- 2,
- delta=0.1,
- msg='Message',
- extras='Extras')
+ asserts.assert_almost_equal(
+ 1, 2, delta=0.1, msg='Message', extras='Extras'
+ )
self.assertRegex(cm.exception.details, r'1 != 2 within 0\.1 delta.*Message')
self.assertEqual(cm.exception.extras, 'Extras')
@@ -77,11 +75,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_not_almost_equal_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
- asserts.assert_not_almost_equal(1,
- 2,
- delta=1,
- msg='Message',
- extras='Extras')
+ asserts.assert_not_almost_equal(
+ 1, 2, delta=1, msg='Message', extras='Extras'
+ )
self.assertRegex(cm.exception.details, r'1 == 2 within 1 delta.*Message')
self.assertEqual(cm.exception.extras, 'Extras')
@@ -116,8 +112,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_not_in_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_not_in(1, [1, 2, 3], msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- '1 unexpectedly found in [1, 2, 3] Message')
+ self.assertEqual(
+ cm.exception.details, '1 unexpectedly found in [1, 2, 3] Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_is_pass(self):
@@ -131,8 +128,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_is_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_is(_OBJECT_1, _OBJECT_2, msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- f'{_OBJECT_1} is not {_OBJECT_2} Message')
+ self.assertEqual(
+ cm.exception.details, f'{_OBJECT_1} is not {_OBJECT_2} Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_is_not_pass(self):
@@ -141,17 +139,18 @@ class AssertsTest(unittest.TestCase):
def test_assert_is_not_fail(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_is_not(_OBJECT_1, _OBJECT_1)
- self.assertEqual(cm.exception.details,
- f'unexpectedly identical: {_OBJECT_1}')
+ self.assertEqual(
+ cm.exception.details, f'unexpectedly identical: {_OBJECT_1}'
+ )
def test_assert_is_not_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
- asserts.assert_is_not(_OBJECT_1,
- _OBJECT_1,
- msg='Message',
- extras='Extras')
- self.assertEqual(cm.exception.details,
- f'unexpectedly identical: {_OBJECT_1} Message')
+ asserts.assert_is_not(
+ _OBJECT_1, _OBJECT_1, msg='Message', extras='Extras'
+ )
+ self.assertEqual(
+ cm.exception.details, f'unexpectedly identical: {_OBJECT_1} Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_count_equal_pass(self):
@@ -162,15 +161,20 @@ class AssertsTest(unittest.TestCase):
asserts.assert_count_equal([3, 3], [3])
self.assertEqual(
cm.exception.details,
- 'Element counts were not equal:\nFirst has 2, Second has 1: 3')
+ 'Element counts were not equal:\nFirst has 2, Second has 1: 3',
+ )
def test_assert_count_equal_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_count_equal((3, 3), (4, 4), msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- ('Element counts were not equal:\n'
- 'First has 2, Second has 0: 3\n'
- 'First has 0, Second has 2: 4 Message'))
+ self.assertEqual(
+ cm.exception.details,
+ (
+ 'Element counts were not equal:\n'
+ 'First has 2, Second has 0: 3\n'
+ 'First has 0, Second has 2: 4 Message'
+ ),
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_less_pass(self):
@@ -199,8 +203,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_less_equal_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_less_equal(2, 1, msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- '2 not less than or equal to 1 Message')
+ self.assertEqual(
+ cm.exception.details, '2 not less than or equal to 1 Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_greater_pass(self):
@@ -229,8 +234,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_greater_equal_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_greater_equal(1, 2, msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- '1 not greater than or equal to 2 Message')
+ self.assertEqual(
+ cm.exception.details, '1 not greater than or equal to 2 Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_is_none_pass(self):
@@ -274,8 +280,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_is_instance_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_is_instance(1.0, int, msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- f'1.0 is not an instance of {int} Message')
+ self.assertEqual(
+ cm.exception.details, f'1.0 is not an instance of {int} Message'
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_not_is_instance_pass(self):
@@ -291,8 +298,9 @@ class AssertsTest(unittest.TestCase):
def test_assert_not_is_instance_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
asserts.assert_not_is_instance('foo', str, msg='Message', extras='Extras')
- self.assertEqual(cm.exception.details,
- f"'foo' is an instance of {str} Message")
+ self.assertEqual(
+ cm.exception.details, f"'foo' is an instance of {str} Message"
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_regex_pass(self):
@@ -303,18 +311,18 @@ class AssertsTest(unittest.TestCase):
asserts.assert_regex('Big socks', r'(r|m)ocks')
self.assertEqual(
cm.exception.details,
- "Regex didn't match: '(r|m)ocks' not found in 'Big socks'")
+ "Regex didn't match: '(r|m)ocks' not found in 'Big socks'",
+ )
def test_assert_regex_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
- asserts.assert_regex('Big socks',
- r'(r|m)ocks',
- msg='Message',
- extras='Extras')
+ asserts.assert_regex(
+ 'Big socks', r'(r|m)ocks', msg='Message', extras='Extras'
+ )
self.assertEqual(
cm.exception.details,
- ("Regex didn't match: '(r|m)ocks' not found in 'Big socks' "
- 'Message'))
+ "Regex didn't match: '(r|m)ocks' not found in 'Big socks' Message",
+ )
self.assertEqual(cm.exception.extras, 'Extras')
def test_assert_not_regex_pass(self):
@@ -325,18 +333,18 @@ class AssertsTest(unittest.TestCase):
asserts.assert_not_regex('Big rocks', r'(r|m)ocks')
self.assertEqual(
cm.exception.details,
- "Regex matched: 'rocks' matches '(r|m)ocks' in 'Big rocks'")
+ "Regex matched: 'rocks' matches '(r|m)ocks' in 'Big rocks'",
+ )
def test_assert_not_regex_fail_with_msg_and_extras(self):
with self.assertRaises(signals.TestFailure) as cm:
- asserts.assert_not_regex('Big mocks',
- r'(r|m)ocks',
- msg='Message',
- extras='Extras')
+ asserts.assert_not_regex(
+ 'Big mocks', r'(r|m)ocks', msg='Message', extras='Extras'
+ )
self.assertEqual(
cm.exception.details,
- ("Regex matched: 'mocks' matches '(r|m)ocks' in 'Big mocks' "
- 'Message'))
+ "Regex matched: 'mocks' matches '(r|m)ocks' in 'Big mocks' Message",
+ )
self.assertEqual(cm.exception.extras, 'Extras')
diff --git a/tests/mobly/base_instrumentation_test_test.py b/tests/mobly/base_instrumentation_test_test.py
index c336b90..fcf52fb 100755
--- a/tests/mobly/base_instrumentation_test_test.py
+++ b/tests/mobly/base_instrumentation_test_test.py
@@ -57,10 +57,12 @@ class BaseInstrumentationTestTest(unittest.TestCase):
def tearDown(self):
shutil.rmtree(self.tmp_dir)
- def assert_parse_instrumentation_options(self, user_params,
- expected_instrumentation_options):
+ def assert_parse_instrumentation_options(
+ self, user_params, expected_instrumentation_options
+ ):
mit = mock_instrumentation_test.MockInstrumentationTest(
- self.tmp_dir, user_params)
+ self.tmp_dir, user_params
+ )
instrumentation_options = mit.parse_instrumentation_options(mit.user_params)
self.assertEqual(instrumentation_options, expected_instrumentation_options)
@@ -82,10 +84,7 @@ class BaseInstrumentationTestTest(unittest.TestCase):
'instrumentation_option_key1': 'value1',
'instrumentation_option_key2': 'value2',
},
- {
- 'key1': 'value1',
- 'key2': 'value2'
- },
+ {'key1': 'value1', 'key2': 'value2'},
)
def test_parse_instrumentation_options_with_mixed_user_params(self):
@@ -96,10 +95,7 @@ class BaseInstrumentationTestTest(unittest.TestCase):
'instrumentation_option_key1': 'value1',
'instrumentation_option_key2': 'value2',
},
- {
- 'key1': 'value1',
- 'key2': 'value2'
- },
+ {'key1': 'value1', 'key2': 'value2'},
)
def run_instrumentation_test(self, instrumentation_output, prefix=None):
@@ -107,7 +103,8 @@ class BaseInstrumentationTestTest(unittest.TestCase):
result = InstrumentationResult()
try:
result.completed_and_passed = mit.run_mock_instrumentation_test(
- instrumentation_output, prefix=prefix)
+ instrumentation_output, prefix=prefix
+ )
except signals.TestError as e:
result.error = e
result.executed = mit.results.executed
@@ -116,29 +113,34 @@ class BaseInstrumentationTestTest(unittest.TestCase):
def assert_equal_test(self, actual_test, expected_test):
(expected_test_name, expected_signal) = expected_test
- self.assertEqual(actual_test.test_class,
- MOCK_INSTRUMENTATION_TEST_CLASS_NAME)
+ self.assertEqual(
+ actual_test.test_class, MOCK_INSTRUMENTATION_TEST_CLASS_NAME
+ )
self.assertEqual(actual_test.test_name, expected_test_name)
- self.assertIsInstance(actual_test.termination_signal.exception,
- expected_signal)
-
- def assert_run_instrumentation_test(self,
- instrumentation_output,
- expected_executed=[],
- expected_skipped=[],
- expected_completed_and_passed=False,
- expected_has_error=False,
- prefix=None,
- expected_executed_times=[]):
- result = self.run_instrumentation_test(bytes(instrumentation_output,
- 'utf-8'),
- prefix=prefix)
+ self.assertIsInstance(
+ actual_test.termination_signal.exception, expected_signal
+ )
+
+ def assert_run_instrumentation_test(
+ self,
+ instrumentation_output,
+ expected_executed=[],
+ expected_skipped=[],
+ expected_completed_and_passed=False,
+ expected_has_error=False,
+ prefix=None,
+ expected_executed_times=[],
+ ):
+ result = self.run_instrumentation_test(
+ bytes(instrumentation_output, 'utf-8'), prefix=prefix
+ )
if expected_has_error:
self.assertIsInstance(result.error, signals.TestError)
else:
self.assertIsNone(result.error)
- self.assertEqual(result.completed_and_passed,
- expected_completed_and_passed)
+ self.assertEqual(
+ result.completed_and_passed, expected_completed_and_passed
+ )
self.assertEqual(len(result.executed), len(expected_executed))
for actual_test, expected_test in zip(result.executed, expected_executed):
self.assert_equal_test(actual_test, expected_test)
@@ -146,8 +148,9 @@ class BaseInstrumentationTestTest(unittest.TestCase):
for actual_test, expected_test in zip(result.skipped, expected_skipped):
self.assert_equal_test(actual_test, expected_test)
if expected_executed_times:
- for actual_test, expected_time in zip(result.executed,
- expected_executed_times):
+ for actual_test, expected_time in zip(
+ result.executed, expected_executed_times
+ ):
(expected_begin_time, expected_end_time) = expected_time
self.assertEqual(actual_test.begin_time, expected_begin_time)
self.assertEqual(actual_test.end_time, expected_end_time)
@@ -173,14 +176,16 @@ am task lock: bring <TASK_ID> to the front and don't allow other tasks to run.
Error: Bad component name: /
"""
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_has_error=True
+ )
def test_run_instrumentation_test_with_no_output(self):
instrumentation_output = """\
"""
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_has_error=True
+ )
def test_run_instrumentation_test_with_missing_test_package(self):
instrumentation_output = """\
@@ -194,8 +199,9 @@ android.util.AndroidException: INSTRUMENTATION_FAILED: com.my.package.test/com.m
INSTRUMENTATION_STATUS: id=ActivityManagerService
INSTRUMENTATION_STATUS: Error=Unable to find instrumentation info for: ComponentInfo{com.my.package.test/com.my.package.test.runner.MyRunner}
INSTRUMENTATION_STATUS_CODE: -1"""
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_has_error=True
+ )
def test_run_instrumentation_test_with_missing_runner(self):
instrumentation_output = """\
@@ -209,19 +215,22 @@ INSTRUMENTATION_STATUS_CODE: -1
at com.android.commands.am.Am.main(Am.java:124)
at com.android.internal.os.RuntimeInit.nativeFinishInit(Native Method)
at com.android.internal.os.RuntimeInit.main(RuntimeInit.java:262)"""
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_has_error=True
+ )
def test_run_instrumentation_test_with_no_tests(self):
instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_completed_and_passed=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_completed_and_passed=True
+ )
@mock.patch('logging.info')
def test_run_instrumentation_test_logs_correctly(self, mock_info_logger):
instrumentation_output = MOCK_EMPTY_INSTRUMENTATION_TEST
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_completed_and_passed=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_completed_and_passed=True
+ )
for mock_call in mock_info_logger.mock_calls:
logged_format = mock_call[1][0]
self.assertIsInstance(logged_format, str)
@@ -257,10 +266,12 @@ INSTRUMENTATION_CODE: -1
('com.my.package.test.BasicTest#basicTest', signals.TestPass),
]
mock_get_time.side_effect = [13, 51]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_completed_and_passed=True,
- expected_executed_times=[(13, 51)])
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_completed_and_passed=True,
+ expected_executed_times=[(13, 51)],
+ )
def test_run_instrumentation_test_with_random_whitespace(self):
instrumentation_output = """\
@@ -312,9 +323,11 @@ INSTRUMENTATION_CODE: -1
expected_executed = [
('com.my.package.test.BasicTest#basicTest', signals.TestPass),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_completed_and_passed=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_completed_and_passed=True,
+ )
def test_run_instrumentation_test_with_prefix_test(self):
instrumentation_output = """\
@@ -343,13 +356,17 @@ OK (1 test)
INSTRUMENTATION_CODE: -1
"""
expected_executed = [
- ('%s.com.my.package.test.BasicTest#basicTest' % MOCK_PREFIX,
- signals.TestPass),
+ (
+ '%s.com.my.package.test.BasicTest#basicTest' % MOCK_PREFIX,
+ signals.TestPass,
+ ),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_completed_and_passed=True,
- prefix=MOCK_PREFIX)
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_completed_and_passed=True,
+ prefix=MOCK_PREFIX,
+ )
def test_run_instrumentation_test_with_failing_test(self):
instrumentation_output = """\
@@ -535,8 +552,9 @@ INSTRUMENTATION_CODE: -1"""
expected_executed = [
('com.my.package.test.BasicTest#failingTest', signals.TestFailure),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_executed=expected_executed
+ )
def test_run_instrumentation_test_with_assumption_failure_test(self):
instrumentation_output = """\
@@ -618,12 +636,16 @@ OK (1 test)
INSTRUMENTATION_CODE: -1"""
expected_skipped = [
- ('com.my.package.test.BasicTest#assumptionFailureTest',
- signals.TestSkip),
+ (
+ 'com.my.package.test.BasicTest#assumptionFailureTest',
+ signals.TestSkip,
+ ),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_skipped=expected_skipped,
- expected_completed_and_passed=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_skipped=expected_skipped,
+ expected_completed_and_passed=True,
+ )
def test_run_instrumentation_test_with_ignored_test(self):
instrumentation_output = """\
@@ -654,9 +676,11 @@ INSTRUMENTATION_CODE: -1"""
expected_skipped = [
('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_skipped=expected_skipped,
- expected_completed_and_passed=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_skipped=expected_skipped,
+ expected_completed_and_passed=True,
+ )
@mock.patch('mobly.utils.get_current_epoch_time')
def test_run_instrumentation_test_with_crashed_test(self, mock_get_time):
@@ -675,10 +699,12 @@ INSTRUMENTATION_CODE: 0"""
('com.my.package.test.BasicTest#crashTest', signals.TestError),
]
mock_get_time.side_effect = [67, 942]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_has_error=True,
- expected_executed_times=[(67, 942)])
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_has_error=True,
+ expected_executed_times=[(67, 942)],
+ )
@mock.patch('mobly.utils.get_current_epoch_time')
def test_run_instrumentation_test_with_crashing_test(self, mock_get_time):
@@ -708,25 +734,31 @@ OK (2 tests)
INSTRUMENTATION_CODE: -1"""
expected_executed = [
- ('com.my.package.test.BasicTest#crashAndRecover1Test',
- signals.TestError),
- ('com.my.package.test.BasicTest#crashAndRecover2Test',
- signals.TestError),
+ (
+ 'com.my.package.test.BasicTest#crashAndRecover1Test',
+ signals.TestError,
+ ),
+ (
+ 'com.my.package.test.BasicTest#crashAndRecover2Test',
+ signals.TestError,
+ ),
]
mock_get_time.side_effect = [16, 412, 4143, 6547]
# TODO(winterfrosts): Fix this issue with overlapping timing
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_completed_and_passed=True,
- expected_executed_times=[(16, 4143),
- (412, 6547)])
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_completed_and_passed=True,
+ expected_executed_times=[(16, 4143), (412, 6547)],
+ )
def test_run_instrumentation_test_with_runner_setup_crash(self):
instrumentation_output = """\
INSTRUMENTATION_RESULT: shortMsg=Process crashed.
INSTRUMENTATION_CODE: 0"""
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output, expected_has_error=True
+ )
def test_run_instrumentation_test_with_runner_teardown_crash(self):
instrumentation_output = """\
@@ -751,9 +783,11 @@ INSTRUMENTATION_CODE: 0
expected_executed = [
('com.my.package.test.BasicTest#basicTest', signals.TestPass),
]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_has_error=True)
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_has_error=True,
+ )
@mock.patch('mobly.utils.get_current_epoch_time')
def test_run_instrumentation_test_with_multiple_tests(self, mock_get_time):
@@ -1036,24 +1070,28 @@ INSTRUMENTATION_CODE: -1"""
('com.my.package.test.BasicTest#passingTest', signals.TestPass),
]
expected_skipped = [
- ('com.my.package.test.BasicTest#assumptionFailureTest',
- signals.TestSkip),
+ (
+ 'com.my.package.test.BasicTest#assumptionFailureTest',
+ signals.TestSkip,
+ ),
('com.my.package.test.BasicTest#ignoredTest', signals.TestSkip),
]
mock_get_time.side_effect = [54, 64, -1, -1, -1, -1, 89, 94]
- self.assert_run_instrumentation_test(instrumentation_output,
- expected_executed=expected_executed,
- expected_skipped=expected_skipped,
- expected_executed_times=[(54, 64),
- (89, 94)])
+ self.assert_run_instrumentation_test(
+ instrumentation_output,
+ expected_executed=expected_executed,
+ expected_skipped=expected_skipped,
+ expected_executed_times=[(54, 64), (89, 94)],
+ )
def test__Instrumentation_block_set_key_on_multiple_equals_sign(self):
- value = "blah=blah, blah2=blah2, blah=2=1=2"
- parsed_line = "INSTRUMENTATION_STATUS: stack=%s" % value
+ value = 'blah=blah, blah2=blah2, blah=2=1=2'
+ parsed_line = 'INSTRUMENTATION_STATUS: stack=%s' % value
block = _InstrumentationBlock()
block.set_key(_InstrumentationStructurePrefixes.STATUS, parsed_line)
- self.assertIn(value,
- block.known_keys[_InstrumentationKnownStatusKeys.STACK])
+ self.assertIn(
+ value, block.known_keys[_InstrumentationKnownStatusKeys.STACK]
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/base_test_test.py b/tests/mobly/base_test_test.py
index b166357..bfc7b75 100755
--- a/tests/mobly/base_test_test.py
+++ b/tests/mobly/base_test_test.py
@@ -33,11 +33,11 @@ from tests.lib import mock_controller
from tests.lib import mock_second_controller
import yaml
-MSG_EXPECTED_EXCEPTION = "This is an expected exception."
-MSG_EXPECTED_TEST_FAILURE = "This is an expected test failure."
-MSG_UNEXPECTED_EXCEPTION = "Unexpected exception!"
+MSG_EXPECTED_EXCEPTION = 'This is an expected exception.'
+MSG_EXPECTED_TEST_FAILURE = 'This is an expected test failure.'
+MSG_UNEXPECTED_EXCEPTION = 'Unexpected exception!'
-MOCK_EXTRA = {"key": "value", "answer_to_everything": 42}
+MOCK_EXTRA = {'key': 'value', 'answer_to_everything': 42}
def never_call():
@@ -55,18 +55,19 @@ class BaseTestTest(unittest.TestCase):
self.mock_test_cls_configs = config_parser.TestRunConfig()
self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
- self.summary_file)
+ self.summary_file
+ )
self.mock_test_cls_configs.controller_configs = {}
self.mock_test_cls_configs.log_path = self.tmp_dir
- self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
+ self.mock_test_cls_configs.user_params = {'some_param': 'hahaha'}
self.mock_test_cls_configs.reporter = mock.MagicMock()
- self.mock_test_name = "test_something"
+ self.mock_test_name = 'test_something'
def tearDown(self):
shutil.rmtree(self.tmp_dir)
def test_paths(self):
- '''Checks the output paths set in `BaseTestClass`.'''
+ """Checks the output paths set in `BaseTestClass`."""
path_checker = mock.MagicMock()
class MockBaseTest(base_test.BaseTestClass):
@@ -76,7 +77,7 @@ class BaseTestTest(unittest.TestCase):
path_checker.root_output_path = self.root_output_path
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
self.assertEqual(path_checker.root_output_path, self.tmp_dir)
self.assertTrue(os.path.exists(path_checker.root_output_path))
expected_log_path = os.path.join(self.tmp_dir, 'MockBaseTest')
@@ -84,33 +85,33 @@ class BaseTestTest(unittest.TestCase):
self.assertTrue(os.path.exists(path_checker.log_path))
def test_current_test_name(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- asserts.assert_true(self.current_test_info.name == "test_func",
- ("Got "
- "unexpected test name %s.") %
- self.current_test_info.name)
+ asserts.assert_true(
+ self.current_test_info.name == 'test_func',
+ 'Got unexpected test name %s.' % self.current_test_info.name,
+ )
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
def test_current_test_info(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
asserts.assert_true(
self.current_test_info.name == 'test_func',
- 'Got unexpected test name %s.' % self.current_test_info.name)
+ 'Got unexpected test name %s.' % self.current_test_info.name,
+ )
output_path = self.current_test_info.output_path
- asserts.assert_true(os.path.exists(output_path),
- 'test output path missing')
+ asserts.assert_true(
+ os.path.exists(output_path), 'test output path missing'
+ )
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run(test_names=['test_func'])
@@ -120,16 +121,17 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNone(actual_record.extras)
def test_current_test_info_in_setup_class(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_class(self):
asserts.assert_true(
self.current_test_info.name == 'setup_class',
- 'Got unexpected test name %s.' % self.current_test_info.name)
+ 'Got unexpected test name %s.' % self.current_test_info.name,
+ )
output_path = self.current_test_info.output_path
- asserts.assert_true(os.path.exists(output_path),
- 'test output path missing')
+ asserts.assert_true(
+ os.path.exists(output_path), 'test output path missing'
+ )
raise Exception(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
@@ -140,12 +142,11 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNone(actual_record.extras)
def test_self_tests_list(self):
-
class MockBaseTest(base_test.BaseTestClass):
def __init__(self, controllers):
super().__init__(controllers)
- self.tests = ("test_something",)
+ self.tests = ('test_something',)
def test_something(self):
pass
@@ -157,15 +158,14 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_something")
+ self.assertEqual(actual_record.test_name, 'test_something')
def test_self_tests_list_fail_by_convention(self):
-
class MockBaseTest(base_test.BaseTestClass):
def __init__(self, controllers):
super().__init__(controllers)
- self.tests = ("not_a_test_something",)
+ self.tests = ('not_a_test_something',)
def not_a_test_something(self):
pass
@@ -175,18 +175,19 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- expected_msg = (r'Test method name not_a_test_something does not follow '
- r'naming convention test_\*, abort.')
+ expected_msg = (
+ r'Test method name not_a_test_something does not follow '
+ r'naming convention test_\*, abort.'
+ )
with self.assertRaisesRegex(base_test.Error, expected_msg):
bt_cls.run()
def test_cli_test_selection_override_self_tests_list(self):
-
class MockBaseTest(base_test.BaseTestClass):
def __init__(self, controllers):
super().__init__(controllers)
- self.tests = ("test_never",)
+ self.tests = ('test_never',)
def test_something(self):
pass
@@ -196,17 +197,16 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_something"])
+ bt_cls.run(test_names=['test_something'])
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_something")
+ self.assertEqual(actual_record.test_name, 'test_something')
def test_cli_test_selection_fail_by_convention(self):
-
class MockBaseTest(base_test.BaseTestClass):
def __init__(self, controllers):
super().__init__(controllers)
- self.tests = ("not_a_test_something",)
+ self.tests = ('not_a_test_something',)
def not_a_test_something(self):
pass
@@ -216,13 +216,14 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- expected_msg = (r'Test method name not_a_test_something does not follow '
- r'naming convention test_\*, abort.')
+ expected_msg = (
+ r'Test method name not_a_test_something does not follow '
+ r'naming convention test_\*, abort.'
+ )
with self.assertRaisesRegex(base_test.Error, expected_msg):
- bt_cls.run(test_names=["not_a_test_something"])
+ bt_cls.run(test_names=['not_a_test_something'])
def test_default_execution_of_all_tests(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_something(self):
@@ -236,7 +237,7 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_something")
+ self.assertEqual(actual_record.test_name, 'test_something')
def test_default_execution_skip_noncallable_tests(self):
mock_decorated = mock.MagicMock()
@@ -268,13 +269,13 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- self.assertNotIn('test_noncallable',
- [test.test_name for test in bt_cls.results.executed])
+ self.assertNotIn(
+ 'test_noncallable', [test.test_name for test in bt_cls.results.executed]
+ )
mock_decorated.assert_called_once_with('test_decorated')
mock_undecorated.assert_called_once_with('test_undecorated')
def test_get_existing_tests_do_not_call_properties(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_something(self):
@@ -289,14 +290,13 @@ class BaseTestTest(unittest.TestCase):
bt_cls.run()
def test_missing_requested_test_func(self):
-
class MockBaseTest(base_test.BaseTestClass):
pass
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- expected_msg = ".* does not have test method test_something"
+ expected_msg = '.* does not have test method test_something'
with self.assertRaisesRegex(base_test.Error, expected_msg):
- bt_cls.run(test_names=["test_something"])
+ bt_cls.run(test_names=['test_something'])
self.assertFalse(bt_cls.results.executed)
def test_setup_class_fail_by_exception(self):
@@ -320,10 +320,10 @@ class BaseTestTest(unittest.TestCase):
# This should execute because the setup_class failure should
# have already been recorded.
if not self.results.is_all_pass:
- teardown_class_call_check("heehee")
+ teardown_class_call_check('heehee')
def on_fail(self, record):
- on_fail_call_check("haha")
+ on_fail_call_check('haha')
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
@@ -332,23 +332,27 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNone(skipped_record.begin_time)
self.assertIsNone(skipped_record.end_time)
utils.validate_test_result(bt_cls.results)
- self.assertEqual(actual_record.test_name, "setup_class")
+ self.assertEqual(actual_record.test_name, 'setup_class')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
- "Requested 2, Skipped 2")
+ expected_summary = (
+ 'Error 1, Executed 0, Failed 0, Passed 0, Requested 2, Skipped 2'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
- teardown_class_call_check.assert_called_once_with("heehee")
- on_fail_call_check.assert_called_once_with("haha")
+ teardown_class_call_check.assert_called_once_with('heehee')
+ on_fail_call_check.assert_called_once_with('haha')
def test_teardown_class_fail_by_exception(self):
mock_test_config = self.mock_test_cls_configs.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ mock_ctrlr_2_config_name = (
+ mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ )
my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
mock_test_config.controller_configs[mock_ctrlr_2_config_name] = copy.copy(
- my_config)
+ my_config
+ )
class MockBaseTest(base_test.BaseTestClass):
@@ -371,8 +375,9 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNotNone(class_record.begin_time)
self.assertIsNotNone(class_record.end_time)
self.assertIsNone(class_record.extras)
- expected_summary = ('Error 1, Executed 1, Failed 0, Passed 1, '
- 'Requested 1, Skipped 0')
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 1, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
# Verify the controller info is recorded correctly.
info = bt_cls.results.controller_info[0]
@@ -383,11 +388,14 @@ class BaseTestTest(unittest.TestCase):
def test_teardown_class_raise_abort_all(self):
mock_test_config = self.mock_test_cls_configs.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ mock_ctrlr_2_config_name = (
+ mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ )
my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
mock_test_config.controller_configs[mock_ctrlr_2_config_name] = copy.copy(
- my_config)
+ my_config
+ )
class MockBaseTest(base_test.BaseTestClass):
@@ -405,8 +413,9 @@ class BaseTestTest(unittest.TestCase):
bt_cls.run()
test_record = bt_cls.results.passed[0]
self.assertTrue(bt_cls.results.is_all_pass)
- expected_summary = ('Error 0, Executed 1, Failed 0, Passed 1, '
- 'Requested 1, Skipped 0')
+ expected_summary = (
+ 'Error 0, Executed 1, Failed 0, Passed 1, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
# Verify the controller info is recorded correctly.
info = bt_cls.results.controller_info[0]
@@ -430,7 +439,7 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_something"])
+ bt_cls.run(test_names=['test_something'])
mock_on_fail.assert_called_once_with('on_fail')
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
@@ -438,14 +447,16 @@ class BaseTestTest(unittest.TestCase):
self.assertIn(
'in setup_test\n '
'raise Exception(MSG_EXPECTED_EXCEPTION)\n'
- 'Exception: This is an expected exception.\n', actual_record.stacktrace)
+ 'Exception: This is an expected exception.\n',
+ actual_record.stacktrace,
+ )
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_setup_test_fail_by_test_signal(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_test(self):
@@ -456,7 +467,7 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_something"])
+ bt_cls.run(test_names=['test_something'])
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
@@ -464,12 +475,12 @@ class BaseTestTest(unittest.TestCase):
self.assertTrue('self.setup_test()' in actual_record.stacktrace)
self.assertIsNone(actual_record.extras)
self.assertTrue(actual_record.end_time)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_assert_fail(self):
-
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
@@ -485,12 +496,12 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertTrue(actual_record.end_time)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_raise_exception(self):
-
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
@@ -506,12 +517,12 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
self.assertFalse(actual_record.extra_errors)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_expects_error(self):
-
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
@@ -528,8 +539,9 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNone(actual_record.extras)
self.assertFalse(actual_record.extra_errors)
self.assertTrue(actual_record.end_time)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_executed_if_test_pass(self):
@@ -538,7 +550,7 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
- my_mock("teardown_test")
+ my_mock('teardown_test')
def test_something(self):
pass
@@ -546,13 +558,14 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- my_mock.assert_called_once_with("teardown_test")
+ my_mock.assert_called_once_with('teardown_test')
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
self.assertTrue(actual_record.end_time)
- expected_summary = ("Error 0, Executed 1, Failed 0, Passed 1, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 0, Executed 1, Failed 0, Passed 1, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_executed_if_setup_test_fails(self):
@@ -564,7 +577,7 @@ class BaseTestTest(unittest.TestCase):
raise Exception(MSG_EXPECTED_EXCEPTION)
def teardown_test(self):
- my_mock("teardown_test")
+ my_mock('teardown_test')
def test_something(self):
pass
@@ -572,13 +585,14 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- my_mock.assert_called_once_with("teardown_test")
+ my_mock.assert_called_once_with('teardown_test')
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
self.assertTrue(actual_record.end_time)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_teardown_test_executed_if_test_fails(self):
@@ -587,7 +601,7 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
- my_mock("teardown_test")
+ my_mock('teardown_test')
def on_pass(self, record):
never_call()
@@ -598,12 +612,13 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- my_mock.assert_called_once_with("teardown_test")
+ my_mock.assert_called_once_with('teardown_test')
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_executed_if_teardown_test_fails(self):
@@ -612,7 +627,7 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
def on_fail(self, record):
- my_mock("on_fail")
+ my_mock('on_fail')
def on_pass(self, record):
never_call()
@@ -630,8 +645,9 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_executed_if_test_fails(self):
@@ -641,7 +657,7 @@ class BaseTestTest(unittest.TestCase):
def on_fail(self, record):
assert self.current_test_info.name == 'test_something'
- my_mock("on_fail")
+ my_mock('on_fail')
def on_pass(self, record):
never_call()
@@ -651,13 +667,14 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- my_mock.assert_called_once_with("on_fail")
+ my_mock.assert_called_once_with('on_fail')
actual_record = bt_cls.results.failed[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_procedure_function_gets_correct_record(self):
@@ -680,13 +697,13 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(on_fail_mock.record.end_time, actual_record.end_time)
self.assertEqual(on_fail_mock.record.stacktrace, actual_record.stacktrace)
self.assertEqual(on_fail_mock.record.extras, actual_record.extras)
- self.assertEqual(on_fail_mock.record.extra_errors,
- actual_record.extra_errors)
+ self.assertEqual(
+ on_fail_mock.record.extra_errors, actual_record.extra_errors
+ )
# But they are not the same object.
self.assertIsNot(on_fail_mock.record, actual_record)
def test_on_fail_cannot_modify_original_record(self):
-
class MockBaseTest(base_test.BaseTestClass):
def on_fail(self, record):
@@ -706,7 +723,7 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
def on_fail(self, record):
- on_fail_mock("on_fail")
+ on_fail_mock('on_fail')
def on_pass(self, record):
never_call()
@@ -719,15 +736,18 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- on_fail_mock.assert_called_once_with("on_fail")
+ on_fail_mock.assert_called_once_with('on_fail')
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
- self.assertEqual(actual_record.extra_errors['teardown_test'].details,
- 'This is an expected exception.ha')
+ self.assertEqual(
+ actual_record.extra_errors['teardown_test'].details,
+ 'This is an expected exception.ha',
+ )
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_executed_if_setup_test_fails_by_exception(self):
@@ -739,20 +759,21 @@ class BaseTestTest(unittest.TestCase):
raise Exception(MSG_EXPECTED_EXCEPTION)
def on_fail(self, record):
- my_mock("on_fail")
+ my_mock('on_fail')
def test_something(self):
pass
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- my_mock.assert_called_once_with("on_fail")
+ my_mock.assert_called_once_with('on_fail')
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_executed_if_setup_class_fails_by_exception(self):
@@ -764,20 +785,21 @@ class BaseTestTest(unittest.TestCase):
raise Exception(MSG_EXPECTED_EXCEPTION)
def on_fail(self, record):
- my_mock("on_fail")
+ my_mock('on_fail')
def test_something(self):
pass
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- my_mock.assert_called_once_with("on_fail")
+ my_mock.assert_called_once_with('on_fail')
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, 'setup_class')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
- "Requested 1, Skipped 1")
+ expected_summary = (
+ 'Error 1, Executed 0, Failed 0, Passed 0, Requested 1, Skipped 1'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_triggered_by_setup_class_failure_then_fail_too(self):
@@ -799,14 +821,16 @@ class BaseTestTest(unittest.TestCase):
setup_class_record = bt_cls.results.error[0]
self.assertEqual(setup_class_record.test_name, 'setup_class')
self.assertEqual(setup_class_record.details, MSG_EXPECTED_EXCEPTION)
- self.assertEqual(setup_class_record.extra_errors['on_fail'].details,
- 'Failure in on_fail.')
- expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
- "Requested 1, Skipped 1")
+ self.assertEqual(
+ setup_class_record.extra_errors['on_fail'].details,
+ 'Failure in on_fail.',
+ )
+ expected_summary = (
+ 'Error 1, Executed 0, Failed 0, Passed 0, Requested 1, Skipped 1'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_failure_to_call_procedure_function_is_recorded(self):
-
class MockBaseTest(base_test.BaseTestClass):
def on_fail(self):
@@ -822,12 +846,13 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_failure_in_procedure_functions_is_recorded(self):
- expected_msg = "Something failed in on_pass."
+ expected_msg = 'Something failed in on_pass.'
class MockBaseTest(base_test.BaseTestClass):
@@ -840,41 +865,44 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- self.assertEqual(actual_record.extra_errors['on_pass'].details,
- expected_msg)
+ self.assertEqual(
+ actual_record.extra_errors['on_pass'].details, expected_msg
+ )
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_both_teardown_and_test_body_raise_exceptions(self):
-
class MockBaseTest(base_test.BaseTestClass):
def teardown_test(self):
asserts.assert_true(False, MSG_EXPECTED_EXCEPTION)
def test_something(self):
- raise Exception("Test Body Exception.")
+ raise Exception('Test Body Exception.')
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
self.assertEqual(actual_record.test_name, self.mock_test_name)
- self.assertEqual(actual_record.details, "Test Body Exception.")
+ self.assertEqual(actual_record.details, 'Test Body Exception.')
self.assertIsNone(actual_record.extras)
- self.assertEqual(actual_record.extra_errors['teardown_test'].details,
- MSG_EXPECTED_EXCEPTION)
+ self.assertEqual(
+ actual_record.extra_errors['teardown_test'].details,
+ MSG_EXPECTED_EXCEPTION,
+ )
self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_exception_objects_in_record(self):
- """Checks that the exception objects are correctly tallied.
- """
+ """Checks that the exception objects are correctly tallied."""
expected_termination_signal = Exception('Test Body Exception.')
expected_extra_error = Exception('teardown_test Exception.')
@@ -889,8 +917,9 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- self.assertIs(actual_record.termination_signal.exception,
- expected_termination_signal)
+ self.assertIs(
+ actual_record.termination_signal.exception, expected_termination_signal
+ )
self.assertIsNotNone(actual_record.termination_signal.stacktrace)
self.assertEqual(len(actual_record.extra_errors), 1)
extra_error = actual_record.extra_errors['teardown_test']
@@ -920,8 +949,7 @@ class BaseTestTest(unittest.TestCase):
self.assertIsNotNone(actual_record.stacktrace)
def test_explicit_pass_but_teardown_test_raises_an_exception(self):
- """Test record result should be marked as ERROR as opposed to PASS.
- """
+ """Test record result should be marked as ERROR as opposed to PASS."""
class MockBaseTest(base_test.BaseTestClass):
@@ -937,15 +965,17 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, 'Test Passed!')
self.assertIsNone(actual_record.extras)
- self.assertEqual(actual_record.extra_errors['teardown_test'].details,
- MSG_EXPECTED_EXCEPTION)
+ self.assertEqual(
+ actual_record.extra_errors['teardown_test'].details,
+ MSG_EXPECTED_EXCEPTION,
+ )
self.assertIsNone(actual_record.extra_errors['teardown_test'].extras)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_pass_cannot_modify_original_record(self):
-
class MockBaseTest(base_test.BaseTestClass):
def on_pass(self, record):
@@ -960,7 +990,6 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, 'test_something')
def test_on_pass_raise_exception(self):
-
class MockBaseTest(base_test.BaseTestClass):
def on_pass(self, record):
@@ -975,14 +1004,15 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
- self.assertEqual(actual_record.extra_errors['on_pass'].details,
- MSG_EXPECTED_EXCEPTION)
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ self.assertEqual(
+ actual_record.extra_errors['on_pass'].details, MSG_EXPECTED_EXCEPTION
+ )
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_on_fail_raise_exception(self):
-
class MockBaseTest(base_test.BaseTestClass):
def on_fail(self, record):
@@ -997,10 +1027,12 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.test_name, self.mock_test_name)
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
- self.assertEqual(actual_record.extra_errors['on_fail'].details,
- MSG_EXPECTED_EXCEPTION)
- expected_summary = ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 1, Skipped 0")
+ self.assertEqual(
+ actual_record.extra_errors['on_fail'].details, MSG_EXPECTED_EXCEPTION
+ )
+ expected_summary = (
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_abort_class_setup_class(self):
@@ -1026,14 +1058,14 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertEqual(len(bt_cls.results.skipped), 3)
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 0, Failed 0, Passed 0, "
- "Requested 3, Skipped 3"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 0, Failed 0, Passed 0, Requested 3, Skipped 3',
+ )
def test_abort_class_in_setup_test(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_test(self):
@@ -1049,14 +1081,14 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertEqual(len(bt_cls.results.skipped), 2)
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 3, Skipped 2"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 3, Skipped 2',
+ )
def test_abort_class_in_on_fail(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_1(self):
@@ -1072,14 +1104,14 @@ class BaseTestTest(unittest.TestCase):
asserts.abort_class(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertEqual(len(bt_cls.results.skipped), 2)
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 3, Skipped 2"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 3, Skipped 2',
+ )
def test_setup_and_teardown_execution_count(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1100,7 +1132,6 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.teardown_test.call_count, 2)
def test_abort_class_in_test(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_1(self):
@@ -1114,15 +1145,15 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
- self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
+ self.assertEqual(bt_cls.results.passed[0].test_name, 'test_1')
self.assertEqual(bt_cls.results.failed[0].details, MSG_EXPECTED_EXCEPTION)
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 2, Failed 1, Passed 1, "
- "Requested 3, Skipped 1"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 2, Failed 1, Passed 1, Requested 3, Skipped 1',
+ )
def test_abort_all_in_setup_class(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_class(self):
@@ -1138,16 +1169,17 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 0, Failed 0, Passed 0, "
- "Requested 3, Skipped 3"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 0, Failed 0, Passed 0, Requested 3, Skipped 3',
+ )
def test_abort_all_in_teardown_class(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_1(self):
@@ -1160,16 +1192,17 @@ class BaseTestTest(unittest.TestCase):
asserts.abort_all(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2'])
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 2, Failed 0, Passed 2, "
- "Requested 2, Skipped 0"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 2, Failed 0, Passed 2, Requested 2, Skipped 0',
+ )
def test_abort_all_in_setup_test(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_test(self):
@@ -1185,16 +1218,17 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 3, Skipped 2"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 3, Skipped 2',
+ )
def test_abort_all_in_on_fail(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_1(self):
@@ -1210,16 +1244,17 @@ class BaseTestTest(unittest.TestCase):
asserts.abort_all(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 1, Failed 1, Passed 0, "
- "Requested 3, Skipped 2"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 1, Failed 1, Passed 0, Requested 3, Skipped 2',
+ )
def test_abort_all_in_on_fail_from_setup_class(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_class(self):
@@ -1238,18 +1273,19 @@ class BaseTestTest(unittest.TestCase):
asserts.abort_all(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
setup_class_record = bt_cls.results.error[0]
self.assertEqual(setup_class_record.test_name, 'setup_class')
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 1, Executed 0, Failed 0, Passed 0, "
- "Requested 3, Skipped 3"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 1, Executed 0, Failed 0, Passed 0, Requested 3, Skipped 3',
+ )
def test_abort_all_in_test(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_1(self):
@@ -1263,18 +1299,19 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- with self.assertRaisesRegex(signals.TestAbortAll,
- MSG_EXPECTED_EXCEPTION) as context:
- bt_cls.run(test_names=["test_1", "test_2", "test_3"])
+ with self.assertRaisesRegex(
+ signals.TestAbortAll, MSG_EXPECTED_EXCEPTION
+ ) as context:
+ bt_cls.run(test_names=['test_1', 'test_2', 'test_3'])
self.assertTrue(hasattr(context.exception, 'results'))
- self.assertEqual(bt_cls.results.passed[0].test_name, "test_1")
+ self.assertEqual(bt_cls.results.passed[0].test_name, 'test_1')
self.assertEqual(bt_cls.results.failed[0].details, MSG_EXPECTED_EXCEPTION)
- self.assertEqual(bt_cls.results.summary_str(),
- ("Error 0, Executed 2, Failed 1, Passed 1, "
- "Requested 3, Skipped 1"))
+ self.assertEqual(
+ bt_cls.results.summary_str(),
+ 'Error 0, Executed 2, Failed 1, Passed 1, Requested 3, Skipped 1',
+ )
def test_uncaught_exception(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1282,20 +1319,21 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.error[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
# Stacktraces can vary. Just check for key words
self.assertIn('test_method()', actual_record.stacktrace)
- self.assertIn('raise Exception(MSG_EXPECTED_EXCEPTION)',
- actual_record.stacktrace)
- self.assertIn('Exception: This is an expected exception.',
- actual_record.stacktrace)
+ self.assertIn(
+ 'raise Exception(MSG_EXPECTED_EXCEPTION)', actual_record.stacktrace
+ )
+ self.assertIn(
+ 'Exception: This is an expected exception.', actual_record.stacktrace
+ )
def test_fail(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1303,14 +1341,13 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_true(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1318,14 +1355,13 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_equal_pass(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1334,12 +1370,11 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
def test_assert_equal_fail(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1348,30 +1383,27 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
- self.assertEqual(actual_record.details, "1 != 2")
+ self.assertEqual(actual_record.test_name, 'test_func')
+ self.assertEqual(actual_record.details, '1 != 2')
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_equal_fail_with_msg(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- asserts.assert_equal(1,
- 2,
- msg=MSG_EXPECTED_EXCEPTION,
- extras=MOCK_EXTRA)
+ asserts.assert_equal(
+ 1, 2, msg=MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA
+ )
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
- expected_msg = "1 != 2 " + MSG_EXPECTED_EXCEPTION
+ self.assertEqual(actual_record.test_name, 'test_func')
+ expected_msg = '1 != 2 ' + MSG_EXPECTED_EXCEPTION
self.assertEqual(actual_record.details, expected_msg)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_raises_pass(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1381,12 +1413,11 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
def test_assert_raises_fail_with_noop(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1396,12 +1427,11 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
- self.assertEqual(actual_record.details, "SomeError not raised")
+ self.assertEqual(actual_record.test_name, 'test_func')
+ self.assertEqual(actual_record.details, 'SomeError not raised')
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_raises_fail_with_wrong_error(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1411,83 +1441,80 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
def test_assert_raises_regex_pass(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- with asserts.assert_raises_regex(SomeError,
- expected_regex=MSG_EXPECTED_EXCEPTION,
- extras=MOCK_EXTRA):
+ with asserts.assert_raises_regex(
+ SomeError, expected_regex=MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA
+ ):
raise SomeError(MSG_EXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
def test_assert_raises_regex_fail_with_noop(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- with asserts.assert_raises_regex(SomeError,
- expected_regex=MSG_EXPECTED_EXCEPTION,
- extras=MOCK_EXTRA):
+ with asserts.assert_raises_regex(
+ SomeError, expected_regex=MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA
+ ):
pass
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
- self.assertEqual(actual_record.details, "SomeError not raised")
+ self.assertEqual(actual_record.test_name, 'test_func')
+ self.assertEqual(actual_record.details, 'SomeError not raised')
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_raises_fail_with_wrong_regex(self):
- wrong_msg = "ha"
+ wrong_msg = 'ha'
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- with asserts.assert_raises_regex(SomeError,
- expected_regex=MSG_EXPECTED_EXCEPTION,
- extras=MOCK_EXTRA):
+ with asserts.assert_raises_regex(
+ SomeError, expected_regex=MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA
+ ):
raise SomeError(wrong_msg)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.failed[0]
- self.assertEqual(actual_record.test_name, "test_func")
- expected_details = ('"This is an expected exception." does not match '
- '"%s"') % wrong_msg
+ self.assertEqual(actual_record.test_name, 'test_func')
+ expected_details = (
+ '"This is an expected exception." does not match "%s"'
+ ) % wrong_msg
self.assertEqual(actual_record.details, expected_details)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_assert_raises_regex_fail_with_wrong_error(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
- with asserts.assert_raises_regex(SomeError,
- expected_regex=MSG_EXPECTED_EXCEPTION,
- extras=MOCK_EXTRA):
+ with asserts.assert_raises_regex(
+ SomeError, expected_regex=MSG_EXPECTED_EXCEPTION, extras=MOCK_EXTRA
+ ):
raise AttributeError(MSG_UNEXPECTED_EXCEPTION)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_UNEXPECTED_EXCEPTION)
self.assertIsNone(actual_record.extras)
def test_explicit_pass(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1495,28 +1522,26 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_implicit_pass(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
pass
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertIsNone(actual_record.details)
self.assertIsNone(actual_record.extras)
def test_skip(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1524,16 +1549,15 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.skipped[0]
self.assertIsNotNone(actual_record.begin_time)
self.assertIsNotNone(actual_record.end_time)
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_skip_if(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -1542,16 +1566,15 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.skipped[0]
self.assertIsNotNone(actual_record.begin_time)
self.assertIsNotNone(actual_record.end_time)
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_skip_in_setup_test(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_test(self):
@@ -1561,11 +1584,11 @@ class BaseTestTest(unittest.TestCase):
never_call()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_func"])
+ bt_cls.run(test_names=['test_func'])
actual_record = bt_cls.results.skipped[0]
self.assertIsNotNone(actual_record.begin_time)
self.assertIsNotNone(actual_record.end_time)
- self.assertEqual(actual_record.test_name, "test_func")
+ self.assertEqual(actual_record.test_name, 'test_func')
self.assertEqual(actual_record.details, MSG_EXPECTED_EXCEPTION)
self.assertEqual(actual_record.extras, MOCK_EXTRA)
@@ -1619,8 +1642,7 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(second_error.extras, '2')
def test_expect_two_tests(self):
- """Errors in `expect` should not leak across tests.
- """
+ """Errors in `expect` should not leak across tests."""
must_call = mock.Mock()
class MockBaseTest(base_test.BaseTestClass):
@@ -1643,8 +1665,7 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(another_record.test_name, 'test_2')
def test_expect_no_op(self):
- """Tests don't fail when expect is not triggered.
- """
+ """Tests don't fail when expect is not triggered."""
must_call = mock.Mock()
class MockBaseTest(base_test.BaseTestClass):
@@ -1851,8 +1872,10 @@ class BaseTestTest(unittest.TestCase):
must_call.assert_called_once_with('ha')
actual_record = bt_cls.results.failed[0]
self.assertEqual(actual_record.test_name, 'test_func')
- self.assertEqual(actual_record.details,
- 'Got an unexpected exception: %s' % MSG_EXPECTED_EXCEPTION)
+ self.assertEqual(
+ actual_record.details,
+ 'Got an unexpected exception: %s' % MSG_EXPECTED_EXCEPTION,
+ )
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_expect_no_raises_custom_msg(self):
@@ -1871,13 +1894,13 @@ class BaseTestTest(unittest.TestCase):
must_call.assert_called_once_with('ha')
actual_record = bt_cls.results.failed[0]
self.assertEqual(actual_record.test_name, 'test_func')
- self.assertEqual(actual_record.details,
- '%s: %s' % (msg, MSG_EXPECTED_EXCEPTION))
+ self.assertEqual(
+ actual_record.details, '%s: %s' % (msg, MSG_EXPECTED_EXCEPTION)
+ )
self.assertEqual(actual_record.extras, MOCK_EXTRA)
def test_expect_true_and_assert_true(self):
- """Error thrown by assert_true should be considered the termination.
- """
+ """Error thrown by assert_true should be considered the termination."""
must_call = mock.Mock()
class MockBaseTest(base_test.BaseTestClass):
@@ -1897,18 +1920,19 @@ class BaseTestTest(unittest.TestCase):
def test_unpack_userparams_required(self):
"""Missing a required param should raise an error."""
- required = ["some_param"]
+ required = ['some_param']
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
bc.unpack_userparams(required)
- expected_value = self.mock_test_cls_configs.user_params["some_param"]
+ expected_value = self.mock_test_cls_configs.user_params['some_param']
self.assertEqual(bc.some_param, expected_value)
def test_unpack_userparams_required_missing(self):
"""Missing a required param should raise an error."""
- required = ["something"]
+ required = ['something']
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
- expected_msg = ('Missing required user param "%s" in test '
- 'configuration.') % required[0]
+ expected_msg = (
+ 'Missing required user param "%s" in test configuration.'
+ ) % required[0]
with self.assertRaisesRegex(base_test.Error, expected_msg):
bc.unpack_userparams(required)
@@ -1916,10 +1940,10 @@ class BaseTestTest(unittest.TestCase):
"""If an optional param is specified, the value should be what's in the
config.
"""
- opt = ["some_param"]
+ opt = ['some_param']
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
bc.unpack_userparams(opt_param_names=opt)
- expected_value = self.mock_test_cls_configs.user_params["some_param"]
+ expected_value = self.mock_test_cls_configs.user_params['some_param']
self.assertEqual(bc.some_param, expected_value)
def test_unpack_userparams_optional_with_default(self):
@@ -1927,16 +1951,16 @@ class BaseTestTest(unittest.TestCase):
param is not in the config, the value should be the default value.
"""
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
- bc.unpack_userparams(optional_thing="whatever")
- self.assertEqual(bc.optional_thing, "whatever")
+ bc.unpack_userparams(optional_thing='whatever')
+ self.assertEqual(bc.optional_thing, 'whatever')
def test_unpack_userparams_default_overwrite_by_optional_param_list(self):
"""If an optional param is specified in kwargs, and the param is in the
config, the value should be the one in the config.
"""
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
- bc.unpack_userparams(some_param="whatever")
- expected_value = self.mock_test_cls_configs.user_params["some_param"]
+ bc.unpack_userparams(some_param='whatever')
+ expected_value = self.mock_test_cls_configs.user_params['some_param']
self.assertEqual(bc.some_param, expected_value)
def test_unpack_userparams_default_overwrite_by_required_param_list(self):
@@ -1946,32 +1970,33 @@ class BaseTestTest(unittest.TestCase):
thrown.
"""
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
- bc.unpack_userparams(req_param_names=['a_kwarg_param'],
- a_kwarg_param="whatever")
- self.assertEqual(bc.a_kwarg_param, "whatever")
+ bc.unpack_userparams(
+ req_param_names=['a_kwarg_param'], a_kwarg_param='whatever'
+ )
+ self.assertEqual(bc.a_kwarg_param, 'whatever')
def test_unpack_userparams_optional_missing(self):
"""Missing an optional param should not raise an error."""
- opt = ["something"]
+ opt = ['something']
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
bc.unpack_userparams(opt_param_names=opt)
def test_unpack_userparams_basic(self):
"""Required and optional params are unpacked properly."""
- required = ["something"]
- optional = ["something_else"]
+ required = ['something']
+ optional = ['something_else']
configs = self.mock_test_cls_configs.copy()
- configs.user_params["something"] = 42
- configs.user_params["something_else"] = 53
+ configs.user_params['something'] = 42
+ configs.user_params['something_else'] = 53
bc = base_test.BaseTestClass(configs)
bc.unpack_userparams(req_param_names=required, opt_param_names=optional)
self.assertEqual(bc.something, 42)
self.assertEqual(bc.something_else, 53)
def test_unpack_userparams_default_overwrite(self):
- default_arg_val = "haha"
- actual_arg_val = "wawa"
- arg_name = "arg1"
+ default_arg_val = 'haha'
+ actual_arg_val = 'wawa'
+ arg_name = 'arg1'
configs = self.mock_test_cls_configs.copy()
configs.user_params[arg_name] = actual_arg_val
bc = base_test.BaseTestClass(configs)
@@ -1980,8 +2005,8 @@ class BaseTestTest(unittest.TestCase):
def test_unpack_userparams_default_None(self):
bc = base_test.BaseTestClass(self.mock_test_cls_configs)
- bc.unpack_userparams(arg1="haha")
- self.assertEqual(bc.arg1, "haha")
+ bc.unpack_userparams(arg1='haha')
+ self.assertEqual(bc.arg1, 'haha')
def test_pre_run_failure(self):
"""Test code path for `pre_run` failure.
@@ -2015,13 +2040,14 @@ class BaseTestTest(unittest.TestCase):
# TODO(angli): remove after the full deprecation of `setup_generated_tests`.
def test_setup_generated_tests(self):
-
class MockBaseTest(base_test.BaseTestClass):
def setup_generated_tests(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2070,13 +2096,14 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.results.skipped, [])
def test_generate_tests_run(self):
-
class MockBaseTest(base_test.BaseTestClass):
def pre_run(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2094,14 +2121,15 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.results.passed[1].test_name, 'test_3_4')
def test_generate_tests_with_uid(self):
-
class MockBaseTest(base_test.BaseTestClass):
def pre_run(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- uid_func=self.uid_logic,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ uid_func=self.uid_logic,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2118,14 +2146,15 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
def test_generate_tests_with_none_uid(self):
-
class MockBaseTest(base_test.BaseTestClass):
def pre_run(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- uid_func=self.uid_logic,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ uid_func=self.uid_logic,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2144,13 +2173,14 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.results.passed[1].uid, 'uid-3-4')
def test_generate_tests_selected_run(self):
-
class MockBaseTest(base_test.BaseTestClass):
def pre_run(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2165,13 +2195,14 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(bt_cls.results.passed[0].test_name, 'test_3_4')
def test_generate_tests_call_outside_of_pre_run(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_ha(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'test_%s_%s' % (a, b)
@@ -2183,23 +2214,26 @@ class BaseTestTest(unittest.TestCase):
bt_cls.run()
actual_record = bt_cls.results.error[0]
utils.validate_test_result(bt_cls.results)
- self.assertEqual(actual_record.test_name, "test_ha")
+ self.assertEqual(actual_record.test_name, 'test_ha')
self.assertEqual(
actual_record.details,
"'generate_tests' cannot be called outside of the followin"
- "g functions: ['pre_run', 'setup_generated_tests'].")
- expected_summary = ("Error 1, Executed 1, Failed 0, Passed 0, "
- "Requested 1, Skipped 0")
+ "g functions: ['pre_run', 'setup_generated_tests'].",
+ )
+ expected_summary = (
+ 'Error 1, Executed 1, Failed 0, Passed 0, Requested 1, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_generate_tests_dup_test_name(self):
-
class MockBaseTest(base_test.BaseTestClass):
def pre_run(self):
- self.generate_tests(test_logic=self.logic,
- name_func=self.name_gen,
- arg_sets=[(1, 2), (3, 4)])
+ self.generate_tests(
+ test_logic=self.logic,
+ name_func=self.name_gen,
+ arg_sets=[(1, 2), (3, 4)],
+ )
def name_gen(self, a, b):
return 'ha'
@@ -2210,13 +2244,15 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
actual_record = bt_cls.results.error[0]
- self.assertEqual(actual_record.test_name, "pre_run")
+ self.assertEqual(actual_record.test_name, 'pre_run')
self.assertEqual(
actual_record.details,
'During test generation of "logic": Test name "ha" already exists'
- ', cannot be duplicated!')
- expected_summary = ("Error 1, Executed 0, Failed 0, Passed 0, "
- "Requested 0, Skipped 0")
+ ', cannot be duplicated!',
+ )
+ expected_summary = (
+ 'Error 1, Executed 0, Failed 0, Passed 0, Requested 0, Skipped 0'
+ )
self.assertEqual(bt_cls.results.summary_str(), expected_summary)
def test_write_user_data(self):
@@ -2229,9 +2265,9 @@ class BaseTestTest(unittest.TestCase):
self.record_data(content)
bt_cls = MockBaseTest(self.mock_test_cls_configs)
- bt_cls.run(test_names=["test_something"])
+ bt_cls.run(test_names=['test_something'])
actual_record = bt_cls.results.passed[0]
- self.assertEqual(actual_record.test_name, "test_something")
+ self.assertEqual(actual_record.test_name, 'test_something')
hit = False
with io.open(self.summary_file, 'r', encoding='utf-8') as f:
for c in yaml.safe_load_all(f):
@@ -2252,11 +2288,14 @@ class BaseTestTest(unittest.TestCase):
"""
mock_test_config = self.mock_test_cls_configs.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ mock_ctrlr_2_config_name = (
+ mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ )
my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
mock_test_config.controller_configs[mock_ctrlr_2_config_name] = copy.copy(
- my_config)
+ my_config
+ )
class ControllerInfoTest(base_test.BaseTestClass):
"""Registers two different controller types and modifies controller
@@ -2282,21 +2321,22 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(info1.controller_info, [{'MyMagic': {'magic': 'Magic'}}])
self.assertEqual(info2.test_class, 'ControllerInfoTest')
self.assertEqual(info2.controller_name, 'AnotherMagicDevice')
- self.assertEqual(info2.controller_info, [{
- 'MyOtherMagic': {
- 'magic': 'Magic',
- 'extra_magic': 'haha'
- }
- }])
+ self.assertEqual(
+ info2.controller_info,
+ [{'MyOtherMagic': {'magic': 'Magic', 'extra_magic': 'haha'}}],
+ )
def test_record_controller_info_fail(self):
mock_test_config = self.mock_test_cls_configs.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- mock_ctrlr_2_config_name = mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ mock_ctrlr_2_config_name = (
+ mock_second_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ )
my_config = [{'serial': 'xxxx', 'magic': 'Magic'}]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
mock_test_config.controller_configs[mock_ctrlr_2_config_name] = copy.copy(
- my_config)
+ my_config
+ )
class ControllerInfoTest(base_test.BaseTestClass):
"""Registers two different controller types and modifies controller
@@ -2320,25 +2360,24 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(len(bt_cls.results.controller_info), 1)
self.assertEqual(info.test_class, 'ControllerInfoTest')
self.assertEqual(info.controller_name, 'AnotherMagicDevice')
- self.assertEqual(info.controller_info, [{
- 'MyOtherMagic': {
- 'magic': 'Magic',
- 'extra_magic': 'haha'
- }
- }])
+ self.assertEqual(
+ info.controller_info,
+ [{'MyOtherMagic': {'magic': 'Magic', 'extra_magic': 'haha'}}],
+ )
record = bt_cls.results.error[0]
print(record.to_dict())
self.assertEqual(record.test_name, 'clean_up')
self.assertIsNotNone(record.begin_time)
self.assertIsNotNone(record.end_time)
- expected_msg = ('Failed to collect controller info from '
- 'mock_controller: Some failure')
+ expected_msg = (
+ 'Failed to collect controller info from mock_controller: Some failure'
+ )
self.assertEqual(record.details, expected_msg)
def test_repeat_invalid_count(self):
-
with self.assertRaisesRegex(
- ValueError, 'The `count` for `repeat` must be larger than 1, got "1".'):
+ ValueError, 'The `count` for `repeat` must be larger than 1, got "1".'
+ ):
class MockBaseTest(base_test.BaseTestClass):
@@ -2347,11 +2386,13 @@ class BaseTestTest(unittest.TestCase):
pass
def test_repeat_invalid_max_consec_error(self):
-
with self.assertRaisesRegex(
ValueError,
- re.escape('The `max_consecutive_error` (4) for `repeat` must be '
- 'smaller than `count` (3).')):
+ re.escape(
+ 'The `max_consecutive_error` (4) for `repeat` must be '
+ 'smaller than `count` (3).'
+ ),
+ ):
class MockBaseTest(base_test.BaseTestClass):
@@ -2384,9 +2425,11 @@ class BaseTestTest(unittest.TestCase):
pass
def pre_run(self):
- self.generate_tests(self._run_test_logic,
- name_func=lambda arg: f'test_generated_{arg}',
- arg_sets=[(1,)])
+ self.generate_tests(
+ self._run_test_logic,
+ name_func=lambda arg: f'test_generated_{arg}',
+ arg_sets=[(1,)],
+ )
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
@@ -2418,7 +2461,8 @@ class BaseTestTest(unittest.TestCase):
@mock.patch('logging.error')
def test_repeat_with_consec_error_at_the_beginning_aborts_repeat(
- self, mock_logging_error):
+ self, mock_logging_error
+ ):
repeat_count = 5
max_consec_error = 2
mock_action = mock.MagicMock()
@@ -2430,16 +2474,21 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
- @base_test.repeat(count=repeat_count,
- max_consecutive_error=max_consec_error)
+ @base_test.repeat(
+ count=repeat_count, max_consecutive_error=max_consec_error
+ )
def test_something(self):
mock_action()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
mock_logging_error.assert_called_with(
- 'Repeated test case "%s" has consecutively failed %d iterations, aborting'
- ' the remaining %d iterations.', 'test_something', 2, 3)
+ 'Repeated test case "%s" has consecutively failed %d iterations,'
+ ' aborting the remaining %d iterations.',
+ 'test_something',
+ 2,
+ 3,
+ )
self.assertEqual(max_consec_error, len(bt_cls.results.executed))
self.assertEqual(max_consec_error, len(bt_cls.results.error))
for i, record in enumerate(bt_cls.results.error):
@@ -2447,7 +2496,8 @@ class BaseTestTest(unittest.TestCase):
@mock.patch('logging.error')
def test_repeat_with_consec_error_in_the_middle_aborts_repeat(
- self, mock_logging_error):
+ self, mock_logging_error
+ ):
repeat_count = 5
max_consec_error = 2
mock_action = mock.MagicMock()
@@ -2461,16 +2511,21 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
- @base_test.repeat(count=repeat_count,
- max_consecutive_error=max_consec_error)
+ @base_test.repeat(
+ count=repeat_count, max_consecutive_error=max_consec_error
+ )
def test_something(self):
mock_action()
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
mock_logging_error.assert_called_with(
- 'Repeated test case "%s" has consecutively failed %d iterations, aborting'
- ' the remaining %d iterations.', 'test_something', 2, 1)
+ 'Repeated test case "%s" has consecutively failed %d iterations,'
+ ' aborting the remaining %d iterations.',
+ 'test_something',
+ 2,
+ 1,
+ )
self.assertEqual(4, len(bt_cls.results.executed))
self.assertEqual(2, len(bt_cls.results.error))
self.assertEqual(2, len(bt_cls.results.passed))
@@ -2491,8 +2546,9 @@ class BaseTestTest(unittest.TestCase):
class MockBaseTest(base_test.BaseTestClass):
- @base_test.repeat(count=repeat_count,
- max_consecutive_error=max_consec_error)
+ @base_test.repeat(
+ count=repeat_count, max_consecutive_error=max_consec_error
+ )
def test_something(self):
mock_action()
@@ -2502,10 +2558,10 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(3, len(bt_cls.results.error))
def test_retry_invalid_count(self):
-
with self.assertRaisesRegex(
ValueError,
- 'The `max_count` for `retry` must be larger than 1, got "1".'):
+ 'The `max_count` for `retry` must be larger than 1, got "1".',
+ ):
class MockBaseTest(base_test.BaseTestClass):
@@ -2525,8 +2581,9 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- self.assertTrue(bt_cls.results.is_all_pass,
- 'This test run should be considered pass.')
+ self.assertTrue(
+ bt_cls.results.is_all_pass, 'This test run should be considered pass.'
+ )
self.assertEqual(1, len(bt_cls.results.executed))
self.assertEqual(1, len(bt_cls.results.passed))
pass_record = bt_cls.results.passed[0]
@@ -2546,8 +2603,9 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- self.assertTrue(bt_cls.results.is_all_pass,
- 'This test run should be considered pass.')
+ self.assertTrue(
+ bt_cls.results.is_all_pass, 'This test run should be considered pass.'
+ )
self.assertEqual(3, len(bt_cls.results.executed))
self.assertEqual(1, len(bt_cls.results.passed))
pass_record = bt_cls.results.passed[0]
@@ -2557,13 +2615,19 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(error_record_1.test_name, 'test_something')
self.assertEqual(error_record_2.test_name, 'test_something_retry_1')
self.assertIs(error_record_1, error_record_2.retry_parent)
+ self.assertEqual(
+ (error_record_1, records.TestParentType.RETRY), error_record_2.parent
+ )
self.assertIs(error_record_2, pass_record.retry_parent)
+ self.assertEqual(
+ (error_record_2, records.TestParentType.RETRY), pass_record.parent
+ )
def test_retry_generated_test_last_pass(self):
max_count = 3
mock_action = mock.MagicMock(
- side_effect=[Exception('Fail 1'),
- Exception('Fail 2'), None])
+ side_effect=[Exception('Fail 1'), Exception('Fail 2'), None]
+ )
class MockBaseTest(base_test.BaseTestClass):
@@ -2572,14 +2636,17 @@ class BaseTestTest(unittest.TestCase):
mock_action()
def pre_run(self):
- self.generate_tests(self._run_test_logic,
- name_func=lambda arg: f'test_generated_{arg}',
- arg_sets=[(1,)])
+ self.generate_tests(
+ self._run_test_logic,
+ name_func=lambda arg: f'test_generated_{arg}',
+ arg_sets=[(1,)],
+ )
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- self.assertTrue(bt_cls.results.is_all_pass,
- 'This test run should be considered pass.')
+ self.assertTrue(
+ bt_cls.results.is_all_pass, 'This test run should be considered pass.'
+ )
self.assertEqual(3, len(bt_cls.results.executed))
self.assertEqual(1, len(bt_cls.results.passed))
pass_record = bt_cls.results.passed[0]
@@ -2589,7 +2656,13 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(error_record_1.test_name, 'test_generated_1')
self.assertEqual(error_record_2.test_name, 'test_generated_1_retry_1')
self.assertIs(error_record_1, error_record_2.retry_parent)
+ self.assertEqual(
+ (error_record_1, records.TestParentType.RETRY), error_record_2.parent
+ )
self.assertIs(error_record_2, pass_record.retry_parent)
+ self.assertEqual(
+ (error_record_2, records.TestParentType.RETRY), pass_record.parent
+ )
def test_retry_all_fail(self):
max_count = 3
@@ -2597,7 +2670,7 @@ class BaseTestTest(unittest.TestCase):
mock_action.side_effect = [
Exception('Fail 1'),
Exception('Fail 2'),
- Exception('Fail 3')
+ Exception('Fail 3'),
]
class MockBaseTest(base_test.BaseTestClass):
@@ -2608,8 +2681,9 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
- self.assertFalse(bt_cls.results.is_all_pass,
- 'This test run should be considered fail.')
+ self.assertFalse(
+ bt_cls.results.is_all_pass, 'This test run should be considered fail.'
+ )
self.assertEqual(3, len(bt_cls.results.executed))
self.assertEqual(3, len(bt_cls.results.error))
error_record_1, error_record_2, error_record_3 = bt_cls.results.error
@@ -2617,10 +2691,15 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(error_record_2.test_name, 'test_something_retry_1')
self.assertEqual(error_record_3.test_name, 'test_something_retry_2')
self.assertIs(error_record_1, error_record_2.retry_parent)
+ self.assertEqual(
+ (error_record_1, records.TestParentType.RETRY), error_record_2.parent
+ )
self.assertIs(error_record_2, error_record_3.retry_parent)
+ self.assertEqual(
+ (error_record_2, records.TestParentType.RETRY), error_record_3.parent
+ )
def test_uid(self):
-
class MockBaseTest(base_test.BaseTestClass):
@records.uid('some-uid')
@@ -2633,7 +2712,6 @@ class BaseTestTest(unittest.TestCase):
self.assertEqual(actual_record.uid, 'some-uid')
def test_uid_not_specified(self):
-
class MockBaseTest(base_test.BaseTestClass):
def test_func(self):
@@ -2666,9 +2744,17 @@ class BaseTestTest(unittest.TestCase):
bt_cls = MockBaseTest(self.mock_test_cls_configs)
bt_cls.run()
self.assertEqual(repeat_count, len(bt_cls.results.passed))
+ previous_record = None
for i, record in enumerate(bt_cls.results.passed):
self.assertEqual(record.test_name, f'test_something_{i}')
self.assertEqual(record.uid, 'some-uid')
+ if i == 0:
+ self.assertIsNone(record.parent)
+ else:
+ self.assertEqual(
+ record.parent, (previous_record, records.TestParentType.REPEAT)
+ )
+ previous_record = record
def test_uid_with_repeat(self):
repeat_count = 3
@@ -2705,5 +2791,5 @@ class BaseTestTest(unittest.TestCase):
logging_patch.debug.assert_called_with('[TestClass]#stage <<< END <<<')
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/config_parser_test.py b/tests/mobly/config_parser_test.py
index 6901819..46548f0 100644
--- a/tests/mobly/config_parser_test.py
+++ b/tests/mobly/config_parser_test.py
@@ -35,26 +35,26 @@ class OutputTest(unittest.TestCase):
def test__load_config_file(self):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u'TestBeds:\n')
- f.write(u' # A test bed where adb will find Android devices.\n')
- f.write(u' - Name: SampleTestBed\n')
- f.write(u' Controllers:\n')
- f.write(u' AndroidDevice: \'*\'\n')
+ f.write('TestBeds:\n')
+ f.write(' # A test bed where adb will find Android devices.\n')
+ f.write(' - Name: SampleTestBed\n')
+ f.write(' Controllers:\n')
+ f.write(" AndroidDevice: '*'\n")
config = config_parser._load_config_file(tmp_file_path)
- self.assertEqual(config['TestBeds'][0]['Name'], u'SampleTestBed')
+ self.assertEqual(config['TestBeds'][0]['Name'], 'SampleTestBed')
def test__load_config_file_with_unicode(self):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u'TestBeds:\n')
- f.write(u' # A test bed where adb will find Android devices.\n')
- f.write(u' - Name: \u901a\n')
- f.write(u' Controllers:\n')
- f.write(u' AndroidDevice: \'*\'\n')
+ f.write('TestBeds:\n')
+ f.write(' # A test bed where adb will find Android devices.\n')
+ f.write(' - Name: \u901a\n')
+ f.write(' Controllers:\n')
+ f.write(" AndroidDevice: '*'\n")
config = config_parser._load_config_file(tmp_file_path)
- self.assertEqual(config['TestBeds'][0]['Name'], u'\u901a')
+ self.assertEqual(config['TestBeds'][0]['Name'], '\u901a')
def test_run_config_type(self):
config = config_parser.TestRunConfig()
@@ -66,13 +66,16 @@ class OutputTest(unittest.TestCase):
expected_value = 'SOME_VALUE'
self.assertEqual(
config.controller_configs.get('NON_EXISTENT_KEY', expected_value),
- expected_value)
+ expected_value,
+ )
def test_run_config_user_params_is_already_initialized(self):
config = config_parser.TestRunConfig()
expected_value = 'SOME_VALUE'
- self.assertEqual(config.user_params.get('NON_EXISTENT_KEY', expected_value),
- expected_value)
+ self.assertEqual(
+ config.user_params.get('NON_EXISTENT_KEY', expected_value),
+ expected_value,
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/controller_manager_test.py b/tests/mobly/controller_manager_test.py
index 53e4cfa..46aa273 100755
--- a/tests/mobly/controller_manager_test.py
+++ b/tests/mobly/controller_manager_test.py
@@ -49,14 +49,16 @@ class ControllerManagerTest(unittest.TestCase):
def test_register_controller_no_config(self):
c_manager = controller_manager.ControllerManager('SomeClass', {})
- with self.assertRaisesRegex(signals.ControllerError,
- 'No corresponding config found for'):
+ with self.assertRaisesRegex(
+ signals.ControllerError, 'No corresponding config found for'
+ ):
c_manager.register_controller(mock_controller)
def test_register_controller_no_config_for_not_required(self):
c_manager = controller_manager.ControllerManager('SomeClass', {})
self.assertIsNone(
- c_manager.register_controller(mock_controller, required=False))
+ c_manager.register_controller(mock_controller, required=False)
+ )
def test_register_controller_dup_register(self):
"""Verifies correctness of registration, internal tally of controllers
@@ -65,8 +67,9 @@ class ControllerManagerTest(unittest.TestCase):
"""
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
registered_name = 'mock_controller'
self.assertTrue(registered_name in c_manager._controller_objects)
@@ -81,8 +84,9 @@ class ControllerManagerTest(unittest.TestCase):
def test_register_controller_return_value(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
magic_devices = c_manager.register_controller(mock_controller)
self.assertEqual(magic_devices[0].magic, 'magic1')
self.assertEqual(magic_devices[1].magic, 'magic2')
@@ -90,8 +94,9 @@ class ControllerManagerTest(unittest.TestCase):
def test_register_controller_change_return_value(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
magic_devices = c_manager.register_controller(mock_controller)
magic1 = magic_devices.pop(0)
self.assertIs(magic1, c_manager._controller_objects['mock_controller'][0])
@@ -100,8 +105,9 @@ class ControllerManagerTest(unittest.TestCase):
def test_register_controller_less_than_min_number(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
expected_msg = 'Expected to get at least 3 controller objects, got 2.'
with self.assertRaisesRegex(signals.ControllerError, expected_msg):
c_manager.register_controller(mock_controller, min_number=3)
@@ -110,19 +116,22 @@ class ControllerManagerTest(unittest.TestCase):
def test_get_controller_info_record_not_serializable(self, _):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
record = c_manager.get_controller_info_records()[0]
actual_controller_info = record.controller_info
- self.assertEqual(actual_controller_info,
- "[{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}]")
+ self.assertEqual(
+ actual_controller_info, "[{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}]"
+ )
def test_controller_record_exists_without_get_info(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
get_info = getattr(mock_controller, 'get_info')
delattr(mock_controller, 'get_info')
try:
@@ -139,8 +148,9 @@ class ControllerManagerTest(unittest.TestCase):
mock_get_info_func.return_value = None
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
record = c_manager.get_controller_info_records()[0]
self.assertIsNone(record.controller_info)
@@ -149,13 +159,15 @@ class ControllerManagerTest(unittest.TestCase):
@mock.patch('mobly.expects._ExpectErrorRecorder.add_error')
@mock.patch('tests.lib.mock_controller.get_info')
- def test_get_controller_info_records_error(self, mock_get_info_func,
- mock_add_error):
+ def test_get_controller_info_records_error(
+ self, mock_get_info_func, mock_add_error
+ ):
mock_get_info_func.side_effect = Exception('Record info failed.')
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
self.assertFalse(c_manager.get_controller_info_records())
mock_add_error.assert_called_once()
@@ -165,36 +177,37 @@ class ControllerManagerTest(unittest.TestCase):
def test_get_controller_info_records(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
record = c_manager.get_controller_info_records()[0]
record_dict = record.to_dict()
record_dict.pop('Timestamp')
self.assertEqual(
- record_dict, {
- 'Controller Info': [{
- 'MyMagic': 'magic1'
- }, {
- 'MyMagic': 'magic2'
- }],
+ record_dict,
+ {
+ 'Controller Info': [{'MyMagic': 'magic1'}, {'MyMagic': 'magic2'}],
'Controller Name': 'MagicDevice',
- 'Test Class': 'SomeClass'
- })
+ 'Test Class': 'SomeClass',
+ },
+ )
def test_get_controller_info_without_registration(self):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
self.assertFalse(c_manager.get_controller_info_records())
@mock.patch('tests.lib.mock_controller.destroy')
def test_unregister_controller(self, mock_destroy_func):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
objects = c_manager.register_controller(mock_controller)
c_manager.unregister_controllers()
mock_destroy_func.assert_called_once_with(objects)
@@ -206,8 +219,9 @@ class ControllerManagerTest(unittest.TestCase):
def test_unregister_controller_error(self, mock_destroy_func, mock_add_error):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.register_controller(mock_controller)
mock_destroy_func.side_effect = Exception('Failed in destroy.')
c_manager.unregister_controllers()
@@ -221,13 +235,14 @@ class ControllerManagerTest(unittest.TestCase):
def test_unregister_controller_without_registration(self, mock_destroy_func):
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
controller_configs = {mock_ctrlr_config_name: ['magic1', 'magic2']}
- c_manager = controller_manager.ControllerManager('SomeClass',
- controller_configs)
+ c_manager = controller_manager.ControllerManager(
+ 'SomeClass', controller_configs
+ )
c_manager.unregister_controllers()
mock_destroy_func.assert_not_called()
self.assertFalse(c_manager._controller_objects)
self.assertFalse(c_manager._controller_modules)
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/controllers/android_device_lib/adb_test.py b/tests/mobly/controllers/android_device_lib/adb_test.py
index a013959..65c7eb5 100755
--- a/tests/mobly/controllers/android_device_lib/adb_test.py
+++ b/tests/mobly/controllers/android_device_lib/adb_test.py
@@ -28,23 +28,30 @@ MOCK_INSTRUMENTATION_OPTIONS = collections.OrderedDict([
('option2', 'value2'),
])
# Mock android instrumentation commands.
-MOCK_BASIC_INSTRUMENTATION_COMMAND = ('am instrument -r -w com.my'
- '.instrumentation.tests/com.android'
- '.common.support.test.runner'
- '.AndroidJUnitRunner')
-MOCK_RUNNER_INSTRUMENTATION_COMMAND = ('am instrument -r -w com.my'
- '.instrumentation.tests/com.my'
- '.instrumentation.runner')
-MOCK_OPTIONS_INSTRUMENTATION_COMMAND = ('am instrument -r -w -e option1 value1'
- ' -e option2 value2 com.my'
- '.instrumentation.tests/com.android'
- '.common.support.test.runner'
- '.AndroidJUnitRunner')
+MOCK_BASIC_INSTRUMENTATION_COMMAND = (
+ 'am instrument -r -w com.my'
+ '.instrumentation.tests/com.android'
+ '.common.support.test.runner'
+ '.AndroidJUnitRunner'
+)
+MOCK_RUNNER_INSTRUMENTATION_COMMAND = (
+ 'am instrument -r -w com.my'
+ '.instrumentation.tests/com.my'
+ '.instrumentation.runner'
+)
+MOCK_OPTIONS_INSTRUMENTATION_COMMAND = (
+ 'am instrument -r -w -e option1 value1'
+ ' -e option2 value2 com.my'
+ '.instrumentation.tests/com.android'
+ '.common.support.test.runner'
+ '.AndroidJUnitRunner'
+)
# Mock root command outputs.
MOCK_ROOT_SUCCESS_OUTPUT = 'adbd is already running as root'
-MOCK_ROOT_ERROR_OUTPUT = (
- 'adb: unable to connect for root: closed'.encode('utf-8'))
+MOCK_ROOT_ERROR_OUTPUT = 'adb: unable to connect for root: closed'.encode(
+ 'utf-8'
+)
# Mock Shell Command
MOCK_SHELL_COMMAND = 'ls'
@@ -66,14 +73,18 @@ class AdbTest(unittest.TestCase):
mock_popen.return_value.stdout.readline.side_effect = ['']
mock_proc.communicate = mock.Mock(
- return_value=('', MOCK_DEFAULT_STDERR.encode('utf-8')))
+ return_value=('', MOCK_DEFAULT_STDERR.encode('utf-8'))
+ )
mock_proc.returncode = 0
return mock_popen
@mock.patch('mobly.utils.run_command')
def test_is_adb_available(self, mock_run_command):
- mock_run_command.return_value = (0, '/usr/local/bin/adb\n'.encode('utf-8'),
- ''.encode('utf-8'))
+ mock_run_command.return_value = (
+ 0,
+ '/usr/local/bin/adb\n'.encode('utf-8'),
+ ''.encode('utf-8'),
+ )
self.assertTrue(adb.is_adb_available())
@mock.patch('mobly.utils.run_command')
@@ -83,23 +94,29 @@ class AdbTest(unittest.TestCase):
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_no_timeout_success(self, mock_run_command):
- mock_run_command.return_value = (0, MOCK_DEFAULT_STDOUT.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
- out = adb.AdbProxy()._exec_cmd(['fake_cmd'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_run_command.return_value = (
+ 0,
+ MOCK_DEFAULT_STDOUT.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
+ out = adb.AdbProxy()._exec_cmd(
+ ['fake_cmd'], shell=False, timeout=None, stderr=None
+ )
self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8'))
mock_run_command.assert_called_with(['fake_cmd'], shell=False, timeout=None)
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_error_with_serial(self, mock_run_command):
# Return 1 for retcode for error.
- mock_run_command.return_value = (1, MOCK_DEFAULT_STDOUT.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ mock_run_command.return_value = (
+ 1,
+ MOCK_DEFAULT_STDOUT.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
mock_serial = 'ABCD1234'
- with self.assertRaisesRegex(adb.AdbError,
- 'Error executing adb cmd .*') as context:
+ with self.assertRaisesRegex(
+ adb.AdbError, 'Error executing adb cmd .*'
+ ) as context:
adb.AdbProxy(mock_serial).fake_cmd()
self.assertEqual(context.exception.serial, mock_serial)
self.assertIn(mock_serial, context.exception.cmd)
@@ -107,38 +124,45 @@ class AdbTest(unittest.TestCase):
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_error_without_serial(self, mock_run_command):
# Return 1 for retcode for error.
- mock_run_command.return_value = (1, MOCK_DEFAULT_STDOUT.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
- with self.assertRaisesRegex(adb.AdbError,
- 'Error executing adb cmd .*') as context:
- adb.AdbProxy()._exec_cmd(['fake_cmd'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_run_command.return_value = (
+ 1,
+ MOCK_DEFAULT_STDOUT.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
+ with self.assertRaisesRegex(
+ adb.AdbError, 'Error executing adb cmd .*'
+ ) as context:
+ adb.AdbProxy()._exec_cmd(
+ ['fake_cmd'], shell=False, timeout=None, stderr=None
+ )
self.assertFalse(context.exception.serial)
mock_run_command.assert_called_with(['fake_cmd'], shell=False, timeout=None)
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_with_timeout_success(self, mock_run_command):
- mock_run_command.return_value = (0, MOCK_DEFAULT_STDOUT.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ mock_run_command.return_value = (
+ 0,
+ MOCK_DEFAULT_STDOUT.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
- out = adb.AdbProxy()._exec_cmd(['fake_cmd'],
- shell=False,
- timeout=1,
- stderr=None)
+ out = adb.AdbProxy()._exec_cmd(
+ ['fake_cmd'], shell=False, timeout=1, stderr=None
+ )
self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8'))
mock_run_command.assert_called_with(['fake_cmd'], shell=False, timeout=1)
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_timed_out(self, mock_run_command):
- mock_run_command.side_effect = subprocess.TimeoutExpired(cmd='mock_command',
- timeout=0.01)
+ mock_run_command.side_effect = subprocess.TimeoutExpired(
+ cmd='mock_command', timeout=0.01
+ )
mock_serial = '1234Abcd'
with self.assertRaisesRegex(
- adb.AdbTimeoutError, 'Timed out executing command "adb -s '
- '1234Abcd fake-cmd" after 0.01s.') as context:
+ adb.AdbTimeoutError,
+ 'Timed out executing command "adb -s 1234Abcd fake-cmd" after 0.01s.',
+ ) as context:
adb.AdbProxy(mock_serial).fake_cmd(timeout=0.01)
self.assertEqual(context.exception.serial, mock_serial)
@@ -146,21 +170,23 @@ class AdbTest(unittest.TestCase):
@mock.patch('mobly.utils.run_command')
def test_exec_cmd_timed_out_without_serial(self, mock_run_command):
- mock_run_command.side_effect = subprocess.TimeoutExpired(cmd='mock_command',
- timeout=0.01)
+ mock_run_command.side_effect = subprocess.TimeoutExpired(
+ cmd='mock_command', timeout=0.01
+ )
with self.assertRaisesRegex(
adb.AdbTimeoutError,
- 'Timed out executing command "adb fake-cmd" after 0.01s.'):
+ 'Timed out executing command "adb fake-cmd" after 0.01s.',
+ ):
adb.AdbProxy().fake_cmd(timeout=0.01)
def test_exec_cmd_with_negative_timeout_value(self):
- with self.assertRaisesRegex(ValueError,
- 'Timeout is not a positive value: -1'):
- adb.AdbProxy()._exec_cmd(['fake_cmd'],
- shell=False,
- timeout=-1,
- stderr=None)
+ with self.assertRaisesRegex(
+ ValueError, 'Timeout is not a positive value: -1'
+ ):
+ adb.AdbProxy()._exec_cmd(
+ ['fake_cmd'], shell=False, timeout=-1, stderr=None
+ )
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
def test_execute_and_process_stdout_reads_stdout(self, mock_popen):
@@ -168,9 +194,9 @@ class AdbTest(unittest.TestCase):
mock_popen.return_value.stdout.readline.side_effect = ['1', '2', '']
mock_handler = mock.MagicMock()
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock_handler)
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock_handler
+ )
self.assertEqual(mock_handler.call_count, 2)
mock_handler.assert_any_call('1')
mock_handler.assert_any_call('2')
@@ -182,50 +208,63 @@ class AdbTest(unittest.TestCase):
self._mock_execute_and_process_stdout_process(mock_popen)
mock_handler = mock.MagicMock()
mock_popen.return_value.communicate = mock.Mock(
- return_value=(unexpected_stdout, MOCK_DEFAULT_STDERR.encode('utf-8')))
+ return_value=(unexpected_stdout, MOCK_DEFAULT_STDERR.encode('utf-8'))
+ )
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock_handler)
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock_handler
+ )
self.assertEqual(mock_handler.call_count, 1)
mock_handler.assert_called_with(unexpected_stdout)
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
@mock.patch('logging.debug')
- def test_execute_and_process_stdout_logs_cmd(self, mock_debug_logger,
- mock_popen):
+ def test_execute_and_process_stdout_logs_cmd(
+ self, mock_debug_logger, mock_popen
+ ):
raw_expected_stdout = ''
expected_stdout = '[elided, processed via handler]'
expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8')
self._mock_execute_and_process_stdout_process(mock_popen)
mock_popen.return_value.communicate = mock.Mock(
- return_value=(raw_expected_stdout, expected_stderr))
+ return_value=(raw_expected_stdout, expected_stderr)
+ )
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock.MagicMock())
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock.MagicMock()
+ )
mock_debug_logger.assert_called_with(
- 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', expected_stdout,
- expected_stderr, 0)
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ 'fake_cmd',
+ expected_stdout,
+ expected_stderr,
+ 0,
+ )
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
@mock.patch('logging.debug')
def test_execute_and_process_stdout_logs_cmd_with_unexpected_stdout(
- self, mock_debug_logger, mock_popen):
+ self, mock_debug_logger, mock_popen
+ ):
raw_expected_stdout = MOCK_DEFAULT_STDOUT.encode('utf-8')
expected_stdout = '[unexpected stdout] %s' % raw_expected_stdout
expected_stderr = MOCK_DEFAULT_STDERR.encode('utf-8')
self._mock_execute_and_process_stdout_process(mock_popen)
mock_popen.return_value.communicate = mock.Mock(
- return_value=(raw_expected_stdout, expected_stderr))
+ return_value=(raw_expected_stdout, expected_stderr)
+ )
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock.MagicMock())
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock.MagicMock()
+ )
mock_debug_logger.assert_called_with(
- 'cmd: %s, stdout: %s, stderr: %s, ret: %s', 'fake_cmd', expected_stdout,
- expected_stderr, 0)
+ 'cmd: %s, stdout: %s, stderr: %s, ret: %s',
+ 'fake_cmd',
+ expected_stdout,
+ expected_stderr,
+ 0,
+ )
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
def test_execute_and_process_stdout_despite_cmd_exits(self, mock_popen):
@@ -234,9 +273,9 @@ class AdbTest(unittest.TestCase):
mock_popen.return_value.stdout.readline.side_effect = ['1', '2', '3', '']
mock_handler = mock.MagicMock()
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock_handler)
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock_handler
+ )
self.assertEqual(mock_handler.call_count, 3)
mock_handler.assert_any_call('1')
@@ -249,9 +288,9 @@ class AdbTest(unittest.TestCase):
mock_popen.return_value.stdout.readline.side_effect = ['1', '2', '3', '']
mock_handler = mock.MagicMock()
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock_handler)
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock_handler
+ )
self.assertEqual(mock_handler.call_count, 3)
mock_handler.assert_any_call('1')
@@ -262,9 +301,9 @@ class AdbTest(unittest.TestCase):
def test_execute_and_process_stdout_returns_stderr(self, mock_popen):
self._mock_execute_and_process_stdout_process(mock_popen)
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock.MagicMock())
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock.MagicMock()
+ )
self.assertEqual(MOCK_DEFAULT_STDERR, err.decode('utf-8'))
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
@@ -273,9 +312,9 @@ class AdbTest(unittest.TestCase):
mock_popen.return_value.returncode = 1
with self.assertRaisesRegex(adb.AdbError, 'Error executing adb cmd .*'):
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock.MagicMock())
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock.MagicMock()
+ )
@mock.patch('mobly.controllers.android_device_lib.adb.subprocess.Popen')
def test_execute_and_process_stdout_when_handler_crash(self, mock_popen):
@@ -285,9 +324,9 @@ class AdbTest(unittest.TestCase):
mock_handler.side_effect = ['', TypeError('fake crash'), '', '']
with self.assertRaisesRegex(TypeError, 'fake crash'):
- err = adb.AdbProxy()._execute_and_process_stdout(['fake_cmd'],
- shell=False,
- handler=mock_handler)
+ err = adb.AdbProxy()._execute_and_process_stdout(
+ ['fake_cmd'], shell=False, handler=mock_handler
+ )
mock_popen.return_value.communicate.assert_called_once_with()
@@ -297,180 +336,192 @@ class AdbTest(unittest.TestCase):
def test_construct_adb_cmd_with_one_command(self):
adb_cmd = adb.AdbProxy()._construct_adb_cmd(
- 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=False)
+ 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=False
+ )
self.assertEqual(adb_cmd, ['adb', 'shell ls /asdafsfd/asdf-asfd/asa'])
def test_construct_adb_cmd_with_one_arg_command(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- 'ls /asdafsfd/asdf-asfd/asa',
- shell=False)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=False
+ )
self.assertEqual(adb_cmd, ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa'])
def test_construct_adb_cmd_with_one_arg_command_list(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- ['ls /asdafsfd/asdf-asfd/asa'],
- shell=False)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=False
+ )
self.assertEqual(adb_cmd, ['adb', 'shell', 'ls /asdafsfd/asdf-asfd/asa'])
def test_construct_adb_cmd_with_special_characters(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- ['a b', '"blah"', r'\/\/'],
- shell=False)
- self.assertEqual(adb_cmd, ['adb', 'shell', 'a b', '"blah"', r"\/\/"])
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['a b', '"blah"', r'\/\/'], shell=False
+ )
+ self.assertEqual(adb_cmd, ['adb', 'shell', 'a b', '"blah"', r'\/\/'])
def test_construct_adb_cmd_with_serial(self):
- adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell',
- 'arg1',
- shell=False)
+ adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd(
+ 'shell', 'arg1', shell=False
+ )
self.assertEqual(adb_cmd, ['adb', '-s', '12345', 'shell', 'arg1'])
def test_construct_adb_cmd_with_list(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'],
- shell=False)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['arg1', 'arg2'], shell=False
+ )
self.assertEqual(adb_cmd, ['adb', 'shell', 'arg1', 'arg2'])
def test_construct_adb_cmd_with_serial_with_list(self):
- adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell',
- ['arg1', 'arg2'],
- shell=False)
+ adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd(
+ 'shell', ['arg1', 'arg2'], shell=False
+ )
self.assertEqual(adb_cmd, ['adb', '-s', '12345', 'shell', 'arg1', 'arg2'])
def test_construct_adb_cmd_with_shell_true(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- 'arg1 arg2',
- shell=True)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', 'arg1 arg2', shell=True
+ )
self.assertEqual(adb_cmd, '"adb" shell arg1 arg2')
def test_construct_adb_cmd_with_shell_true_with_one_command(self):
adb_cmd = adb.AdbProxy()._construct_adb_cmd(
- 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=True)
+ 'shell ls /asdafsfd/asdf-asfd/asa', [], shell=True
+ )
self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa ')
def test_construct_adb_cmd_with_shell_true_with_one_arg_command(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- 'ls /asdafsfd/asdf-asfd/asa',
- shell=True)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', 'ls /asdafsfd/asdf-asfd/asa', shell=True
+ )
self.assertEqual(adb_cmd, '"adb" shell ls /asdafsfd/asdf-asfd/asa')
def test_construct_adb_cmd_with_shell_true_with_one_arg_command_list(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- ['ls /asdafsfd/asdf-asfd/asa'],
- shell=True)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['ls /asdafsfd/asdf-asfd/asa'], shell=True
+ )
self.assertEqual(adb_cmd, '"adb" shell \'ls /asdafsfd/asdf-asfd/asa\'')
def test_construct_adb_cmd_with_shell_true_with_auto_quotes(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell',
- ['a b', '"blah"', r'\/\/'],
- shell=True)
- self.assertEqual(adb_cmd, '"adb" shell \'a b\' \'"blah"\' \'\\/\\/\'')
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['a b', '"blah"', r'\/\/'], shell=True
+ )
+ self.assertEqual(adb_cmd, "\"adb\" shell 'a b' '\"blah\"' '\\/\\/'")
def test_construct_adb_cmd_with_shell_true_with_serial(self):
- adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell',
- 'arg1 arg2',
- shell=True)
+ adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd(
+ 'shell', 'arg1 arg2', shell=True
+ )
self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2')
def test_construct_adb_cmd_with_shell_true_with_list(self):
- adb_cmd = adb.AdbProxy()._construct_adb_cmd('shell', ['arg1', 'arg2'],
- shell=True)
+ adb_cmd = adb.AdbProxy()._construct_adb_cmd(
+ 'shell', ['arg1', 'arg2'], shell=True
+ )
self.assertEqual(adb_cmd, '"adb" shell arg1 arg2')
def test_construct_adb_cmd_with_shell_true_with_serial_with_list(self):
- adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd('shell',
- ['arg1', 'arg2'],
- shell=True)
+ adb_cmd = adb.AdbProxy('12345')._construct_adb_cmd(
+ 'shell', ['arg1', 'arg2'], shell=True
+ )
self.assertEqual(adb_cmd, '"adb" -s "12345" shell arg1 arg2')
def test_exec_adb_cmd(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT
adb.AdbProxy().shell(['arg1', 'arg2'])
- mock_exec_cmd.assert_called_once_with(['adb', 'shell', 'arg1', 'arg2'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_exec_cmd.assert_called_once_with(
+ ['adb', 'shell', 'arg1', 'arg2'],
+ shell=False,
+ timeout=None,
+ stderr=None,
+ )
def test_exec_adb_cmd_with_shell_true(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT
adb.AdbProxy().shell('arg1 arg2', shell=True)
- mock_exec_cmd.assert_called_once_with('"adb" shell arg1 arg2',
- shell=True,
- timeout=None,
- stderr=None)
+ mock_exec_cmd.assert_called_once_with(
+ '"adb" shell arg1 arg2', shell=True, timeout=None, stderr=None
+ )
def test_exec_adb_cmd_formats_command(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
- with mock.patch.object(adb.AdbProxy,
- '_construct_adb_cmd') as mock_construct_adb_cmd:
+ with mock.patch.object(
+ adb.AdbProxy, '_construct_adb_cmd'
+ ) as mock_construct_adb_cmd:
mock_adb_cmd = mock.MagicMock()
mock_adb_args = mock.MagicMock()
mock_construct_adb_cmd.return_value = mock_adb_cmd
mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT
adb.AdbProxy().shell(mock_adb_args)
- mock_construct_adb_cmd.assert_called_once_with('shell',
- mock_adb_args,
- shell=False)
- mock_exec_cmd.assert_called_once_with(mock_adb_cmd,
- shell=False,
- timeout=None,
- stderr=None)
+ mock_construct_adb_cmd.assert_called_once_with(
+ 'shell', mock_adb_args, shell=False
+ )
+ mock_exec_cmd.assert_called_once_with(
+ mock_adb_cmd, shell=False, timeout=None, stderr=None
+ )
def test_exec_adb_cmd_formats_command_with_shell_true(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
- with mock.patch.object(adb.AdbProxy,
- '_construct_adb_cmd') as mock_construct_adb_cmd:
+ with mock.patch.object(
+ adb.AdbProxy, '_construct_adb_cmd'
+ ) as mock_construct_adb_cmd:
mock_adb_cmd = mock.MagicMock()
mock_adb_args = mock.MagicMock()
mock_construct_adb_cmd.return_value = mock_adb_cmd
adb.AdbProxy().shell(mock_adb_args, shell=True)
- mock_construct_adb_cmd.assert_called_once_with('shell',
- mock_adb_args,
- shell=True)
- mock_exec_cmd.assert_called_once_with(mock_adb_cmd,
- shell=True,
- timeout=None,
- stderr=None)
+ mock_construct_adb_cmd.assert_called_once_with(
+ 'shell', mock_adb_args, shell=True
+ )
+ mock_exec_cmd.assert_called_once_with(
+ mock_adb_cmd, shell=True, timeout=None, stderr=None
+ )
def test_execute_adb_and_process_stdout_formats_command(self):
with mock.patch.object(
- adb.AdbProxy,
- '_execute_and_process_stdout') as mock_execute_and_process_stdout:
- with mock.patch.object(adb.AdbProxy,
- '_construct_adb_cmd') as mock_construct_adb_cmd:
+ adb.AdbProxy, '_execute_and_process_stdout'
+ ) as mock_execute_and_process_stdout:
+ with mock.patch.object(
+ adb.AdbProxy, '_construct_adb_cmd'
+ ) as mock_construct_adb_cmd:
mock_adb_cmd = mock.MagicMock()
mock_adb_args = mock.MagicMock()
mock_handler = mock.MagicMock()
mock_construct_adb_cmd.return_value = mock_adb_cmd
- adb.AdbProxy()._execute_adb_and_process_stdout('shell',
- mock_adb_args,
- shell=False,
- handler=mock_handler)
- mock_construct_adb_cmd.assert_called_once_with('shell',
- mock_adb_args,
- shell=False)
+ adb.AdbProxy()._execute_adb_and_process_stdout(
+ 'shell', mock_adb_args, shell=False, handler=mock_handler
+ )
+ mock_construct_adb_cmd.assert_called_once_with(
+ 'shell', mock_adb_args, shell=False
+ )
mock_execute_and_process_stdout.assert_called_once_with(
- mock_adb_cmd, shell=False, handler=mock_handler)
+ mock_adb_cmd, shell=False, handler=mock_handler
+ )
@mock.patch('mobly.utils.run_command')
def test_exec_adb_cmd_with_stderr_pipe(self, mock_run_command):
- mock_run_command.return_value = (0, MOCK_DEFAULT_STDOUT.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ mock_run_command.return_value = (
+ 0,
+ MOCK_DEFAULT_STDOUT.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
stderr_redirect = io.BytesIO()
out = adb.AdbProxy().shell('arg1 arg2', shell=True, stderr=stderr_redirect)
self.assertEqual(MOCK_DEFAULT_STDOUT, out.decode('utf-8'))
- self.assertEqual(MOCK_DEFAULT_STDERR,
- stderr_redirect.getvalue().decode('utf-8'))
+ self.assertEqual(
+ MOCK_DEFAULT_STDERR, stderr_redirect.getvalue().decode('utf-8')
+ )
@mock.patch('mobly.utils.run_command')
def test_connect_success(self, mock_run_command):
mock_address = 'localhost:1234'
mock_run_command.return_value = (
- 0, f'connected to {mock_address}'.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ 0,
+ f'connected to {mock_address}'.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
out = adb.AdbProxy().connect(mock_address)
self.assertEqual('connected to localhost:1234', out.decode('utf-8'))
@@ -479,8 +530,10 @@ class AdbTest(unittest.TestCase):
def test_connect_already_connected(self, mock_run_command):
mock_address = 'localhost:1234'
mock_run_command.return_value = (
- 0, f'already connected to {mock_address}'.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ 0,
+ f'already connected to {mock_address}'.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
out = adb.AdbProxy().connect(mock_address)
self.assertEqual('already connected to localhost:1234', out.decode('utf-8'))
@@ -488,11 +541,15 @@ class AdbTest(unittest.TestCase):
@mock.patch('mobly.utils.run_command')
def test_connect_fail(self, mock_run_command):
mock_address = 'localhost:1234'
- mock_run_command.return_value = (0, 'Connection refused\n'.encode('utf-8'),
- MOCK_DEFAULT_STDERR.encode('utf-8'))
+ mock_run_command.return_value = (
+ 0,
+ 'Connection refused\n'.encode('utf-8'),
+ MOCK_DEFAULT_STDERR.encode('utf-8'),
+ )
with self.assertRaisesRegex(
- adb.AdbError, 'Error executing adb cmd "connect localhost:1234".'):
+ adb.AdbError, 'Error executing adb cmd "connect localhost:1234".'
+ ):
out = adb.AdbProxy().connect(mock_address)
def test_getprop(self):
@@ -503,18 +560,22 @@ class AdbTest(unittest.TestCase):
['adb', 'shell', 'getprop', 'haha'],
shell=False,
stderr=None,
- timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
+ timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC,
+ )
def test_getprop_custom_timeout(self):
timeout_s = adb.DEFAULT_GETPROP_TIMEOUT_SEC * 2
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.return_value = b'blah'
- self.assertEqual(adb.AdbProxy().getprop('haha', timeout=timeout_s),
- 'blah')
- mock_exec_cmd.assert_called_once_with(['adb', 'shell', 'getprop', 'haha'],
- shell=False,
- stderr=None,
- timeout=timeout_s)
+ self.assertEqual(
+ adb.AdbProxy().getprop('haha', timeout=timeout_s), 'blah'
+ )
+ mock_exec_cmd.assert_called_once_with(
+ ['adb', 'shell', 'getprop', 'haha'],
+ shell=False,
+ stderr=None,
+ timeout=timeout_s,
+ )
def test__parse_getprop_output_special_values(self):
mock_adb_output = (
@@ -530,9 +591,10 @@ class AdbTest(unittest.TestCase):
)
parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output)
expected_output = {
- 'persist.sys.boot.reason.history':
- ('reboot,adb,1558549857\nreboot,factory_reset,1558483886\n'
- 'reboot,1558483823'),
+ 'persist.sys.boot.reason.history': (
+ 'reboot,adb,1558549857\nreboot,factory_reset,1558483886\n'
+ 'reboot,1558483823'
+ ),
'selinux.abc': 'key: value',
'persist.something': 'haha\n',
'selinux.restorecon_recursive': '/data/misc_ce/10',
@@ -542,26 +604,28 @@ class AdbTest(unittest.TestCase):
self.assertEqual(parsed_props, expected_output)
def test__parse_getprop_output_malformat_output(self):
- mock_adb_output = (
- b'[selinux.restorecon_recursive][/data/misc_ce/10]\n' # Malformat
+ mock_adb_output = ( # Malformat
+ b'[selinux.restorecon_recursive][/data/misc_ce/10]\n'
b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\n'
- b'[persist.something]: [haha]\n')
+ b'[persist.something]: [haha]\n'
+ )
parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output)
expected_output = {
'persist.sys.boot.reason': 'reboot,adb,1558549857',
- 'persist.something': 'haha'
+ 'persist.something': 'haha',
}
self.assertEqual(parsed_props, expected_output)
def test__parse_getprop_output_special_line_separator(self):
- mock_adb_output = (
- b'[selinux.restorecon_recursive][/data/misc_ce/10]\r\n' # Malformat
+ mock_adb_output = ( # Malformat
+ b'[selinux.restorecon_recursive][/data/misc_ce/10]\r\n'
b'[persist.sys.boot.reason]: [reboot,adb,1558549857]\r\n'
- b'[persist.something]: [haha]\r\n')
+ b'[persist.something]: [haha]\r\n'
+ )
parsed_props = adb.AdbProxy()._parse_getprop_output(mock_adb_output)
expected_output = {
'persist.sys.boot.reason': 'reboot,adb,1558549857',
- 'persist.something': 'haha'
+ 'persist.something': 'haha',
}
self.assertEqual(parsed_props, expected_output)
@@ -572,42 +636,51 @@ class AdbTest(unittest.TestCase):
b'\n[sendbug.preferred.domain]: [google.com]\n'
b'[sys.uidcpupower]: []\n'
b'[sys.wifitracing.started]: [1]\n'
- b'[telephony.lteOnCdmaDevice]: [1]\n\n')
+ b'[telephony.lteOnCdmaDevice]: [1]\n\n'
+ )
actual_output = adb.AdbProxy().getprops([
'sys.wifitracing.started', # "numeric" value
'sys.uidcpupower', # empty value
'sendbug.preferred.domain', # string value
- 'nonExistentProp'
+ 'nonExistentProp',
])
self.assertEqual(
- actual_output, {
+ actual_output,
+ {
'sys.wifitracing.started': '1',
'sys.uidcpupower': '',
- 'sendbug.preferred.domain': 'google.com'
- })
+ 'sendbug.preferred.domain': 'google.com',
+ },
+ )
mock_exec_cmd.assert_called_once_with(
['adb', 'shell', 'getprop'],
shell=False,
stderr=None,
- timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
+ timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC,
+ )
mock_sleep.assert_not_called()
@mock.patch('time.sleep', return_value=mock.MagicMock())
def test_getprops_when_empty_string_randomly_returned(self, mock_sleep):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.side_effect = [
- b'', (b'\n[ro.build.id]: [AB42]\n'
- b'[ro.build.type]: [userdebug]\n\n')
+ b'',
+ b'\n[ro.build.id]: [AB42]\n[ro.build.type]: [userdebug]\n\n',
]
actual_output = adb.AdbProxy().getprops(['ro.build.id'])
- self.assertEqual(actual_output, {
- 'ro.build.id': 'AB42',
- })
+ self.assertEqual(
+ actual_output,
+ {
+ 'ro.build.id': 'AB42',
+ },
+ )
self.assertEqual(mock_exec_cmd.call_count, 2)
- mock_exec_cmd.assert_called_with(['adb', 'shell', 'getprop'],
- shell=False,
- stderr=None,
- timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'shell', 'getprop'],
+ shell=False,
+ stderr=None,
+ timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC,
+ )
self.assertEqual(mock_sleep.call_count, 1)
mock_sleep.assert_called_with(1)
@@ -618,16 +691,34 @@ class AdbTest(unittest.TestCase):
actual_output = adb.AdbProxy().getprops(['ro.build.id'])
self.assertEqual(actual_output, {})
self.assertEqual(mock_exec_cmd.call_count, 3)
- mock_exec_cmd.assert_called_with(['adb', 'shell', 'getprop'],
- shell=False,
- stderr=None,
- timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC)
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'shell', 'getprop'],
+ shell=False,
+ stderr=None,
+ timeout=adb.DEFAULT_GETPROP_TIMEOUT_SEC,
+ )
self.assertEqual(mock_sleep.call_count, 2)
mock_sleep.assert_called_with(1)
def test_forward(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
- adb.AdbProxy().forward(MOCK_SHELL_COMMAND)
+ adb.AdbProxy().forward(['tcp:12345', 'tcp:98765'])
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'forward', 'tcp:12345', 'tcp:98765'],
+ shell=False,
+ timeout=None,
+ stderr=None,
+ )
+
+ def test_reverse(self):
+ with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
+ adb.AdbProxy().reverse(['tcp:12345', 'tcp:98765'])
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'reverse', 'tcp:12345', 'tcp:98765'],
+ shell=False,
+ timeout=None,
+ stderr=None,
+ )
def test_instrument_without_parameters(self):
"""Verifies the AndroidDevice object's instrument command is correct in
@@ -639,7 +730,8 @@ class AdbTest(unittest.TestCase):
['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND],
shell=False,
timeout=None,
- stderr=None)
+ stderr=None,
+ )
self.assertEqual(output, mock_exec_cmd.return_value)
def test_instrument_with_runner(self):
@@ -647,13 +739,15 @@ class AdbTest(unittest.TestCase):
with a runner specified.
"""
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
- stdout = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE,
- runner=MOCK_INSTRUMENTATION_RUNNER)
+ stdout = adb.AdbProxy().instrument(
+ MOCK_INSTRUMENTATION_PACKAGE, runner=MOCK_INSTRUMENTATION_RUNNER
+ )
mock_exec_cmd.assert_called_once_with(
['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND],
shell=False,
timeout=None,
- stderr=None)
+ stderr=None,
+ )
self.assertEqual(stdout, mock_exec_cmd.return_value)
def test_instrument_with_options(self):
@@ -661,13 +755,15 @@ class AdbTest(unittest.TestCase):
with options.
"""
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
- stdout = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE,
- options=MOCK_INSTRUMENTATION_OPTIONS)
+ stdout = adb.AdbProxy().instrument(
+ MOCK_INSTRUMENTATION_PACKAGE, options=MOCK_INSTRUMENTATION_OPTIONS
+ )
mock_exec_cmd.assert_called_once_with(
['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND],
shell=False,
timeout=None,
- stderr=None)
+ stderr=None,
+ )
self.assertEqual(stdout, mock_exec_cmd.return_value)
def test_instrument_with_handler(self):
@@ -679,14 +775,16 @@ class AdbTest(unittest.TestCase):
pass
with mock.patch.object(
- adb.AdbProxy,
- '_execute_and_process_stdout') as mock_execute_and_process_stdout:
- stderr = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE,
- handler=mock_handler)
+ adb.AdbProxy, '_execute_and_process_stdout'
+ ) as mock_execute_and_process_stdout:
+ stderr = adb.AdbProxy().instrument(
+ MOCK_INSTRUMENTATION_PACKAGE, handler=mock_handler
+ )
mock_execute_and_process_stdout.assert_called_once_with(
['adb', 'shell', MOCK_BASIC_INSTRUMENTATION_COMMAND],
shell=False,
- handler=mock_handler)
+ handler=mock_handler,
+ )
self.assertEqual(stderr, mock_execute_and_process_stdout.return_value)
def test_instrument_with_handler_with_runner(self):
@@ -698,15 +796,18 @@ class AdbTest(unittest.TestCase):
pass
with mock.patch.object(
- adb.AdbProxy,
- '_execute_and_process_stdout') as mock_execute_and_process_stdout:
- stderr = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE,
- runner=MOCK_INSTRUMENTATION_RUNNER,
- handler=mock_handler)
+ adb.AdbProxy, '_execute_and_process_stdout'
+ ) as mock_execute_and_process_stdout:
+ stderr = adb.AdbProxy().instrument(
+ MOCK_INSTRUMENTATION_PACKAGE,
+ runner=MOCK_INSTRUMENTATION_RUNNER,
+ handler=mock_handler,
+ )
mock_execute_and_process_stdout.assert_called_once_with(
['adb', 'shell', MOCK_RUNNER_INSTRUMENTATION_COMMAND],
shell=False,
- handler=mock_handler)
+ handler=mock_handler,
+ )
self.assertEqual(stderr, mock_execute_and_process_stdout.return_value)
def test_instrument_with_handler_with_options(self):
@@ -718,25 +819,27 @@ class AdbTest(unittest.TestCase):
pass
with mock.patch.object(
- adb.AdbProxy,
- '_execute_and_process_stdout') as mock_execute_and_process_stdout:
- stderr = adb.AdbProxy().instrument(MOCK_INSTRUMENTATION_PACKAGE,
- options=MOCK_INSTRUMENTATION_OPTIONS,
- handler=mock_handler)
+ adb.AdbProxy, '_execute_and_process_stdout'
+ ) as mock_execute_and_process_stdout:
+ stderr = adb.AdbProxy().instrument(
+ MOCK_INSTRUMENTATION_PACKAGE,
+ options=MOCK_INSTRUMENTATION_OPTIONS,
+ handler=mock_handler,
+ )
mock_execute_and_process_stdout.assert_called_once_with(
['adb', 'shell', MOCK_OPTIONS_INSTRUMENTATION_COMMAND],
shell=False,
- handler=mock_handler)
+ handler=mock_handler,
+ )
self.assertEqual(stderr, mock_execute_and_process_stdout.return_value)
@mock.patch.object(adb.AdbProxy, '_exec_cmd')
def test_root_success(self, mock_exec_cmd):
mock_exec_cmd.return_value = MOCK_ROOT_SUCCESS_OUTPUT
output = adb.AdbProxy().root()
- mock_exec_cmd.assert_called_once_with(['adb', 'root'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_exec_cmd.assert_called_once_with(
+ ['adb', 'root'], shell=False, timeout=None, stderr=None
+ )
self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT)
@mock.patch('time.sleep', return_value=mock.MagicMock())
@@ -744,13 +847,12 @@ class AdbTest(unittest.TestCase):
def test_root_success_with_retry(self, mock_exec_cmd, mock_sleep):
mock_exec_cmd.side_effect = [
adb.AdbError('adb root', '', MOCK_ROOT_ERROR_OUTPUT, 1),
- MOCK_ROOT_SUCCESS_OUTPUT
+ MOCK_ROOT_SUCCESS_OUTPUT,
]
output = adb.AdbProxy().root()
- mock_exec_cmd.assert_called_with(['adb', 'root'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'root'], shell=False, timeout=None, stderr=None
+ )
self.assertEqual(output, MOCK_ROOT_SUCCESS_OUTPUT)
self.assertEqual(mock_sleep.call_count, 1)
mock_sleep.assert_called_with(10)
@@ -758,17 +860,20 @@ class AdbTest(unittest.TestCase):
@mock.patch('time.sleep', return_value=mock.MagicMock())
@mock.patch.object(adb.AdbProxy, '_exec_cmd')
def test_root_raises_adb_error_when_all_retries_failed(
- self, mock_exec_cmd, mock_sleep):
- mock_exec_cmd.side_effect = adb.AdbError('adb root', '',
- MOCK_ROOT_ERROR_OUTPUT, 1)
- expected_msg = ('Error executing adb cmd "adb root". '
- 'ret: 1, stdout: , stderr: %s' % MOCK_ROOT_ERROR_OUTPUT)
+ self, mock_exec_cmd, mock_sleep
+ ):
+ mock_exec_cmd.side_effect = adb.AdbError(
+ 'adb root', '', MOCK_ROOT_ERROR_OUTPUT, 1
+ )
+ expected_msg = (
+ 'Error executing adb cmd "adb root". ret: 1, stdout: , stderr: %s'
+ % MOCK_ROOT_ERROR_OUTPUT
+ )
with self.assertRaisesRegex(adb.AdbError, expected_msg):
adb.AdbProxy().root()
- mock_exec_cmd.assert_called_with(['adb', 'root'],
- shell=False,
- timeout=None,
- stderr=None)
+ mock_exec_cmd.assert_called_with(
+ ['adb', 'root'], shell=False, timeout=None, stderr=None
+ )
self.assertEqual(mock_sleep.call_count, adb.ADB_ROOT_RETRY_ATTEMPTS - 1)
mock_sleep.assert_has_calls([mock.call(10), mock.call(20)])
@@ -780,7 +885,8 @@ class AdbTest(unittest.TestCase):
['adb', 'shell', 'command', '-v', MOCK_SHELL_COMMAND],
shell=False,
timeout=None,
- stderr=None)
+ stderr=None,
+ )
def test_has_shell_command_with_existing_command(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
@@ -790,15 +896,17 @@ class AdbTest(unittest.TestCase):
def test_has_shell_command_with_missing_command_on_older_devices(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT
- mock_exec_cmd.side_effect = adb.AdbError(MOCK_ADB_SHELL_COMMAND_CHECK, '',
- '', 0)
+ mock_exec_cmd.side_effect = adb.AdbError(
+ MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 0
+ )
self.assertFalse(adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND))
def test_has_shell_command_with_missing_command_on_newer_devices(self):
with mock.patch.object(adb.AdbProxy, '_exec_cmd') as mock_exec_cmd:
mock_exec_cmd.return_value = MOCK_DEFAULT_COMMAND_OUTPUT
- mock_exec_cmd.side_effect = adb.AdbError(MOCK_ADB_SHELL_COMMAND_CHECK, '',
- '', 1)
+ mock_exec_cmd.side_effect = adb.AdbError(
+ MOCK_ADB_SHELL_COMMAND_CHECK, '', '', 1
+ )
self.assertFalse(adb.AdbProxy().has_shell_command(MOCK_SHELL_COMMAND))
@mock.patch.object(adb.AdbProxy, 'getprop')
@@ -811,25 +919,30 @@ class AdbTest(unittest.TestCase):
['adb', 'shell', 'am', 'get-current-user'],
shell=False,
stderr=None,
- timeout=None)
+ timeout=None,
+ )
self.assertEqual(user_id, 123)
@mock.patch.object(adb.AdbProxy, 'getprop')
@mock.patch.object(adb.AdbProxy, '_exec_cmd')
def test_current_user_id_between_21_and_24(self, mock_exec_cmd, mock_getprop):
mock_getprop.return_value = b'23'
- mock_exec_cmd.return_value = (b'Users:\n'
- b'UserInfo{123:Owner:13} serialNo=0\n'
- b'Created: <unknown>\n'
- b'Last logged in: +1h22m12s497ms ago\n'
- b'UserInfo{456:Owner:14} serialNo=0\n'
- b'Created: <unknown>\n'
- b'Last logged in: +1h01m12s497ms ago\n')
+ mock_exec_cmd.return_value = (
+ b'Users:\n'
+ b'UserInfo{123:Owner:13} serialNo=0\n'
+ b'Created: <unknown>\n'
+ b'Last logged in: +1h22m12s497ms ago\n'
+ b'UserInfo{456:Owner:14} serialNo=0\n'
+ b'Created: <unknown>\n'
+ b'Last logged in: +1h01m12s497ms ago\n'
+ )
user_id = adb.AdbProxy().current_user_id
- mock_exec_cmd.assert_called_once_with(['adb', 'shell', 'dumpsys', 'user'],
- shell=False,
- stderr=None,
- timeout=None)
+ mock_exec_cmd.assert_called_once_with(
+ ['adb', 'shell', 'dumpsys', 'user'],
+ shell=False,
+ stderr=None,
+ timeout=None,
+ )
self.assertEqual(user_id, 123)
diff --git a/tests/mobly/controllers/android_device_lib/callback_handler_test.py b/tests/mobly/controllers/android_device_lib/callback_handler_test.py
index a30408f..2f3398c 100755
--- a/tests/mobly/controllers/android_device_lib/callback_handler_test.py
+++ b/tests/mobly/controllers/android_device_lib/callback_handler_test.py
@@ -18,7 +18,7 @@ from unittest import mock
from mobly.controllers.android_device_lib import callback_handler
from mobly.controllers.android_device_lib import jsonrpc_client_base
-MOCK_CALLBACK_ID = "1-0"
+MOCK_CALLBACK_ID = '1-0'
MOCK_RAW_EVENT = {
'callbackId': '2-1',
'name': 'AsyncTaskResult',
@@ -26,26 +26,28 @@ MOCK_RAW_EVENT = {
'data': {
'exampleData': "Here's a simple event.",
'successful': True,
- 'secretNumber': 12
- }
+ 'secretNumber': 12,
+ },
}
class CallbackHandlerTest(unittest.TestCase):
- """Unit tests for mobly.controllers.android_device_lib.callback_handler.
- """
+ """Unit tests for mobly.controllers.android_device_lib.callback_handler."""
def test_timeout_value(self):
- self.assertGreaterEqual(jsonrpc_client_base._SOCKET_READ_TIMEOUT,
- callback_handler.MAX_TIMEOUT)
+ self.assertGreaterEqual(
+ jsonrpc_client_base._SOCKET_READ_TIMEOUT, callback_handler.MAX_TIMEOUT
+ )
def test_callback_id_property(self):
mock_event_client = mock.Mock()
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
self.assertEqual(handler.callback_id, MOCK_CALLBACK_ID)
with self.assertRaises(AttributeError):
handler.callback_id = 'ha'
@@ -53,11 +55,13 @@ class CallbackHandlerTest(unittest.TestCase):
def test_event_dict_to_snippet_event(self):
mock_event_client = mock.Mock()
mock_event_client.eventWaitAndGet = mock.Mock(return_value=MOCK_RAW_EVENT)
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
event = handler.waitAndGet('ha')
self.assertEqual(event.name, MOCK_RAW_EVENT['name'])
self.assertEqual(event.creation_time, MOCK_RAW_EVENT['time'])
@@ -66,15 +70,20 @@ class CallbackHandlerTest(unittest.TestCase):
def test_wait_and_get_timeout(self):
mock_event_client = mock.Mock()
- java_timeout_msg = ('com.google.android.mobly.snippet.event.'
- 'EventSnippet$EventSnippetException: timeout.')
+ java_timeout_msg = (
+ 'com.google.android.mobly.snippet.event.'
+ 'EventSnippet$EventSnippetException: timeout.'
+ )
mock_event_client.eventWaitAndGet = mock.Mock(
- side_effect=jsonrpc_client_base.ApiError(mock.Mock(), java_timeout_msg))
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ side_effect=jsonrpc_client_base.ApiError(mock.Mock(), java_timeout_msg)
+ )
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
expected_msg = 'Timed out after waiting .*s for event "ha" .*'
with self.assertRaisesRegex(callback_handler.TimeoutError, expected_msg):
handler.waitAndGet('ha')
@@ -82,11 +91,13 @@ class CallbackHandlerTest(unittest.TestCase):
def test_wait_for_event(self):
mock_event_client = mock.Mock()
mock_event_client.eventWaitAndGet = mock.Mock(return_value=MOCK_RAW_EVENT)
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
def some_condition(event):
return event.data['successful']
@@ -96,14 +107,17 @@ class CallbackHandlerTest(unittest.TestCase):
def test_wait_for_event_negative(self):
mock_event_client = mock.Mock()
mock_event_client.eventWaitAndGet = mock.Mock(return_value=MOCK_RAW_EVENT)
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
expected_msg = (
'Timed out after 0.01s waiting for an "AsyncTaskResult" event that'
- ' satisfies the predicate "some_condition".')
+ ' satisfies the predicate "some_condition".'
+ )
def some_condition(event):
return False
@@ -112,25 +126,26 @@ class CallbackHandlerTest(unittest.TestCase):
handler.waitForEvent('AsyncTaskResult', some_condition, 0.01)
def test_wait_for_event_max_timeout(self):
- """waitForEvent should not raise the timeout exceed threshold error.
- """
+ """waitForEvent should not raise the timeout exceed threshold error."""
mock_event_client = mock.Mock()
mock_event_client.eventWaitAndGet = mock.Mock(return_value=MOCK_RAW_EVENT)
- handler = callback_handler.CallbackHandler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client,
- ret_value=None,
- method_name=None,
- ad=mock.Mock())
+ handler = callback_handler.CallbackHandler(
+ callback_id=MOCK_CALLBACK_ID,
+ event_client=mock_event_client,
+ ret_value=None,
+ method_name=None,
+ ad=mock.Mock(),
+ )
def some_condition(event):
return event.data['successful']
big_timeout = callback_handler.MAX_TIMEOUT * 2
# This line should not raise.
- event = handler.waitForEvent('AsyncTaskResult',
- some_condition,
- timeout=big_timeout)
+ event = handler.waitForEvent(
+ 'AsyncTaskResult', some_condition, timeout=big_timeout
+ )
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/controllers/android_device_lib/callback_handler_v2_test.py b/tests/mobly/controllers/android_device_lib/callback_handler_v2_test.py
index b598cae..a7b8e9f 100644
--- a/tests/mobly/controllers/android_device_lib/callback_handler_v2_test.py
+++ b/tests/mobly/controllers/android_device_lib/callback_handler_v2_test.py
@@ -28,22 +28,24 @@ MOCK_RAW_EVENT = {
'data': {
'exampleData': "Here's a simple event.",
'successful': True,
- 'secretNumber': 12
- }
+ 'secretNumber': 12,
+ },
}
class CallbackHandlerV2Test(unittest.TestCase):
"""Unit tests for callback_handler_v2.CallbackHandlerV2."""
- def _make_callback_handler(self,
- callback_id=None,
- event_client=None,
- ret_value=None,
- method_name=None,
- device=None,
- rpc_max_timeout_sec=600,
- default_timeout_sec=120):
+ def _make_callback_handler(
+ self,
+ callback_id=None,
+ event_client=None,
+ ret_value=None,
+ method_name=None,
+ device=None,
+ rpc_max_timeout_sec=600,
+ default_timeout_sec=120,
+ ):
return callback_handler_v2.CallbackHandlerV2(
callback_id=callback_id,
event_client=event_client,
@@ -51,7 +53,8 @@ class CallbackHandlerV2Test(unittest.TestCase):
method_name=method_name,
device=device,
rpc_max_timeout_sec=rpc_max_timeout_sec,
- default_timeout_sec=default_timeout_sec)
+ default_timeout_sec=default_timeout_sec,
+ )
def assert_event_correct(self, actual_event, expected_raw_event_dict):
expected_event = callback_event.from_dict(expected_raw_event_dict)
@@ -60,12 +63,14 @@ class CallbackHandlerV2Test(unittest.TestCase):
def test_wait_and_get(self):
mock_event_client = mock.Mock()
mock_event_client.eventWaitAndGet = mock.Mock(return_value=MOCK_RAW_EVENT)
- handler = self._make_callback_handler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client)
+ handler = self._make_callback_handler(
+ callback_id=MOCK_CALLBACK_ID, event_client=mock_event_client
+ )
event = handler.waitAndGet('ha')
self.assert_event_correct(event, MOCK_RAW_EVENT)
mock_event_client.eventWaitAndGet.assert_called_once_with(
- MOCK_CALLBACK_ID, 'ha', mock.ANY)
+ MOCK_CALLBACK_ID, 'ha', mock.ANY
+ )
def test_wait_and_get_timeout_arg_transform(self):
mock_event_client = mock.Mock()
@@ -76,12 +81,14 @@ class CallbackHandlerV2Test(unittest.TestCase):
expected_rpc_timeout_ms = 10000
_ = handler.waitAndGet('ha', timeout=wait_and_get_timeout_sec)
mock_event_client.eventWaitAndGet.assert_called_once_with(
- mock.ANY, mock.ANY, expected_rpc_timeout_ms)
+ mock.ANY, mock.ANY, expected_rpc_timeout_ms
+ )
def test_wait_for_event(self):
mock_event_client = mock.Mock()
- handler = self._make_callback_handler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client)
+ handler = self._make_callback_handler(
+ callback_id=MOCK_CALLBACK_ID, event_client=mock_event_client
+ )
event_should_ignore = {
'callbackId': '2-1',
@@ -89,10 +96,11 @@ class CallbackHandlerV2Test(unittest.TestCase):
'time': 20460228696,
'data': {
'successful': False,
- }
+ },
}
mock_event_client.eventWaitAndGet.side_effect = [
- event_should_ignore, MOCK_RAW_EVENT
+ event_should_ignore,
+ MOCK_RAW_EVENT,
]
def some_condition(event):
@@ -107,11 +115,13 @@ class CallbackHandlerV2Test(unittest.TestCase):
def test_get_all(self):
mock_event_client = mock.Mock()
- handler = self._make_callback_handler(callback_id=MOCK_CALLBACK_ID,
- event_client=mock_event_client)
+ handler = self._make_callback_handler(
+ callback_id=MOCK_CALLBACK_ID, event_client=mock_event_client
+ )
mock_event_client.eventGetAll = mock.Mock(
- return_value=[MOCK_RAW_EVENT, MOCK_RAW_EVENT])
+ return_value=[MOCK_RAW_EVENT, MOCK_RAW_EVENT]
+ )
all_events = handler.getAll('ha')
self.assertEqual(len(all_events), 2)
@@ -119,29 +129,36 @@ class CallbackHandlerV2Test(unittest.TestCase):
self.assert_event_correct(event, MOCK_RAW_EVENT)
mock_event_client.eventGetAll.assert_called_once_with(
- MOCK_CALLBACK_ID, 'ha')
+ MOCK_CALLBACK_ID, 'ha'
+ )
def test_wait_and_get_timeout_message_pattern_matches(self):
mock_event_client = mock.Mock()
android_snippet_timeout_msg = (
'com.google.android.mobly.snippet.event.EventSnippet$'
- 'EventSnippetException: timeout.')
+ 'EventSnippetException: timeout.'
+ )
mock_event_client.eventWaitAndGet = mock.Mock(
- side_effect=errors.ApiError(mock.Mock(), android_snippet_timeout_msg))
- handler = self._make_callback_handler(event_client=mock_event_client,
- method_name='test_method')
-
- expected_msg = ('Timed out after waiting .*s for event "ha" triggered by '
- 'test_method .*')
- with self.assertRaisesRegex(errors.CallbackHandlerTimeoutError,
- expected_msg):
+ side_effect=errors.ApiError(mock.Mock(), android_snippet_timeout_msg)
+ )
+ handler = self._make_callback_handler(
+ event_client=mock_event_client, method_name='test_method'
+ )
+
+ expected_msg = (
+ 'Timed out after waiting .*s for event "ha" triggered by test_method .*'
+ )
+ with self.assertRaisesRegex(
+ errors.CallbackHandlerTimeoutError, expected_msg
+ ):
handler.waitAndGet('ha')
def test_wait_and_get_reraise_if_pattern_not_match(self):
mock_event_client = mock.Mock()
snippet_timeout_msg = 'Snippet executed with error.'
mock_event_client.eventWaitAndGet = mock.Mock(
- side_effect=errors.ApiError(mock.Mock(), snippet_timeout_msg))
+ side_effect=errors.ApiError(mock.Mock(), snippet_timeout_msg)
+ )
handler = self._make_callback_handler(event_client=mock_event_client)
with self.assertRaisesRegex(errors.ApiError, snippet_timeout_msg):
diff --git a/tests/mobly/controllers/android_device_lib/errors_test.py b/tests/mobly/controllers/android_device_lib/errors_test.py
index 196aa03..38a0ac1 100755
--- a/tests/mobly/controllers/android_device_lib/errors_test.py
+++ b/tests/mobly/controllers/android_device_lib/errors_test.py
@@ -31,19 +31,20 @@ class ErrorsTest(unittest.TestCase):
device = mock.MagicMock()
device.__repr__ = lambda _: '[MockDevice]'
exception = errors.ServiceError(device, 'Some error message.')
- self.assertEqual(str(exception),
- '[MockDevice]::Service<None> Some error message.')
+ self.assertEqual(
+ str(exception), '[MockDevice]::Service<None> Some error message.'
+ )
def test_subclass_service_error(self):
-
class Error(errors.ServiceError):
SERVICE_TYPE = 'SomeType'
device = mock.MagicMock()
device.__repr__ = lambda _: '[MockDevice]'
exception = Error(device, 'Some error message.')
- self.assertEqual(str(exception),
- '[MockDevice]::Service<SomeType> Some error message.')
+ self.assertEqual(
+ str(exception), '[MockDevice]::Service<SomeType> Some error message.'
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/controllers/android_device_lib/fastboot_test.py b/tests/mobly/controllers/android_device_lib/fastboot_test.py
index 6e59dea..86b697a 100644
--- a/tests/mobly/controllers/android_device_lib/fastboot_test.py
+++ b/tests/mobly/controllers/android_device_lib/fastboot_test.py
@@ -24,19 +24,24 @@ class FastbootTest(unittest.TestCase):
@mock.patch('mobly.controllers.android_device_lib.fastboot.Popen')
@mock.patch('logging.debug')
def test_fastboot_commands_and_results_are_logged_to_debug_log(
- self, mock_debug_logger, mock_popen):
+ self, mock_debug_logger, mock_popen
+ ):
expected_stdout = 'stdout'
expected_stderr = b'stderr'
mock_popen.return_value.communicate = mock.Mock(
- return_value=(expected_stdout, expected_stderr))
+ return_value=(expected_stdout, expected_stderr)
+ )
mock_popen.return_value.returncode = 123
fastboot.FastbootProxy().fake_command('extra', 'flags')
mock_debug_logger.assert_called_with(
'cmd: %s, stdout: %s, stderr: %s, ret: %s',
- '\'fastboot fake-command extra flags\'', expected_stdout,
- expected_stderr, 123)
+ "'fastboot fake-command extra flags'",
+ expected_stdout,
+ expected_stderr,
+ 123,
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py b/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py
index 4cbeb35..1861cc0 100755
--- a/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py
+++ b/tests/mobly/controllers/android_device_lib/jsonrpc_client_base_test.py
@@ -28,8 +28,7 @@ class FakeRpcClient(jsonrpc_client_base.JsonRpcClientBase):
class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
- """Unit tests for mobly.controllers.android_device_lib.jsonrpc_client_base.
- """
+ """Unit tests for mobly.controllers.android_device_lib.jsonrpc_client_base."""
@mock.patch('socket.create_connection')
def test_open_timeout_io_error(self, mock_create_connection):
@@ -66,7 +65,8 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
client = FakeRpcClient()
with self.assertRaisesRegex(
jsonrpc_client_base.ProtocolError,
- jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE):
+ jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE,
+ ):
client.connect()
def test_disconnect(self):
@@ -124,8 +124,9 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
Test that when the handshake is given an unknown status then the client
will not be given a uid.
"""
- self.setup_mock_socket_file(mock_create_connection,
- resp=self.MOCK_RESP_UNKNOWN_STATUS)
+ self.setup_mock_socket_file(
+ mock_create_connection, resp=self.MOCK_RESP_UNKNOWN_STATUS
+ )
client = FakeRpcClient()
client.connect()
self.assertEqual(client.uid, jsonrpc_client_base.UNKNOWN_UID)
@@ -182,7 +183,8 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
with self.assertRaisesRegex(
jsonrpc_client_base.ProtocolError,
- jsonrpc_client_base.ProtocolError.MISMATCHED_API_ID):
+ jsonrpc_client_base.ProtocolError.MISMATCHED_API_ID,
+ ):
client.some_rpc(1, 2, 3)
@mock.patch('socket.create_connection')
@@ -201,7 +203,8 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
with self.assertRaisesRegex(
jsonrpc_client_base.ProtocolError,
- jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_SERVER):
+ jsonrpc_client_base.ProtocolError.NO_RESPONSE_FROM_SERVER,
+ ):
client.some_rpc(1, 2, 3)
@mock.patch('socket.create_connection')
@@ -232,7 +235,8 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
Logic is the same as test_rpc_send_to_socket.
"""
fake_file = self.setup_mock_socket_file(
- mock_create_connection, resp=self.MOCK_RESP_WITHOUT_CALLBACK)
+ mock_create_connection, resp=self.MOCK_RESP_WITHOUT_CALLBACK
+ )
client = FakeRpcClient()
client.connect()
@@ -275,15 +279,17 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
response = client._client_receive()
self.assertEqual(response, testing_rpc_response)
- client.log.debug.assert_called_with('Snippet received: %s',
- testing_rpc_response)
+ client.log.debug.assert_called_with(
+ 'Snippet received: %s', testing_rpc_response
+ )
@mock.patch('socket.create_connection')
def test_rpc_truncated_logging_short_response(self, mock_create_connection):
"""Test rpc response will full logged when length is short."""
fake_file = self.setup_mock_socket_file(mock_create_connection)
testing_rpc_response = self.generate_rpc_response(
- int(jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH / 2))
+ int(jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH / 2)
+ )
fake_file.resp = testing_rpc_response
client = FakeRpcClient()
@@ -293,17 +299,19 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
response = client._client_receive()
self.assertEqual(response, testing_rpc_response)
- client.log.debug.assert_called_with('Snippet received: %s',
- testing_rpc_response)
+ client.log.debug.assert_called_with(
+ 'Snippet received: %s', testing_rpc_response
+ )
@mock.patch('socket.create_connection')
- def test_rpc_truncated_logging_fit_size_response(self,
- mock_create_connection):
- """Test rpc response will full logged when length is equal to threshold.
- """
+ def test_rpc_truncated_logging_fit_size_response(
+ self, mock_create_connection
+ ):
+ """Test rpc response will full logged when length is equal to threshold."""
fake_file = self.setup_mock_socket_file(mock_create_connection)
testing_rpc_response = self.generate_rpc_response(
- jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH)
+ jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH
+ )
fake_file.resp = testing_rpc_response
client = FakeRpcClient()
@@ -313,8 +321,9 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
response = client._client_receive()
self.assertEqual(response, testing_rpc_response)
- client.log.debug.assert_called_with('Snippet received: %s',
- testing_rpc_response)
+ client.log.debug.assert_called_with(
+ 'Snippet received: %s', testing_rpc_response
+ )
@mock.patch('socket.create_connection')
def test_rpc_truncated_logging_long_response(self, mock_create_connection):
@@ -334,8 +343,11 @@ class JsonRpcClientBaseTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
# DEBUG level log should truncated by given length.
client.log.debug.assert_called_with(
'Snippet received: %s... %d chars are truncated',
- testing_rpc_response[:jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH],
- resp_len - jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH)
+ testing_rpc_response[
+ : jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH
+ ],
+ resp_len - jsonrpc_client_base._MAX_RPC_RESP_LOGGING_LENGTH,
+ )
def test_close_scoket_connection(self):
client = FakeRpcClient()
diff --git a/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py b/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py
index 8ac7b78..2cdcd5c 100755
--- a/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py
+++ b/tests/mobly/controllers/android_device_lib/jsonrpc_shell_base_test.py
@@ -37,8 +37,9 @@ class JsonRpcClientBaseTest(unittest.TestCase):
@mock.patch.object(android_device, 'list_adb_devices')
@mock.patch.object(android_device, 'get_instances')
@mock.patch.object(os, 'environ', new={})
- def test_load_device_when_one_device(self, mock_get_instances,
- mock_list_adb_devices):
+ def test_load_device_when_one_device(
+ self, mock_get_instances, mock_list_adb_devices
+ ):
mock_list_adb_devices.return_value = ['1234']
mock_device = mock.MagicMock(spec=android_device.AndroidDevice)
mock_get_instances.return_value = [mock_device]
@@ -49,8 +50,9 @@ class JsonRpcClientBaseTest(unittest.TestCase):
@mock.patch.object(android_device, 'list_adb_devices')
@mock.patch.object(android_device, 'get_instances')
@mock.patch.object(os, 'environ', new={'ANDROID_SERIAL': '1234'})
- def test_load_device_when_android_serial(self, mock_get_instances,
- mock_list_adb_devices):
+ def test_load_device_when_android_serial(
+ self, mock_get_instances, mock_list_adb_devices
+ ):
mock_list_adb_devices.return_value = ['1234', '4321']
mock_device = mock.MagicMock(spec=android_device.AndroidDevice)
mock_get_instances.return_value = [mock_device]
@@ -62,8 +64,9 @@ class JsonRpcClientBaseTest(unittest.TestCase):
def test_load_device_when_no_devices(self, mock_list_adb_devices):
mock_list_adb_devices.return_value = []
json_shell = jsonrpc_shell_base.JsonRpcShellBase()
- with self.assertRaisesRegex(jsonrpc_shell_base.Error,
- 'No adb device found!'):
+ with self.assertRaisesRegex(
+ jsonrpc_shell_base.Error, 'No adb device found!'
+ ):
json_shell.load_device()
@mock.patch.object(android_device, 'list_adb_devices')
@@ -71,8 +74,9 @@ class JsonRpcClientBaseTest(unittest.TestCase):
def test_load_device_when_unspecified_device(self, mock_list_adb_devices):
mock_list_adb_devices.return_value = ['1234', '4321']
json_shell = jsonrpc_shell_base.JsonRpcShellBase()
- with self.assertRaisesRegex(jsonrpc_shell_base.Error,
- 'Expected one phone.*'):
+ with self.assertRaisesRegex(
+ jsonrpc_shell_base.Error, 'Expected one phone.*'
+ ):
json_shell.load_device()
@mock.patch.object(android_device, 'list_adb_devices')
@@ -80,8 +84,9 @@ class JsonRpcClientBaseTest(unittest.TestCase):
def test_load_device_when_device_not_found(self, mock_list_adb_devices):
mock_list_adb_devices.return_value = ['4321']
json_shell = jsonrpc_shell_base.JsonRpcShellBase()
- with self.assertRaisesRegex(jsonrpc_shell_base.Error,
- 'Device "1234" is not found by adb.'):
+ with self.assertRaisesRegex(
+ jsonrpc_shell_base.Error, 'Device "1234" is not found by adb.'
+ ):
json_shell.load_device(serial='1234')
diff --git a/tests/mobly/controllers/android_device_lib/service_manager_test.py b/tests/mobly/controllers/android_device_lib/service_manager_test.py
index 1eae045..471c83f 100755
--- a/tests/mobly/controllers/android_device_lib/service_manager_test.py
+++ b/tests/mobly/controllers/android_device_lib/service_manager_test.py
@@ -62,7 +62,7 @@ class ServiceManagerTest(unittest.TestCase):
def assert_recorded_one_error(self, message):
self.assertEqual(expects.recorder.error_count, 1)
- for _, error in (expects.DEFAULT_TEST_RESULT_RECORD.extra_errors.items()):
+ for _, error in expects.DEFAULT_TEST_RESULT_RECORD.extra_errors.items():
self.assertIn(message, error.details)
def test_service_manager_instantiation(self):
@@ -102,13 +102,13 @@ class ServiceManagerTest(unittest.TestCase):
manager.register('mock_service', base_service)
def test_register_wrong_subclass_type(self):
-
class MyClass:
pass
manager = service_manager.ServiceManager(mock.MagicMock())
- with self.assertRaisesRegex(service_manager.Error,
- '.* is not a subclass of BaseService!'):
+ with self.assertRaisesRegex(
+ service_manager.Error, '.* is not a subclass of BaseService!'
+ ):
manager.register('mock_service', MyClass)
def test_register_dup_alias(self):
@@ -139,7 +139,8 @@ class ServiceManagerTest(unittest.TestCase):
service1.ha = mock.MagicMock()
service2.ha = mock.MagicMock()
manager.for_each(
- lambda service: manager._service_objects.pop(service.alias))
+ lambda service: manager._service_objects.pop(service.alias)
+ )
self.assertFalse(manager._service_objects)
def test_for_each_one_fail(self):
@@ -169,14 +170,16 @@ class ServiceManagerTest(unittest.TestCase):
service3.create_output_excerpts = mock.MagicMock()
service1.create_output_excerpts.return_value = ['path/to/1.txt']
service2.create_output_excerpts.return_value = [
- 'path/to/2-1.txt', 'path/to/2-2.txt'
+ 'path/to/2-1.txt',
+ 'path/to/2-2.txt',
]
service3.create_output_excerpts.return_value = []
mock_test_info = mock.MagicMock(output_path='path/to')
result = manager.create_output_excerpts_all(mock_test_info)
self.assertEqual(result['mock_service1'], ['path/to/1.txt'])
- self.assertEqual(result['mock_service2'],
- ['path/to/2-1.txt', 'path/to/2-2.txt'])
+ self.assertEqual(
+ result['mock_service2'], ['path/to/2-1.txt', 'path/to/2-2.txt']
+ )
self.assertEqual(result['mock_service3'], [])
def test_unregister(self):
@@ -201,7 +204,8 @@ class ServiceManagerTest(unittest.TestCase):
manager = service_manager.ServiceManager(mock.MagicMock())
with self.assertRaisesRegex(
service_manager.Error,
- '.* No service is registered with alias "mock_service"'):
+ '.* No service is registered with alias "mock_service"',
+ ):
manager.unregister('mock_service')
def test_unregister_handle_error_from_stop(self):
@@ -211,7 +215,8 @@ class ServiceManagerTest(unittest.TestCase):
service.stop_func.side_effect = Exception('Something failed in stop.')
manager.unregister('mock_service')
self.assert_recorded_one_error(
- 'Failed to stop service instance "mock_service".')
+ 'Failed to stop service instance "mock_service".'
+ )
def test_unregister_all(self):
manager = service_manager.ServiceManager(mock.MagicMock())
@@ -238,7 +243,8 @@ class ServiceManagerTest(unittest.TestCase):
self.assertTrue(service1.is_alive)
self.assertFalse(service2.is_alive)
self.assert_recorded_one_error(
- 'Failed to stop service instance "mock_service1".')
+ 'Failed to stop service instance "mock_service1".'
+ )
def test_start_all(self):
manager = service_manager.ServiceManager(mock.MagicMock())
@@ -256,7 +262,8 @@ class ServiceManagerTest(unittest.TestCase):
self.assertEqual(service2.start_func.call_count, 1)
self.assertEqual(
mock_call_tracker.mock_calls,
- [mock.call.start1(None), mock.call.start2(None)])
+ [mock.call.start1(None), mock.call.start2(None)],
+ )
def test_start_all_with_already_started_services(self):
manager = service_manager.ServiceManager(mock.MagicMock())
@@ -295,8 +302,9 @@ class ServiceManagerTest(unittest.TestCase):
manager.stop_all()
self.assertFalse(service1.is_alive)
self.assertFalse(service2.is_alive)
- self.assertEqual(mock_call_tracker.mock_calls,
- [mock.call.stop2(), mock.call.stop1()])
+ self.assertEqual(
+ mock_call_tracker.mock_calls, [mock.call.stop2(), mock.call.stop1()]
+ )
self.assertEqual(service1.start_func.call_count, 1)
self.assertEqual(service2.start_func.call_count, 1)
self.assertEqual(service1.stop_func.call_count, 1)
@@ -359,8 +367,8 @@ class ServiceManagerTest(unittest.TestCase):
mock_call_tracker.pause2 = service2.pause_func
manager.pause_all()
self.assertEqual(
- mock_call_tracker.mock_calls,
- [mock.call.pause2(), mock.call.pause1()])
+ mock_call_tracker.mock_calls, [mock.call.pause2(), mock.call.pause1()]
+ )
self.assertEqual(service1.pause_func.call_count, 1)
self.assertEqual(service2.pause_func.call_count, 1)
self.assertEqual(service1.resume_func.call_count, 0)
@@ -392,8 +400,8 @@ class ServiceManagerTest(unittest.TestCase):
manager.pause_all()
manager.resume_all()
self.assertEqual(
- mock_call_tracker.mock_calls,
- [mock.call.resume1(), mock.call.resume2()])
+ mock_call_tracker.mock_calls, [mock.call.resume1(), mock.call.resume2()]
+ )
self.assertEqual(service1.pause_func.call_count, 1)
self.assertEqual(service2.pause_func.call_count, 1)
self.assertEqual(service1.resume_func.call_count, 1)
@@ -434,8 +442,10 @@ class ServiceManagerTest(unittest.TestCase):
def test_start_services_non_existent(self):
manager = service_manager.ServiceManager(mock.MagicMock())
- msg = ('.* No service is registered under the name "mock_service", '
- 'cannot start.')
+ msg = (
+ '.* No service is registered under the name "mock_service", '
+ 'cannot start.'
+ )
with self.assertRaisesRegex(service_manager.Error, msg):
manager.start_services(['mock_service'])
@@ -452,8 +462,10 @@ class ServiceManagerTest(unittest.TestCase):
def test_resume_services_non_existent(self):
manager = service_manager.ServiceManager(mock.MagicMock())
- msg = ('.* No service is registered under the name "mock_service", '
- 'cannot resume.')
+ msg = (
+ '.* No service is registered under the name "mock_service", '
+ 'cannot resume.'
+ )
with self.assertRaisesRegex(service_manager.Error, msg):
manager.resume_services(['mock_service'])
diff --git a/tests/mobly/controllers/android_device_lib/services/logcat_test.py b/tests/mobly/controllers/android_device_lib/services/logcat_test.py
index df15d76..66a20f8 100755
--- a/tests/mobly/controllers/android_device_lib/services/logcat_test.py
+++ b/tests/mobly/controllers/android_device_lib/services/logcat_test.py
@@ -29,24 +29,25 @@ from tests.lib import mock_android_device
# The expected result of the cat adb operation.
MOCK_ADB_LOGCAT_CAT_RESULT = [
'02-29 14:02:21.456 4454 Something\n',
- '02-29 14:02:21.789 4454 Something again\n'
+ '02-29 14:02:21.789 4454 Something again\n',
]
# A mocked piece of adb logcat output.
-MOCK_ADB_LOGCAT = (u'02-29 14:02:19.123 4454 Nothing\n'
- u'%s'
- u'02-29 14:02:22.123 4454 Something again and again\n'
- ) % u''.join(MOCK_ADB_LOGCAT_CAT_RESULT)
+MOCK_ADB_LOGCAT = (
+ '02-29 14:02:19.123 4454 Nothing\n'
+ '%s'
+ '02-29 14:02:22.123 4454 Something again and again\n'
+) % ''.join(MOCK_ADB_LOGCAT_CAT_RESULT)
# The expected result of the cat adb operation.
MOCK_ADB_UNICODE_LOGCAT_CAT_RESULT = [
'02-29 14:02:21.456 4454 Something \u901a\n',
- '02-29 14:02:21.789 4454 Something again\n'
+ '02-29 14:02:21.789 4454 Something again\n',
]
# A mocked piece of adb logcat output.
MOCK_ADB_UNICODE_LOGCAT = (
- u'02-29 14:02:19.123 4454 Nothing\n'
- u'%s'
- u'02-29 14:02:22.123 4454 Something again and again\n'
-) % u''.join(MOCK_ADB_UNICODE_LOGCAT_CAT_RESULT)
+ '02-29 14:02:19.123 4454 Nothing\n'
+ '%s'
+ '02-29 14:02:22.123 4454 Something again and again\n'
+) % ''.join(MOCK_ADB_UNICODE_LOGCAT_CAT_RESULT)
# Mock start and end time of the adb cat.
MOCK_ADB_LOGCAT_BEGIN_TIME = '02-29 14:02:20.123'
@@ -54,11 +55,17 @@ MOCK_ADB_LOGCAT_END_TIME = '02-29 14:02:22.000'
# Mock AdbError for missing logpersist scripts
MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR = adb.AdbError(
- 'logpersist.stop --clear', b'',
- '/system/bin/sh: logpersist.stop: not found', 0)
+ 'logpersist.stop --clear',
+ b'',
+ '/system/bin/sh: logpersist.stop: not found',
+ 0,
+)
MOCK_LOGPERSIST_START_MISSING_ADB_ERROR = adb.AdbError(
- 'logpersist.start --clear', b'',
- b'/system/bin/sh: logpersist.stop: not found', 0)
+ 'logpersist.start --clear',
+ b'',
+ b'/system/bin/sh: logpersist.stop: not found',
+ 0,
+)
class LogcatTest(unittest.TestCase):
@@ -72,8 +79,7 @@ class LogcatTest(unittest.TestCase):
self.tmp_dir = tempfile.mkdtemp()
def tearDown(self):
- """Removes the temp dir.
- """
+ """Removes the temp dir."""
shutil.rmtree(self.tmp_dir)
def AssertFileContains(self, content, file_path):
@@ -86,18 +92,29 @@ class LogcatTest(unittest.TestCase):
output = f.read()
self.assertNotIn(content, output)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
@mock.patch('mobly.logger.get_log_file_timestamp')
- def test_start_and_stop(self, get_timestamp_mock, open_logcat_mock,
- stop_proc_mock, start_proc_mock, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ def test_start_and_stop(
+ self,
+ get_timestamp_mock,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
"""Verifies the steps of collecting adb logcat on an AndroidDevice
object, including various function calls and the expected behaviors of
the calls.
@@ -109,17 +126,18 @@ class LogcatTest(unittest.TestCase):
logcat_service.start()
# Verify start did the correct operations.
self.assertTrue(logcat_service._adb_logcat_process)
- expected_log_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial,
- 'logcat,%s,fakemodel,123.txt' % ad.serial)
+ expected_log_path = os.path.join(
+ logging.log_path,
+ 'AndroidDevice%s' % ad.serial,
+ 'logcat,%s,fakemodel,123.txt' % ad.serial,
+ )
create_dir_mock.assert_called_with(os.path.dirname(expected_log_path))
adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 >> %s'
- start_proc_mock.assert_called_with(adb_cmd %
- (ad.serial, '"%s" ' % expected_log_path),
- shell=True)
+ start_proc_mock.assert_called_with(
+ adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True
+ )
self.assertEqual(logcat_service.adb_logcat_file_path, expected_log_path)
- expected_msg = ('Logcat thread is already running, cannot start another'
- ' one.')
+ expected_msg = 'Logcat thread is already running, cannot start another one.'
# Expect error if start is called back to back.
with self.assertRaisesRegex(logcat.Error, expected_msg):
logcat_service.start()
@@ -129,15 +147,21 @@ class LogcatTest(unittest.TestCase):
self.assertIsNone(logcat_service._adb_logcat_process)
self.assertEqual(logcat_service.adb_logcat_file_path, expected_log_path)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device.list_fastboot_devices',
- return_value='1')
- def test_start_in_fastboot_mode(self, _, start_proc_mock, FastbootProxy,
- MockAdbProxy):
+ @mock.patch(
+ 'mobly.controllers.android_device.list_fastboot_devices', return_value='1'
+ )
+ def test_start_in_fastboot_mode(
+ self, _, start_proc_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
logcat_service = logcat.Logcat(ad)
@@ -146,17 +170,27 @@ class LogcatTest(unittest.TestCase):
self.assertFalse(logcat_service._adb_logcat_process)
start_proc_mock.assert_not_called()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
- def test_update_config(self, open_logcat_mock, stop_proc_mock,
- start_proc_mock, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_update_config(
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
logcat_service = logcat.Logcat(ad)
@@ -164,56 +198,82 @@ class LogcatTest(unittest.TestCase):
logcat_service.stop()
new_log_params = '-a -b -c'
new_file_path = 'some/path/log.txt'
- new_config = logcat.Config(logcat_params=new_log_params,
- output_file_path=new_file_path)
+ new_config = logcat.Config(
+ logcat_params=new_log_params, output_file_path=new_file_path
+ )
logcat_service.update_config(new_config)
logcat_service.start()
self.assertTrue(logcat_service._adb_logcat_process)
create_dir_mock.assert_has_calls([mock.call('some/path')])
- expected_adb_cmd = (' "adb" -s 1 logcat -v threadtime -T 1 -a -b -c >> '
- '"some/path/log.txt" ')
+ expected_adb_cmd = (
+ ' "adb" -s 1 logcat -v threadtime -T 1 -a -b -c >> "some/path/log.txt" '
+ )
start_proc_mock.assert_called_with(expected_adb_cmd, shell=True)
self.assertEqual(logcat_service.adb_logcat_file_path, 'some/path/log.txt')
logcat_service.stop()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
- def test_update_config_while_running(self, open_logcat_mock, stop_proc_mock,
- start_proc_mock, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ def test_update_config_while_running(
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
logcat_service = logcat.Logcat(ad)
logcat_service.start()
- new_config = logcat.Config(logcat_params='-blah',
- output_file_path='some/path/file.txt')
+ new_config = logcat.Config(
+ logcat_params='-blah', output_file_path='some/path/file.txt'
+ )
with self.assertRaisesRegex(
logcat.Error,
- 'Logcat thread is already running, cannot start another one'):
+ 'Logcat thread is already running, cannot start another one',
+ ):
logcat_service.update_config(new_config)
self.assertTrue(logcat_service.is_alive)
logcat_service.stop()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
@mock.patch(
'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log',
- return_value=mock_android_device.MockAdbProxy('1'))
- def test_pause_and_resume(self, clear_adb_mock, open_logcat_mock,
- stop_proc_mock, start_proc_mock, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ def test_pause_and_resume(
+ self,
+ clear_adb_mock,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
logcat_service = logcat.Logcat(ad, logcat.Config(clear_log=True))
@@ -230,44 +290,58 @@ class LogcatTest(unittest.TestCase):
clear_adb_mock.assert_not_called()
logcat_service.stop()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch(
'mobly.controllers.android_device_lib.services.logcat.Logcat.clear_adb_log',
- return_value=mock_android_device.MockAdbProxy('1'))
- def test_logcat_service_create_output_excerpts(self, clear_adb_mock,
- stop_proc_mock,
- start_proc_mock, FastbootProxy,
- MockAdbProxy):
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ def test_logcat_service_create_output_excerpts(
+ self,
+ clear_adb_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
logcat_service = logcat.Logcat(ad)
logcat_service._start()
- def _write_logcat_file_and_assert_excerpts_exists(logcat_file_content,
- test_begin_time,
- test_name):
+ def _write_logcat_file_and_assert_excerpts_exists(
+ logcat_file_content, test_begin_time, test_name
+ ):
with open(logcat_service.adb_logcat_file_path, 'a') as f:
f.write(logcat_file_content)
test_output_dir = os.path.join(self.tmp_dir, test_name)
mock_record = records.TestResultRecord(test_name)
mock_record.begin_time = test_begin_time
mock_record.signature = f'{test_name}-{test_begin_time}'
- test_run_info = runtime_test_info.RuntimeTestInfo(test_name,
- test_output_dir,
- mock_record)
+ test_run_info = runtime_test_info.RuntimeTestInfo(
+ test_name, test_output_dir, mock_record
+ )
actual_path = logcat_service.create_output_excerpts(test_run_info)[0]
expected_path = os.path.join(
- test_output_dir, '{test_name}-{test_begin_time}'.format(
- test_name=test_name, test_begin_time=test_begin_time),
- 'logcat,{mock_serial},fakemodel,{test_name}-{test_begin_time}.txt'.
- format(mock_serial=mock_serial,
- test_name=test_name,
- test_begin_time=test_begin_time))
+ test_output_dir,
+ '{test_name}-{test_begin_time}'.format(
+ test_name=test_name, test_begin_time=test_begin_time
+ ),
+ 'logcat,{mock_serial},fakemodel,{test_name}-{test_begin_time}.txt'
+ .format(
+ mock_serial=mock_serial,
+ test_name=test_name,
+ test_begin_time=test_begin_time,
+ ),
+ )
self.assertEqual(actual_path, expected_path)
self.assertTrue(os.path.exists(expected_path))
return expected_path
@@ -306,19 +380,29 @@ class LogcatTest(unittest.TestCase):
)
self.assertEqual(os.stat(expected_path3).st_size, 0)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
@mock.patch('mobly.logger.get_log_file_timestamp')
- def test_take_logcat_with_extra_params(self, get_timestamp_mock,
- open_logcat_mock, stop_proc_mock,
- start_proc_mock, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ def test_take_logcat_with_extra_params(
+ self,
+ get_timestamp_mock,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
"""Verifies the steps of collecting adb logcat on an AndroidDevice
object, including various function calls and the expected behaviors of
the calls.
@@ -332,21 +416,27 @@ class LogcatTest(unittest.TestCase):
logcat_service.start()
# Verify start did the correct operations.
self.assertTrue(logcat_service._adb_logcat_process)
- expected_log_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial,
- 'logcat,%s,fakemodel,123.txt' % ad.serial)
+ expected_log_path = os.path.join(
+ logging.log_path,
+ 'AndroidDevice%s' % ad.serial,
+ 'logcat,%s,fakemodel,123.txt' % ad.serial,
+ )
create_dir_mock.assert_called_with(os.path.dirname(expected_log_path))
adb_cmd = ' "adb" -s %s logcat -v threadtime -T 1 -b radio >> %s'
- start_proc_mock.assert_called_with(adb_cmd %
- (ad.serial, '"%s" ' % expected_log_path),
- shell=True)
+ start_proc_mock.assert_called_with(
+ adb_cmd % (ad.serial, '"%s" ' % expected_log_path), shell=True
+ )
self.assertEqual(logcat_service.adb_logcat_file_path, expected_log_path)
logcat_service.stop()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_instantiation(self, MockFastboot, MockAdbProxy):
"""Verifies the AndroidDevice object's basic attributes are correctly
set after instantiation.
@@ -357,10 +447,14 @@ class LogcatTest(unittest.TestCase):
self.assertIsNone(logcat_service._adb_logcat_process)
self.assertIsNone(logcat_service.adb_logcat_file_path)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock.MagicMock())
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock.MagicMock(),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test__enable_logpersist_with_logpersist(self, MockFastboot, MockAdbProxy):
mock_serial = '1'
mock_adb_proxy = MockAdbProxy.return_value
@@ -381,12 +475,17 @@ class LogcatTest(unittest.TestCase):
mock.call('logpersist.start'),
])
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock.MagicMock())
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
- def test__enable_logpersist_with_user_build_device(self, MockFastboot,
- MockAdbProxy):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock.MagicMock(),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ def test__enable_logpersist_with_user_build_device(
+ self, MockFastboot, MockAdbProxy
+ ):
mock_serial = '1'
mock_adb_proxy = MockAdbProxy.return_value
mock_adb_proxy.getprops.return_value = {
@@ -403,13 +502,17 @@ class LogcatTest(unittest.TestCase):
logcat_service._enable_logpersist()
mock_adb_proxy.shell.assert_not_called()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock.MagicMock())
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock.MagicMock(),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test__enable_logpersist_with_missing_all_logpersist(
- self, MockFastboot, MockAdbProxy):
-
+ self, MockFastboot, MockAdbProxy
+ ):
def adb_shell_helper(command):
if command == 'logpersist.start':
raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR
@@ -435,13 +538,17 @@ class LogcatTest(unittest.TestCase):
logcat_service._enable_logpersist()
mock_adb_proxy.shell.assert_not_called()
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock.MagicMock())
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock.MagicMock(),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test__enable_logpersist_with_missing_logpersist_stop(
- self, MockFastboot, MockAdbProxy):
-
+ self, MockFastboot, MockAdbProxy
+ ):
def adb_shell_helper(command):
if command == 'logpersist.stop --clear':
raise MOCK_LOGPERSIST_STOP_MISSING_ADB_ERROR
@@ -467,13 +574,17 @@ class LogcatTest(unittest.TestCase):
mock.call('logpersist.stop --clear'),
])
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock.MagicMock())
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock.MagicMock(),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test__enable_logpersist_with_missing_logpersist_start(
- self, MockFastboot, MockAdbProxy):
-
+ self, MockFastboot, MockAdbProxy
+ ):
def adb_shell_helper(command):
if command == 'logpersist.start':
raise MOCK_LOGPERSIST_START_MISSING_ADB_ERROR
@@ -498,14 +609,17 @@ class LogcatTest(unittest.TestCase):
mock_adb_proxy.shell.assert_not_called()
@mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy')
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_clear_adb_log(self, MockFastboot, MockAdbProxy):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
ad.adb.logcat = mock.MagicMock()
ad.adb.logcat.side_effect = adb.AdbError(
- cmd='cmd', stdout=b'', stderr=b'failed to clear "main" log', ret_code=1)
+ cmd='cmd', stdout=b'', stderr=b'failed to clear "main" log', ret_code=1
+ )
logcat_service = logcat.Logcat(ad)
logcat_service.clear_adb_log()
diff --git a/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py b/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py
index 16a30aa..b6431d5 100755
--- a/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py
+++ b/tests/mobly/controllers/android_device_lib/services/snippet_management_service_test.py
@@ -19,7 +19,9 @@ from mobly.controllers.android_device_lib import snippet_client_v2
from mobly.controllers.android_device_lib.services import snippet_management_service
MOCK_PACKAGE = 'com.mock.package'
-SNIPPET_CLIENT_V2_CLASS_PATH = 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+SNIPPET_CLIENT_V2_CLASS_PATH = (
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+)
class SnippetManagementServiceTest(unittest.TestCase):
@@ -27,7 +29,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_empty_manager_start_stop(self):
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.start()
# When no client is registered, manager is never alive.
self.assertFalse(manager.is_alive)
@@ -38,21 +41,24 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_get_snippet_client(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
self.assertEqual(manager.get_snippet_client('foo'), mock_client)
@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_get_snippet_client_fail(self, _):
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
self.assertIsNone(manager.get_snippet_client('foo'))
@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_stop_with_live_client(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.initialize.assert_called_once_with()
manager.stop()
@@ -67,28 +73,35 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_add_snippet_client_without_config(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_class.assert_called_once_with(
- package=mock.ANY, ad=mock.ANY, config=None)
+ package=mock.ANY, ad=mock.ANY, config=None
+ )
@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_add_snippet_client_with_config(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
snippet_config = snippet_client_v2.Config()
manager.add_snippet_client('foo', MOCK_PACKAGE, snippet_config)
mock_class.assert_called_once_with(
- package=mock.ANY, ad=mock.ANY, config=snippet_config)
+ package=mock.ANY, ad=mock.ANY, config=snippet_config
+ )
@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_add_snippet_client_dup_name(self, _):
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
- msg = ('.* Name "foo" is already registered with package ".*", it '
- 'cannot be used again.')
+ msg = (
+ '.* Name "foo" is already registered with package ".*", it '
+ 'cannot be used again.'
+ )
with self.assertRaisesRegex(snippet_management_service.Error, msg):
manager.add_snippet_client('foo', MOCK_PACKAGE + 'ha')
@@ -97,10 +110,13 @@ class SnippetManagementServiceTest(unittest.TestCase):
mock_client = mock_class.return_value
mock_client.package = MOCK_PACKAGE
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
- msg = ('Snippet package "com.mock.package" has already been loaded '
- 'under name "foo".')
+ msg = (
+ 'Snippet package "com.mock.package" has already been loaded '
+ 'under name "foo".'
+ )
with self.assertRaisesRegex(snippet_management_service.Error, msg):
manager.add_snippet_client('bar', MOCK_PACKAGE)
@@ -109,7 +125,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
mock_client = mock.MagicMock()
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.remove_snippet_client('foo')
msg = 'No snippet client is registered with name "foo".'
@@ -121,17 +138,20 @@ class SnippetManagementServiceTest(unittest.TestCase):
mock_client = mock.MagicMock()
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
with self.assertRaisesRegex(
snippet_management_service.Error,
- 'No snippet client is registered with name "foo".'):
+ 'No snippet client is registered with name "foo".',
+ ):
manager.remove_snippet_client('foo')
@mock.patch(SNIPPET_CLIENT_V2_CLASS_PATH)
def test_start_with_live_service(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.initialize.reset_mock()
mock_client.is_alive = True
@@ -146,7 +166,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_pause(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.pause()
mock_client.close_connection.assert_called_once_with()
@@ -155,7 +176,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_resume_positive_case(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.is_alive = False
manager.resume()
@@ -165,7 +187,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
def test_resume_negative_case(self, mock_class):
mock_client = mock_class.return_value
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
mock_client.is_alive = True
manager.resume()
@@ -176,7 +199,8 @@ class SnippetManagementServiceTest(unittest.TestCase):
mock_client = mock.MagicMock()
mock_class.return_value = mock_client
manager = snippet_management_service.SnippetManagementService(
- mock.MagicMock())
+ mock.MagicMock()
+ )
manager.add_snippet_client('foo', MOCK_PACKAGE)
manager.foo.ha('param')
mock_client.ha.assert_called_once_with('param')
diff --git a/tests/mobly/controllers/android_device_lib/sl4a_client_test.py b/tests/mobly/controllers/android_device_lib/sl4a_client_test.py
index 08560d4..bf11b07 100755
--- a/tests/mobly/controllers/android_device_lib/sl4a_client_test.py
+++ b/tests/mobly/controllers/android_device_lib/sl4a_client_test.py
@@ -22,43 +22,60 @@ from tests.lib import mock_android_device
class Sl4aClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
- """Unit tests for mobly.controllers.android_device_lib.sl4a_client.
- """
+ """Unit tests for mobly.controllers.android_device_lib.sl4a_client."""
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_start_app_and_connect(self, mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_start_app_and_connect(
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[b'\n'])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess, resp_lines=[b'\n']
+ )
client = self._make_client()
client.start_app_and_connect()
self.assertEqual(8080, client.device_port)
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_app_not_installed(self, mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_app_not_installed(
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[b'\n'])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess, resp_lines=[b'\n']
+ )
client = self._make_client(adb_proxy=mock_android_device.MockAdbProxy())
- with self.assertRaisesRegex(jsonrpc_client_base.AppStartError,
- '.* SL4A is not installed on .*'):
+ with self.assertRaisesRegex(
+ jsonrpc_client_base.AppStartError, '.* SL4A is not installed on .*'
+ ):
client.start_app_and_connect()
def _make_client(self, adb_proxy=None):
adb_proxy = adb_proxy or mock_android_device.MockAdbProxy(
- installed_packages=['com.googlecode.android_scripting'])
+ installed_packages=['com.googlecode.android_scripting']
+ )
ad = mock.Mock()
ad.adb = adb_proxy
ad.build_info = {
@@ -67,11 +84,12 @@ class Sl4aClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
}
return sl4a_client.Sl4aClient(ad=ad)
- def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess,
- resp_lines):
+ def _setup_mock_instrumentation_cmd(
+ self, mock_start_standing_subprocess, resp_lines
+ ):
mock_proc = mock_start_standing_subprocess()
mock_proc.stdout.readline.side_effect = resp_lines
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/controllers/android_device_lib/snippet_client_test.py b/tests/mobly/controllers/android_device_lib/snippet_client_test.py
index 53da1ae..5f31c47 100755
--- a/tests/mobly/controllers/android_device_lib/snippet_client_test.py
+++ b/tests/mobly/controllers/android_device_lib/snippet_client_test.py
@@ -23,13 +23,14 @@ from tests.lib import mock_android_device
MOCK_PACKAGE_NAME = 'some.package.name'
MOCK_MISSING_PACKAGE_NAME = 'not.installed'
-JSONRPC_BASE_CLASS = 'mobly.controllers.android_device_lib.jsonrpc_client_base.JsonRpcClientBase'
+JSONRPC_BASE_CLASS = (
+ 'mobly.controllers.android_device_lib.jsonrpc_client_base.JsonRpcClientBase'
+)
MOCK_USER_ID = 0
class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
- """Unit tests for mobly.controllers.android_device_lib.snippet_client.
- """
+ """Unit tests for mobly.controllers.android_device_lib.snippet_client."""
def test_check_app_installed_normal(self):
sc = self._make_client()
@@ -38,29 +39,40 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
def test_check_app_installed_fail_app_not_installed(self):
sc = self._make_client(mock_android_device.MockAdbProxy())
expected_msg = '.* %s is not installed.' % MOCK_PACKAGE_NAME
- with self.assertRaisesRegex(snippet_client.AppStartPreCheckError,
- expected_msg):
+ with self.assertRaisesRegex(
+ snippet_client.AppStartPreCheckError, expected_msg
+ ):
sc._check_app_installed()
def test_check_app_installed_fail_not_instrumented(self):
sc = self._make_client(
- mock_android_device.MockAdbProxy(
- installed_packages=[MOCK_PACKAGE_NAME]))
- expected_msg = ('.* %s is installed, but it is not instrumented.' %
- MOCK_PACKAGE_NAME)
- with self.assertRaisesRegex(snippet_client.AppStartPreCheckError,
- expected_msg):
+ mock_android_device.MockAdbProxy(installed_packages=[MOCK_PACKAGE_NAME])
+ )
+ expected_msg = (
+ '.* %s is installed, but it is not instrumented.' % MOCK_PACKAGE_NAME
+ )
+ with self.assertRaisesRegex(
+ snippet_client.AppStartPreCheckError, expected_msg
+ ):
sc._check_app_installed()
def test_check_app_installed_fail_target_not_installed(self):
sc = self._make_client(
- mock_android_device.MockAdbProxy(instrumented_packages=[(
- MOCK_PACKAGE_NAME, snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
- MOCK_MISSING_PACKAGE_NAME)]))
- expected_msg = ('.* Instrumentation target %s is not installed.' %
- MOCK_MISSING_PACKAGE_NAME)
- with self.assertRaisesRegex(snippet_client.AppStartPreCheckError,
- expected_msg):
+ mock_android_device.MockAdbProxy(
+ instrumented_packages=[(
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ MOCK_MISSING_PACKAGE_NAME,
+ )]
+ )
+ )
+ expected_msg = (
+ '.* Instrumentation target %s is not installed.'
+ % MOCK_MISSING_PACKAGE_NAME
+ )
+ with self.assertRaisesRegex(
+ snippet_client.AppStartPreCheckError, expected_msg
+ ):
sc._check_app_installed()
@mock.patch('socket.create_connection')
@@ -91,10 +103,13 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
callback.getAll('eventName')
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_snippet_restore_event_client(self, mock_get_port,
- mock_create_connection):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_snippet_restore_event_client(
+ self, mock_get_port, mock_create_connection
+ ):
mock_get_port.return_value = 789
fake_file = self.setup_mock_socket_file(mock_create_connection)
client = self._make_client()
@@ -130,24 +145,37 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
mock_create_connection.side_effect = IOError('socket timed out')
with self.assertRaisesRegex(
jsonrpc_client_base.AppRestoreConnectionError,
- ('Failed to restore app connection for %s at host port %s, '
- 'device port %s') % (MOCK_PACKAGE_NAME, 789, 456)):
+ (
+ 'Failed to restore app connection for %s at host port %s, '
+ 'device port %s'
+ )
+ % (MOCK_PACKAGE_NAME, 789, 456),
+ ):
client.restore_app_connection()
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_snippet_start_app_and_connect(self, mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_snippet_start_app_and_connect(
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[
- b'SNIPPET START, PROTOCOL 1 0\n',
- b'SNIPPET SERVING, PORT 123\n',
- ])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess,
+ resp_lines=[
+ b'SNIPPET START, PROTOCOL 1 0\n',
+ b'SNIPPET SERVING, PORT 123\n',
+ ],
+ )
client = self._make_client()
client.start_app_and_connect()
self.assertEqual(123, client.device_port)
@@ -155,8 +183,9 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_snippet_stop_app(self, mock_stop_standing_subprocess,
- mock_create_connection):
+ def test_snippet_stop_app(
+ self, mock_stop_standing_subprocess, mock_create_connection
+ ):
adb_proxy = mock.MagicMock()
adb_proxy.shell.return_value = b'OK (0 tests)'
client = self._make_client(adb_proxy)
@@ -179,14 +208,15 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_snippet_stop_app_stops_event_client(self,
- mock_stop_standing_subprocess,
- mock_create_connection):
+ def test_snippet_stop_app_stops_event_client(
+ self, mock_stop_standing_subprocess, mock_create_connection
+ ):
adb_proxy = mock.MagicMock()
adb_proxy.shell.return_value = b'OK (0 tests)'
client = self._make_client(adb_proxy)
event_client = snippet_client.SnippetClient(
- package=MOCK_PACKAGE_NAME, ad=client._ad)
+ package=MOCK_PACKAGE_NAME, ad=client._ad
+ )
client._event_client = event_client
event_client_conn = mock.Mock()
event_client._conn = event_client_conn
@@ -200,12 +230,14 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
def test_snippet_stop_app_stops_event_client_without_connection(
- self, mock_stop_standing_subprocess, mock_create_connection):
+ self, mock_stop_standing_subprocess, mock_create_connection
+ ):
adb_proxy = mock.MagicMock()
adb_proxy.shell.return_value = b'OK (0 tests)'
client = self._make_client(adb_proxy)
event_client = snippet_client.SnippetClient(
- package=MOCK_PACKAGE_NAME, ad=client._ad)
+ package=MOCK_PACKAGE_NAME, ad=client._ad
+ )
client._event_client = event_client
event_client._conn = None
@@ -217,7 +249,8 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
def test_snippet_stop_app_without_event_client(
- self, mock_stop_standing_subprocess, mock_create_connection):
+ self, mock_stop_standing_subprocess, mock_create_connection
+ ):
adb_proxy = mock.MagicMock()
adb_proxy.shell.return_value = b'OK (0 tests)'
client = self._make_client(adb_proxy)
@@ -231,8 +264,8 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(snippet_client.SnippetClient, 'connect')
def test_event_client_does_not_stop_port_forwarding(
- self, mock_stop_standing_subprocess, mock_create_connection,
- mock_connect):
+ self, mock_stop_standing_subprocess, mock_create_connection, mock_connect
+ ):
adb_proxy = mock.MagicMock()
adb_proxy.shell.return_value = b'OK (0 tests)'
client = self._make_client(adb_proxy)
@@ -253,55 +286,78 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
event_client._adb.forward.assert_not_called()
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client.SnippetClient.'
- 'disable_hidden_api_blacklist')
+ 'disable_hidden_api_blacklist'
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client.SnippetClient.'
- 'stop_app')
- def test_start_app_and_connect_precheck_fail(self, mock_stop, mock_precheck,
- mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ 'stop_app'
+ )
+ def test_start_app_and_connect_precheck_fail(
+ self,
+ mock_stop,
+ mock_precheck,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[
- b'SNIPPET START, PROTOCOL 1 0\n',
- b'SNIPPET SERVING, PORT 123\n',
- ])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess,
+ resp_lines=[
+ b'SNIPPET START, PROTOCOL 1 0\n',
+ b'SNIPPET SERVING, PORT 123\n',
+ ],
+ )
client = self._make_client()
mock_precheck.side_effect = snippet_client.AppStartPreCheckError(
- client.ad, 'ha')
+ client.ad, 'ha'
+ )
with self.assertRaisesRegex(snippet_client.AppStartPreCheckError, 'ha'):
client.start_app_and_connect()
mock_stop.assert_not_called()
self.assertFalse(client.is_alive)
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect'
)
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app'
)
- def test_start_app_and_connect_generic_error(self, mock_stop, mock_start,
- mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ def test_start_app_and_connect_generic_error(
+ self,
+ mock_stop,
+ mock_start,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[
- b'SNIPPET START, PROTOCOL 1 0\n',
- b'SNIPPET SERVING, PORT 123\n',
- ])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess,
+ resp_lines=[
+ b'SNIPPET START, PROTOCOL 1 0\n',
+ b'SNIPPET SERVING, PORT 123\n',
+ ],
+ )
client = self._make_client()
mock_start.side_effect = Exception('ha')
with self.assertRaisesRegex(Exception, 'ha'):
@@ -310,10 +366,14 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
self.assertFalse(client.is_alive)
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client.SnippetClient._start_app_and_connect'
)
@@ -321,14 +381,21 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
'mobly.controllers.android_device_lib.snippet_client.SnippetClient.stop_app'
)
def test_start_app_and_connect_fail_stop_also_fail(
- self, mock_stop, mock_start, mock_get_port,
- mock_start_standing_subprocess, mock_create_connection):
+ self,
+ mock_stop,
+ mock_start,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
- self._setup_mock_instrumentation_cmd(mock_start_standing_subprocess,
- resp_lines=[
- b'SNIPPET START, PROTOCOL 1 0\n',
- b'SNIPPET SERVING, PORT 123\n',
- ])
+ self._setup_mock_instrumentation_cmd(
+ mock_start_standing_subprocess,
+ resp_lines=[
+ b'SNIPPET START, PROTOCOL 1 0\n',
+ b'SNIPPET SERVING, PORT 123\n',
+ ],
+ )
client = self._make_client()
mock_start.side_effect = Exception('Some error')
mock_stop.side_effect = Exception('Another error')
@@ -337,19 +404,34 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
mock_stop.assert_called_once_with()
self.assertFalse(client.is_alive)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._do_start_app')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._check_app_installed')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._read_protocol_line')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient.connect')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_snippet_start_on_sdk_21(self, mock_get_port, mock_connect,
- mock_read_protocol_line,
- mock_check_app_installed, mock_do_start_app):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._do_start_app'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._check_app_installed'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._read_protocol_line'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient.connect'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_snippet_start_on_sdk_21(
+ self,
+ mock_get_port,
+ mock_connect,
+ mock_read_protocol_line,
+ mock_check_app_installed,
+ mock_do_start_app,
+ ):
"""Check that `--user` is not added to start command on SDK < 24."""
def _mocked_shell(arg):
@@ -374,24 +456,40 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
client._adb.shell = mock.Mock(return_value=b'setsid')
client.start_app_and_connect()
cmd_setsid = '%s am instrument -w -e action start %s/%s' % (
- snippet_client._SETSID_COMMAND, MOCK_PACKAGE_NAME,
- snippet_client._INSTRUMENTATION_RUNNER_PACKAGE)
+ snippet_client._SETSID_COMMAND,
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ )
mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)])
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._do_start_app')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._check_app_installed')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient._read_protocol_line')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'SnippetClient.connect')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._do_start_app'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._check_app_installed'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient._read_protocol_line'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'SnippetClient.connect'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
def test_snippet_start_app_and_connect_persistent_session(
- self, mock_get_port, mock_connect, mock_read_protocol_line,
- mock_check_app_installed, mock_do_start_app):
-
+ self,
+ mock_get_port,
+ mock_connect,
+ mock_read_protocol_line,
+ mock_check_app_installed,
+ mock_do_start_app,
+ ):
def _mocked_shell(arg):
if 'setsid' in arg:
raise adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code')
@@ -415,8 +513,11 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
client._adb.current_user_id = MOCK_USER_ID
client.start_app_and_connect()
cmd_setsid = '%s am instrument --user %s -w -e action start %s/%s' % (
- snippet_client._SETSID_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME,
- snippet_client._INSTRUMENTATION_RUNNER_PACKAGE)
+ snippet_client._SETSID_COMMAND,
+ MOCK_USER_ID,
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ )
mock_do_start_app.assert_has_calls([mock.call(cmd_setsid)])
# Test 'setsid' does not exist, but 'nohup' exsits
@@ -424,67 +525,97 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
client._adb.shell = _mocked_shell
client.start_app_and_connect()
cmd_nohup = '%s am instrument --user %s -w -e action start %s/%s' % (
- snippet_client._NOHUP_COMMAND, MOCK_USER_ID, MOCK_PACKAGE_NAME,
- snippet_client._INSTRUMENTATION_RUNNER_PACKAGE)
+ snippet_client._NOHUP_COMMAND,
+ MOCK_USER_ID,
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ )
mock_do_start_app.assert_has_calls(
- [mock.call(cmd_setsid), mock.call(cmd_nohup)])
+ [mock.call(cmd_setsid), mock.call(cmd_nohup)]
+ )
# Test both 'setsid' and 'nohup' do not exist
client._adb.shell = mock.Mock(
- side_effect=adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code'))
+ side_effect=adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code')
+ )
client = self._make_client()
client.start_app_and_connect()
cmd_not_persist = ' am instrument --user %s -w -e action start %s/%s' % (
- MOCK_USER_ID, MOCK_PACKAGE_NAME,
- snippet_client._INSTRUMENTATION_RUNNER_PACKAGE)
+ MOCK_USER_ID,
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ )
mock_do_start_app.assert_has_calls([
mock.call(cmd_setsid),
mock.call(cmd_nohup),
- mock.call(cmd_not_persist)
+ mock.call(cmd_not_persist),
])
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
- def test_snippet_start_app_crash(self, mock_get_port,
- mock_start_standing_subprocess,
- mock_create_connection):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
+ def test_snippet_start_app_crash(
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
mock_get_port.return_value = 456
self.setup_mock_socket_file(mock_create_connection)
self._setup_mock_instrumentation_cmd(
mock_start_standing_subprocess,
- resp_lines=[b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n'])
+ resp_lines=[b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n'],
+ )
client = self._make_client()
with self.assertRaisesRegex(
snippet_client.ProtocolVersionError,
- 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.'):
+ 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.',
+ ):
client.start_app_and_connect()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
def test_snippet_start_app_and_connect_unknown_protocol(
- self, mock_get_port, mock_start_standing_subprocess):
+ self, mock_get_port, mock_start_standing_subprocess
+ ):
mock_get_port.return_value = 789
self._setup_mock_instrumentation_cmd(
mock_start_standing_subprocess,
- resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n'])
+ resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n'],
+ )
client = self._make_client()
- with self.assertRaisesRegex(snippet_client.ProtocolVersionError,
- 'SNIPPET START, PROTOCOL 99 0'):
+ with self.assertRaisesRegex(
+ snippet_client.ProtocolVersionError, 'SNIPPET START, PROTOCOL 99 0'
+ ):
client.start_app_and_connect()
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
def test_snippet_start_app_and_connect_header_junk(
- self, mock_get_port, mock_start_standing_subprocess,
- mock_create_connection):
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
self.setup_mock_socket_file(mock_create_connection)
self._setup_mock_instrumentation_cmd(
mock_start_standing_subprocess,
@@ -494,19 +625,27 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
b'SNIPPET START, PROTOCOL 1 0\n',
b'Maybe in the middle too\n',
b'SNIPPET SERVING, PORT 123\n',
- ])
+ ],
+ )
client = self._make_client()
client.start_app_and_connect()
self.assertEqual(123, client.device_port)
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client.'
- 'utils.get_available_host_port')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client.'
+ 'utils.get_available_host_port'
+ )
def test_snippet_start_app_and_connect_no_valid_line(
- self, mock_get_port, mock_start_standing_subprocess,
- mock_create_connection):
+ self,
+ mock_get_port,
+ mock_start_standing_subprocess,
+ mock_create_connection,
+ ):
mock_get_port.return_value = 456
self.setup_mock_socket_file(mock_create_connection)
self._setup_mock_instrumentation_cmd(
@@ -515,10 +654,13 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
b'This is some header junk\n',
b'Some phones print arbitrary output\n',
b'', # readline uses '' to mark EOF
- ])
+ ],
+ )
client = self._make_client()
- with self.assertRaisesRegex(jsonrpc_client_base.AppStartError,
- 'Unexpected EOF waiting for app to start'):
+ with self.assertRaisesRegex(
+ jsonrpc_client_base.AppStartError,
+ 'Unexpected EOF waiting for app to start',
+ ):
client.start_app_and_connect()
@mock.patch('builtins.print')
@@ -545,9 +687,12 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
def _make_client(self, adb_proxy=None):
adb_proxy = adb_proxy or mock_android_device.MockAdbProxy(
- instrumented_packages=[(MOCK_PACKAGE_NAME,
- snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
- MOCK_PACKAGE_NAME)])
+ instrumented_packages=[(
+ MOCK_PACKAGE_NAME,
+ snippet_client._INSTRUMENTATION_RUNNER_PACKAGE,
+ MOCK_PACKAGE_NAME,
+ )]
+ )
ad = mock.Mock()
ad.adb = adb_proxy
ad.adb.current_user_id = MOCK_USER_ID
@@ -557,11 +702,12 @@ class SnippetClientTest(jsonrpc_client_test_base.JsonRpcClientTestBase):
}
return snippet_client.SnippetClient(package=MOCK_PACKAGE_NAME, ad=ad)
- def _setup_mock_instrumentation_cmd(self, mock_start_standing_subprocess,
- resp_lines):
+ def _setup_mock_instrumentation_cmd(
+ self, mock_start_standing_subprocess, resp_lines
+ ):
mock_proc = mock_start_standing_subprocess()
mock_proc.stdout.readline.side_effect = resp_lines
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/controllers/android_device_lib/snippet_client_v2_test.py b/tests/mobly/controllers/android_device_lib/snippet_client_v2_test.py
index 86d889b..07e3d0d 100644
--- a/tests/mobly/controllers/android_device_lib/snippet_client_v2_test.py
+++ b/tests/mobly/controllers/android_device_lib/snippet_client_v2_test.py
@@ -24,9 +24,12 @@ from mobly.snippet import errors
from tests.lib import mock_android_device
MOCK_PACKAGE_NAME = 'some.package.name'
-MOCK_SERVER_PATH = f'{MOCK_PACKAGE_NAME}/{snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE}'
+MOCK_SERVER_PATH = (
+ f'{MOCK_PACKAGE_NAME}/{snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE}'
+)
MOCK_USER_ID = 0
MOCK_DEVICE_PORT = 1234
+MOCK_HOST_PORT = 2345
class _MockAdbProxy(mock_android_device.MockAdbProxy):
@@ -41,6 +44,8 @@ class _MockAdbProxy(mock_android_device.MockAdbProxy):
Attributes:
+ default_host_port: int, return this port if `self.forward` got 'tcp:0' as
+ host port.
mock_shell_func: mock.Mock, used for recording the calls to the shell
method.
mock_forward_func: mock.Mock, used for recording the calls to the forward
@@ -50,6 +55,7 @@ class _MockAdbProxy(mock_android_device.MockAdbProxy):
def __init__(self, *args, **kwargs):
"""Initializes the instance of _MockAdbProxy."""
super().__init__(*args, **kwargs)
+ self.default_host_port = MOCK_HOST_PORT
self.mock_shell_func = mock.Mock()
self.mock_forward_func = mock.Mock()
@@ -69,6 +75,18 @@ class _MockAdbProxy(mock_android_device.MockAdbProxy):
"""Mock `forward` of mobly.controllers.android_device_lib.adb.AdbProxy."""
self.mock_forward_func(*args, **kwargs)
+ adb_args = None
+ if 'args' in kwargs:
+ adb_args = kwargs['args']
+ else:
+ adb_args = args[0]
+
+ host_port = str(self.default_host_port)
+ if len(adb_args) >= 1 and adb_args[0] != 'tcp:0':
+ # Extract port from strings like 'tcp:12345'
+ host_port = adb_args[0][4:]
+ return f'{host_port}\n'.encode('utf-8')
+
def _setup_mock_socket_file(mock_socket_create_conn, resp):
"""Sets up a mock socket file from the mock connection.
@@ -92,24 +110,25 @@ def _setup_mock_socket_file(mock_socket_create_conn, resp):
class SnippetClientV2Test(unittest.TestCase):
"""Unit tests for SnippetClientV2."""
- def _make_client(
- self, adb_proxy=None, mock_properties=None, config=None
- ):
- adb_proxy = adb_proxy or _MockAdbProxy(instrumented_packages=[
- (MOCK_PACKAGE_NAME, snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE,
- MOCK_PACKAGE_NAME)
- ],
- mock_properties=mock_properties)
+ def _make_client(self, adb_proxy=None, mock_properties=None, config=None):
+ adb_proxy = adb_proxy or _MockAdbProxy(
+ instrumented_packages=[(
+ MOCK_PACKAGE_NAME,
+ snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE,
+ MOCK_PACKAGE_NAME,
+ )],
+ mock_properties=mock_properties,
+ )
self.adb = adb_proxy
device = mock.Mock()
device.adb = adb_proxy
device.adb.current_user_id = MOCK_USER_ID
device.build_info = {
- 'build_version_codename':
- adb_proxy.getprop('ro.build.version.codename'),
- 'build_version_sdk':
- adb_proxy.getprop('ro.build.version.sdk'),
+ 'build_version_codename': adb_proxy.getprop(
+ 'ro.build.version.codename'
+ ),
+ 'build_version_sdk': adb_proxy.getprop('ro.build.version.sdk'),
}
self.device = device
@@ -122,63 +141,75 @@ class SnippetClientV2Test(unittest.TestCase):
mock_properties.update(extra_properties)
self._make_client(mock_properties=mock_properties)
- def _mock_server_process_starting_response(self,
- mock_start_subprocess,
- resp_lines=None):
+ def _mock_server_process_starting_response(
+ self, mock_start_subprocess, resp_lines=None
+ ):
resp_lines = resp_lines or [
- b'SNIPPET START, PROTOCOL 1 0', b'SNIPPET SERVING, PORT 1234'
+ b'SNIPPET START, PROTOCOL 1 0',
+ b'SNIPPET SERVING, PORT 1234',
]
mock_proc = mock_start_subprocess.return_value
mock_proc.stdout.readline.side_effect = resp_lines
- def _make_client_and_mock_socket_conn(self,
- mock_socket_create_conn,
- socket_resp=None,
- device_port=MOCK_DEVICE_PORT,
- adb_proxy=None,
- mock_properties=None,
- set_counter=True):
+ def _make_client_and_mock_socket_conn(
+ self,
+ mock_socket_create_conn,
+ socket_resp=None,
+ device_port=MOCK_DEVICE_PORT,
+ adb_proxy=None,
+ mock_properties=None,
+ set_counter=True,
+ ):
"""Makes the snippet client and mocks the socket connection."""
self._make_client(adb_proxy, mock_properties)
if socket_resp is None:
socket_resp = [b'{"status": true, "uid": 1}']
- self.mock_socket_file = _setup_mock_socket_file(mock_socket_create_conn,
- socket_resp)
+ self.mock_socket_file = _setup_mock_socket_file(
+ mock_socket_create_conn, socket_resp
+ )
self.client.device_port = device_port
self.socket_conn = mock_socket_create_conn.return_value
if set_counter:
self.client._counter = self.client._id_counter()
- def _assert_client_resources_released(self, mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_get_port):
+ def _assert_client_resources_released(
+ self, mock_start_subprocess, mock_stop_standing_subprocess, host_port
+ ):
"""Asserts the resources had been released before the client stopped."""
self.assertIs(self.client._proc, None)
self.adb.mock_shell_func.assert_any_call(
f'am instrument --user {MOCK_USER_ID} -w -e action stop '
- f'{MOCK_SERVER_PATH}')
+ f'{MOCK_SERVER_PATH}'
+ )
mock_stop_standing_subprocess.assert_called_once_with(
- mock_start_subprocess.return_value)
+ mock_start_subprocess.return_value
+ )
self.assertFalse(self.client.is_alive)
self.assertIs(self.client._conn, None)
self.socket_conn.close.assert_called()
self.assertIs(self.client.host_port, None)
- self.adb.mock_forward_func.assert_any_call(
- ['--remove', f'tcp:{mock_get_port.return_value}'])
+ self.adb.mock_forward_func.assert_any_call(['--remove', f'tcp:{host_port}'])
self.assertIsNone(self.client._event_client)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- def test_the_whole_lifecycle_with_a_sync_rpc(self, mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_socket_create_conn,
- mock_get_port):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_the_whole_lifecycle_with_a_sync_rpc(
+ self,
+ mock_start_subprocess,
+ mock_stop_standing_subprocess,
+ mock_socket_create_conn,
+ _,
+ ):
"""Tests the whole lifecycle of the client with sending a sync RPC."""
socket_resp = [
b'{"status": true, "uid": 1}',
@@ -186,40 +217,51 @@ class SnippetClientV2Test(unittest.TestCase):
]
expected_socket_writes = [
mock.call(b'{"cmd": "initiate", "uid": -1}\n'),
- mock.call(b'{"id": 0, "method": "some_sync_rpc", '
- b'"params": [1, 2, "hello"]}\n'),
+ mock.call(
+ b'{"id": 0, "method": "some_sync_rpc", "params": [1, 2, "hello"]}\n'
+ ),
]
- self._make_client_and_mock_socket_conn(mock_socket_create_conn,
- socket_resp,
- set_counter=False)
+ self._make_client_and_mock_socket_conn(
+ mock_socket_create_conn, socket_resp, set_counter=False
+ )
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.initialize()
rpc_result = self.client.some_sync_rpc(1, 2, 'hello')
self.client.stop()
- self._assert_client_resources_released(mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_get_port)
+ self._assert_client_resources_released(
+ mock_start_subprocess, mock_stop_standing_subprocess, MOCK_HOST_PORT
+ )
- self.assertListEqual(self.mock_socket_file.write.call_args_list,
- expected_socket_writes)
+ self.assertListEqual(
+ self.mock_socket_file.write.call_args_list, expected_socket_writes
+ )
self.assertEqual(rpc_result, 123)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.callback_handler_v2.'
- 'CallbackHandlerV2')
- def test_the_whole_lifecycle_with_an_async_rpc(self, mock_callback_class,
- mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_socket_create_conn,
- mock_get_port):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.callback_handler_v2.'
+ 'CallbackHandlerV2'
+ )
+ def test_the_whole_lifecycle_with_an_async_rpc(
+ self,
+ mock_callback_class,
+ mock_start_subprocess,
+ mock_stop_standing_subprocess,
+ mock_socket_create_conn,
+ _,
+ ):
"""Tests the whole lifecycle of the client with sending an async RPC."""
mock_socket_resp = [
b'{"status": true, "uid": 1}',
@@ -228,13 +270,15 @@ class SnippetClientV2Test(unittest.TestCase):
]
expected_socket_writes = [
mock.call(b'{"cmd": "initiate", "uid": -1}\n'),
- mock.call(b'{"id": 0, "method": "some_async_rpc", '
- b'"params": [1, 2, "async"]}\n'),
+ mock.call(
+ b'{"id": 0, "method": "some_async_rpc", '
+ b'"params": [1, 2, "async"]}\n'
+ ),
mock.call(b'{"cmd": "continue", "uid": 1}\n'),
]
- self._make_client_and_mock_socket_conn(mock_socket_create_conn,
- mock_socket_resp,
- set_counter=False)
+ self._make_client_and_mock_socket_conn(
+ mock_socket_create_conn, mock_socket_resp, set_counter=False
+ )
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.initialize()
@@ -242,12 +286,13 @@ class SnippetClientV2Test(unittest.TestCase):
event_client = self.client._event_client
self.client.stop()
- self._assert_client_resources_released(mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_get_port)
+ self._assert_client_resources_released(
+ mock_start_subprocess, mock_stop_standing_subprocess, MOCK_HOST_PORT
+ )
- self.assertListEqual(self.mock_socket_file.write.call_args_list,
- expected_socket_writes)
+ self.assertListEqual(
+ self.mock_socket_file.write.call_args_list, expected_socket_writes
+ )
mock_callback_class.assert_called_with(
callback_id='1-0',
event_client=event_client,
@@ -255,25 +300,35 @@ class SnippetClientV2Test(unittest.TestCase):
method_name='some_async_rpc',
device=self.device,
rpc_max_timeout_sec=snippet_client_v2._SOCKET_READ_TIMEOUT,
- default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC)
+ default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC,
+ )
self.assertIs(rpc_result, mock_callback_class.return_value)
self.assertIsNone(event_client.host_port, None)
self.assertIsNone(event_client.device_port, None)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
@mock.patch('mobly.utils.stop_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.callback_handler_v2.'
- 'CallbackHandlerV2')
- def test_the_whole_lifecycle_with_multiple_rpcs(self, mock_callback_class,
- mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_socket_create_conn,
- mock_get_port):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.callback_handler_v2.'
+ 'CallbackHandlerV2'
+ )
+ def test_the_whole_lifecycle_with_multiple_rpcs(
+ self,
+ mock_callback_class,
+ mock_start_subprocess,
+ mock_stop_standing_subprocess,
+ mock_socket_create_conn,
+ _,
+ ):
"""Tests the whole lifecycle of the client with sending multiple RPCs."""
# Prepare the test
mock_socket_resp = [
@@ -285,9 +340,9 @@ class SnippetClientV2Test(unittest.TestCase):
b'{"id": 2, "result": 789, "error": null, "callback": null}',
b'{"id": 3, "result": 321, "error": null, "callback": "2-0"}',
]
- self._make_client_and_mock_socket_conn(mock_socket_create_conn,
- mock_socket_resp,
- set_counter=False)
+ self._make_client_and_mock_socket_conn(
+ mock_socket_create_conn, mock_socket_resp, set_counter=False
+ )
self._mock_server_process_starting_response(mock_start_subprocess)
rpc_results_expected = [
@@ -299,7 +354,8 @@ class SnippetClientV2Test(unittest.TestCase):
# Extract the two mock objects to use as return values of callback handler
# class
mock_callback_class.side_effect = [
- rpc_results_expected[1], rpc_results_expected[3]
+ rpc_results_expected[1],
+ rpc_results_expected[3],
]
# Run tests
@@ -314,14 +370,17 @@ class SnippetClientV2Test(unittest.TestCase):
# Assertions
mock_callback_class_calls_expected = [
- mock.call(callback_id='1-0',
- event_client=event_client,
- ret_value=456,
- method_name='some_async_rpc',
- device=self.device,
- rpc_max_timeout_sec=snippet_client_v2._SOCKET_READ_TIMEOUT,
- default_timeout_sec=(
- snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC)),
+ mock.call(
+ callback_id='1-0',
+ event_client=event_client,
+ ret_value=456,
+ method_name='some_async_rpc',
+ device=self.device,
+ rpc_max_timeout_sec=snippet_client_v2._SOCKET_READ_TIMEOUT,
+ default_timeout_sec=(
+ snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC
+ ),
+ ),
mock.call(
callback_id='2-0',
event_client=event_client,
@@ -329,13 +388,14 @@ class SnippetClientV2Test(unittest.TestCase):
method_name='some_async_rpc',
device=self.device,
rpc_max_timeout_sec=snippet_client_v2._SOCKET_READ_TIMEOUT,
- default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC)
+ default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC,
+ ),
]
self.assertListEqual(rpc_results, rpc_results_expected)
mock_callback_class.assert_has_calls(mock_callback_class_calls_expected)
- self._assert_client_resources_released(mock_start_subprocess,
- mock_stop_standing_subprocess,
- mock_get_port)
+ self._assert_client_resources_released(
+ mock_start_subprocess, mock_stop_standing_subprocess, MOCK_HOST_PORT
+ )
self.assertIsNone(event_client.host_port, None)
self.assertIsNone(event_client.device_port, None)
@@ -355,18 +415,23 @@ class SnippetClientV2Test(unittest.TestCase):
"""Tests that app checker fails without instrumenting app."""
self._make_client(_MockAdbProxy(installed_packages=[MOCK_PACKAGE_NAME]))
expected_msg = (
- f'.* {MOCK_PACKAGE_NAME} is installed, but it is not instrumented.')
+ f'.* {MOCK_PACKAGE_NAME} is installed, but it is not instrumented.'
+ )
with self.assertRaisesRegex(errors.ServerStartPreCheckError, expected_msg):
self.client._validate_snippet_app_on_device()
def test_check_app_installed_fail_instrumentation_not_installed(self):
"""Tests that app checker fails without installing instrumentation."""
self._make_client(
- _MockAdbProxy(instrumented_packages=[(
- MOCK_PACKAGE_NAME,
- snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE,
- 'not.installed')]))
- expected_msg = ('.* Instrumentation target not.installed is not installed.')
+ _MockAdbProxy(
+ instrumented_packages=[(
+ MOCK_PACKAGE_NAME,
+ snippet_client_v2._INSTRUMENTATION_RUNNER_PACKAGE,
+ 'not.installed',
+ )]
+ )
+ )
+ expected_msg = '.* Instrumentation target not.installed is not installed.'
with self.assertRaisesRegex(errors.ServerStartPreCheckError, expected_msg):
self.client._validate_snippet_app_on_device()
@@ -379,7 +444,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.device.is_rootable = True
self.client._disable_hidden_api_blocklist()
self.adb.mock_shell_func.assert_called_with(
- 'settings put global hidden_api_blacklist_exemptions "*"')
+ 'settings put global hidden_api_blacklist_exemptions "*"'
+ )
def test_disable_hidden_api_low_sdk(self):
"""Tests it doesn't disable hidden api with low SDK."""
@@ -401,8 +467,10 @@ class SnippetClientV2Test(unittest.TestCase):
self.client._disable_hidden_api_blocklist()
self.adb.mock_shell_func.assert_not_called()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
@mock.patch.object(_MockAdbProxy, 'shell', return_value=b'setsid')
def test_start_server_with_user_id(self, mock_adb, mock_start_subprocess):
"""Tests that `--user` is added to starting command with SDK >= 24."""
@@ -411,17 +479,51 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- (f'setsid am instrument --user {MOCK_USER_ID} -w -e action start '
- f'{MOCK_SERVER_PATH}')
+ 'adb',
+ 'shell',
+ (
+ f'setsid am instrument --user {MOCK_USER_ID} -w -e action start '
+ f'{MOCK_SERVER_PATH}'
+ ),
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
self.assertEqual(self.client.device_port, 1234)
mock_adb.assert_called_with(['which', 'setsid'])
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch.object(_MockAdbProxy, 'shell', return_value=b'setsid')
+ def test_start_server_with_config_specific_user_id(
+ self, _, mock_start_subprocess
+ ):
+ """Tests that the correct `--user` argument is passed."""
+ self._make_client(config=snippet_client_v2.Config(user_id=42))
+ self._mock_server_process_starting_response(mock_start_subprocess)
+ self.assertEqual(self.client.user_id, 42)
+
+ self.client.start_server()
+ start_cmd_list = [
+ 'adb',
+ 'shell',
+ (
+ 'setsid am instrument --user 42 -w -e action start '
+ f'{MOCK_SERVER_PATH}'
+ ),
+ ]
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
+
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
@mock.patch.object(_MockAdbProxy, 'shell', return_value=b'setsid')
def test_start_server_without_user_id(self, mock_adb, mock_start_subprocess):
"""Tests that `--user` is not added to starting command on SDK < 24."""
@@ -430,41 +532,55 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- f'setsid am instrument -w -e action start {MOCK_SERVER_PATH}'
+ 'adb',
+ 'shell',
+ f'setsid am instrument -w -e action start {MOCK_SERVER_PATH}',
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
mock_adb.assert_called_with(['which', 'setsid'])
self.assertEqual(self.client.device_port, 1234)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch.object(_MockAdbProxy,
- 'shell',
- side_effect=adb.AdbError('cmd', 'stdout', 'stderr',
- 'ret_code'))
- def test_start_server_without_persisting_commands(self, mock_adb,
- mock_start_subprocess):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch.object(
+ _MockAdbProxy,
+ 'shell',
+ side_effect=adb.AdbError('cmd', 'stdout', 'stderr', 'ret_code'),
+ )
+ def test_start_server_without_persisting_commands(
+ self, mock_adb, mock_start_subprocess
+ ):
"""Checks the starting server command without persisting commands."""
self._make_client()
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- (f' am instrument --user {MOCK_USER_ID} -w -e action start '
- f'{MOCK_SERVER_PATH}')
+ 'adb',
+ 'shell',
+ (
+ f' am instrument --user {MOCK_USER_ID} -w -e action start '
+ f'{MOCK_SERVER_PATH}'
+ ),
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
mock_adb.assert_has_calls(
- [mock.call(['which', 'setsid']),
- mock.call(['which', 'nohup'])])
+ [mock.call(['which', 'setsid']), mock.call(['which', 'nohup'])]
+ )
self.assertEqual(self.client.device_port, 1234)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_with_nohup(self, mock_start_subprocess):
"""Checks the starting server command with nohup."""
self._make_client()
@@ -479,16 +595,23 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- (f'nohup am instrument --user {MOCK_USER_ID} -w -e action start '
- f'{MOCK_SERVER_PATH}')
+ 'adb',
+ 'shell',
+ (
+ f'nohup am instrument --user {MOCK_USER_ID} -w -e action start '
+ f'{MOCK_SERVER_PATH}'
+ ),
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
self.assertEqual(self.client.device_port, 1234)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_with_setsid(self, mock_start_subprocess):
"""Checks the starting server command with setsid."""
self._make_client()
@@ -502,16 +625,23 @@ class SnippetClientV2Test(unittest.TestCase):
self.client._adb.shell = _mocked_shell
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- (f'setsid am instrument --user {MOCK_USER_ID} -w -e action start '
- f'{MOCK_SERVER_PATH}')
+ 'adb',
+ 'shell',
+ (
+ f'setsid am instrument --user {MOCK_USER_ID} -w -e action start '
+ f'{MOCK_SERVER_PATH}'
+ ),
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
self.assertEqual(self.client.device_port, 1234)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_with_instrument_options(self, mock_start_subprocess):
"""Checks the starting server command with instrument options."""
config = snippet_client_v2.Config(
@@ -524,57 +654,79 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.start_server()
start_cmd_list = [
- 'adb', 'shell',
- (f' am instrument --user {MOCK_USER_ID} -w -e action start '
- f'{instrument_options_str} {MOCK_SERVER_PATH}')
+ 'adb',
+ 'shell',
+ (
+ f' am instrument --user {MOCK_USER_ID} -w -e action start '
+ f'{instrument_options_str} {MOCK_SERVER_PATH}'
+ ),
]
- self.assertListEqual(mock_start_subprocess.call_args_list,
- [mock.call(start_cmd_list, shell=False)])
+ self.assertListEqual(
+ mock_start_subprocess.call_args_list,
+ [mock.call(start_cmd_list, shell=False)],
+ )
self.assertEqual(self.client.device_port, 1234)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_server_crash(self, mock_start_standing_subprocess):
"""Tests that starting server process crashes."""
self._make_client()
self._mock_server_process_starting_response(
mock_start_standing_subprocess,
- resp_lines=[b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n'])
+ resp_lines=[b'INSTRUMENTATION_RESULT: shortMsg=Process crashed.\n'],
+ )
with self.assertRaisesRegex(
errors.ServerStartProtocolError,
- 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.'):
+ 'INSTRUMENTATION_RESULT: shortMsg=Process crashed.',
+ ):
self.client.start_server()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_unknown_protocol_version(
- self, mock_start_standing_subprocess):
+ self, mock_start_standing_subprocess
+ ):
"""Tests that starting server process reports unknown protocol version."""
self._make_client()
self._mock_server_process_starting_response(
mock_start_standing_subprocess,
- resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n'])
- with self.assertRaisesRegex(errors.ServerStartProtocolError,
- 'SNIPPET START, PROTOCOL 99 0'):
+ resp_lines=[b'SNIPPET START, PROTOCOL 99 0\n'],
+ )
+ with self.assertRaisesRegex(
+ errors.ServerStartProtocolError, 'SNIPPET START, PROTOCOL 99 0'
+ ):
self.client.start_server()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- def test_start_server_invalid_device_port(self,
- mock_start_standing_subprocess):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_start_server_invalid_device_port(
+ self, mock_start_standing_subprocess
+ ):
"""Tests that starting server process reports invalid device port."""
self._make_client()
self._mock_server_process_starting_response(
mock_start_standing_subprocess,
resp_lines=[
- b'SNIPPET START, PROTOCOL 1 0\n', b'SNIPPET SERVING, PORT ABC\n'
- ])
- with self.assertRaisesRegex(errors.ServerStartProtocolError,
- 'SNIPPET SERVING, PORT ABC'):
+ b'SNIPPET START, PROTOCOL 1 0\n',
+ b'SNIPPET SERVING, PORT ABC\n',
+ ],
+ )
+ with self.assertRaisesRegex(
+ errors.ServerStartProtocolError, 'SNIPPET SERVING, PORT ABC'
+ ):
self.client.start_server()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_with_junk(self, mock_start_standing_subprocess):
"""Tests that starting server process reports known protocol with junk."""
self._make_client()
@@ -586,12 +738,15 @@ class SnippetClientV2Test(unittest.TestCase):
b'SNIPPET START, PROTOCOL 1 0\n',
b'Maybe in the middle too\n',
b'SNIPPET SERVING, PORT 123\n',
- ])
+ ],
+ )
self.client.start_server()
self.assertEqual(123, self.client.device_port)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_start_server_no_valid_line(self, mock_start_standing_subprocess):
"""Tests that starting server process reports unknown protocol message."""
self._make_client()
@@ -601,10 +756,12 @@ class SnippetClientV2Test(unittest.TestCase):
b'This is some header junk\n',
b'Some phones print arbitrary output\n',
b'', # readline uses '' to mark EOF
- ])
+ ],
+ )
with self.assertRaisesRegex(
errors.ServerStartError,
- 'Unexpected EOF when waiting for server to start.'):
+ 'Unexpected EOF when waiting for server to start.',
+ ):
self.client.start_server()
@mock.patch('mobly.utils.stop_standing_subprocess')
@@ -622,19 +779,22 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertIs(self.client._proc, None)
self.adb.mock_shell_func.assert_called_once_with(
f'am instrument --user {MOCK_USER_ID} -w -e action stop '
- f'{MOCK_SERVER_PATH}')
+ f'{MOCK_SERVER_PATH}'
+ )
mock_stop_standing_subprocess.assert_called_once_with(mock_proc)
self.assertFalse(self.client.is_alive)
self.assertIs(self.client._conn, None)
mock_conn.close.assert_called_once_with()
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
self.assertIsNone(self.client._event_client)
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_stop_when_server_is_already_cleaned(self,
- mock_stop_standing_subprocess):
+ def test_stop_when_server_is_already_cleaned(
+ self, mock_stop_standing_subprocess
+ ):
"""Tests that stop server process when subprocess is already cleaned."""
self._make_client()
self.client._proc = None
@@ -648,17 +808,20 @@ class SnippetClientV2Test(unittest.TestCase):
mock_stop_standing_subprocess.assert_not_called()
self.adb.assert_called_once_with(
f'am instrument --user {MOCK_USER_ID} -w -e action stop '
- f'{MOCK_SERVER_PATH}')
+ f'{MOCK_SERVER_PATH}'
+ )
self.assertFalse(self.client.is_alive)
self.assertIs(self.client._conn, None)
mock_conn.close.assert_called_once_with()
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_stop_when_conn_is_already_cleaned(self,
- mock_stop_standing_subprocess):
+ def test_stop_when_conn_is_already_cleaned(
+ self, mock_stop_standing_subprocess
+ ):
"""Tests that stop server process when the connection is already closed."""
self._make_client()
mock_proc = mock.Mock()
@@ -672,17 +835,20 @@ class SnippetClientV2Test(unittest.TestCase):
mock_stop_standing_subprocess.assert_called_once_with(mock_proc)
self.adb.assert_called_once_with(
f'am instrument --user {MOCK_USER_ID} -w -e action stop '
- f'{MOCK_SERVER_PATH}')
+ f'{MOCK_SERVER_PATH}'
+ )
self.assertFalse(self.client.is_alive)
self.assertIs(self.client._conn, None)
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(_MockAdbProxy, 'shell', return_value=b'Closed with error.')
- def test_stop_with_device_side_error(self, mock_adb_shell,
- mock_stop_standing_subprocess):
+ def test_stop_with_device_side_error(
+ self, mock_adb_shell, mock_stop_standing_subprocess
+ ):
"""Tests all resources will be cleaned when server stop throws an error."""
self._make_client()
mock_proc = mock.Mock()
@@ -690,21 +856,24 @@ class SnippetClientV2Test(unittest.TestCase):
mock_conn = mock.Mock()
self.client._conn = mock_conn
self.client.host_port = 12345
- with self.assertRaisesRegex(android_device_lib_errors.DeviceError,
- 'Closed with error'):
+ with self.assertRaisesRegex(
+ android_device_lib_errors.DeviceError, 'Closed with error'
+ ):
self.client.stop()
self.assertIs(self.client._proc, None)
mock_stop_standing_subprocess.assert_called_once_with(mock_proc)
mock_adb_shell.assert_called_once_with(
f'am instrument --user {MOCK_USER_ID} -w -e action stop '
- f'{MOCK_SERVER_PATH}')
+ f'{MOCK_SERVER_PATH}'
+ )
self.assertFalse(self.client.is_alive)
self.assertIs(self.client._conn, None)
mock_conn.close.assert_called_once_with()
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
@mock.patch('mobly.utils.stop_standing_subprocess')
def test_stop_with_conn_close_error(self, mock_stop_standing_subprocess):
@@ -723,16 +892,22 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.stop()
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
@mock.patch('mobly.utils.stop_standing_subprocess')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'create_socket_connection')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'send_handshake_request')
- def test_stop_with_event_client(self, mock_send_handshake_func,
- mock_create_socket_conn_func,
- mock_stop_standing_subprocess):
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'create_socket_connection'
+ )
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'send_handshake_request'
+ )
+ def test_stop_with_event_client(
+ self,
+ mock_send_handshake_func,
+ mock_create_socket_conn_func,
+ mock_stop_standing_subprocess,
+ ):
"""Tests that stopping with an event client works normally."""
del mock_send_handshake_func
del mock_create_socket_conn_func
@@ -759,16 +934,22 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertIsNone(self.client._event_client)
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
@mock.patch('mobly.utils.stop_standing_subprocess')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'create_socket_connection')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'send_handshake_request')
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'create_socket_connection'
+ )
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'send_handshake_request'
+ )
def test_stop_with_event_client_stops_port_forwarding_once(
- self, mock_send_handshake_func, mock_create_socket_conn_func,
- mock_stop_standing_subprocess):
+ self,
+ mock_send_handshake_func,
+ mock_create_socket_conn_func,
+ mock_stop_standing_subprocess,
+ ):
"""Tests that client with an event client stops port forwarding once."""
del mock_send_handshake_func
del mock_create_socket_conn_func
@@ -785,7 +966,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertIsNone(self.client._event_client)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:12345'])
+ ['--remove', 'tcp:12345']
+ )
def test_close_connection_normally(self):
"""Tests that closing connection works normally."""
@@ -800,7 +982,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertIs(self.client.host_port, None)
mock_conn.close.assert_called_once_with()
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:123'])
+ ['--remove', 'tcp:123']
+ )
def test_close_connection_when_host_port_has_been_released(self):
"""Tests that close connection when the host port has been released."""
@@ -827,18 +1010,23 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertIs(self.client._conn, None)
self.assertIs(self.client.host_port, None)
self.device.adb.mock_forward_func.assert_called_once_with(
- ['--remove', 'tcp:123'])
+ ['--remove', 'tcp:123']
+ )
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- def test_send_sync_rpc_normally(self, mock_start_subprocess,
- mock_socket_create_conn, mock_get_port):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_send_sync_rpc_normally(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that sending a sync RPC works normally."""
- del mock_get_port
socket_resp = [
b'{"status": true, "uid": 1}',
b'{"id": 0, "result": 123, "error": null, "callback": null}',
@@ -851,16 +1039,30 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertEqual(rpc_result, 123)
self.mock_socket_file.write.assert_called_with(
- b'{"id": 0, "method": "some_rpc", "params": [1, 2, "hello"]}\n')
+ b'{"id": 0, "method": "some_rpc", "params": [1, 2, "hello"]}\n'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.callback_handler_v2.'
- 'CallbackHandlerV2')
- def test_async_rpc_start_event_client(self, mock_callback_class,
- mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.callback_handler_v2.'
+ 'CallbackHandlerV2'
+ )
+ def test_async_rpc_start_event_client(
+ self,
+ mock_callback_class,
+ mock_start_subprocess,
+ mock_socket_create_conn,
+ _,
+ ):
"""Tests that sending an async RPC starts the event client."""
socket_resp = [
b'{"status": true, "uid": 1}',
@@ -870,15 +1072,19 @@ class SnippetClientV2Test(unittest.TestCase):
]
socket_write_expected = [
mock.call(b'{"cmd": "initiate", "uid": -1}\n'),
- mock.call(b'{"id": 0, "method": "some_async_rpc", '
- b'"params": [1, 2, "hello"]}\n'),
+ mock.call(
+ b'{"id": 0, "method": "some_async_rpc", '
+ b'"params": [1, 2, "hello"]}\n'
+ ),
mock.call(b'{"cmd": "continue", "uid": 1}\n'),
- mock.call(b'{"id": 1, "method": "eventGetAll", '
- b'"params": ["1-0", "eventName"]}\n'),
+ mock.call(
+ b'{"id": 1, "method": "eventGetAll", '
+ b'"params": ["1-0", "eventName"]}\n'
+ ),
]
- self._make_client_and_mock_socket_conn(mock_socket_create_conn,
- socket_resp,
- set_counter=True)
+ self._make_client_and_mock_socket_conn(
+ mock_socket_create_conn, socket_resp, set_counter=True
+ )
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.host_port = 12345
@@ -892,7 +1098,8 @@ class SnippetClientV2Test(unittest.TestCase):
method_name='some_async_rpc',
device=self.device,
rpc_max_timeout_sec=snippet_client_v2._SOCKET_READ_TIMEOUT,
- default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC)
+ default_timeout_sec=snippet_client_v2._CALLBACK_DEFAULT_TIMEOUT_SEC,
+ )
self.assertIs(rpc_result, mock_callback_class.return_value)
# Ensure the event client is alive
@@ -915,38 +1122,52 @@ class SnippetClientV2Test(unittest.TestCase):
socket_write_expected,
)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port')
- def test_initialize_client_normally(self, mock_get_port,
- mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_initialize_client_normally(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that initializing the client works normally."""
- mock_get_port.return_value = 12345
+ host_port = 12345
socket_resp = [b'{"status": true, "uid": 1}']
- self._make_client_and_mock_socket_conn(mock_socket_create_conn,
- socket_resp,
- set_counter=True)
+ self._make_client_and_mock_socket_conn(
+ mock_socket_create_conn,
+ socket_resp,
+ set_counter=True,
+ )
+ self.device.adb.default_host_port = host_port
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.initialize()
self.assertTrue(self.client.is_alive)
self.assertEqual(self.client.uid, 1)
- self.assertEqual(self.client.host_port, 12345)
+ self.assertEqual(self.client.host_port, host_port)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
self.assertEqual(next(self.client._counter), 0)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port')
- def test_restore_event_client(self, mock_get_port, mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_restore_event_client(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests restoring the event client."""
- mock_get_port.return_value = 12345
+ host_port = 12345
socket_resp = [
# response of handshake when initializing the client
b'{"status": true, "uid": 1}',
@@ -980,33 +1201,36 @@ class SnippetClientV2Test(unittest.TestCase):
mock.call(b'{"cmd": "initiate", "uid": -1}\n'),
]
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
+ self.device.adb.default_host_port = host_port
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.make_connection()
callback = self.client.some_async_rpc()
# before reconnect, clients use previously selected ports
- self.assertEqual(self.client.host_port, 12345)
+ self.assertEqual(self.client.host_port, host_port)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
- self.assertEqual(callback._event_client.host_port, 12345)
+ self.assertEqual(callback._event_client.host_port, host_port)
self.assertEqual(callback._event_client.device_port, MOCK_DEVICE_PORT)
self.assertEqual(next(self.client._event_client._counter), 0)
# after reconnect, if host port specified, clients use specified port
- self.client.restore_server_connection(port=54321)
- self.assertEqual(self.client.host_port, 54321)
+ host_port_2 = 54321
+ self.client.restore_server_connection(port=host_port_2)
+ self.assertEqual(self.client.host_port, host_port_2)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
- self.assertEqual(callback._event_client.host_port, 54321)
+ self.assertEqual(callback._event_client.host_port, host_port_2)
self.assertEqual(callback._event_client.device_port, MOCK_DEVICE_PORT)
self.assertEqual(next(self.client._event_client._counter), 0)
# after reconnect, if host port not specified, clients use selected
# available port
- mock_get_port.return_value = 56789
+ host_port_3 = 56789
+ self.device.adb.default_host_port = host_port_3
self.client.restore_server_connection()
- self.assertEqual(self.client.host_port, 56789)
+ self.assertEqual(self.client.host_port, host_port_3)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
- self.assertEqual(callback._event_client.host_port, 56789)
+ self.assertEqual(callback._event_client.host_port, host_port_3)
self.assertEqual(callback._event_client.device_port, MOCK_DEVICE_PORT)
self.assertEqual(next(self.client._event_client._counter), 0)
@@ -1015,25 +1239,35 @@ class SnippetClientV2Test(unittest.TestCase):
mock_socket_create_conn.side_effect = IOError('socket timed out')
with self.assertRaisesRegex(
errors.ServerRestoreConnectionError,
- (f'Failed to restore server connection for {MOCK_PACKAGE_NAME} at '
- f'host port 56789, device port {MOCK_DEVICE_PORT}')):
+ (
+ f'Failed to restore server connection for {MOCK_PACKAGE_NAME} at '
+ f'host port {host_port_3}, device port {MOCK_DEVICE_PORT}'
+ ),
+ ):
self.client.restore_server_connection()
- self.assertListEqual(self.mock_socket_file.write.call_args_list,
- socket_write_expected)
+ self.assertListEqual(
+ self.mock_socket_file.write.call_args_list, socket_write_expected
+ )
@mock.patch.object(snippet_client_v2.SnippetClientV2, '_make_connection')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'send_handshake_request')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'create_socket_connection')
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'send_handshake_request'
+ )
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'create_socket_connection'
+ )
def test_restore_server_connection_with_event_client(
- self, mock_create_socket_conn_func, mock_send_handshake_func,
- mock_make_connection):
+ self,
+ mock_create_socket_conn_func,
+ mock_send_handshake_func,
+ mock_make_connection,
+ ):
"""Tests restoring server connection when the event client is not None."""
self._make_client()
- event_client = snippet_client_v2.SnippetClientV2('mock-package',
- mock.Mock())
+ event_client = snippet_client_v2.SnippetClientV2(
+ 'mock-package', mock.Mock()
+ )
self.client._event_client = event_client
self.client.device_port = 54321
self.client.uid = 5
@@ -1046,7 +1280,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertEqual(next(event_client._counter), 0)
mock_create_socket_conn_func.assert_called_once_with()
mock_send_handshake_func.assert_called_once_with(
- -1, snippet_client_v2.ConnectionHandshakeCommand.INIT)
+ -1, snippet_client_v2.ConnectionHandshakeCommand.INIT
+ )
@mock.patch('builtins.print')
def test_help_rpc_when_printing_by_default(self, mock_print):
@@ -1072,69 +1307,117 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertEqual(mock_rpc.return_value, result)
mock_print.assert_not_called()
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
- def test_make_connection_normally(self, mock_get_port, mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_make_connection_normally(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that making a connection works normally."""
- del mock_get_port
socket_resp = [b'{"status": true, "uid": 1}']
+ host_port = 12345
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
+ self.device.adb.default_host_port = host_port
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.make_connection()
self.assertEqual(self.client.uid, 1)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
self.adb.mock_forward_func.assert_called_once_with(
- ['tcp:12345', f'tcp:{MOCK_DEVICE_PORT}'])
+ ['tcp:0', f'tcp:{MOCK_DEVICE_PORT}']
+ )
mock_socket_create_conn.assert_called_once_with(
- ('localhost', 12345), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT)
+ ('localhost', host_port), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT
+ )
self.socket_conn.settimeout.assert_called_once_with(
- snippet_client_v2._SOCKET_READ_TIMEOUT)
+ snippet_client_v2._SOCKET_READ_TIMEOUT
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
- def test_make_connection_with_preset_host_port(self, mock_get_port,
- mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_make_connection_with_preset_host_port(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that make a connection with the preset host port."""
- del mock_get_port
+ host_port = 23456
socket_resp = [b'{"status": true, "uid": 1}']
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
self._mock_server_process_starting_response(mock_start_subprocess)
- self.client.host_port = 23456
+ self.client.host_port = host_port
self.client.make_connection()
self.assertEqual(self.client.uid, 1)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
# Test that the host port for forwarding is 23456 instead of 12345
self.adb.mock_forward_func.assert_called_once_with(
- ['tcp:23456', f'tcp:{MOCK_DEVICE_PORT}'])
+ [f'tcp:{host_port}', f'tcp:{MOCK_DEVICE_PORT}']
+ )
mock_socket_create_conn.assert_called_once_with(
- ('localhost', 23456), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT)
+ ('localhost', host_port), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT
+ )
self.socket_conn.settimeout.assert_called_once_with(
- snippet_client_v2._SOCKET_READ_TIMEOUT)
+ snippet_client_v2._SOCKET_READ_TIMEOUT
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
- def test_make_connection_with_ip(self, mock_get_port, mock_start_subprocess,
- mock_socket_create_conn):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_make_connection_with_preset_host_port_that_is_forwarded(
+ self, mock_start_subprocess, mock_socket_create_conn, mock_occupied_ports
+ ):
+ """Tests that make a connection with the preset host port."""
+ host_port = 23456
+ mock_occupied_ports.return_value = [host_port]
+ socket_resp = [b'{"status": true, "uid": 1}']
+ self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
+ self._mock_server_process_starting_response(mock_start_subprocess)
+ self.client.host_port = host_port
+
+ with self.assertRaisesRegex(
+ errors.Error, f'Cannot forward to host port {host_port}'
+ ):
+ self.client.make_connection()
+
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
+ @mock.patch('socket.create_connection')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_make_connection_with_ip(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that make a connection with 127.0.0.1 instead of localhost."""
- del mock_get_port
+ host_port = 12345
socket_resp = [b'{"status": true, "uid": 1}']
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
+ self.device.adb.default_host_port = host_port
self._mock_server_process_starting_response(mock_start_subprocess)
mock_conn = mock_socket_create_conn.return_value
@@ -1153,86 +1436,103 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertEqual(self.client.uid, 1)
self.assertEqual(self.client.device_port, MOCK_DEVICE_PORT)
self.adb.mock_forward_func.assert_called_once_with(
- ['tcp:12345', f'tcp:{MOCK_DEVICE_PORT}'])
+ ['tcp:0', f'tcp:{MOCK_DEVICE_PORT}']
+ )
mock_socket_create_conn.assert_any_call(
- ('127.0.0.1', 12345), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT)
+ ('127.0.0.1', host_port), snippet_client_v2._SOCKET_CONNECTION_TIMEOUT
+ )
self.socket_conn.settimeout.assert_called_once_with(
- snippet_client_v2._SOCKET_READ_TIMEOUT)
+ snippet_client_v2._SOCKET_READ_TIMEOUT
+ )
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- def test_make_connection_io_error(self, mock_socket_create_conn,
- mock_get_port):
+ def test_make_connection_io_error(self, mock_socket_create_conn, _):
"""Tests IOError occurred trying to create a socket connection."""
- del mock_get_port
mock_socket_create_conn.side_effect = IOError()
with self.assertRaises(IOError):
self._make_client()
self.client.device_port = 123
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- def test_make_connection_timeout(self, mock_socket_create_conn,
- mock_get_port):
+ def test_make_connection_timeout(self, mock_socket_create_conn, _):
"""Tests timeout occurred trying to create a socket connection."""
- del mock_get_port
mock_socket_create_conn.side_effect = socket.timeout
with self.assertRaises(socket.timeout):
self._make_client()
self.client.device_port = 123
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_make_connection_receives_none_handshake_response(
- self, mock_start_subprocess, mock_socket_create_conn, mock_get_port):
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests make_connection receives None as the handshake response."""
- del mock_get_port
socket_resp = [None]
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
self._mock_server_process_starting_response(mock_start_subprocess)
with self.assertRaisesRegex(
- errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE):
+ errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE
+ ):
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_make_connection_receives_empty_handshake_response(
- self, mock_start_subprocess, mock_socket_create_conn, mock_get_port):
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests make_connection receives an empty handshake response."""
- del mock_get_port
socket_resp = [b'']
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
self._mock_server_process_starting_response(mock_start_subprocess)
with self.assertRaisesRegex(
- errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE):
+ errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_HANDSHAKE
+ ):
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_make_connection_receives_invalid_handshake_response(
- self, mock_start_subprocess, mock_socket_create_conn, mock_get_port):
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests make_connection receives an invalid handshake response."""
- del mock_get_port
socket_resp = [b'{"status": false, "uid": 1}']
self._make_client_and_mock_socket_conn(mock_socket_create_conn, socket_resp)
self._mock_server_process_starting_response(mock_start_subprocess)
@@ -1240,18 +1540,20 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.make_connection()
self.assertEqual(self.client.uid, -1)
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
- def test_make_connection_send_handshake_request_error(self,
- mock_start_subprocess,
- mock_socket_create_conn,
- mock_get_port):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
+ def test_make_connection_send_handshake_request_error(
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that an error occurred trying to send a handshake request."""
- del mock_get_port
self._make_client_and_mock_socket_conn(mock_socket_create_conn)
self._mock_server_process_starting_response(mock_start_subprocess)
self.mock_socket_file.write.side_effect = socket.error('Socket write error')
@@ -1259,34 +1561,43 @@ class SnippetClientV2Test(unittest.TestCase):
with self.assertRaisesRegex(errors.Error, 'Socket write error'):
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_make_connection_receive_handshake_response_error(
- self, mock_start_subprocess, mock_socket_create_conn, mock_get_port):
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that an error occurred trying to receive a handshake response."""
- del mock_get_port
self._make_client_and_mock_socket_conn(mock_socket_create_conn)
self._mock_server_process_starting_response(mock_start_subprocess)
self.mock_socket_file.readline.side_effect = socket.error(
- 'Socket read error')
+ 'Socket read error'
+ )
with self.assertRaisesRegex(errors.Error, 'Socket read error'):
self.client.make_connection()
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.get_available_host_port',
- return_value=12345)
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'adb.list_occupied_adb_ports',
+ return_value=[],
+ )
@mock.patch('socket.create_connection')
- @mock.patch('mobly.controllers.android_device_lib.snippet_client_v2.'
- 'utils.start_standing_subprocess')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.'
+ 'utils.start_standing_subprocess'
+ )
def test_make_connection_decode_handshake_response_bytes_error(
- self, mock_start_subprocess, mock_socket_create_conn, mock_get_port):
+ self, mock_start_subprocess, mock_socket_create_conn, _
+ ):
"""Tests that an error occurred trying to decode a handshake response."""
- del mock_get_port
self._make_client_and_mock_socket_conn(mock_socket_create_conn)
self._mock_server_process_starting_response(mock_start_subprocess)
self.client.log = mock.Mock()
@@ -1299,7 +1610,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.log.error.assert_has_calls([
mock.call(
'Failed to decode socket response bytes using encoding utf8: %s',
- socket_response)
+ socket_response,
+ )
])
def test_rpc_sending_and_receiving(self):
@@ -1309,14 +1621,16 @@ class SnippetClientV2Test(unittest.TestCase):
"""
self._make_client()
rpc_request = '{"id": 0, "method": "some_rpc", "params": []}'
- rpc_response_expected = ('{"id": 0, "result": 123, "error": null, '
- '"callback": null}')
+ rpc_response_expected = (
+ '{"id": 0, "result": 123, "error": null, "callback": null}'
+ )
socket_write_expected = [
mock.call(b'{"id": 0, "method": "some_rpc", "params": []}\n')
]
- socket_response = (b'{"id": 0, "result": 123, "error": null, '
- b'"callback": null}')
+ socket_response = (
+ b'{"id": 0, "result": 123, "error": null, "callback": null}'
+ )
mock_socket_file = mock.Mock()
mock_socket_file.readline.return_value = socket_response
@@ -1325,8 +1639,9 @@ class SnippetClientV2Test(unittest.TestCase):
rpc_response = self.client.send_rpc_request(rpc_request)
self.assertEqual(rpc_response, rpc_response_expected)
- self.assertEqual(mock_socket_file.write.call_args_list,
- socket_write_expected)
+ self.assertEqual(
+ mock_socket_file.write.call_args_list, socket_write_expected
+ )
def test_rpc_send_socket_write_error(self):
"""Tests that an error occurred trying to write the socket file."""
@@ -1355,7 +1670,8 @@ class SnippetClientV2Test(unittest.TestCase):
self.client._client = mock.Mock()
socket_response = bytes(
'{"id": 0, "result": 123, "error": null, "callback": null}',
- encoding='cp037')
+ encoding='cp037',
+ )
self.client._client.readline.return_value = socket_response
rpc_request = '{"id": 0, "method": "some_rpc", "params": []}'
@@ -1365,16 +1681,19 @@ class SnippetClientV2Test(unittest.TestCase):
self.client.log.error.assert_has_calls([
mock.call(
'Failed to decode socket response bytes using encoding utf8: %s',
- socket_response)
+ socket_response,
+ )
])
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'send_handshake_request')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'create_socket_connection')
- def test_make_conn_with_forwarded_port_init(self,
- mock_create_socket_conn_func,
- mock_send_handshake_func):
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'send_handshake_request'
+ )
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'create_socket_connection'
+ )
+ def test_make_conn_with_forwarded_port_init(
+ self, mock_create_socket_conn_func, mock_send_handshake_func
+ ):
"""Tests make_connection_with_forwarded_port initiates a new session."""
self._make_client()
self.client._counter = None
@@ -1385,27 +1704,32 @@ class SnippetClientV2Test(unittest.TestCase):
self.assertEqual(next(self.client._counter), 0)
mock_create_socket_conn_func.assert_called_once_with()
mock_send_handshake_func.assert_called_once_with(
- -1, snippet_client_v2.ConnectionHandshakeCommand.INIT)
-
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'send_handshake_request')
- @mock.patch.object(snippet_client_v2.SnippetClientV2,
- 'create_socket_connection')
- def test_make_conn_with_forwarded_port_continue(self,
- mock_create_socket_conn_func,
- mock_send_handshake_func):
+ -1, snippet_client_v2.ConnectionHandshakeCommand.INIT
+ )
+
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'send_handshake_request'
+ )
+ @mock.patch.object(
+ snippet_client_v2.SnippetClientV2, 'create_socket_connection'
+ )
+ def test_make_conn_with_forwarded_port_continue(
+ self, mock_create_socket_conn_func, mock_send_handshake_func
+ ):
"""Tests make_connection_with_forwarded_port continues current session."""
self._make_client()
self.client._counter = None
self.client.make_connection_with_forwarded_port(
- 12345, 54321, 3, snippet_client_v2.ConnectionHandshakeCommand.CONTINUE)
+ 12345, 54321, 3, snippet_client_v2.ConnectionHandshakeCommand.CONTINUE
+ )
self.assertEqual(self.client.host_port, 12345)
self.assertEqual(self.client.device_port, 54321)
self.assertEqual(next(self.client._counter), 0)
mock_create_socket_conn_func.assert_called_once_with()
mock_send_handshake_func.assert_called_once_with(
- 3, snippet_client_v2.ConnectionHandshakeCommand.CONTINUE)
+ 3, snippet_client_v2.ConnectionHandshakeCommand.CONTINUE
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/controllers/android_device_lib/snippet_event_test.py b/tests/mobly/controllers/android_device_lib/snippet_event_test.py
index e59461c..367a139 100755
--- a/tests/mobly/controllers/android_device_lib/snippet_event_test.py
+++ b/tests/mobly/controllers/android_device_lib/snippet_event_test.py
@@ -25,14 +25,15 @@ MOCK_DATA = {'foo': 'bar'}
class SnippetEventTest(unittest.TestCase):
def test_basic(self):
- """Verifies that an event object can be created and logged properly.
- """
- event = snippet_event.SnippetEvent(MOCK_CALLBACK_ID, MOCK_EVENT_NAME,
- MOCK_CREATION_TIME, MOCK_DATA)
+ """Verifies that an event object can be created and logged properly."""
+ event = snippet_event.SnippetEvent(
+ MOCK_CALLBACK_ID, MOCK_EVENT_NAME, MOCK_CREATION_TIME, MOCK_DATA
+ )
self.assertEqual(
repr(event),
- "SnippetEvent(callback_id: myCallbackId, name: onXyzEvent, "
- "creation_time: 12345678, data: {'foo': 'bar'})")
+ 'SnippetEvent(callback_id: myCallbackId, name: onXyzEvent, '
+ "creation_time: 12345678, data: {'foo': 'bar'})",
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/controllers/android_device_test.py b/tests/mobly/controllers/android_device_test.py
index 3682c94..81c2965 100755
--- a/tests/mobly/controllers/android_device_test.py
+++ b/tests/mobly/controllers/android_device_test.py
@@ -50,68 +50,88 @@ class AndroidDeviceTest(unittest.TestCase):
self.tmp_dir = tempfile.mkdtemp()
def tearDown(self):
- """Removes the temp dir.
- """
+ """Removes the temp dir."""
shutil.rmtree(self.tmp_dir)
# Tests for android_device module functions.
# These tests use mock AndroidDevice instances.
- @mock.patch.object(android_device,
- 'get_all_instances',
- new=mock_android_device.get_all_instances)
- @mock.patch.object(android_device,
- 'list_adb_devices',
- new=mock_android_device.list_adb_devices)
- @mock.patch.object(android_device,
- 'list_adb_devices_by_usb_id',
- new=mock_android_device.list_adb_devices)
+ @mock.patch.object(
+ android_device,
+ 'get_all_instances',
+ new=mock_android_device.get_all_instances,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices',
+ new=mock_android_device.list_adb_devices,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices_by_usb_id',
+ new=mock_android_device.list_adb_devices,
+ )
def test_create_with_pickup_all(self):
pick_all_token = android_device.ANDROID_DEVICE_PICK_ALL_TOKEN
actual_ads = android_device.create(pick_all_token)
- for actual, expected in zip(actual_ads,
- mock_android_device.get_mock_ads(5)):
+ for actual, expected in zip(
+ actual_ads, mock_android_device.get_mock_ads(5)
+ ):
self.assertEqual(actual.serial, expected.serial)
- @mock.patch.object(android_device,
- 'get_instances',
- new=mock_android_device.get_instances)
- @mock.patch.object(android_device,
- 'list_adb_devices',
- new=mock_android_device.list_adb_devices)
- @mock.patch.object(android_device,
- 'list_adb_devices_by_usb_id',
- new=mock_android_device.list_adb_devices)
+ @mock.patch.object(
+ android_device, 'get_instances', new=mock_android_device.get_instances
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices',
+ new=mock_android_device.list_adb_devices,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices_by_usb_id',
+ new=mock_android_device.list_adb_devices,
+ )
def test_create_with_string_list(self):
- string_list = [u'1', '2']
+ string_list = ['1', '2']
actual_ads = android_device.create(string_list)
for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
self.assertEqual(actual_ad.serial, expected_serial)
- @mock.patch.object(android_device,
- 'get_instances_with_configs',
- new=mock_android_device.get_instances_with_configs)
- @mock.patch.object(android_device,
- 'list_adb_devices',
- new=mock_android_device.list_adb_devices)
- @mock.patch.object(android_device,
- 'list_adb_devices_by_usb_id',
- new=mock_android_device.list_adb_devices)
+ @mock.patch.object(
+ android_device,
+ 'get_instances_with_configs',
+ new=mock_android_device.get_instances_with_configs,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices',
+ new=mock_android_device.list_adb_devices,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices_by_usb_id',
+ new=mock_android_device.list_adb_devices,
+ )
def test_create_with_dict_list(self):
string_list = [{'serial': '1'}, {'serial': '2'}]
actual_ads = android_device.create(string_list)
for actual_ad, expected_serial in zip(actual_ads, ['1', '2']):
self.assertEqual(actual_ad.serial, expected_serial)
- @mock.patch.object(android_device,
- 'get_instances_with_configs',
- new=mock_android_device.get_instances_with_configs)
- @mock.patch.object(android_device,
- 'list_adb_devices',
- new=mock_android_device.list_adb_devices)
- @mock.patch.object(android_device,
- 'list_adb_devices_by_usb_id',
- return_value=['usb:1'])
+ @mock.patch.object(
+ android_device,
+ 'get_instances_with_configs',
+ new=mock_android_device.get_instances_with_configs,
+ )
+ @mock.patch.object(
+ android_device,
+ 'list_adb_devices',
+ new=mock_android_device.list_adb_devices,
+ )
+ @mock.patch.object(
+ android_device, 'list_adb_devices_by_usb_id', return_value=['usb:1']
+ )
def test_create_with_usb_id(self, mock_list_adb_devices_by_usb_id):
string_list = [{'serial': '1'}, {'serial': '2'}, {'serial': 'usb:1'}]
actual_ads = android_device.create(string_list)
@@ -137,8 +157,9 @@ class AndroidDeviceTest(unittest.TestCase):
@mock.patch('mobly.controllers.android_device.list_adb_devices')
@mock.patch('mobly.controllers.android_device.list_adb_devices_by_usb_id')
@mock.patch('mobly.controllers.android_device.AndroidDevice')
- def test_get_instances(self, mock_ad_class, mock_list_adb_usb, mock_list_adb,
- mock_list_fastboot):
+ def test_get_instances(
+ self, mock_ad_class, mock_list_adb_usb, mock_list_adb, mock_list_fastboot
+ ):
mock_list_fastboot.return_value = ['0']
mock_list_adb.return_value = ['1']
mock_list_adb_usb.return_value = []
@@ -150,14 +171,15 @@ class AndroidDeviceTest(unittest.TestCase):
@mock.patch('mobly.controllers.android_device.list_adb_devices')
@mock.patch('mobly.controllers.android_device.list_adb_devices_by_usb_id')
@mock.patch('mobly.controllers.android_device.AndroidDevice')
- def test_get_instances_do_not_exist(self, mock_ad_class, mock_list_adb_usb,
- mock_list_adb, mock_list_fastboot):
+ def test_get_instances_do_not_exist(
+ self, mock_ad_class, mock_list_adb_usb, mock_list_adb, mock_list_fastboot
+ ):
mock_list_fastboot.return_value = []
mock_list_adb.return_value = []
mock_list_adb_usb.return_value = []
with self.assertRaisesRegex(
errors.Error,
- 'Android device serial "1" is specified in config but is not reachable'
+ 'Android device serial "1" is specified in config but is not reachable',
):
android_device.get_instances(['1'])
@@ -165,8 +187,9 @@ class AndroidDeviceTest(unittest.TestCase):
@mock.patch('mobly.controllers.android_device.list_adb_devices')
@mock.patch('mobly.controllers.android_device.list_adb_devices_by_usb_id')
@mock.patch('mobly.controllers.android_device.AndroidDevice')
- def test_get_instances_with_configs(self, mock_ad_class, mock_list_adb_usb,
- mock_list_adb, mock_list_fastboot):
+ def test_get_instances_with_configs(
+ self, mock_ad_class, mock_list_adb_usb, mock_list_adb, mock_list_fastboot
+ ):
mock_list_fastboot.return_value = ['1']
mock_list_adb.return_value = ['2']
mock_list_adb_usb.return_value = []
@@ -179,24 +202,24 @@ class AndroidDeviceTest(unittest.TestCase):
config = {'something': 'random'}
with self.assertRaisesRegex(
errors.Error,
- f'Required value "serial" is missing in AndroidDevice config {config}'):
+ f'Required value "serial" is missing in AndroidDevice config {config}',
+ ):
android_device.get_instances_with_configs([config])
@mock.patch('mobly.controllers.android_device.list_fastboot_devices')
@mock.patch('mobly.controllers.android_device.list_adb_devices')
@mock.patch('mobly.controllers.android_device.list_adb_devices_by_usb_id')
@mock.patch('mobly.controllers.android_device.AndroidDevice')
- def test_get_instances_with_configsdo_not_exist(self, mock_ad_class,
- mock_list_adb_usb,
- mock_list_adb,
- mock_list_fastboot):
+ def test_get_instances_with_configsdo_not_exist(
+ self, mock_ad_class, mock_list_adb_usb, mock_list_adb, mock_list_fastboot
+ ):
mock_list_fastboot.return_value = []
mock_list_adb.return_value = []
mock_list_adb_usb.return_value = []
config = {'serial': '1'}
with self.assertRaisesRegex(
errors.Error,
- 'Android device serial "1" is specified in config but is not reachable'
+ 'Android device serial "1" is specified in config but is not reachable',
):
android_device.get_instances_with_configs([config])
@@ -213,8 +236,10 @@ class AndroidDeviceTest(unittest.TestCase):
def test_get_devices_no_match(self):
ads = mock_android_device.get_mock_ads(5)
- expected_msg = ('Could not find a target device that matches condition'
- ": {'label': 'selected'}.")
+ expected_msg = (
+ 'Could not find a target device that matches condition'
+ ": {'label': 'selected'}."
+ )
with self.assertRaisesRegex(android_device.Error, expected_msg):
selected_ads = android_device.get_devices(ads, label='selected')
@@ -229,16 +254,17 @@ class AndroidDeviceTest(unittest.TestCase):
expected_serial = '1'
expected_h_port = 5555
ads[1].h_port = expected_h_port
- ad = android_device.get_device(ads,
- serial=expected_serial,
- h_port=expected_h_port)
+ ad = android_device.get_device(
+ ads, serial=expected_serial, h_port=expected_h_port
+ )
self.assertEqual(ad.serial, expected_serial)
self.assertEqual(ad.h_port, expected_h_port)
def test_get_device_no_match(self):
ads = mock_android_device.get_mock_ads(5)
- expected_msg = ('Could not find a target device that matches condition'
- ": {'serial': 5}.")
+ expected_msg = (
+ "Could not find a target device that matches condition: {'serial': 5}."
+ )
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad = android_device.get_device(ads, serial=len(ads))
@@ -261,7 +287,8 @@ class AndroidDeviceTest(unittest.TestCase):
ad.skip_logcat = False
ad.is_required = True
ads[1].services.logcat.start = mock.MagicMock(
- side_effect=android_device.Error(msg))
+ side_effect=android_device.Error(msg)
+ )
with self.assertRaisesRegex(android_device.Error, msg):
android_device._start_services_on_ads(ads)
ads[0].services.stop_all.assert_called_once_with()
@@ -273,35 +300,36 @@ class AndroidDeviceTest(unittest.TestCase):
ads[0].services.logcat.start = mock.MagicMock()
ads[1].services.logcat.start = mock.MagicMock()
ads[2].services.logcat.start = mock.MagicMock(
- side_effect=Exception('Should not have called this.'))
+ side_effect=Exception('Should not have called this.')
+ )
ads[2].skip_logcat = True
android_device._start_services_on_ads(ads)
def test_take_bug_reports(self):
ads = mock_android_device.get_mock_ads(3)
android_device.take_bug_reports(ads, 'test_something', 'sometime')
- ads[0].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='sometime',
- destination=None)
- ads[1].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='sometime',
- destination=None)
- ads[2].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='sometime',
- destination=None)
+ ads[0].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='sometime', destination=None
+ )
+ ads[1].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='sometime', destination=None
+ )
+ ads[2].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='sometime', destination=None
+ )
def test_take_bug_reports_with_int_begin_time(self):
ads = mock_android_device.get_mock_ads(3)
android_device.take_bug_reports(ads, 'test_something', 123)
- ads[0].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='123',
- destination=None)
- ads[1].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='123',
- destination=None)
- ads[2].take_bug_report.assert_called_once_with(test_name='test_something',
- begin_time='123',
- destination=None)
+ ads[0].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='123', destination=None
+ )
+ ads[1].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='123', destination=None
+ )
+ ads[2].take_bug_report.assert_called_once_with(
+ test_name='test_something', begin_time='123', destination=None
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_take_bug_reports_with_none_values(self, get_log_file_timestamp_mock):
@@ -309,24 +337,28 @@ class AndroidDeviceTest(unittest.TestCase):
get_log_file_timestamp_mock.return_value = mock_timestamp
ads = mock_android_device.get_mock_ads(3)
android_device.take_bug_reports(ads)
- ads[0].take_bug_report.assert_called_once_with(test_name=None,
- begin_time=mock_timestamp,
- destination=None)
- ads[1].take_bug_report.assert_called_once_with(test_name=None,
- begin_time=mock_timestamp,
- destination=None)
- ads[2].take_bug_report.assert_called_once_with(test_name=None,
- begin_time=mock_timestamp,
- destination=None)
+ ads[0].take_bug_report.assert_called_once_with(
+ test_name=None, begin_time=mock_timestamp, destination=None
+ )
+ ads[1].take_bug_report.assert_called_once_with(
+ test_name=None, begin_time=mock_timestamp, destination=None
+ )
+ ads[2].take_bug_report.assert_called_once_with(
+ test_name=None, begin_time=mock_timestamp, destination=None
+ )
# Tests for android_device.AndroidDevice class.
# These tests mock out any interaction with the OS and real android device
# in AndroidDeivce.
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_instantiation(self, MockFastboot, MockAdbProxy):
"""Verifies the AndroidDevice object's basic attributes are correctly
set after instantiation.
@@ -335,19 +367,25 @@ class AndroidDeviceTest(unittest.TestCase):
ad = android_device.AndroidDevice(serial=mock_serial)
self.assertEqual(ad.serial, '1')
self.assertEqual(ad.model, 'fakemodel')
- expected_lp = os.path.join(logging.log_path,
- 'AndroidDevice%s' % mock_serial)
+ expected_lp = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % mock_serial
+ )
self.assertEqual(ad.log_path, expected_lp)
self.assertIsNotNone(ad.services.logcat)
self.assertIsNotNone(ad.services.snippets)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
- def test_AndroidDevice_load_config(self, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_load_config(
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
config = {'space': 'the final frontier', 'number': 1, 'debug_tag': 'my_tag'}
ad = android_device.AndroidDevice(serial=mock_serial)
@@ -356,24 +394,34 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(ad.number, 1)
self.assertEqual(ad.debug_tag, 'my_tag')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
- def test_AndroidDevice_load_config_dup(self, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_load_config_dup(
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
config = {'serial': 'new_serial'}
ad = android_device.AndroidDevice(serial=mock_serial)
- with self.assertRaisesRegex(android_device.DeviceError,
- 'Attribute serial already exists with'):
+ with self.assertRaisesRegex(
+ android_device.DeviceError, 'Attribute serial already exists with'
+ ):
ad.load_config(config)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_build_info(self, MockFastboot, MockAdbProxy):
"""Verifies the AndroidDevice object's basic attributes are correctly
set after instantiation.
@@ -382,8 +430,10 @@ class AndroidDeviceTest(unittest.TestCase):
build_info = ad.build_info
self.assertEqual(build_info['build_id'], 'AB42')
self.assertEqual(build_info['build_type'], 'userdebug')
- self.assertEqual(build_info['build_fingerprint'],
- 'FakeModel:Dessert/AB42/1234567:userdebug/dev-keys')
+ self.assertEqual(
+ build_info['build_fingerprint'],
+ 'FakeModel:Dessert/AB42/1234567:userdebug/dev-keys',
+ )
self.assertEqual(build_info['build_version_codename'], 'Z')
self.assertEqual(build_info['build_version_incremental'], '1234567')
self.assertEqual(build_info['build_version_sdk'], '28')
@@ -394,17 +444,23 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(build_info['hardware'], 'marlin')
self.assertEqual(len(build_info), len(android_device.CACHED_SYSTEM_PROPS))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- '1',
- mock_properties={
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'userdebug',
- }))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ '1',
+ mock_properties={
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'userdebug',
+ },
+ ),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_build_info_with_minimal_properties(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
build_info = ad.build_info
self.assertEqual(build_info['build_id'], 'AB42')
@@ -419,10 +475,14 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(build_info['debuggable'], '')
self.assertEqual(build_info['hardware'], '')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_build_info_cached(self, MockFastboot, MockAdbProxy):
"""Verifies the AndroidDevice object's basic attributes are correctly
set after instantiation.
@@ -433,40 +493,80 @@ class AndroidDeviceTest(unittest.TestCase):
_ = ad.build_info
self.assertEqual(ad.adb.getprops_call_count, 1)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- '1',
- mock_properties={
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'userdebug',
- 'ro.debuggable': '1',
- }))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device.list_fastboot_devices',
+ return_value=mock.MagicMock(),
+ )
+ def test_AndroidDevice_model_property_is_cached(
+ self, mock_list_fastboot_devices, _
+ ):
+ """Accessing `model` a second time shouldn't invoke all the fastboot/adb
+ calls again.
+ """
+ mock_serial = 1
+ # mock returns '2' so the device is not considered in bootloader mode.
+ mock_list_fastboot_devices.return_value = ['2']
+ ad = android_device.AndroidDevice(serial=mock_serial)
+ ad.model
+ mock_count_first = mock_list_fastboot_devices.call_count
+ ad.model # access `model` again.
+ mock_count_second = mock_list_fastboot_devices.call_count
+ self.assertEqual(mock_count_first, mock_count_second)
+
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ '1',
+ mock_properties={
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'userdebug',
+ 'ro.debuggable': '1',
+ },
+ ),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_is_rootable_when_userdebug_device(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
self.assertTrue(ad.is_rootable)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- '1',
- mock_properties={
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'user',
- 'ro.debuggable': '0',
- }))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
- def test_AndroidDevice_is_rootable_when_user_device(self, MockFastboot,
- MockAdbProxy):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ '1',
+ mock_properties={
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'user',
+ 'ro.debuggable': '0',
+ },
+ ),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ def test_AndroidDevice_is_rootable_when_user_device(
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
self.assertFalse(ad.is_rootable)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_device_info(self, MockFastboot, MockAdbProxy):
ad = android_device.AndroidDevice(serial=1)
device_info = ad.device_info
@@ -480,237 +580,328 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(device_info['user_added_info']['sim_type'], 'Fi')
self.assertEqual(device_info['user_added_info']['build_id'], 'CD42')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_serial_is_valid(self, MockFastboot, MockAdbProxy):
- """Verifies that the serial is a primitive string type and serializable.
- """
+ """Verifies that the serial is a primitive string type and serializable."""
ad = android_device.AndroidDevice(serial=1)
self.assertTrue(isinstance(ad.serial, str))
yaml.safe_dump(ad.serial)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_is_emulator_when_realish_device(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
self.assertFalse(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('localhost:123'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('localhost:123'),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('localhost:123'))
+ return_value=mock_android_device.MockFastbootProxy('localhost:123'),
+ )
def test_AndroidDevice_is_emulator_when_local_networked_device(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
# Although these devices are usually emulators, there might be a reason
# to do this with a real device.
ad = android_device.AndroidDevice(serial='localhost:123')
self.assertFalse(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('example.com:123'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('example:123'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('example.com:123'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('example:123'),
+ )
def test_AndroidDevice_is_emulator_when_remote_networked_device(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='example.com:123')
self.assertFalse(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- 'localhost:5554',
- mock_properties={
- 'ro.hardware': 'ranchu',
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'userdebug',
- }))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ 'localhost:5554',
+ mock_properties={
+ 'ro.hardware': 'ranchu',
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'userdebug',
+ },
+ ),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('localhost:5554'))
- def test_AndroidDevice_is_emulator_when_ranchu_device(self, MockFastboot,
- MockAdbProxy):
+ return_value=mock_android_device.MockFastbootProxy('localhost:5554'),
+ )
+ def test_AndroidDevice_is_emulator_when_ranchu_device(
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='localhost:5554')
self.assertTrue(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- '1',
- mock_properties={
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'userdebug',
- 'ro.hardware': 'goldfish',
- }))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ '1',
+ mock_properties={
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'userdebug',
+ 'ro.hardware': 'goldfish',
+ },
+ ),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_is_emulator_when_goldfish_device(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
self.assertTrue(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- 'example.com:123',
- mock_properties={
- 'ro.build.id': 'AB42',
- 'ro.build.type': 'userdebug',
- 'ro.build.characteristics': 'emulator',
- }))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(
+ 'example.com:123',
+ mock_properties={
+ 'ro.build.id': 'AB42',
+ 'ro.build.type': 'userdebug',
+ 'ro.build.characteristics': 'emulator',
+ },
+ ),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('example.com:123'))
+ return_value=mock_android_device.MockFastbootProxy('example.com:123'),
+ )
def test_AndroidDevice_is_emulator_when_emulator_characteristic(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='example.com:123')
self.assertTrue(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('emulator-5554'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('emulator-5554'),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('emulator-5554'))
+ return_value=mock_android_device.MockFastbootProxy('emulator-5554'),
+ )
def test_AndroidDevice_is_emulator_when_emulator_serial(
- self, MockFastboot, MockAdbProxy):
+ self, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='emulator-5554')
self.assertTrue(ad.is_emulator)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
- @mock.patch('mobly.controllers.android_device.list_fastboot_devices',
- return_value='1')
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device.list_fastboot_devices', return_value='1'
+ )
def test_AndroidDevice_is_fastboot(self, _, MockFastboot, MockAdbProxy):
ad = android_device.AndroidDevice(serial='1')
self.assertTrue(ad.is_bootloader)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
- def test_AndroidDevice_generate_filename_default(self,
- get_log_file_timestamp_mock,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_generate_filename_default(
+ self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy
+ ):
mock_serial = 1
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
filename = ad.generate_filename('MagicLog')
self.assertEqual(filename, 'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
@mock.patch('mobly.logger.sanitize_filename')
def test_AndroidDevice_generate_filename_assert_sanitation(
- self, sanitize_filename_mock, get_log_file_timestamp_mock, MockFastboot,
- MockAdbProxy):
+ self,
+ sanitize_filename_mock,
+ get_log_file_timestamp_mock,
+ MockFastboot,
+ MockAdbProxy,
+ ):
mock_serial = 1
sanitize_filename_mock.return_value = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
filename = ad.generate_filename('MagicLog')
sanitize_filename_mock.assert_called_with(
- 'MagicLog,1,fakemodel,07-22-2019_17-53-34-450')
+ 'MagicLog,1,fakemodel,07-22-2019_17-53-34-450'
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
- def test_AndroidDevice_generate_filename_with_ext(self,
- get_log_file_timestamp_mock,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_generate_filename_with_ext(
+ self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy
+ ):
mock_serial = 1
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
filename = ad.generate_filename('MagicLog', extension_name='log')
- self.assertEqual(filename,
- 'MagicLog,1,fakemodel,07-22-2019_17-53-34-450.log')
+ self.assertEqual(
+ filename, 'MagicLog,1,fakemodel,07-22-2019_17-53-34-450.log'
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_generate_filename_with_debug_tag(
- self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+ self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy
+ ):
mock_serial = 1
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
ad.debug_tag = 'RoleX'
filename = ad.generate_filename('MagicLog')
- self.assertEqual(filename,
- 'MagicLog,RoleX,1,fakemodel,07-22-2019_17-53-34-450')
+ self.assertEqual(
+ filename, 'MagicLog,RoleX,1,fakemodel,07-22-2019_17-53-34-450'
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_generate_filename_with_runtime_info(
- self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+ self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy
+ ):
mock_serial = 1
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
- mock_record = mock.MagicMock(test_name='test_xyz',
- begin_time='1234567',
- signature='test_xyz-1234567')
- mock_test_info = runtime_test_info.RuntimeTestInfo(mock_record.test_name,
- '/tmp/blah/',
- mock_record)
+ mock_record = mock.MagicMock(
+ test_name='test_xyz', begin_time='1234567', signature='test_xyz-1234567'
+ )
+ mock_test_info = runtime_test_info.RuntimeTestInfo(
+ mock_record.test_name, '/tmp/blah/', mock_record
+ )
filename = ad.generate_filename('MagicLog', time_identifier=mock_test_info)
self.assertEqual(filename, 'MagicLog,1,fakemodel,test_xyz-1234567')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_generate_filename_with_custom_timestamp(
- self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy):
+ self, get_log_file_timestamp_mock, MockFastboot, MockAdbProxy
+ ):
mock_serial = 1
ad = android_device.AndroidDevice(serial=mock_serial)
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
- filename = ad.generate_filename('MagicLog',
- time_identifier='my_special_time')
+ filename = ad.generate_filename(
+ 'MagicLog', time_identifier='my_special_time'
+ )
self.assertEqual(filename, 'MagicLog,1,fakemodel,my_special_time')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
- def test_AndroidDevice_take_bug_report(self, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_take_bug_report(
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
"""Verifies AndroidDevice.take_bug_report calls the correct adb command
and writes the bugreport file to the correct path.
"""
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
- output_path = ad.take_bug_report(test_name='test_something',
- begin_time='sometime')
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ output_path = ad.take_bug_report(
+ test_name='test_something', begin_time='sometime'
+ )
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
- os.path.join(expected_path,
- 'bugreport,test_something,1,fakemodel,sometime.zip'))
+ os.path.join(
+ expected_path, 'bugreport,test_something,1,fakemodel,sometime.zip'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1', fail_br=True))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1', fail_br=True),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
- def test_AndroidDevice_take_bug_report_fail(self, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ def test_AndroidDevice_take_bug_report_fail(
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
"""Verifies AndroidDevice.take_bug_report writes out the correct message
when taking bugreport fails.
"""
@@ -720,170 +911,247 @@ class AndroidDeviceTest(unittest.TestCase):
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.take_bug_report(test_name='test_something', begin_time='sometime')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_take_bug_report_without_args(
- self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ get_log_file_timestamp_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
output_path = ad.take_bug_report()
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
self.assertEqual(
output_path,
- os.path.join(expected_path,
- 'bugreport,1,fakemodel,07-22-2019_17-53-34-450.zip'))
+ os.path.join(
+ expected_path, 'bugreport,1,fakemodel,07-22-2019_17-53-34-450.zip'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_take_bug_report_with_only_test_name(
- self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ get_log_file_timestamp_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
output_path = ad.take_bug_report(test_name='test_something')
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
os.path.join(
expected_path,
- 'bugreport,test_something,1,fakemodel,07-22-2019_17-53-34-450.zip'))
+ 'bugreport,test_something,1,fakemodel,07-22-2019_17-53-34-450.zip',
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
def test_AndroidDevice_take_bug_report_with_only_begin_time(
- self, create_dir_mock, FastbootProxy, MockAdbProxy):
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
output_path = ad.take_bug_report(begin_time='sometime')
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
- os.path.join(expected_path, 'bugreport,1,fakemodel,sometime.zip'))
+ os.path.join(expected_path, 'bugreport,1,fakemodel,sometime.zip'),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
def test_AndroidDevice_take_bug_report_with_int_begin_time(
- self, create_dir_mock, FastbootProxy, MockAdbProxy):
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
output_path = ad.take_bug_report(begin_time=123)
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
- output_path, os.path.join(expected_path,
- 'bugreport,1,fakemodel,123.zip'))
+ output_path,
+ os.path.join(expected_path, 'bugreport,1,fakemodel,123.zip'),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
@mock.patch('mobly.utils.create_dir')
def test_AndroidDevice_take_bug_report_with_positional_args(
- self, create_dir_mock, FastbootProxy, MockAdbProxy):
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
output_path = ad.take_bug_report('test_something', 'sometime')
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
- os.path.join(expected_path,
- 'bugreport,test_something,1,fakemodel,sometime.zip'))
+ os.path.join(
+ expected_path, 'bugreport,test_something,1,fakemodel,sometime.zip'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
def test_AndroidDevice_take_bug_report_with_destination(
- self, create_dir_mock, FastbootProxy, MockAdbProxy):
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
dest = tempfile.gettempdir()
- output_path = ad.take_bug_report(test_name="test_something",
- begin_time="sometime",
- destination=dest)
+ output_path = ad.take_bug_report(
+ test_name='test_something', begin_time='sometime', destination=dest
+ )
expected_path = os.path.join(dest)
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
- os.path.join(expected_path,
- 'bugreport,test_something,1,fakemodel,sometime.zip'))
-
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(
- '1', fail_br_before_N=True))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ os.path.join(
+ expected_path, 'bugreport,test_something,1,fakemodel,sometime.zip'
+ ),
+ )
+
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1', fail_br_before_N=True),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
- def test_AndroidDevice_take_bug_report_fallback(self, create_dir_mock,
- FastbootProxy, MockAdbProxy):
+ def test_AndroidDevice_take_bug_report_fallback(
+ self, create_dir_mock, FastbootProxy, MockAdbProxy
+ ):
"""Verifies AndroidDevice.take_bug_report falls back to traditional
bugreport on builds that do not have bugreportz.
"""
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
- output_path = ad.take_bug_report(test_name='test_something',
- begin_time='sometime')
- expected_path = os.path.join(logging.log_path,
- 'AndroidDevice%s' % ad.serial, 'BugReports')
+ output_path = ad.take_bug_report(
+ test_name='test_something', begin_time='sometime'
+ )
+ expected_path = os.path.join(
+ logging.log_path, 'AndroidDevice%s' % ad.serial, 'BugReports'
+ )
create_dir_mock.assert_called_with(expected_path)
self.assertEqual(
output_path,
- os.path.join(expected_path,
- 'bugreport,test_something,1,fakemodel,sometime.txt'))
+ os.path.join(
+ expected_path, 'bugreport,test_something,1,fakemodel,sometime.txt'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.logger.get_log_file_timestamp')
- def test_AndroidDevice_take_screenshot(self, get_log_file_timestamp_mock,
- create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_take_screenshot(
+ self,
+ get_log_file_timestamp_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
full_pic_path = ad.take_screenshot(self.tmp_dir)
self.assertEqual(
full_pic_path,
- os.path.join(self.tmp_dir,
- 'screenshot,1,fakemodel,07-22-2019_17-53-34-450.png'))
+ os.path.join(
+ self.tmp_dir, 'screenshot,1,fakemodel,07-22-2019_17-53-34-450.png'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.logger.get_log_file_timestamp')
def test_AndroidDevice_take_screenshot_with_prefix(
- self, get_log_file_timestamp_mock, create_dir_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ get_log_file_timestamp_mock,
+ create_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
get_log_file_timestamp_mock.return_value = '07-22-2019_17-53-34-450'
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
@@ -892,17 +1160,24 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(
full_pic_path,
- os.path.join(self.tmp_dir,
- 'page_a,1,fakemodel,07-22-2019_17-53-34-450.png'))
+ os.path.join(
+ self.tmp_dir, 'page_a,1,fakemodel,07-22-2019_17-53-34-450.png'
+ ),
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_AndroidDevice_change_log_path(self, stop_proc_mock, start_proc_mock,
- FastbootProxy, MockAdbProxy):
+ def test_AndroidDevice_change_log_path(
+ self, stop_proc_mock, start_proc_mock, FastbootProxy, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
old_path = ad.log_path
new_log_path = tempfile.mkdtemp()
@@ -910,16 +1185,19 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertTrue(os.path.exists(new_log_path))
self.assertFalse(os.path.exists(old_path))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_AndroidDevice_change_log_path_no_log_exists(self, stop_proc_mock,
- start_proc_mock,
- FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_change_log_path_no_log_exists(
+ self, stop_proc_mock, start_proc_mock, FastbootProxy, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
old_path = ad.log_path
new_log_path = tempfile.mkdtemp()
@@ -927,30 +1205,44 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertTrue(os.path.exists(new_log_path))
self.assertFalse(os.path.exists(old_path))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('127.0.0.1:5557'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('127.0.0.1:5557'),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('127.0.0.1:5557'))
+ return_value=mock_android_device.MockFastbootProxy('127.0.0.1:5557'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
def test_AndroidDevice_with_reserved_character_in_serial_log_path(
- self, stop_proc_mock, start_proc_mock, FastbootProxy, MockAdbProxy):
+ self, stop_proc_mock, start_proc_mock, FastbootProxy, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='127.0.0.1:5557')
base_log_path = os.path.basename(ad.log_path)
self.assertEqual(base_log_path, 'AndroidDevice127.0.0.1-5557')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
def test_AndroidDevice_change_log_path_with_service(
- self, open_logcat_mock, stop_proc_mock, start_proc_mock, creat_dir_mock,
- FastbootProxy, MockAdbProxy):
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ creat_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.services.logcat.start()
new_log_path = tempfile.mkdtemp()
@@ -958,35 +1250,53 @@ class AndroidDeviceTest(unittest.TestCase):
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.log_path = new_log_path
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
def test_AndroidDevice_change_log_path_with_existing_file(
- self, stop_proc_mock, start_proc_mock, creat_dir_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ stop_proc_mock,
+ start_proc_mock,
+ creat_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
new_log_path = tempfile.mkdtemp()
new_file_path = os.path.join(new_log_path, 'file.txt')
with io.open(new_file_path, 'w', encoding='utf-8') as f:
- f.write(u'hahah.')
+ f.write('hahah.')
expected_msg = '.* Logs already exist .*'
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.log_path = new_log_path
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
- def test_AndroidDevice_update_serial(self, stop_proc_mock, start_proc_mock,
- creat_dir_mock, FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_update_serial(
+ self,
+ stop_proc_mock,
+ start_proc_mock,
+ creat_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.update_serial('2')
self.assertEqual(ad.serial, '2')
@@ -994,114 +1304,160 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(ad.adb.serial, ad.serial)
self.assertEqual(ad.fastboot.serial, ad.serial)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.create_dir')
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
def test_AndroidDevice_update_serial_with_service_running(
- self, open_logcat_mock, stop_proc_mock, start_proc_mock, creat_dir_mock,
- FastbootProxy, MockAdbProxy):
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ creat_dir_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.services.logcat.start()
- expected_msg = '.* Cannot change device serial number when there is service running.'
+ expected_msg = (
+ '.* Cannot change device serial number when there is service running.'
+ )
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.update_serial('2')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_load_snippet(self, MockGetPort, MockSnippetClient,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_load_snippet(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
self.assertTrue(hasattr(ad, 'snippet'))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_getattr(self, MockGetPort, MockSnippetClient,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_getattr(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
value = {'value': 42}
actual_value = getattr(ad, 'some_attr', value)
self.assertEqual(actual_value, value)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2',
- return_value=MockSnippetClient)
+ return_value=MockSnippetClient,
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_load_snippet_dup_package(self, MockGetPort,
- MockSnippetClient,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_load_snippet_dup_package(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
- expected_msg = ('Snippet package "%s" has already been loaded under '
- 'name "snippet".') % MOCK_SNIPPET_PACKAGE_NAME
+ expected_msg = (
+ 'Snippet package "%s" has already been loaded under name "snippet".'
+ ) % MOCK_SNIPPET_PACKAGE_NAME
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.load_snippet('snippet2', MOCK_SNIPPET_PACKAGE_NAME)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch(
'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2',
- return_value=MockSnippetClient)
+ return_value=MockSnippetClient,
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_load_snippet_dup_snippet_name(self, MockGetPort,
- MockSnippetClient,
- MockFastboot,
- MockAdbProxy):
+ def test_AndroidDevice_load_snippet_dup_snippet_name(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
- expected_msg = ('.* Attribute "snippet" already exists, please use a '
- 'different name.')
+ expected_msg = (
+ '.* Attribute "snippet" already exists, please use a different name.'
+ )
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME + 'haha')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
def test_AndroidDevice_load_snippet_dup_attribute_name(
- self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
- expected_msg = ('Attribute "%s" already exists, please use a different'
- ' name') % 'adb'
+ expected_msg = (
+ 'Attribute "%s" already exists, please use a different name'
+ ) % 'adb'
with self.assertRaisesRegex(android_device.Error, expected_msg):
ad.load_snippet('adb', MOCK_SNIPPET_PACKAGE_NAME)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_load_snippet_start_app_fails(self, MockGetPort,
- MockSnippetClient,
- MockFastboot,
- MockAdbProxy):
+ def test_AndroidDevice_load_snippet_start_app_fails(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
"""Verifies that the correct exception is raised if start app failed.
It's possible that the `stop` call as part of the start app failure
@@ -1117,15 +1473,21 @@ class AndroidDeviceTest(unittest.TestCase):
except Exception as e:
assertIs(e, expected_e)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
def test_AndroidDevice_load_snippet_with_snippet_config(
- self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy):
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
snippet_config = snippet_client_v2.Config()
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME, snippet_config)
@@ -1134,78 +1496,110 @@ class AndroidDeviceTest(unittest.TestCase):
package=mock.ANY, ad=mock.ANY, config=snippet_config
)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
- def test_AndroidDevice_unload_snippet(self, MockGetPort, MockSnippetClient,
- MockFastboot, MockAdbProxy):
+ def test_AndroidDevice_unload_snippet(
+ self, MockGetPort, MockSnippetClient, MockFastboot, MockAdbProxy
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
ad.unload_snippet('snippet')
self.assertFalse(hasattr(ad, 'snippet'))
with self.assertRaisesRegex(
android_device.SnippetError,
- '<AndroidDevice|1> No snippet registered with name "snippet"'):
+ '<AndroidDevice|1> No snippet registered with name "snippet"',
+ ):
ad.unload_snippet('snippet')
# Loading the same snippet again should succeed
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
self.assertTrue(hasattr(ad, 'snippet'))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
@mock.patch(
- 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2')
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.snippet_client_v2.SnippetClientV2'
+ )
@mock.patch('mobly.utils.get_available_host_port')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
- def test_AndroidDevice_snippet_cleanup(self, open_logcat_mock, MockGetPort,
- MockSnippetClient, MockFastboot,
- MockAdbProxy):
+ def test_AndroidDevice_snippet_cleanup(
+ self,
+ open_logcat_mock,
+ MockGetPort,
+ MockSnippetClient,
+ MockFastboot,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
ad.services.start_all()
ad.load_snippet('snippet', MOCK_SNIPPET_PACKAGE_NAME)
ad.unload_snippet('snippet')
self.assertFalse(hasattr(ad, 'snippet'))
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
def test_AndroidDevice_debug_tag(self, MockFastboot, MockAdbProxy):
mock_serial = '1'
ad = android_device.AndroidDevice(serial=mock_serial)
self.assertEqual(ad.debug_tag, '1')
- with self.assertRaisesRegex(android_device.DeviceError,
- r'<AndroidDevice\|1> Something'):
+ with self.assertRaisesRegex(
+ android_device.DeviceError, r'<AndroidDevice\|1> Something'
+ ):
raise android_device.DeviceError(ad, 'Something')
# Verify that debug tag's setter updates the debug prefix correctly.
ad.debug_tag = 'Mememe'
- with self.assertRaisesRegex(android_device.DeviceError,
- r'<AndroidDevice\|Mememe> Something'):
+ with self.assertRaisesRegex(
+ android_device.DeviceError, r'<AndroidDevice\|Mememe> Something'
+ ):
raise android_device.DeviceError(ad, 'Something')
# Verify that repr is changed correctly.
- with self.assertRaisesRegex(Exception,
- r'(<AndroidDevice\|Mememe>, \'Something\')'):
+ with self.assertRaisesRegex(
+ Exception, r'(<AndroidDevice\|Mememe>, \'Something\')'
+ ):
raise Exception(ad, 'Something')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
- def test_AndroidDevice_handle_usb_disconnect(self, open_logcat_mock,
- stop_proc_mock, start_proc_mock,
- FastbootProxy, MockAdbProxy):
-
+ def test_AndroidDevice_handle_usb_disconnect(
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
class MockService(base_service.BaseService):
def __init__(self, device, configs=None):
@@ -1241,17 +1635,25 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertTrue(ad.services.is_any_alive)
self.assertTrue(ad.services.mock_service.resume_called)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
- def test_AndroidDevice_handle_reboot(self, open_logcat_mock, stop_proc_mock,
- start_proc_mock, FastbootProxy,
- MockAdbProxy):
-
+ def test_AndroidDevice_handle_reboot(
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
class MockService(base_service.BaseService):
def __init__(self, device, configs=None):
@@ -1287,16 +1689,25 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertTrue(ad.services.is_any_alive)
self.assertFalse(ad.services.mock_service.resume_called)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
def test_AndroidDevice_handle_reboot_changes_build_info(
- self, open_logcat_mock, stop_proc_mock, start_proc_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
with ad.handle_reboot():
ad.adb.mock_properties['ro.build.type'] = 'user'
@@ -1306,16 +1717,25 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertFalse(ad.is_rootable)
self.assertEqual(ad.adb.getprops_call_count, 2)
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch('mobly.utils.start_standing_subprocess', return_value='process')
@mock.patch('mobly.utils.stop_standing_subprocess')
@mock.patch.object(logcat.Logcat, '_open_logcat_file')
def test_AndroidDevice_handle_reboot_changes_build_info_with_caching(
- self, open_logcat_mock, stop_proc_mock, start_proc_mock, FastbootProxy,
- MockAdbProxy):
+ self,
+ open_logcat_mock,
+ stop_proc_mock,
+ start_proc_mock,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1') # Call getprops 1.
rootable_states = [ad.is_rootable]
with ad.handle_reboot():
@@ -1328,25 +1748,37 @@ class AndroidDeviceTest(unittest.TestCase):
self.assertEqual(ad.adb.getprops_call_count, 4)
self.assertEqual(rootable_states, [True, True, False, False, False])
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch(
'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
side_effect=[
- False, False,
- adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
- timeout=5,
- serial=1), True
- ])
+ False,
+ False,
+ adb.AdbTimeoutError(
+ ['adb', 'shell', 'getprop sys.boot_completed'],
+ timeout=5,
+ serial=1,
+ ),
+ True,
+ ],
+ )
@mock.patch('time.sleep', return_value=None)
@mock.patch('time.time', side_effect=[0, 5, 10, 15, 20, 25, 30])
- def test_AndroidDevice_wait_for_completion_completed(self, MockTime,
- MockSleep,
- MockIsBootCompleted,
- FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_wait_for_completion_completed(
+ self,
+ MockTime,
+ MockSleep,
+ MockIsBootCompleted,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
raised = False
try:
@@ -1355,27 +1787,43 @@ class AndroidDeviceTest(unittest.TestCase):
raised = True
self.assertFalse(
raised,
- 'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.')
+ 'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.',
+ )
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy('1'))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy('1'))
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy('1'),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy('1'),
+ )
@mock.patch(
'mobly.controllers.android_device.AndroidDevice.is_boot_completed',
side_effect=[
- False, False,
- adb.AdbTimeoutError(['adb', 'shell', 'getprop sys.boot_completed'],
- timeout=5,
- serial=1), False, False, False, False
- ])
+ False,
+ False,
+ adb.AdbTimeoutError(
+ ['adb', 'shell', 'getprop sys.boot_completed'],
+ timeout=5,
+ serial=1,
+ ),
+ False,
+ False,
+ False,
+ False,
+ ],
+ )
@mock.patch('time.sleep', return_value=None)
@mock.patch('time.perf_counter', side_effect=[0, 5, 10, 15, 20, 25, 30])
- def test_AndroidDevice_wait_for_completion_never_boot(self, MockTime,
- MockSleep,
- MockIsBootCompleted,
- FastbootProxy,
- MockAdbProxy):
+ def test_AndroidDevice_wait_for_completion_never_boot(
+ self,
+ MockTime,
+ MockSleep,
+ MockIsBootCompleted,
+ FastbootProxy,
+ MockAdbProxy,
+ ):
ad = android_device.AndroidDevice(serial='1')
raised = False
try:
@@ -1385,7 +1833,8 @@ class AndroidDeviceTest(unittest.TestCase):
raised = True
self.assertFalse(
raised,
- 'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.')
+ 'adb.AdbError or adb.AdbTimeoutError exception raised but not handled.',
+ )
def test_AndroidDevice_parse_device_list_when_decode_error(self):
gbk_str = b'\xc4\xe3\xba\xc3'
diff --git a/tests/mobly/logger_test.py b/tests/mobly/logger_test.py
index e0ac14d..d975ac7 100755
--- a/tests/mobly/logger_test.py
+++ b/tests/mobly/logger_test.py
@@ -33,18 +33,19 @@ class LoggerTest(unittest.TestCase):
shutil.rmtree(self.log_dir)
def test_epoch_to_log_line_timestamp(self):
- actual_stamp = logger.epoch_to_log_line_timestamp(1469134262116,
- time_zone=pytz.utc)
- self.assertEqual("07-21 20:51:02.116", actual_stamp)
+ actual_stamp = logger.epoch_to_log_line_timestamp(
+ 1469134262116, time_zone=pytz.utc
+ )
+ self.assertEqual('07-21 20:51:02.116', actual_stamp)
def test_is_valid_logline_timestamp(self):
- self.assertTrue(logger.is_valid_logline_timestamp("06-21 17:44:42.336"))
+ self.assertTrue(logger.is_valid_logline_timestamp('06-21 17:44:42.336'))
def test_is_valid_logline_timestamp_when_wrong_length(self):
- self.assertFalse(logger.is_valid_logline_timestamp(" 06-21 17:44:42.336"))
+ self.assertFalse(logger.is_valid_logline_timestamp(' 06-21 17:44:42.336'))
def test_is_valid_logline_timestamp_when_invalid_content(self):
- self.assertFalse(logger.is_valid_logline_timestamp("------------------"))
+ self.assertFalse(logger.is_valid_logline_timestamp('------------------'))
@mock.patch('mobly.utils.create_alias')
def test_create_latest_log_alias(self, mock_create_alias):
@@ -53,24 +54,28 @@ class LoggerTest(unittest.TestCase):
@mock.patch('mobly.logger._setup_test_logger')
@mock.patch('mobly.logger.create_latest_log_alias')
- def test_setup_test_logger_creates_log_alias(self,
- mock_create_latest_log_alias,
- mock__setup_test_logger):
+ def test_setup_test_logger_creates_log_alias(
+ self, mock_create_latest_log_alias, mock__setup_test_logger
+ ):
logger.setup_test_logger(self.log_dir)
- mock__setup_test_logger.assert_called_once_with(self.log_dir, logging.INFO,
- None)
- mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
- alias='latest')
+ mock__setup_test_logger.assert_called_once_with(
+ self.log_dir, logging.INFO, None
+ )
+ mock_create_latest_log_alias.assert_called_once_with(
+ self.log_dir, alias='latest'
+ )
@mock.patch('mobly.logger._setup_test_logger')
@mock.patch('mobly.logger.create_latest_log_alias')
def test_setup_test_logger_creates_log_alias_with_custom_value(
- self, mock_create_latest_log_alias, mock__setup_test_logger):
+ self, mock_create_latest_log_alias, mock__setup_test_logger
+ ):
mock_alias = mock.MagicMock()
logger.setup_test_logger(self.log_dir, alias=mock_alias)
- mock_create_latest_log_alias.assert_called_once_with(self.log_dir,
- alias=mock_alias)
+ mock_create_latest_log_alias.assert_called_once_with(
+ self.log_dir, alias=mock_alias
+ )
def test_sanitize_filename_when_valid(self):
fake_filename = 'logcat.txt'
@@ -114,8 +119,9 @@ class LoggerTest(unittest.TestCase):
def test__sanitize_windows_filename_when_path_characters(self):
fake_filename = '/\\'
expected_filename = '__'
- self.assertEqual(logger._sanitize_windows_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger._sanitize_windows_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_specical_characters(self):
fake_filename = '<>:"|?*\x00'
@@ -129,8 +135,9 @@ class LoggerTest(unittest.TestCase):
('con.txt', 'mobly_con.txt'),
('connections.log', 'connections.log'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_prn(self):
for fake_filename, expected_filename in [
@@ -139,8 +146,9 @@ class LoggerTest(unittest.TestCase):
('prn.txt', 'mobly_prn.txt'),
('prnters.log', 'prnters.log'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_aux(self):
for fake_filename, expected_filename in [
@@ -149,8 +157,9 @@ class LoggerTest(unittest.TestCase):
('aux.txt', 'mobly_aux.txt'),
('auxiliaries.log', 'auxiliaries.log'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_nul(self):
for fake_filename, expected_filename in [
@@ -159,8 +168,9 @@ class LoggerTest(unittest.TestCase):
('nul.txt', 'mobly_nul.txt'),
('nullptrs.log', 'nullptrs.log'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_com(self):
for fake_filename, expected_filename in [
@@ -178,8 +188,9 @@ class LoggerTest(unittest.TestCase):
('com0.log', 'mobly_com0.log'),
('com0files.log', 'com0files.log'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_lpt(self):
for fake_filename, expected_filename in [
@@ -197,8 +208,9 @@ class LoggerTest(unittest.TestCase):
('lpt3.txt', 'mobly_lpt3.txt'),
('lpt3_file.txt', 'lpt3_file.txt'),
]:
- self.assertEqual(logger.sanitize_filename(fake_filename),
- expected_filename)
+ self.assertEqual(
+ logger.sanitize_filename(fake_filename), expected_filename
+ )
def test_sanitize_filename_when_ends_with_space(self):
fake_filename = 'logcat.txt '
@@ -217,8 +229,9 @@ class LoggerTest(unittest.TestCase):
adapted_logger = logger.PrefixLoggerAdapter(mock.Mock(), extra)
kwargs = mock.Mock()
- processed_log, processed_kwargs = adapted_logger.process('mock log line',
- kwargs=kwargs)
+ processed_log, processed_kwargs = adapted_logger.process(
+ 'mock log line', kwargs=kwargs
+ )
self.assertEqual(processed_log, '[MOCK_PREFIX] mock log line')
self.assertIs(processed_kwargs, kwargs)
@@ -231,12 +244,13 @@ class LoggerTest(unittest.TestCase):
adapted_logger.set_log_prefix('[NEW]')
kwargs = mock.Mock()
- processed_log, processed_kwargs = adapted_logger.process('mock log line',
- kwargs=kwargs)
+ processed_log, processed_kwargs = adapted_logger.process(
+ 'mock log line', kwargs=kwargs
+ )
self.assertEqual(processed_log, '[NEW] mock log line')
self.assertIs(processed_kwargs, kwargs)
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/output_test.py b/tests/mobly/output_test.py
index 4b2d94a..bbffa89 100755
--- a/tests/mobly/output_test.py
+++ b/tests/mobly/output_test.py
@@ -47,7 +47,7 @@ class OutputTest(unittest.TestCase):
self.base_mock_test_config.controller_configs = {}
self.base_mock_test_config.user_params = {
'icecream': 42,
- 'extra_param': 'haha'
+ 'extra_param': 'haha',
}
self.base_mock_test_config.log_path = self.tmp_dir
self.log_dir = self.base_mock_test_config.log_path
@@ -59,13 +59,10 @@ class OutputTest(unittest.TestCase):
def create_mock_test_config(self, base_mock_test_config):
mock_test_config = base_mock_test_config.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- my_config = [{
- 'serial': 'xxxx',
- 'magic': 'Magic1'
- }, {
- 'serial': 'xxxx',
- 'magic': 'Magic2'
- }]
+ my_config = [
+ {'serial': 'xxxx', 'magic': 'Magic1'},
+ {'serial': 'xxxx', 'magic': 'Magic2'},
+ ]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
return mock_test_config
@@ -76,8 +73,9 @@ class OutputTest(unittest.TestCase):
return (summary_file_path, debug_log_path, info_log_path)
def assert_output_logs_exist(self, output_dir):
- (summary_file_path, debug_log_path,
- info_log_path) = self.get_output_logs(output_dir)
+ (summary_file_path, debug_log_path, info_log_path) = self.get_output_logs(
+ output_dir
+ )
self.assertTrue(os.path.isfile(summary_file_path))
self.assertTrue(os.path.isfile(debug_log_path))
self.assertTrue(os.path.isfile(info_log_path))
@@ -96,8 +94,10 @@ class OutputTest(unittest.TestCase):
with tr.mobly_logger() as log_path:
self.assertEqual(log_path, logging.log_path)
- @unittest.skipIf(platform.system() == 'Windows',
- 'Symlinks are usually specific to Unix operating systems')
+ @unittest.skipIf(
+ platform.system() == 'Windows',
+ 'Symlinks are usually specific to Unix operating systems',
+ )
def test_symlink(self):
"""Verifies the symlink is created and links properly."""
mock_test_config = self.create_mock_test_config(self.base_mock_test_config)
@@ -107,12 +107,14 @@ class OutputTest(unittest.TestCase):
symlink = os.path.join(self.log_dir, self.testbed_name, 'latest')
self.assertEqual(os.readlink(symlink), logging.log_path)
- @unittest.skipIf(platform.system() != 'Windows',
- 'Shortcuts are specific to Windows operating systems')
+ @unittest.skipIf(
+ platform.system() != 'Windows',
+ 'Shortcuts are specific to Windows operating systems',
+ )
def test_shortcut(self):
"""Verifies the shortcut is created and links properly."""
shortcut_path = os.path.join(self.log_dir, self.testbed_name, 'latest.lnk')
- shell = client.Dispatch("WScript.Shell")
+ shell = client.Dispatch('WScript.Shell')
shortcut = shell.CreateShortCut(shortcut_path)
self.assertFalse(shortcut.Targetpath)
mock_test_config = self.create_mock_test_config(self.base_mock_test_config)
@@ -122,9 +124,11 @@ class OutputTest(unittest.TestCase):
shortcut = shell.CreateShortCut(shortcut_path)
# Normalize paths for case and truncation
normalized_shortcut_path = os.path.normcase(
- win32file.GetLongPathName(shortcut.Targetpath))
+ win32file.GetLongPathName(shortcut.Targetpath)
+ )
normalized_logger_path = os.path.normcase(
- win32file.GetLongPathName(logging.log_path))
+ win32file.GetLongPathName(logging.log_path)
+ )
self.assertEqual(normalized_shortcut_path, normalized_logger_path)
@mock.patch('mobly.utils.create_alias')
@@ -134,8 +138,9 @@ class OutputTest(unittest.TestCase):
with tr.mobly_logger():
pass
expected_alias_dir = os.path.join(self.log_dir, self.testbed_name, 'latest')
- mock_create_alias.assert_called_once_with(logging.log_path,
- expected_alias_dir)
+ mock_create_alias.assert_called_once_with(
+ logging.log_path, expected_alias_dir
+ )
@mock.patch('mobly.utils.create_alias')
def test_mobly_logger_with_custom_latest_log_alias(self, mock_create_alias):
@@ -143,14 +148,17 @@ class OutputTest(unittest.TestCase):
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger(alias='history'):
pass
- expected_alias_dir = os.path.join(self.log_dir, self.testbed_name,
- 'history')
- mock_create_alias.assert_called_once_with(logging.log_path,
- expected_alias_dir)
+ expected_alias_dir = os.path.join(
+ self.log_dir, self.testbed_name, 'history'
+ )
+ mock_create_alias.assert_called_once_with(
+ logging.log_path, expected_alias_dir
+ )
@mock.patch('mobly.utils.create_alias')
def test_mobly_logger_skips_latest_log_alias_when_none(
- self, mock_create_alias):
+ self, mock_create_alias
+ ):
mock_test_config = self.create_mock_test_config(self.base_mock_test_config)
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger(alias=None):
@@ -159,7 +167,8 @@ class OutputTest(unittest.TestCase):
@mock.patch('mobly.utils.create_alias')
def test_mobly_logger_skips_latest_log_alias_when_empty(
- self, mock_create_alias):
+ self, mock_create_alias
+ ):
mock_test_config = self.create_mock_test_config(self.base_mock_test_config)
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger(alias=''):
@@ -182,15 +191,17 @@ class OutputTest(unittest.TestCase):
tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
tr.run()
output_dir = logging.root_output_path
- (summary_file_path, debug_log_path,
- info_log_path) = self.assert_output_logs_exist(output_dir)
+ (summary_file_path, debug_log_path, info_log_path) = (
+ self.assert_output_logs_exist(output_dir)
+ )
self.assert_log_contents(debug_log_path, whitelist=[debug_uuid, info_uuid])
- self.assert_log_contents(info_log_path,
- whitelist=[info_uuid],
- blacklist=[debug_uuid])
+ self.assert_log_contents(
+ info_log_path, whitelist=[info_uuid], blacklist=[debug_uuid]
+ )
- @mock.patch('mobly.logger.get_log_file_timestamp',
- side_effect=str(time.time()))
+ @mock.patch(
+ 'mobly.logger.get_log_file_timestamp', side_effect=str(time.time())
+ )
def test_run_twice_for_two_sets_of_logs(self, mock_timestamp):
"""Verifies the expected output files from a test run.
@@ -210,8 +221,9 @@ class OutputTest(unittest.TestCase):
self.assert_output_logs_exist(output_dir1)
self.assert_output_logs_exist(output_dir2)
- @mock.patch('mobly.logger.get_log_file_timestamp',
- side_effect=str(time.time()))
+ @mock.patch(
+ 'mobly.logger.get_log_file_timestamp', side_effect=str(time.time())
+ )
def test_teardown_erases_logs(self, mock_timestamp):
"""Verifies the expected output files from a test run.
@@ -237,17 +249,23 @@ class OutputTest(unittest.TestCase):
self.assertNotEqual(output_dir1, output_dir2)
- (summary_file_path1, debug_log_path1,
- info_log_path1) = self.get_output_logs(output_dir1)
- (summary_file_path2, debug_log_path2,
- info_log_path2) = self.get_output_logs(output_dir2)
-
- self.assert_log_contents(debug_log_path1,
- whitelist=[debug_uuid1, info_uuid1],
- blacklist=[info_uuid2, debug_uuid2])
- self.assert_log_contents(debug_log_path2,
- whitelist=[debug_uuid2, info_uuid2],
- blacklist=[info_uuid1, debug_uuid1])
+ (summary_file_path1, debug_log_path1, info_log_path1) = (
+ self.get_output_logs(output_dir1)
+ )
+ (summary_file_path2, debug_log_path2, info_log_path2) = (
+ self.get_output_logs(output_dir2)
+ )
+
+ self.assert_log_contents(
+ debug_log_path1,
+ whitelist=[debug_uuid1, info_uuid1],
+ blacklist=[info_uuid2, debug_uuid2],
+ )
+ self.assert_log_contents(
+ debug_log_path2,
+ whitelist=[debug_uuid2, info_uuid2],
+ blacklist=[info_uuid1, debug_uuid1],
+ )
def test_basic_output(self):
"""Verifies the expected output files from a test run.
@@ -260,22 +278,24 @@ class OutputTest(unittest.TestCase):
with tr.mobly_logger():
tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
tr.run()
- expected_class_path = os.path.join(logging.root_output_path,
- 'IntegrationTest')
+ expected_class_path = os.path.join(
+ logging.root_output_path, 'IntegrationTest'
+ )
self.assertEqual(expected_class_path, logging.log_path)
os.path.exists(logging.log_path)
output_dir = logging.root_output_path
- (summary_file_path, debug_log_path,
- info_log_path) = self.assert_output_logs_exist(output_dir)
+ (summary_file_path, debug_log_path, info_log_path) = (
+ self.assert_output_logs_exist(output_dir)
+ )
summary_entries = []
with io.open(summary_file_path, 'r', encoding='utf-8') as f:
for entry in yaml.safe_load_all(f):
self.assertTrue(entry['Type'])
summary_entries.append(entry)
self.assert_log_contents(debug_log_path, whitelist=['DEBUG', 'INFO'])
- self.assert_log_contents(info_log_path,
- whitelist=['INFO'],
- blacklist=['DEBUG'])
+ self.assert_log_contents(
+ info_log_path, whitelist=['INFO'], blacklist=['DEBUG']
+ )
def test_teardown_class_output(self):
"""Verifies the summary file includes the failure record for
@@ -284,8 +304,9 @@ class OutputTest(unittest.TestCase):
mock_test_config = self.base_mock_test_config.copy()
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger():
- tr.add_test_class(mock_test_config,
- teardown_class_failure_test.TearDownClassFailureTest)
+ tr.add_test_class(
+ mock_test_config, teardown_class_failure_test.TearDownClassFailureTest
+ )
tr.run()
output_dir = logging.root_output_path
summary_file_path = os.path.join(output_dir, records.OUTPUT_FILE_SUMMARY)
@@ -294,14 +315,18 @@ class OutputTest(unittest.TestCase):
raw_content = f.read()
f.seek(0)
for entry in yaml.safe_load_all(f):
- if (entry['Type'] == 'Record' and
- entry[records.TestResultEnums.RECORD_NAME] == 'teardown_class'):
+ if (
+ entry['Type'] == 'Record'
+ and entry[records.TestResultEnums.RECORD_NAME] == 'teardown_class'
+ ):
found = True
break
self.assertTrue(
- found, 'No record for teardown_class found in the output file:\n %s' %
- raw_content)
+ found,
+ 'No record for teardown_class found in the output file:\n %s'
+ % raw_content,
+ )
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/records_test.py b/tests/mobly/records_test.py
index ec6254d..5c1d027 100755
--- a/tests/mobly/records_test.py
+++ b/tests/mobly/records_test.py
@@ -50,8 +50,7 @@ class RecordTestRecursiveError(Exception):
class RecordsTest(unittest.TestCase):
- """This test class tests the implementation of classes in mobly.records.
- """
+ """This test class tests the implementation of classes in mobly.records."""
def setUp(self):
self.tn = 'test_name'
@@ -63,13 +62,15 @@ class RecordsTest(unittest.TestCase):
def tearDown(self):
shutil.rmtree(self.tmp_path)
- def verify_record(self,
- record,
- result,
- details,
- extras,
- termination_signal_type=None,
- stacktrace=None):
+ def verify_record(
+ self,
+ record,
+ result,
+ details,
+ extras,
+ termination_signal_type=None,
+ stacktrace=None,
+ ):
record.update_record()
# Verify each field.
self.assertEqual(record.test_name, self.tn)
@@ -86,15 +87,18 @@ class RecordsTest(unittest.TestCase):
d[records.TestResultEnums.RECORD_NAME] = self.tn
d[records.TestResultEnums.RECORD_RESULT] = result
d[records.TestResultEnums.RECORD_DETAILS] = details
- d[records.TestResultEnums.
- RECORD_TERMINATION_SIGNAL_TYPE] = termination_signal_type
+ d[records.TestResultEnums.RECORD_TERMINATION_SIGNAL_TYPE] = (
+ termination_signal_type
+ )
d[records.TestResultEnums.RECORD_EXTRAS] = extras
d[records.TestResultEnums.RECORD_BEGIN_TIME] = record.begin_time
d[records.TestResultEnums.RECORD_END_TIME] = record.end_time
- d[records.TestResultEnums.
- RECORD_SIGNATURE] = f'{self.tn}-{record.begin_time}'
+ d[records.TestResultEnums.RECORD_SIGNATURE] = (
+ f'{self.tn}-{record.begin_time}'
+ )
d[records.TestResultEnums.RECORD_UID] = None
d[records.TestResultEnums.RECORD_RETRY_PARENT] = None
+ d[records.TestResultEnums.RECORD_PARENT] = None
d[records.TestResultEnums.RECORD_CLASS] = None
d[records.TestResultEnums.RECORD_EXTRA_ERRORS] = {}
d[records.TestResultEnums.RECORD_STACKTRACE] = stacktrace
@@ -114,42 +118,50 @@ class RecordsTest(unittest.TestCase):
record = records.TestResultRecord(self.tn)
record.test_begin()
record.test_pass()
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_PASS,
- details=None,
- extras=None)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_PASS,
+ details=None,
+ extras=None,
+ )
def test_result_record_explicit_pass_with_float_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestPass(self.details, self.float_extra)
record.test_pass(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_PASS,
- details=self.details,
- termination_signal_type='TestPass',
- extras=self.float_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_PASS,
+ details=self.details,
+ termination_signal_type='TestPass',
+ extras=self.float_extra,
+ )
def test_result_record_explicit_pass_with_json_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestPass(self.details, self.json_extra)
record.test_pass(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_PASS,
- details=self.details,
- termination_signal_type='TestPass',
- extras=self.json_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_PASS,
+ details=self.details,
+ termination_signal_type='TestPass',
+ extras=self.json_extra,
+ )
def test_result_record_fail_none(self):
"""Verifies that `test_fail` can be called without an error object."""
record = records.TestResultRecord(self.tn)
record.test_begin()
record.test_fail()
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details=None,
- extras=None)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details=None,
+ extras=None,
+ )
def test_result_record_fail_stacktrace(self):
record = records.TestResultRecord(self.tn)
@@ -161,91 +173,109 @@ class RecordsTest(unittest.TestCase):
# Verify stacktrace separately if we expect a non-None value.
# Because stacktrace includes file names and line numbers, we can't do
# a simple equality check.
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details='Something failed.',
- termination_signal_type='Exception',
- extras=None,
- stacktrace='in test_result_record_fail_stacktrace\n '
- 'raise Exception(\'Something failed.\')\nException: '
- 'Something failed.\n')
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details='Something failed.',
+ termination_signal_type='Exception',
+ extras=None,
+ stacktrace=(
+ 'in test_result_record_fail_stacktrace\n '
+ "raise Exception('Something failed.')\nException: "
+ 'Something failed.\n'
+ ),
+ )
def test_result_record_fail_with_float_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestFailure(self.details, self.float_extra)
record.test_fail(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details=self.details,
- termination_signal_type='TestFailure',
- extras=self.float_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details=self.details,
+ termination_signal_type='TestFailure',
+ extras=self.float_extra,
+ )
def test_result_record_fail_with_unicode_test_signal(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
- details = u'\u2022'
+ details = '\u2022'
s = signals.TestFailure(details, self.float_extra)
record.test_fail(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details=details,
- termination_signal_type='TestFailure',
- extras=self.float_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details=details,
+ termination_signal_type='TestFailure',
+ extras=self.float_extra,
+ )
def test_result_record_fail_with_unicode_exception(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
- details = u'\u2022'
+ details = '\u2022'
s = Exception(details)
record.test_fail(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details=details,
- termination_signal_type='Exception',
- extras=None)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details=details,
+ termination_signal_type='Exception',
+ extras=None,
+ )
def test_result_record_fail_with_json_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestFailure(self.details, self.json_extra)
record.test_fail(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_FAIL,
- details=self.details,
- termination_signal_type='TestFailure',
- extras=self.json_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_FAIL,
+ details=self.details,
+ termination_signal_type='TestFailure',
+ extras=self.json_extra,
+ )
def test_result_record_skip_none(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
record.test_skip()
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_SKIP,
- details=None,
- extras=None)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_SKIP,
+ details=None,
+ extras=None,
+ )
def test_result_record_skip_with_float_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestSkip(self.details, self.float_extra)
record.test_skip(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_SKIP,
- details=self.details,
- termination_signal_type='TestSkip',
- extras=self.float_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_SKIP,
+ details=self.details,
+ termination_signal_type='TestSkip',
+ extras=self.float_extra,
+ )
def test_result_record_skip_with_json_extra(self):
record = records.TestResultRecord(self.tn)
record.test_begin()
s = signals.TestSkip(self.details, self.json_extra)
record.test_skip(s)
- self.verify_record(record=record,
- result=records.TestResultEnums.TEST_RESULT_SKIP,
- details=self.details,
- termination_signal_type='TestSkip',
- extras=self.json_extra)
+ self.verify_record(
+ record=record,
+ result=records.TestResultEnums.TEST_RESULT_SKIP,
+ details=self.details,
+ termination_signal_type='TestSkip',
+ extras=self.json_extra,
+ )
def test_result_add_operator_success(self):
record1 = records.TestResultRecord(self.tn)
@@ -254,8 +284,9 @@ class RecordsTest(unittest.TestCase):
record1.test_pass(s)
tr1 = records.TestResult()
tr1.add_record(record1)
- controller_info = records.ControllerInfoRecord('SomeClass', 'MockDevice',
- ['magicA', 'magicB'])
+ controller_info = records.ControllerInfoRecord(
+ 'SomeClass', 'MockDevice', ['magicA', 'magicB']
+ )
tr1.add_controller_info_record(controller_info)
record2 = records.TestResultRecord(self.tn)
record2.test_begin()
@@ -263,8 +294,9 @@ class RecordsTest(unittest.TestCase):
record2.test_pass(s)
tr2 = records.TestResult()
tr2.add_record(record2)
- controller_info = records.ControllerInfoRecord('SomeClass', 'MockDevice',
- ['magicC'])
+ controller_info = records.ControllerInfoRecord(
+ 'SomeClass', 'MockDevice', ['magicC']
+ )
tr2.add_controller_info_record(controller_info)
tr2 += tr1
self.assertTrue(tr2.passed, [tr1, tr2])
@@ -348,6 +380,36 @@ class RecordsTest(unittest.TestCase):
utils.validate_test_result(tr)
self.assertFalse(tr.is_all_pass)
+ def test_is_all_pass_with_retry(self):
+ s = signals.TestFailure(self.details, self.float_extra)
+ record1 = records.TestResultRecord(self.tn)
+ record1.test_begin()
+ record1.test_fail(s)
+ record2 = records.TestResultRecord(self.tn)
+ record2.test_begin()
+ record2.test_pass()
+ record2.parent = (record1, records.TestParentType.RETRY)
+ tr = records.TestResult()
+ tr.add_record(record1)
+ tr.add_record(record2)
+ utils.validate_test_result(tr)
+ self.assertTrue(tr.is_all_pass)
+
+ def test_is_all_pass_with_repeat(self):
+ s = signals.TestFailure(self.details, self.float_extra)
+ record1 = records.TestResultRecord(self.tn)
+ record1.test_begin()
+ record1.test_fail(s)
+ record2 = records.TestResultRecord(self.tn)
+ record2.test_begin()
+ record2.test_pass()
+ record2.parent = (record1, records.TestParentType.REPEAT)
+ tr = records.TestResult()
+ tr.add_record(record1)
+ tr.add_record(record2)
+ utils.validate_test_result(tr)
+ self.assertFalse(tr.is_all_pass)
+
def test_is_all_pass_with_add_class_error(self):
"""Verifies that is_all_pass yields correct value when add_class_error is
used.
@@ -378,16 +440,19 @@ class RecordsTest(unittest.TestCase):
writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
with io.open(dump_path, 'r', encoding='utf-8') as f:
content = yaml.safe_load(f)
- self.assertEqual(content['Type'],
- records.TestSummaryEntryType.RECORD.value)
- self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
- self.details)
- self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
- self.float_extra)
+ self.assertEqual(
+ content['Type'], records.TestSummaryEntryType.RECORD.value
+ )
+ self.assertEqual(
+ content[records.TestResultEnums.RECORD_DETAILS], self.details
+ )
+ self.assertEqual(
+ content[records.TestResultEnums.RECORD_EXTRAS], self.float_extra
+ )
def test_summary_write_dump_with_unicode(self):
- unicode_details = u'\u901a' # utf-8 -> b'\xe9\x80\x9a'
- unicode_extras = u'\u8fc7' # utf-8 -> b'\xe8\xbf\x87'
+ unicode_details = '\u901a' # utf-8 -> b'\xe9\x80\x9a'
+ unicode_extras = '\u8fc7' # utf-8 -> b'\xe8\xbf\x87'
s = signals.TestFailure(unicode_details, unicode_extras)
record1 = records.TestResultRecord(self.tn)
record1.test_begin()
@@ -397,12 +462,15 @@ class RecordsTest(unittest.TestCase):
writer.dump(record1.to_dict(), records.TestSummaryEntryType.RECORD)
with io.open(dump_path, 'r', encoding='utf-8') as f:
content = yaml.safe_load(f)
- self.assertEqual(content['Type'],
- records.TestSummaryEntryType.RECORD.value)
- self.assertEqual(content[records.TestResultEnums.RECORD_DETAILS],
- unicode_details)
- self.assertEqual(content[records.TestResultEnums.RECORD_EXTRAS],
- unicode_extras)
+ self.assertEqual(
+ content['Type'], records.TestSummaryEntryType.RECORD.value
+ )
+ self.assertEqual(
+ content[records.TestResultEnums.RECORD_DETAILS], unicode_details
+ )
+ self.assertEqual(
+ content[records.TestResultEnums.RECORD_EXTRAS], unicode_extras
+ )
@mock.patch('mobly.utils.get_current_epoch_time')
def test_signature(self, mock_time_src):
@@ -424,8 +492,9 @@ class RecordsTest(unittest.TestCase):
for c in yaml.safe_load_all(f):
contents.append(c)
for content in contents:
- self.assertEqual(content['Type'],
- records.TestSummaryEntryType.USER_DATA.value)
+ self.assertEqual(
+ content['Type'], records.TestSummaryEntryType.USER_DATA.value
+ )
self.assertEqual(contents[0]['a'], user_data1['a'])
self.assertEqual(contents[1]['b'], user_data2['b'])
@@ -456,16 +525,17 @@ class RecordsTest(unittest.TestCase):
def test_add_controller_info_record(self):
tr = records.TestResult()
self.assertFalse(tr.controller_info)
- controller_info = records.ControllerInfoRecord('SomeClass', 'MockDevice',
- ['magicA', 'magicB'])
+ controller_info = records.ControllerInfoRecord(
+ 'SomeClass', 'MockDevice', ['magicA', 'magicB']
+ )
tr.add_controller_info_record(controller_info)
self.assertTrue(tr.controller_info[0])
self.assertEqual(tr.controller_info[0].controller_name, 'MockDevice')
- self.assertEqual(tr.controller_info[0].controller_info,
- ['magicA', 'magicB'])
+ self.assertEqual(
+ tr.controller_info[0].controller_info, ['magicA', 'magicB']
+ )
def test_uid(self):
-
@records.uid('some-uuid')
def test_uid_helper():
"""Dummy test used by `test_uid` for testing the uid decorator."""
diff --git a/tests/mobly/snippet/callback_event_test.py b/tests/mobly/snippet/callback_event_test.py
index 2593cc3..afd122d 100755
--- a/tests/mobly/snippet/callback_event_test.py
+++ b/tests/mobly/snippet/callback_event_test.py
@@ -28,12 +28,14 @@ class CallbackEventTest(unittest.TestCase):
def test_basic(self):
"""Verifies that an event object can be created and logged properly."""
- event = callback_event.CallbackEvent(MOCK_CALLBACK_ID, MOCK_EVENT_NAME,
- MOCK_CREATION_TIME, MOCK_DATA)
+ event = callback_event.CallbackEvent(
+ MOCK_CALLBACK_ID, MOCK_EVENT_NAME, MOCK_CREATION_TIME, MOCK_DATA
+ )
self.assertEqual(
repr(event),
- "CallbackEvent(callback_id: myCallbackId, name: onXyzEvent, "
- "creation_time: 12345678, data: {'foo': 'bar'})")
+ 'CallbackEvent(callback_id: myCallbackId, name: onXyzEvent, '
+ "creation_time: 12345678, data: {'foo': 'bar'})",
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/snippet/callback_handler_base_test.py b/tests/mobly/snippet/callback_handler_base_test.py
index 0891fd5..32199b2 100644
--- a/tests/mobly/snippet/callback_handler_base_test.py
+++ b/tests/mobly/snippet/callback_handler_base_test.py
@@ -28,25 +28,34 @@ MOCK_RAW_EVENT = {
'data': {
'exampleData': "Here's a simple event.",
'successful': True,
- 'secretNumber': 12
- }
+ 'secretNumber': 12,
+ },
}
class FakeCallbackHandler(callback_handler_base.CallbackHandlerBase):
"""Fake client class for unit tests."""
- def __init__(self,
- callback_id=None,
- event_client=None,
- ret_value=None,
- method_name=None,
- device=None,
- rpc_max_timeout_sec=120,
- default_timeout_sec=120):
+ def __init__(
+ self,
+ callback_id=None,
+ event_client=None,
+ ret_value=None,
+ method_name=None,
+ device=None,
+ rpc_max_timeout_sec=120,
+ default_timeout_sec=120,
+ ):
"""Initializes a fake callback handler object used for unit tests."""
- super().__init__(callback_id, event_client, ret_value, method_name, device,
- rpc_max_timeout_sec, default_timeout_sec)
+ super().__init__(
+ callback_id,
+ event_client,
+ ret_value,
+ method_name,
+ device,
+ rpc_max_timeout_sec,
+ default_timeout_sec,
+ )
self.mock_rpc_func = mock.Mock()
def callEventWaitAndGetRpc(self, *args, **kwargs):
@@ -66,15 +75,18 @@ class CallbackHandlerBaseTest(unittest.TestCase):
self.assertEqual(str(actual_event), str(expected_event))
def test_default_timeout_too_large(self):
- err_msg = ('The max timeout of a single RPC must be no smaller than '
- 'the default timeout of the callback handler. '
- 'Got rpc_max_timeout_sec=10, default_timeout_sec=20.')
+ err_msg = (
+ 'The max timeout of a single RPC must be no smaller than '
+ 'the default timeout of the callback handler. '
+ 'Got rpc_max_timeout_sec=10, default_timeout_sec=20.'
+ )
with self.assertRaisesRegex(ValueError, err_msg):
_ = FakeCallbackHandler(rpc_max_timeout_sec=10, default_timeout_sec=20)
def test_timeout_property(self):
- handler = FakeCallbackHandler(rpc_max_timeout_sec=20,
- default_timeout_sec=10)
+ handler = FakeCallbackHandler(
+ rpc_max_timeout_sec=20, default_timeout_sec=10
+ )
self.assertEqual(handler.rpc_max_timeout_sec, 20)
self.assertEqual(handler.default_timeout_sec, 10)
with self.assertRaises(AttributeError):
@@ -92,39 +104,48 @@ class CallbackHandlerBaseTest(unittest.TestCase):
def test_event_dict_to_snippet_event(self):
handler = FakeCallbackHandler(callback_id=MOCK_CALLBACK_ID)
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
event = handler.waitAndGet('ha', timeout=10)
self.assert_event_correct(event, MOCK_RAW_EVENT)
handler.mock_rpc_func.callEventWaitAndGetRpc.assert_called_once_with(
- MOCK_CALLBACK_ID, 'ha', 10)
+ MOCK_CALLBACK_ID, 'ha', 10
+ )
def test_wait_and_get_timeout_default(self):
handler = FakeCallbackHandler(rpc_max_timeout_sec=20, default_timeout_sec=5)
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
_ = handler.waitAndGet('ha')
handler.mock_rpc_func.callEventWaitAndGetRpc.assert_called_once_with(
- mock.ANY, mock.ANY, 5)
+ mock.ANY, mock.ANY, 5
+ )
def test_wait_and_get_timeout_ecxeed_threshold(self):
rpc_max_timeout_sec = 5
big_timeout_sec = 10
- handler = FakeCallbackHandler(rpc_max_timeout_sec=rpc_max_timeout_sec,
- default_timeout_sec=rpc_max_timeout_sec)
+ handler = FakeCallbackHandler(
+ rpc_max_timeout_sec=rpc_max_timeout_sec,
+ default_timeout_sec=rpc_max_timeout_sec,
+ )
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
expected_msg = (
f'Specified timeout {big_timeout_sec} is longer than max timeout '
- f'{rpc_max_timeout_sec}.')
+ f'{rpc_max_timeout_sec}.'
+ )
with self.assertRaisesRegex(errors.CallbackHandlerBaseError, expected_msg):
handler.waitAndGet('ha', big_timeout_sec)
def test_wait_for_event(self):
handler = FakeCallbackHandler()
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
def some_condition(event):
return event.data['successful']
@@ -135,48 +156,56 @@ class CallbackHandlerBaseTest(unittest.TestCase):
def test_wait_for_event_negative(self):
handler = FakeCallbackHandler()
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
expected_msg = (
'Timed out after 0.01s waiting for an "AsyncTaskResult" event that'
- ' satisfies the predicate "some_condition".')
+ ' satisfies the predicate "some_condition".'
+ )
def some_condition(_):
return False
- with self.assertRaisesRegex(errors.CallbackHandlerTimeoutError,
- expected_msg):
+ with self.assertRaisesRegex(
+ errors.CallbackHandlerTimeoutError, expected_msg
+ ):
handler.waitForEvent('AsyncTaskResult', some_condition, 0.01)
def test_wait_for_event_max_timeout(self):
"""waitForEvent should not raise the timeout exceed threshold error."""
rpc_max_timeout_sec = 5
big_timeout_sec = 10
- handler = FakeCallbackHandler(rpc_max_timeout_sec=rpc_max_timeout_sec,
- default_timeout_sec=rpc_max_timeout_sec)
+ handler = FakeCallbackHandler(
+ rpc_max_timeout_sec=rpc_max_timeout_sec,
+ default_timeout_sec=rpc_max_timeout_sec,
+ )
handler.mock_rpc_func.callEventWaitAndGetRpc = mock.Mock(
- return_value=MOCK_RAW_EVENT)
+ return_value=MOCK_RAW_EVENT
+ )
def some_condition(event):
return event.data['successful']
# This line should not raise.
- event = handler.waitForEvent('AsyncTaskResult',
- some_condition,
- timeout=big_timeout_sec)
+ event = handler.waitForEvent(
+ 'AsyncTaskResult', some_condition, timeout=big_timeout_sec
+ )
self.assert_event_correct(event, MOCK_RAW_EVENT)
def test_get_all(self):
handler = FakeCallbackHandler(callback_id=MOCK_CALLBACK_ID)
handler.mock_rpc_func.callEventGetAllRpc = mock.Mock(
- return_value=[MOCK_RAW_EVENT, MOCK_RAW_EVENT])
+ return_value=[MOCK_RAW_EVENT, MOCK_RAW_EVENT]
+ )
all_events = handler.getAll('ha')
for event in all_events:
self.assert_event_correct(event, MOCK_RAW_EVENT)
handler.mock_rpc_func.callEventGetAllRpc.assert_called_once_with(
- MOCK_CALLBACK_ID, 'ha')
+ MOCK_CALLBACK_ID, 'ha'
+ )
if __name__ == '__main__':
diff --git a/tests/mobly/snippet/client_base_test.py b/tests/mobly/snippet/client_base_test.py
index d9d99bd..57a3ed8 100755
--- a/tests/mobly/snippet/client_base_test.py
+++ b/tests/mobly/snippet/client_base_test.py
@@ -25,7 +25,8 @@ from mobly.snippet import errors
def _generate_fix_length_rpc_response(
response_length,
- template='{"id": 0, "result": "%s", "error": null, "callback": null}'):
+ template='{"id": 0, "result": "%s", "error": null, "callback": null}',
+):
"""Generates an RPC response string with specified length.
This function generates a random string and formats the template with the
@@ -46,9 +47,11 @@ def _generate_fix_length_rpc_response(
# '%s' in the template, of which the length is 2.
result_length = response_length - (len(template) - 2)
if result_length < 0:
- raise ValueError(f'The response_length should be no smaller than '
- f'template_length + 2. Got response_length '
- f'{response_length}, template_length {len(template)}.')
+ raise ValueError(
+ 'The response_length should be no smaller than '
+ 'template_length + 2. Got response_length '
+ f'{response_length}, template_length {len(template)}.'
+ )
chars = string.ascii_letters + string.digits
return template % ''.join(random.choice(chars) for _ in range(result_length))
@@ -102,8 +105,9 @@ class ClientBaseTest(unittest.TestCase):
@mock.patch.object(FakeClient, 'before_starting_server')
@mock.patch.object(FakeClient, 'start_server')
@mock.patch.object(FakeClient, '_make_connection')
- def test_init_server_stage_order(self, mock_make_conn_func, mock_start_func,
- mock_before_func):
+ def test_init_server_stage_order(
+ self, mock_make_conn_func, mock_start_func, mock_before_func
+ ):
"""Test that initialization runs its stages in expected order."""
order_manager = mock.Mock()
order_manager.attach_mock(mock_before_func, 'mock_before_func')
@@ -121,8 +125,9 @@ class ClientBaseTest(unittest.TestCase):
@mock.patch.object(FakeClient, 'stop')
@mock.patch.object(FakeClient, 'before_starting_server')
- def test_init_server_before_starting_server_fail(self, mock_before_func,
- mock_stop_func):
+ def test_init_server_before_starting_server_fail(
+ self, mock_before_func, mock_stop_func
+ ):
"""Test before_starting_server stage of initialization fails."""
mock_before_func.side_effect = Exception('ha')
@@ -142,8 +147,9 @@ class ClientBaseTest(unittest.TestCase):
@mock.patch.object(FakeClient, 'stop')
@mock.patch.object(FakeClient, '_make_connection')
- def test_init_server_make_connection_fail(self, mock_make_conn_func,
- mock_stop_func):
+ def test_init_server_make_connection_fail(
+ self, mock_make_conn_func, mock_stop_func
+ ):
"""Test _make_connection stage of initialization fails."""
mock_make_conn_func.side_effect = Exception('ha')
@@ -156,9 +162,14 @@ class ClientBaseTest(unittest.TestCase):
@mock.patch.object(FakeClient, 'send_rpc_request')
@mock.patch.object(FakeClient, '_decode_response_string_and_validate_format')
@mock.patch.object(FakeClient, '_handle_rpc_response')
- def test_rpc_stage_dependencies(self, mock_handle_resp, mock_decode_resp_str,
- mock_send_request, mock_gen_request,
- mock_precheck):
+ def test_rpc_stage_dependencies(
+ self,
+ mock_handle_resp,
+ mock_decode_resp_str,
+ mock_send_request,
+ mock_gen_request,
+ mock_precheck,
+ ):
"""Test the internal dependencies when sending an RPC.
When sending an RPC, it calls multiple functions in specific order, and
@@ -175,16 +186,19 @@ class ClientBaseTest(unittest.TestCase):
"""
self.client.initialize()
- expected_response_str = ('{"id": 0, "result": 123, "error": null, '
- '"callback": null}')
+ expected_response_str = (
+ '{"id": 0, "result": 123, "error": null, "callback": null}'
+ )
expected_response_dict = {
'id': 0,
'result': 123,
'error': None,
'callback': None,
}
- expected_request = ('{"id": 10, "method": "some_rpc", "params": [1, 2],'
- '"kwargs": {"test_key": 3}')
+ expected_request = (
+ '{"id": 10, "method": "some_rpc", "params": [1, 2],'
+ '"kwargs": {"test_key": 3}'
+ )
expected_result = 123
mock_gen_request.return_value = expected_request
@@ -205,9 +219,14 @@ class ClientBaseTest(unittest.TestCase):
@mock.patch.object(FakeClient, 'send_rpc_request')
@mock.patch.object(FakeClient, '_decode_response_string_and_validate_format')
@mock.patch.object(FakeClient, '_handle_rpc_response')
- def test_rpc_precheck_fail(self, mock_handle_resp, mock_decode_resp_str,
- mock_send_request, mock_gen_request,
- mock_precheck):
+ def test_rpc_precheck_fail(
+ self,
+ mock_handle_resp,
+ mock_decode_resp_str,
+ mock_send_request,
+ mock_gen_request,
+ mock_precheck,
+ ):
"""Test when RPC precheck fails it will skip sending the RPC."""
self.client.initialize()
mock_precheck.side_effect = Exception('server_died')
@@ -227,8 +246,10 @@ class ClientBaseTest(unittest.TestCase):
with all required fields.
"""
request = self.client._gen_rpc_request(0, 'test_rpc', 1, 2, test_key=3)
- expected_result = ('{"id": 0, "kwargs": {"test_key": 3}, '
- '"method": "test_rpc", "params": [1, 2]}')
+ expected_result = (
+ '{"id": 0, "kwargs": {"test_key": 3}, '
+ '"method": "test_rpc", "params": [1, 2]}'
+ )
self.assertEqual(request, expected_result)
def test_gen_request_without_kwargs(self):
@@ -243,43 +264,52 @@ class ClientBaseTest(unittest.TestCase):
def test_rpc_no_response(self):
"""Test parsing an empty RPC response."""
- with self.assertRaisesRegex(errors.ProtocolError,
- errors.ProtocolError.NO_RESPONSE_FROM_SERVER):
+ with self.assertRaisesRegex(
+ errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_SERVER
+ ):
self.client._decode_response_string_and_validate_format(0, '')
- with self.assertRaisesRegex(errors.ProtocolError,
- errors.ProtocolError.NO_RESPONSE_FROM_SERVER):
+ with self.assertRaisesRegex(
+ errors.ProtocolError, errors.ProtocolError.NO_RESPONSE_FROM_SERVER
+ ):
self.client._decode_response_string_and_validate_format(0, None)
def test_rpc_response_missing_fields(self):
"""Test parsing an RPC response that misses some required fields."""
mock_resp_without_id = '{"result": 123, "error": null, "callback": null}'
with self.assertRaisesRegex(
- errors.ProtocolError,
- errors.ProtocolError.RESPONSE_MISSING_FIELD % 'id'):
+ errors.ProtocolError, errors.ProtocolError.RESPONSE_MISSING_FIELD % 'id'
+ ):
self.client._decode_response_string_and_validate_format(
- 10, mock_resp_without_id)
+ 10, mock_resp_without_id
+ )
mock_resp_without_result = '{"id": 10, "error": null, "callback": null}'
with self.assertRaisesRegex(
errors.ProtocolError,
- errors.ProtocolError.RESPONSE_MISSING_FIELD % 'result'):
+ errors.ProtocolError.RESPONSE_MISSING_FIELD % 'result',
+ ):
self.client._decode_response_string_and_validate_format(
- 10, mock_resp_without_result)
+ 10, mock_resp_without_result
+ )
mock_resp_without_error = '{"id": 10, "result": 123, "callback": null}'
with self.assertRaisesRegex(
errors.ProtocolError,
- errors.ProtocolError.RESPONSE_MISSING_FIELD % 'error'):
+ errors.ProtocolError.RESPONSE_MISSING_FIELD % 'error',
+ ):
self.client._decode_response_string_and_validate_format(
- 10, mock_resp_without_error)
+ 10, mock_resp_without_error
+ )
mock_resp_without_callback = '{"id": 10, "result": 123, "error": null}'
with self.assertRaisesRegex(
errors.ProtocolError,
- errors.ProtocolError.RESPONSE_MISSING_FIELD % 'callback'):
+ errors.ProtocolError.RESPONSE_MISSING_FIELD % 'callback',
+ ):
self.client._decode_response_string_and_validate_format(
- 10, mock_resp_without_callback)
+ 10, mock_resp_without_callback
+ )
def test_rpc_response_error(self):
"""Test parsing an RPC response with a non-empty error field."""
@@ -299,15 +329,17 @@ class ClientBaseTest(unittest.TestCase):
'id': 10,
'result': 123,
'error': None,
- 'callback': '1-0'
+ 'callback': '1-0',
}
- with mock.patch.object(self.client,
- 'handle_callback') as mock_handle_callback:
+ with mock.patch.object(
+ self.client, 'handle_callback'
+ ) as mock_handle_callback:
expected_callback = mock.Mock()
mock_handle_callback.return_value = expected_callback
- rpc_result = self.client._handle_rpc_response('some_rpc',
- mock_resp_with_callback)
+ rpc_result = self.client._handle_rpc_response(
+ 'some_rpc', mock_resp_with_callback
+ )
mock_handle_callback.assert_called_with('1-0', 123, 'some_rpc')
# Ensure the RPC function returns what handle_callback returned
self.assertIs(expected_callback, rpc_result)
@@ -317,10 +349,11 @@ class ClientBaseTest(unittest.TestCase):
'id': 10,
'result': 123,
'error': None,
- 'callback': None
+ 'callback': None,
}
- with mock.patch.object(self.client,
- 'handle_callback') as mock_handle_callback:
+ with mock.patch.object(
+ self.client, 'handle_callback'
+ ) as mock_handle_callback:
self.client._handle_rpc_response('some_rpc', mock_resp_without_callback)
mock_handle_callback.assert_not_called()
@@ -330,8 +363,9 @@ class ClientBaseTest(unittest.TestCase):
wrong_id = 20
resp = f'{{"id": {right_id}, "result": 1, "error": null, "callback": null}}'
- with self.assertRaisesRegex(errors.ProtocolError,
- errors.ProtocolError.MISMATCHED_API_ID):
+ with self.assertRaisesRegex(
+ errors.ProtocolError, errors.ProtocolError.MISMATCHED_API_ID
+ ):
self.client._decode_response_string_and_validate_format(wrong_id, resp)
@mock.patch.object(FakeClient, 'send_rpc_request')
@@ -343,7 +377,8 @@ class ClientBaseTest(unittest.TestCase):
self.client.initialize()
resp = _generate_fix_length_rpc_response(
- client_base._MAX_RPC_RESP_LOGGING_LENGTH * 2)
+ client_base._MAX_RPC_RESP_LOGGING_LENGTH * 2
+ )
mock_send_request.return_value = resp
self.client.some_rpc(1, 2)
mock_log.debug.assert_called_with('Snippet received: %s', resp)
@@ -357,7 +392,8 @@ class ClientBaseTest(unittest.TestCase):
self.client.initialize()
resp = _generate_fix_length_rpc_response(
- int(client_base._MAX_RPC_RESP_LOGGING_LENGTH // 2))
+ int(client_base._MAX_RPC_RESP_LOGGING_LENGTH // 2)
+ )
mock_send_request.return_value = resp
self.client.some_rpc(1, 2)
mock_log.debug.assert_called_with('Snippet received: %s', resp)
@@ -371,7 +407,8 @@ class ClientBaseTest(unittest.TestCase):
self.client.initialize()
resp = _generate_fix_length_rpc_response(
- client_base._MAX_RPC_RESP_LOGGING_LENGTH)
+ client_base._MAX_RPC_RESP_LOGGING_LENGTH
+ )
mock_send_request.return_value = resp
self.client.some_rpc(1, 2)
mock_log.debug.assert_called_with('Snippet received: %s', resp)
@@ -390,8 +427,9 @@ class ClientBaseTest(unittest.TestCase):
self.client.some_rpc(1, 2)
mock_log.debug.assert_called_with(
'Snippet received: %s... %d chars are truncated',
- resp[:client_base._MAX_RPC_RESP_LOGGING_LENGTH],
- len(resp) - max_len)
+ resp[: client_base._MAX_RPC_RESP_LOGGING_LENGTH],
+ len(resp) - max_len,
+ )
@mock.patch.object(FakeClient, 'send_rpc_request')
def test_rpc_call_increment_counter(self, mock_send_request):
diff --git a/tests/mobly/suite_runner_test.py b/tests/mobly/suite_runner_test.py
index dabf74f..b1023e7 100755
--- a/tests/mobly/suite_runner_test.py
+++ b/tests/mobly/suite_runner_test.py
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-import inspect
import io
import os
import shutil
@@ -23,8 +22,6 @@ from unittest import mock
from mobly import base_suite
from mobly import base_test
-from mobly import config_parser
-from mobly import test_runner
from mobly import suite_runner
from tests.lib import integration2_test
from tests.lib import integration_test
@@ -43,53 +40,67 @@ class SuiteRunnerTest(unittest.TestCase):
shutil.rmtree(self.tmp_dir)
def test_select_no_args(self):
- identifiers = suite_runner.compute_selected_tests(test_classes=[
- integration_test.IntegrationTest, integration2_test.Integration2Test
- ],
- selected_tests=None)
+ identifiers = suite_runner.compute_selected_tests(
+ test_classes=[
+ integration_test.IntegrationTest,
+ integration2_test.Integration2Test,
+ ],
+ selected_tests=None,
+ )
self.assertEqual(
{
integration_test.IntegrationTest: None,
integration2_test.Integration2Test: None,
- }, identifiers)
+ },
+ identifiers,
+ )
def test_select_by_class(self):
identifiers = suite_runner.compute_selected_tests(
test_classes=[
- integration_test.IntegrationTest, integration2_test.Integration2Test
+ integration_test.IntegrationTest,
+ integration2_test.Integration2Test,
],
- selected_tests=['IntegrationTest'])
+ selected_tests=['IntegrationTest'],
+ )
self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
def test_select_by_method(self):
identifiers = suite_runner.compute_selected_tests(
test_classes=[
- integration_test.IntegrationTest, integration2_test.Integration2Test
+ integration_test.IntegrationTest,
+ integration2_test.Integration2Test,
],
- selected_tests=['IntegrationTest.test_a', 'IntegrationTest.test_b'])
- self.assertEqual({integration_test.IntegrationTest: ['test_a', 'test_b']},
- identifiers)
+ selected_tests=['IntegrationTest.test_a', 'IntegrationTest.test_b'],
+ )
+ self.assertEqual(
+ {integration_test.IntegrationTest: ['test_a', 'test_b']}, identifiers
+ )
def test_select_all_clobbers_method(self):
identifiers = suite_runner.compute_selected_tests(
test_classes=[
- integration_test.IntegrationTest, integration2_test.Integration2Test
+ integration_test.IntegrationTest,
+ integration2_test.Integration2Test,
],
- selected_tests=['IntegrationTest.test_a', 'IntegrationTest'])
+ selected_tests=['IntegrationTest.test_a', 'IntegrationTest'],
+ )
self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
identifiers = suite_runner.compute_selected_tests(
test_classes=[
- integration_test.IntegrationTest, integration2_test.Integration2Test
+ integration_test.IntegrationTest,
+ integration2_test.Integration2Test,
],
- selected_tests=['IntegrationTest', 'IntegrationTest.test_a'])
+ selected_tests=['IntegrationTest', 'IntegrationTest.test_a'],
+ )
self.assertEqual({integration_test.IntegrationTest: None}, identifiers)
@mock.patch('sys.exit')
def test_run_suite(self, mock_exit):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u"""
+ f.write("""
TestBeds:
# A test bed where adb will find Android devices.
- Name: SampleTestBed
@@ -99,23 +110,25 @@ class SuiteRunnerTest(unittest.TestCase):
icecream: 42
extra_param: 'haha'
""")
- suite_runner.run_suite([integration_test.IntegrationTest],
- argv=['-c', tmp_file_path])
+ suite_runner.run_suite(
+ [integration_test.IntegrationTest], argv=['-c', tmp_file_path]
+ )
mock_exit.assert_not_called()
@mock.patch('sys.exit')
def test_run_suite_with_failures(self, mock_exit):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u"""
+ f.write("""
TestBeds:
# A test bed where adb will find Android devices.
- Name: SampleTestBed
Controllers:
MagicDevice: '*'
""")
- suite_runner.run_suite([integration_test.IntegrationTest],
- argv=['-c', tmp_file_path])
+ suite_runner.run_suite(
+ [integration_test.IntegrationTest], argv=['-c', tmp_file_path]
+ )
mock_exit.assert_called_once_with(1)
@mock.patch('sys.exit')
@@ -138,7 +151,7 @@ class SuiteRunnerTest(unittest.TestCase):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u"""
+ f.write("""
TestBeds:
# A test bed where adb will find Android devices.
- Name: SampleTestBed
@@ -169,10 +182,9 @@ class SuiteRunnerTest(unittest.TestCase):
mock_cls_instance = mock.MagicMock()
mock_test_class.return_value = mock_cls_instance
suite_runner._print_test_names([mock_test_class])
- mock_cls_instance._pre_run.side_effect = Exception(
- 'Something went wrong.')
+ mock_cls_instance._pre_run.side_effect = Exception('Something went wrong.')
mock_cls_instance._clean_up.assert_called_once()
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/test_runner_test.py b/tests/mobly/test_runner_test.py
index 0343e0d..bd9a8fd 100755
--- a/tests/mobly/test_runner_test.py
+++ b/tests/mobly/test_runner_test.py
@@ -17,7 +17,6 @@ import logging
import os
import re
import shutil
-import sys
import tempfile
import unittest
from unittest import mock
@@ -26,7 +25,6 @@ from mobly import config_parser
from mobly import records
from mobly import signals
from mobly import test_runner
-from mobly import utils
from tests.lib import mock_android_device
from tests.lib import mock_controller
from tests.lib import integration_test
@@ -49,7 +47,7 @@ class TestRunnerTest(unittest.TestCase):
self.base_mock_test_config.controller_configs = {}
self.base_mock_test_config.user_params = {
'icecream': 42,
- 'extra_param': 'haha'
+ 'extra_param': 'haha',
}
self.base_mock_test_config.log_path = self.tmp_dir
self.log_dir = self.base_mock_test_config.log_path
@@ -59,11 +57,13 @@ class TestRunnerTest(unittest.TestCase):
shutil.rmtree(self.tmp_dir)
def _assertControllerInfoEqual(self, info, expected_info_dict):
- self.assertEqual(expected_info_dict['Controller Name'],
- info.controller_name)
+ self.assertEqual(
+ expected_info_dict['Controller Name'], info.controller_name
+ )
self.assertEqual(expected_info_dict['Test Class'], info.test_class)
- self.assertEqual(expected_info_dict['Controller Info'],
- info.controller_info)
+ self.assertEqual(
+ expected_info_dict['Controller Info'], info.controller_info
+ )
def test_run_twice(self):
"""Verifies that:
@@ -73,20 +73,18 @@ class TestRunnerTest(unittest.TestCase):
"""
mock_test_config = self.base_mock_test_config.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- my_config = [{
- 'serial': 'xxxx',
- 'magic': 'Magic1'
- }, {
- 'serial': 'xxxx',
- 'magic': 'Magic2'
- }]
+ my_config = [
+ {'serial': 'xxxx', 'magic': 'Magic1'},
+ {'serial': 'xxxx', 'magic': 'Magic2'},
+ ]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger():
tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
tr.run()
self.assertTrue(
- mock_test_config.controller_configs[mock_ctrlr_config_name][0])
+ mock_test_config.controller_configs[mock_ctrlr_config_name][0]
+ )
with tr.mobly_logger():
tr.run()
results = tr.results.summary_dict()
@@ -94,24 +92,22 @@ class TestRunnerTest(unittest.TestCase):
self.assertEqual(results['Executed'], 2)
self.assertEqual(results['Passed'], 2)
expected_info_dict = {
- 'Controller Info': [{
- 'MyMagic': {
- 'magic': 'Magic1'
- }
- }, {
- 'MyMagic': {
- 'magic': 'Magic2'
- }
- }],
+ 'Controller Info': [
+ {'MyMagic': {'magic': 'Magic1'}},
+ {'MyMagic': {'magic': 'Magic2'}},
+ ],
'Controller Name': 'MagicDevice',
'Test Class': 'IntegrationTest',
}
- self._assertControllerInfoEqual(tr.results.controller_info[0],
- expected_info_dict)
- self._assertControllerInfoEqual(tr.results.controller_info[1],
- expected_info_dict)
- self.assertNotEqual(tr.results.controller_info[0],
- tr.results.controller_info[1])
+ self._assertControllerInfoEqual(
+ tr.results.controller_info[0], expected_info_dict
+ )
+ self._assertControllerInfoEqual(
+ tr.results.controller_info[1], expected_info_dict
+ )
+ self.assertNotEqual(
+ tr.results.controller_info[0], tr.results.controller_info[1]
+ )
def test_summary_file_entries(self):
"""Verifies the output summary's file format.
@@ -121,40 +117,46 @@ class TestRunnerTest(unittest.TestCase):
"""
mock_test_config = self.base_mock_test_config.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- my_config = [{
- 'serial': 'xxxx',
- 'magic': 'Magic1'
- }, {
- 'serial': 'xxxx',
- 'magic': 'Magic2'
- }]
+ my_config = [
+ {'serial': 'xxxx', 'magic': 'Magic1'},
+ {'serial': 'xxxx', 'magic': 'Magic2'},
+ ]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger():
tr.add_test_class(mock_test_config, integration_test.IntegrationTest)
tr.run()
- summary_path = os.path.join(logging.root_output_path,
- records.OUTPUT_FILE_SUMMARY)
+ summary_path = os.path.join(
+ logging.root_output_path, records.OUTPUT_FILE_SUMMARY
+ )
with io.open(summary_path, 'r', encoding='utf-8') as f:
summary_entries = list(yaml.safe_load_all(f))
self.assertEqual(len(summary_entries), 4)
# Verify the first entry is the list of test names.
- self.assertEqual(summary_entries[0]['Type'],
- records.TestSummaryEntryType.TEST_NAME_LIST.value)
- self.assertEqual(summary_entries[1]['Type'],
- records.TestSummaryEntryType.RECORD.value)
- self.assertEqual(summary_entries[2]['Type'],
- records.TestSummaryEntryType.CONTROLLER_INFO.value)
- self.assertEqual(summary_entries[3]['Type'],
- records.TestSummaryEntryType.SUMMARY.value)
+ self.assertEqual(
+ summary_entries[0]['Type'],
+ records.TestSummaryEntryType.TEST_NAME_LIST.value,
+ )
+ self.assertEqual(
+ summary_entries[1]['Type'], records.TestSummaryEntryType.RECORD.value
+ )
+ self.assertEqual(
+ summary_entries[2]['Type'],
+ records.TestSummaryEntryType.CONTROLLER_INFO.value,
+ )
+ self.assertEqual(
+ summary_entries[3]['Type'], records.TestSummaryEntryType.SUMMARY.value
+ )
def test_run(self):
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
self.base_mock_test_config.controller_configs[
- mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
+ mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ ] = '*'
with tr.mobly_logger():
- tr.add_test_class(self.base_mock_test_config,
- integration_test.IntegrationTest)
+ tr.add_test_class(
+ self.base_mock_test_config, integration_test.IntegrationTest
+ )
tr.run()
results = tr.results.summary_dict()
self.assertEqual(results['Requested'], 1)
@@ -167,9 +169,11 @@ class TestRunnerTest(unittest.TestCase):
def test_run_without_mobly_logger_context(self):
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
self.base_mock_test_config.controller_configs[
- mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = '*'
- tr.add_test_class(self.base_mock_test_config,
- integration_test.IntegrationTest)
+ mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
+ ] = '*'
+ tr.add_test_class(
+ self.base_mock_test_config, integration_test.IntegrationTest
+ )
tr.run()
results = tr.results.summary_dict()
self.assertEqual(results['Requested'], 1)
@@ -179,16 +183,24 @@ class TestRunnerTest(unittest.TestCase):
record = tr.results.executed[0]
self.assertEqual(record.test_class, 'IntegrationTest')
- @mock.patch('mobly.controllers.android_device_lib.adb.AdbProxy',
- return_value=mock_android_device.MockAdbProxy(1))
- @mock.patch('mobly.controllers.android_device_lib.fastboot.FastbootProxy',
- return_value=mock_android_device.MockFastbootProxy(1))
- @mock.patch('mobly.controllers.android_device.list_adb_devices',
- return_value=['1'])
- @mock.patch('mobly.controllers.android_device.get_all_instances',
- return_value=mock_android_device.get_mock_ads(1))
- def test_run_two_test_classes(self, mock_get_all, mock_list_adb,
- mock_fastboot, mock_adb):
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.adb.AdbProxy',
+ return_value=mock_android_device.MockAdbProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device_lib.fastboot.FastbootProxy',
+ return_value=mock_android_device.MockFastbootProxy(1),
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device.list_adb_devices', return_value=['1']
+ )
+ @mock.patch(
+ 'mobly.controllers.android_device.get_all_instances',
+ return_value=mock_android_device.get_mock_ads(1),
+ )
+ def test_run_two_test_classes(
+ self, mock_get_all, mock_list_adb, mock_fastboot, mock_adb
+ ):
"""Verifies that running more than one test class in one test run works
properly.
@@ -197,13 +209,10 @@ class TestRunnerTest(unittest.TestCase):
"""
mock_test_config = self.base_mock_test_config.copy()
mock_ctrlr_config_name = mock_controller.MOBLY_CONTROLLER_CONFIG_NAME
- my_config = [{
- 'serial': 'xxxx',
- 'magic': 'Magic1'
- }, {
- 'serial': 'xxxx',
- 'magic': 'Magic2'
- }]
+ my_config = [
+ {'serial': 'xxxx', 'magic': 'Magic1'},
+ {'serial': 'xxxx', 'magic': 'Magic2'},
+ ]
mock_test_config.controller_configs[mock_ctrlr_config_name] = my_config
mock_test_config.controller_configs['AndroidDevice'] = [{'serial': '1'}]
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
@@ -228,20 +237,18 @@ class TestRunnerTest(unittest.TestCase):
"""
config1 = self.base_mock_test_config.copy()
config1.controller_configs[mock_controller.MOBLY_CONTROLLER_CONFIG_NAME] = [
- {
- 'serial': 'xxxx'
- }
+ {'serial': 'xxxx'}
]
config2 = config1.copy()
config2.user_params['icecream'] = 10
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with tr.mobly_logger():
- tr.add_test_class(config1,
- integration_test.IntegrationTest,
- name_suffix='FirstConfig')
- tr.add_test_class(config2,
- integration_test.IntegrationTest,
- name_suffix='SecondConfig')
+ tr.add_test_class(
+ config1, integration_test.IntegrationTest, name_suffix='FirstConfig'
+ )
+ tr.add_test_class(
+ config2, integration_test.IntegrationTest, name_suffix='SecondConfig'
+ )
tr.run()
results = tr.results.summary_dict()
self.assertEqual(results['Requested'], 2)
@@ -280,8 +287,9 @@ class TestRunnerTest(unittest.TestCase):
logging.getLogger().handlers[0].setLevel(logging.WARNING)
tr.run()
- self.assertIn('Test received a SIGTERM. Aborting all tests.',
- log_output.output[0])
+ self.assertIn(
+ 'Test received a SIGTERM. Aborting all tests.', log_output.output[0]
+ )
self.assertIn('Abort all subsequent test classes', log_output.output[1])
self.assertIn('Test received a SIGTERM.', log_output.output[1])
@@ -290,42 +298,52 @@ class TestRunnerTest(unittest.TestCase):
with self.assertRaisesRegex(
test_runner.Error,
'TestRunner\'s log folder is "/different/log/dir", but a test '
- r'config with a different log folder \("%s"\) was added.' %
- re.escape(self.log_dir)):
- tr.add_test_class(self.base_mock_test_config,
- integration_test.IntegrationTest)
+ r'config with a different log folder \("%s"\) was added.'
+ % re.escape(self.log_dir),
+ ):
+ tr.add_test_class(
+ self.base_mock_test_config, integration_test.IntegrationTest
+ )
def test_add_test_class_mismatched_testbed_name(self):
tr = test_runner.TestRunner(self.log_dir, 'different_test_bed')
with self.assertRaisesRegex(
test_runner.Error,
'TestRunner\'s test bed is "different_test_bed", but a test '
- r'config with a different test bed \("%s"\) was added.' %
- self.testbed_name):
- tr.add_test_class(self.base_mock_test_config,
- integration_test.IntegrationTest)
+ r'config with a different test bed \("%s"\) was added.'
+ % self.testbed_name,
+ ):
+ tr.add_test_class(
+ self.base_mock_test_config, integration_test.IntegrationTest
+ )
def test_run_no_tests(self):
tr = test_runner.TestRunner(self.log_dir, self.testbed_name)
with self.assertRaisesRegex(test_runner.Error, 'No tests to execute.'):
tr.run()
- @mock.patch('mobly.test_runner._find_test_class',
- return_value=type('SampleTest', (), {}))
- @mock.patch('mobly.test_runner.config_parser.load_test_config_file',
- return_value=[config_parser.TestRunConfig()])
+ @mock.patch(
+ 'mobly.test_runner._find_test_class',
+ return_value=type('SampleTest', (), {}),
+ )
+ @mock.patch(
+ 'mobly.test_runner.config_parser.load_test_config_file',
+ return_value=[config_parser.TestRunConfig()],
+ )
@mock.patch('mobly.test_runner.TestRunner', return_value=mock.MagicMock())
def test_main_parse_args(self, mock_test_runner, mock_config, mock_find_test):
test_runner.main(['-c', 'some/path/foo.yaml', '-b', 'hello'])
mock_config.assert_called_with('some/path/foo.yaml', None)
- @mock.patch('mobly.test_runner._find_test_class',
- return_value=integration_test.IntegrationTest)
+ @mock.patch(
+ 'mobly.test_runner._find_test_class',
+ return_value=integration_test.IntegrationTest,
+ )
@mock.patch('sys.exit')
def test_main(self, mock_exit, mock_find_test):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u"""
+ f.write("""
TestBeds:
# A test bed where adb will find Android devices.
- Name: SampleTestBed
@@ -338,13 +356,15 @@ class TestRunnerTest(unittest.TestCase):
test_runner.main(['-c', tmp_file_path])
mock_exit.assert_not_called()
- @mock.patch('mobly.test_runner._find_test_class',
- return_value=integration_test.IntegrationTest)
+ @mock.patch(
+ 'mobly.test_runner._find_test_class',
+ return_value=integration_test.IntegrationTest,
+ )
@mock.patch('sys.exit')
def test_main_with_failures(self, mock_exit, mock_find_test):
tmp_file_path = os.path.join(self.tmp_dir, 'config.yml')
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u"""
+ f.write("""
TestBeds:
# A test bed where adb will find Android devices.
- Name: SampleTestBed
@@ -382,10 +402,9 @@ class TestRunnerTest(unittest.TestCase):
mock_cls_instance = mock.MagicMock()
mock_test_class.return_value = mock_cls_instance
test_runner._print_test_names(mock_test_class)
- mock_cls_instance._pre_run.side_effect = Exception(
- 'Something went wrong.')
+ mock_cls_instance._pre_run.side_effect = Exception('Something went wrong.')
mock_cls_instance._clean_up.assert_called_once()
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/test_suite_test.py b/tests/mobly/test_suite_test.py
index d3537f8..4eadfdb 100755
--- a/tests/mobly/test_suite_test.py
+++ b/tests/mobly/test_suite_test.py
@@ -36,16 +36,17 @@ class TestSuiteTest(unittest.TestCase):
self.mock_test_cls_configs = config_parser.TestRunConfig()
self.summary_file = os.path.join(self.tmp_dir, 'summary.yaml')
self.mock_test_cls_configs.summary_writer = records.TestSummaryWriter(
- self.summary_file)
+ self.summary_file
+ )
self.mock_test_cls_configs.log_path = self.tmp_dir
- self.mock_test_cls_configs.user_params = {"some_param": "hahaha"}
+ self.mock_test_cls_configs.user_params = {'some_param': 'hahaha'}
self.mock_test_cls_configs.reporter = mock.MagicMock()
self.base_mock_test_config = config_parser.TestRunConfig()
self.base_mock_test_config.testbed_name = 'SampleTestBed'
self.base_mock_test_config.controller_configs = {}
self.base_mock_test_config.user_params = {
'icecream': 42,
- 'extra_param': 'haha'
+ 'extra_param': 'haha',
}
self.base_mock_test_config.log_path = self.tmp_dir
@@ -74,5 +75,5 @@ class TestSuiteTest(unittest.TestCase):
self.assertIsNot(self.controller1, self.controller2)
-if __name__ == "__main__":
+if __name__ == '__main__':
unittest.main()
diff --git a/tests/mobly/utils_test.py b/tests/mobly/utils_test.py
index 7e95718..fff3803 100755
--- a/tests/mobly/utils_test.py
+++ b/tests/mobly/utils_test.py
@@ -45,11 +45,14 @@ ADB_MODULE_PACKAGE_NAME = 'mobly.controllers.android_device_lib.adb'
def _is_process_running(pid):
"""Whether the process with given PID is running."""
if os.name == 'nt':
- return str(pid) in subprocess.check_output([
- 'tasklist',
- '/fi',
- f'PID eq {pid}',
- ]).decode()
+ return (
+ str(pid)
+ in subprocess.check_output([
+ 'tasklist',
+ '/fi',
+ f'PID eq {pid}',
+ ]).decode()
+ )
try:
# os.kill throws OSError if the process with PID pid is not running.
@@ -102,19 +105,24 @@ class UtilsTest(unittest.TestCase):
else:
return ['sleep', str(wait_secs)]
- @unittest.skipIf(os.name == "nt",
- 'collect_process_tree only available on Unix like system.')
+ @unittest.skipIf(
+ os.name == 'nt',
+ 'collect_process_tree only available on Unix like system.',
+ )
@mock.patch('subprocess.check_output')
def test_collect_process_tree_without_child(self, mock_check_output):
- mock_check_output.side_effect = (subprocess.CalledProcessError(
- -1, 'fake_cmd'))
+ mock_check_output.side_effect = subprocess.CalledProcessError(
+ -1, 'fake_cmd'
+ )
pid_list = utils._collect_process_tree(123)
self.assertListEqual(pid_list, [])
- @unittest.skipIf(os.name == "nt",
- 'collect_process_tree only available on Unix like system.')
+ @unittest.skipIf(
+ os.name == 'nt',
+ 'collect_process_tree only available on Unix like system.',
+ )
@mock.patch('subprocess.check_output')
def test_collect_process_tree_returns_list(self, mock_check_output):
# Creates subprocess 777 with descendants looks like:
@@ -151,8 +159,9 @@ class UtilsTest(unittest.TestCase):
@mock.patch.object(os, 'kill')
@mock.patch.object(utils, '_collect_process_tree')
- def test_kill_process_tree_on_unix_succeeds(self, mock_collect_process_tree,
- mock_os_kill):
+ def test_kill_process_tree_on_unix_succeeds(
+ self, mock_collect_process_tree, mock_os_kill
+ ):
mock_collect_process_tree.return_value = [799, 888, 890]
mock_proc = mock.MagicMock()
mock_proc.pid = 123
@@ -170,7 +179,8 @@ class UtilsTest(unittest.TestCase):
@mock.patch.object(os, 'kill')
@mock.patch.object(utils, '_collect_process_tree')
def test_kill_process_tree_on_unix_kill_children_failed_throws_error(
- self, mock_collect_process_tree, mock_os_kill):
+ self, mock_collect_process_tree, mock_os_kill
+ ):
mock_collect_process_tree.return_value = [799, 888, 890]
mock_os_kill.side_effect = [None, OSError(), None]
mock_proc = mock.MagicMock()
@@ -184,7 +194,8 @@ class UtilsTest(unittest.TestCase):
@mock.patch.object(utils, '_collect_process_tree')
def test_kill_process_tree_on_unix_kill_proc_failed_throws_error(
- self, mock_collect_process_tree):
+ self, mock_collect_process_tree
+ ):
mock_collect_process_tree.return_value = []
mock_proc = mock.MagicMock()
mock_proc.pid = 123
@@ -262,13 +273,15 @@ class UtilsTest(unittest.TestCase):
mock_proc.communicate.return_value = ('fake_out', 'fake_err')
mock_proc.returncode = 127
- out = utils.run_command(mock_command,
- stdout=mock_stdout,
- stderr=mock_stderr,
- shell=mock_shell,
- timeout=mock_timeout,
- env=mock_env,
- universal_newlines=mock_universal_newlines)
+ out = utils.run_command(
+ mock_command,
+ stdout=mock_stdout,
+ stderr=mock_stderr,
+ shell=mock_shell,
+ timeout=mock_timeout,
+ env=mock_env,
+ universal_newlines=mock_universal_newlines,
+ )
self.assertEqual(out, (127, 'fake_out', 'fake_err'))
mock_popen.assert_called_with(
@@ -283,8 +296,9 @@ class UtilsTest(unittest.TestCase):
mock_timer.assert_called_with(1234, mock.ANY)
def test_run_command_with_universal_newlines_false(self):
- _, out, _ = utils.run_command(self.sleep_cmd(0.01),
- universal_newlines=False)
+ _, out, _ = utils.run_command(
+ self.sleep_cmd(0.01), universal_newlines=False
+ )
self.assertIsInstance(out, bytes)
@@ -352,19 +366,29 @@ class UtilsTest(unittest.TestCase):
# │ └─ Y (grandchild)
# ├─ C (child)
# └─ D (child)
- process_tree_args = ('subprocess_a', [
- ('child_b', [
- ('grand_child_x', [
- ('great_grand_child_1', []),
- ('great_grand_child_2', []),
- ]),
- ('grand_child_y', []),
- ]),
- ('child_c', []),
- ('child_d', []),
- ])
- subprocess_a = multiprocessing.Process(target=_fork_children_processes,
- args=process_tree_args)
+ process_tree_args = (
+ 'subprocess_a',
+ [
+ (
+ 'child_b',
+ [
+ (
+ 'grand_child_x',
+ [
+ ('great_grand_child_1', []),
+ ('great_grand_child_2', []),
+ ],
+ ),
+ ('grand_child_y', []),
+ ],
+ ),
+ ('child_c', []),
+ ('child_d', []),
+ ],
+ )
+ subprocess_a = multiprocessing.Process(
+ target=_fork_children_processes, args=process_tree_args
+ )
subprocess_a.start()
mock_subprocess_a_popen = mock.MagicMock()
mock_subprocess_a_popen.pid = subprocess_a.pid
@@ -376,16 +400,17 @@ class UtilsTest(unittest.TestCase):
subprocess_a.join(timeout=1)
mock_subprocess_a_popen.wait.assert_called_once()
- @unittest.skipIf(sys.version_info >= (3, 4) and sys.version_info < (3, 5),
- 'Python 3.4 does not support `None` max_workers.')
+ @unittest.skipIf(
+ sys.version_info >= (3, 4) and sys.version_info < (3, 5),
+ 'Python 3.4 does not support `None` max_workers.',
+ )
def test_concurrent_exec_when_none_workers(self):
-
def adder(a, b):
return a + b
- with mock.patch.object(futures,
- 'ThreadPoolExecutor',
- wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+ with mock.patch.object(
+ futures, 'ThreadPoolExecutor', wraps=futures.ThreadPoolExecutor
+ ) as thread_pool_spy:
results = utils.concurrent_exec(adder, [(1, 1), (2, 2)], max_workers=None)
thread_pool_spy.assert_called_once_with(max_workers=None)
@@ -395,13 +420,12 @@ class UtilsTest(unittest.TestCase):
self.assertIn(4, results)
def test_concurrent_exec_when_default_max_workers(self):
-
def adder(a, b):
return a + b
- with mock.patch.object(futures,
- 'ThreadPoolExecutor',
- wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+ with mock.patch.object(
+ futures, 'ThreadPoolExecutor', wraps=futures.ThreadPoolExecutor
+ ) as thread_pool_spy:
results = utils.concurrent_exec(adder, [(1, 1), (2, 2)])
thread_pool_spy.assert_called_once_with(max_workers=30)
@@ -411,13 +435,12 @@ class UtilsTest(unittest.TestCase):
self.assertIn(4, results)
def test_concurrent_exec_when_custom_max_workers(self):
-
def adder(a, b):
return a + b
- with mock.patch.object(futures,
- 'ThreadPoolExecutor',
- wraps=futures.ThreadPoolExecutor) as thread_pool_spy:
+ with mock.patch.object(
+ futures, 'ThreadPoolExecutor', wraps=futures.ThreadPoolExecutor
+ ) as thread_pool_spy:
results = utils.concurrent_exec(adder, [(1, 1), (2, 2)], max_workers=1)
thread_pool_spy.assert_called_once_with(max_workers=1)
@@ -427,18 +450,20 @@ class UtilsTest(unittest.TestCase):
def test_concurrent_exec_makes_all_calls(self):
mock_function = mock.MagicMock()
- _ = utils.concurrent_exec(mock_function, [
- (1, 1),
- (2, 2),
- (3, 3),
- ])
+ _ = utils.concurrent_exec(
+ mock_function,
+ [
+ (1, 1),
+ (2, 2),
+ (3, 3),
+ ],
+ )
self.assertEqual(mock_function.call_count, 3)
mock_function.assert_has_calls(
- [mock.call(1, 1), mock.call(2, 2),
- mock.call(3, 3)], any_order=True)
+ [mock.call(1, 1), mock.call(2, 2), mock.call(3, 3)], any_order=True
+ )
def test_concurrent_exec_generates_results(self):
-
def adder(a, b):
return a + b
@@ -451,42 +476,54 @@ class UtilsTest(unittest.TestCase):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
- utils.concurrent_exec(fake_int, [
- (1,),
- ('123',),
- ('not_int',),
- (5435,),
- ])
+ utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('123',),
+ ('not_int',),
+ (5435,),
+ ],
+ )
self.assertEqual(mock_call_recorder.call_count, 4)
- mock_call_recorder.assert_has_calls([
- mock.call(1),
- mock.call('123'),
- mock.call('not_int'),
- mock.call(5435),
- ],
- any_order=True)
+ mock_call_recorder.assert_has_calls(
+ [
+ mock.call(1),
+ mock.call('123'),
+ mock.call('not_int'),
+ mock.call(5435),
+ ],
+ any_order=True,
+ )
def test_concurrent_exec_when_exception_generates_results(self):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
- results = utils.concurrent_exec(fake_int, [
- (1,),
- ('123',),
- ('not_int',),
- (5435,),
- ])
+ results = utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('123',),
+ ('not_int',),
+ (5435,),
+ ],
+ )
self.assertEqual(len(results), 4)
self.assertIn(1, results)
@@ -500,42 +537,54 @@ class UtilsTest(unittest.TestCase):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
- utils.concurrent_exec(fake_int, [
- (1,),
- ('not_int1',),
- ('not_int2',),
- (5435,),
- ])
+ utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('not_int1',),
+ ('not_int2',),
+ (5435,),
+ ],
+ )
self.assertEqual(mock_call_recorder.call_count, 4)
- mock_call_recorder.assert_has_calls([
- mock.call(1),
- mock.call('not_int1'),
- mock.call('not_int2'),
- mock.call(5435),
- ],
- any_order=True)
+ mock_call_recorder.assert_has_calls(
+ [
+ mock.call(1),
+ mock.call('not_int1'),
+ mock.call('not_int2'),
+ mock.call(5435),
+ ],
+ any_order=True,
+ )
def test_concurrent_exec_when_multiple_exceptions_generates_results(self):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
- results = utils.concurrent_exec(fake_int, [
- (1,),
- ('not_int1',),
- ('not_int2',),
- (5435,),
- ])
+ results = utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('not_int1',),
+ ('not_int2',),
+ (5435,),
+ ],
+ )
self.assertEqual(len(results), 4)
self.assertIn(1, results)
@@ -547,12 +596,12 @@ class UtilsTest(unittest.TestCase):
self.assertNotEqual(exceptions[0], exceptions[1])
def test_concurrent_exec_when_raising_exception_generates_results(self):
-
def adder(a, b):
return a + b
- results = utils.concurrent_exec(adder, [(1, 1), (2, 2)],
- raise_on_exception=True)
+ results = utils.concurrent_exec(
+ adder, [(1, 1), (2, 2)], raise_on_exception=True
+ )
self.assertEqual(len(results), 2)
self.assertIn(2, results)
self.assertIn(4, results)
@@ -561,58 +610,74 @@ class UtilsTest(unittest.TestCase):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
with self.assertRaisesRegex(RuntimeError, '.*not_int.*'):
- _ = utils.concurrent_exec(fake_int, [
- (1,),
- ('123',),
- ('not_int',),
- (5435,),
- ],
- raise_on_exception=True)
+ _ = utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('123',),
+ ('not_int',),
+ (5435,),
+ ],
+ raise_on_exception=True,
+ )
self.assertEqual(mock_call_recorder.call_count, 4)
- mock_call_recorder.assert_has_calls([
- mock.call(1),
- mock.call('123'),
- mock.call('not_int'),
- mock.call(5435),
- ],
- any_order=True)
+ mock_call_recorder.assert_has_calls(
+ [
+ mock.call(1),
+ mock.call('123'),
+ mock.call('not_int'),
+ mock.call(5435),
+ ],
+ any_order=True,
+ )
def test_concurrent_exec_when_raising_multiple_exceptions_makes_all_calls(
- self):
+ self,
+ ):
mock_call_recorder = mock.MagicMock()
lock_call_count = threading.Lock()
- def fake_int(a,):
+ def fake_int(
+ a,
+ ):
with lock_call_count:
mock_call_recorder(a)
return int(a)
with self.assertRaisesRegex(
RuntimeError,
- r'(?m).*(not_int1(.|\s)+not_int2|not_int2(.|\s)+not_int1).*'):
- _ = utils.concurrent_exec(fake_int, [
- (1,),
- ('not_int1',),
- ('not_int2',),
- (5435,),
- ],
- raise_on_exception=True)
+ r'(?m).*(not_int1(.|\s)+not_int2|not_int2(.|\s)+not_int1).*',
+ ):
+ _ = utils.concurrent_exec(
+ fake_int,
+ [
+ (1,),
+ ('not_int1',),
+ ('not_int2',),
+ (5435,),
+ ],
+ raise_on_exception=True,
+ )
self.assertEqual(mock_call_recorder.call_count, 4)
- mock_call_recorder.assert_has_calls([
- mock.call(1),
- mock.call('not_int1'),
- mock.call('not_int2'),
- mock.call(5435),
- ],
- any_order=True)
+ mock_call_recorder.assert_has_calls(
+ [
+ mock.call(1),
+ mock.call('not_int1'),
+ mock.call('not_int2'),
+ mock.call(5435),
+ ],
+ any_order=True,
+ )
def test_create_dir(self):
new_path = os.path.join(self.tmp_dir, 'haha')
@@ -634,14 +699,17 @@ class UtilsTest(unittest.TestCase):
@mock.patch(f'{ADB_MODULE_PACKAGE_NAME}.is_adb_available', return_value=False)
@mock.patch('portpicker.pick_unused_port', return_value=MOCK_AVAILABLE_PORT)
@mock.patch(f'{ADB_MODULE_PACKAGE_NAME}.list_occupied_adb_ports')
- def test_get_available_port_positive_no_adb(self,
- mock_list_occupied_adb_ports, *_):
+ def test_get_available_port_positive_no_adb(
+ self, mock_list_occupied_adb_ports, *_
+ ):
self.assertEqual(utils.get_available_host_port(), MOCK_AVAILABLE_PORT)
mock_list_occupied_adb_ports.assert_not_called()
@mock.patch(f'{ADB_MODULE_PACKAGE_NAME}.is_adb_available', return_value=True)
- @mock.patch(f'{ADB_MODULE_PACKAGE_NAME}.list_occupied_adb_ports',
- return_value=[MOCK_AVAILABLE_PORT])
+ @mock.patch(
+ f'{ADB_MODULE_PACKAGE_NAME}.list_occupied_adb_ports',
+ return_value=[MOCK_AVAILABLE_PORT],
+ )
@mock.patch('portpicker.pick_unused_port', return_value=MOCK_AVAILABLE_PORT)
def test_get_available_port_negative(self, *_):
with self.assertRaisesRegex(utils.Error, 'Failed to find.* retries'):
@@ -672,36 +740,38 @@ class UtilsTest(unittest.TestCase):
def test_load_file_to_base64_str_reads_bytes_file_as_base64_string(self):
tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
- expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
+ expected_base64_encoding = 'SGVsbG93IHdvcmxkIQ=='
with io.open(tmp_file_path, 'wb') as f:
f.write(b'Hellow world!')
- self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
- expected_base64_encoding)
+ self.assertEqual(
+ utils.load_file_to_base64_str(tmp_file_path), expected_base64_encoding
+ )
def test_load_file_to_base64_str_reads_text_file_as_base64_string(self):
tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
- expected_base64_encoding = u'SGVsbG93IHdvcmxkIQ=='
+ expected_base64_encoding = 'SGVsbG93IHdvcmxkIQ=='
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u'Hellow world!')
- self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
- expected_base64_encoding)
+ f.write('Hellow world!')
+ self.assertEqual(
+ utils.load_file_to_base64_str(tmp_file_path), expected_base64_encoding
+ )
def test_load_file_to_base64_str_reads_unicode_file_as_base64_string(self):
tmp_file_path = os.path.join(self.tmp_dir, 'b64.bin')
- expected_base64_encoding = u'6YCa'
+ expected_base64_encoding = '6YCa'
with io.open(tmp_file_path, 'w', encoding='utf-8') as f:
- f.write(u'\u901a')
- self.assertEqual(utils.load_file_to_base64_str(tmp_file_path),
- expected_base64_encoding)
+ f.write('\u901a')
+ self.assertEqual(
+ utils.load_file_to_base64_str(tmp_file_path), expected_base64_encoding
+ )
def test_cli_cmd_to_string(self):
cmd = ['"adb"', 'a b', 'c//']
- self.assertEqual(utils.cli_cmd_to_string(cmd), '\'"adb"\' \'a b\' c//')
+ self.assertEqual(utils.cli_cmd_to_string(cmd), "'\"adb\"' 'a b' c//")
cmd = 'adb -s meme do something ab_cd'
self.assertEqual(utils.cli_cmd_to_string(cmd), cmd)
def test_get_settable_properties(self):
-
class SomeClass:
regular_attr = 'regular_attr'
_foo = 'foo'
@@ -726,26 +796,31 @@ class UtilsTest(unittest.TestCase):
self.assertEqual(actual, ['settable_prop'])
def test_find_subclasses_in_module_when_one_subclass(self):
- subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
- integration_test)
+ subclasses = utils.find_subclasses_in_module(
+ [base_test.BaseTestClass], integration_test
+ )
self.assertEqual(len(subclasses), 1)
self.assertEqual(subclasses[0], integration_test.IntegrationTest)
def test_find_subclasses_in_module_when_indirect_subclass(self):
- subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
- mock_instrumentation_test)
+ subclasses = utils.find_subclasses_in_module(
+ [base_test.BaseTestClass], mock_instrumentation_test
+ )
self.assertEqual(len(subclasses), 1)
- self.assertEqual(subclasses[0],
- mock_instrumentation_test.MockInstrumentationTest)
+ self.assertEqual(
+ subclasses[0], mock_instrumentation_test.MockInstrumentationTest
+ )
def test_find_subclasses_in_module_when_no_subclasses(self):
- subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
- mock_controller)
+ subclasses = utils.find_subclasses_in_module(
+ [base_test.BaseTestClass], mock_controller
+ )
self.assertEqual(len(subclasses), 0)
def test_find_subclasses_in_module_when_multiple_subclasses(self):
- subclasses = utils.find_subclasses_in_module([base_test.BaseTestClass],
- multiple_subclasses_module)
+ subclasses = utils.find_subclasses_in_module(
+ [base_test.BaseTestClass], multiple_subclasses_module
+ )
self.assertEqual(len(subclasses), 2)
self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
@@ -753,7 +828,8 @@ class UtilsTest(unittest.TestCase):
def test_find_subclasses_in_module_when_multiple_base_classes(self):
subclasses = utils.find_subclasses_in_module(
[base_test.BaseTestClass, test_runner.TestRunner],
- multiple_subclasses_module)
+ multiple_subclasses_module,
+ )
self.assertEqual(len(subclasses), 4)
self.assertIn(multiple_subclasses_module.Subclass1Test, subclasses)
self.assertIn(multiple_subclasses_module.Subclass2Test, subclasses)
@@ -762,37 +838,45 @@ class UtilsTest(unittest.TestCase):
def test_find_subclasses_in_module_when_only_some_base_classes_present(self):
subclasses = utils.find_subclasses_in_module(
- [signals.TestSignal, test_runner.TestRunner],
- multiple_subclasses_module)
+ [signals.TestSignal, test_runner.TestRunner], multiple_subclasses_module
+ )
self.assertEqual(len(subclasses), 2)
self.assertIn(multiple_subclasses_module.Subclass1Runner, subclasses)
self.assertIn(multiple_subclasses_module.Subclass2Runner, subclasses)
def test_find_subclass_in_module_when_one_subclass(self):
- subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
- integration_test)
+ subclass = utils.find_subclass_in_module(
+ base_test.BaseTestClass, integration_test
+ )
self.assertEqual(subclass, integration_test.IntegrationTest)
def test_find_subclass_in_module_when_indirect_subclass(self):
- subclass = utils.find_subclass_in_module(base_test.BaseTestClass,
- mock_instrumentation_test)
- self.assertEqual(subclass,
- mock_instrumentation_test.MockInstrumentationTest)
+ subclass = utils.find_subclass_in_module(
+ base_test.BaseTestClass, mock_instrumentation_test
+ )
+ self.assertEqual(
+ subclass, mock_instrumentation_test.MockInstrumentationTest
+ )
def test_find_subclass_in_module_when_no_subclasses(self):
with self.assertRaisesRegex(
- ValueError, '.*Expected 1 subclass of BaseTestClass per module, found'
- r' \[\].*'):
- _ = utils.find_subclass_in_module(base_test.BaseTestClass,
- mock_controller)
+ ValueError,
+ '.*Expected 1 subclass of BaseTestClass per module, found' r' \[\].*',
+ ):
+ _ = utils.find_subclass_in_module(
+ base_test.BaseTestClass, mock_controller
+ )
def test_find_subclass_in_module_when_multiple_subclasses(self):
with self.assertRaisesRegex(
- ValueError, '.*Expected 1 subclass of BaseTestClass per module, found'
+ ValueError,
+ '.*Expected 1 subclass of BaseTestClass per module, found'
r' \[(\'Subclass1Test\', \'Subclass2Test\''
- r'|\'Subclass2Test\', \'Subclass1Test\')\].*'):
- _ = utils.find_subclass_in_module(base_test.BaseTestClass,
- multiple_subclasses_module)
+ r'|\'Subclass2Test\', \'Subclass1Test\')\].*',
+ ):
+ _ = utils.find_subclass_in_module(
+ base_test.BaseTestClass, multiple_subclasses_module
+ )
if __name__ == '__main__':
diff --git a/tools/sl4a_shell.py b/tools/sl4a_shell.py
index e8365da..6ad656e 100755
--- a/tools/sl4a_shell.py
+++ b/tools/sl4a_shell.py
@@ -51,9 +51,11 @@ class Sl4aShell(jsonrpc_shell_base.JsonRpcShellBase):
def _get_banner(self, serial):
lines = [
- 'Connected to %s.' % serial, 'Call methods against:',
- ' ad (android_device.AndroidDevice)', ' sl4a or s (SL4A)',
- ' ed (EventDispatcher)'
+ 'Connected to %s.' % serial,
+ 'Call methods against:',
+ ' ad (android_device.AndroidDevice)',
+ ' sl4a or s (SL4A)',
+ ' ed (EventDispatcher)',
]
return '\n'.join(lines)
@@ -63,7 +65,8 @@ if __name__ == '__main__':
parser.add_argument(
'-s',
'--serial',
- help='Device serial to connect to (if more than one device is connected)')
+ help='Device serial to connect to (if more than one device is connected)',
+ )
args = parser.parse_args()
logging.basicConfig(level=logging.INFO)
Sl4aShell().main(args.serial)
diff --git a/tools/snippet_shell.py b/tools/snippet_shell.py
index 74e23c1..1d5fad4 100755
--- a/tools/snippet_shell.py
+++ b/tools/snippet_shell.py
@@ -46,27 +46,35 @@ class SnippetShell(jsonrpc_shell_base.JsonRpcShellBase):
def _get_banner(self, serial):
lines = [
- 'Connected to %s.' % serial, 'Call methods against:',
- ' ad (android_device.AndroidDevice)', ' snippet or s (Snippet)'
+ 'Connected to %s.' % serial,
+ 'Call methods against:',
+ ' ad (android_device.AndroidDevice)',
+ ' snippet or s (Snippet)',
]
return '\n'.join(lines)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
- description='Interactive client for Mobly code snippets.')
+ description='Interactive client for Mobly code snippets.'
+ )
parser.add_argument(
'-s',
'--serial',
- help='Device serial to connect to (if more than one device is connected)')
- parser.add_argument('package',
- metavar='PACKAGE_NAME',
- type=str,
- nargs='?',
- help='The package name of the snippet to use.')
- parser.add_argument('--mbs',
- help='Whether to connect to Mobly Bundled Snippets',
- action='store_true')
+ help='Device serial to connect to (if more than one device is connected)',
+ )
+ parser.add_argument(
+ 'package',
+ metavar='PACKAGE_NAME',
+ type=str,
+ nargs='?',
+ help='The package name of the snippet to use.',
+ )
+ parser.add_argument(
+ '--mbs',
+ help='Whether to connect to Mobly Bundled Snippets',
+ action='store_true',
+ )
args = parser.parse_args()
if args.package and args.mbs:
print('Cannot specify both --package and --mbs', file=sys.stderr)