diff --git a/.ci/fail_skipped_tests.py b/.ci/fail_skipped_tests.py index 2f4c446..438d169 100755 --- a/.ci/fail_skipped_tests.py +++ b/.ci/fail_skipped_tests.py @@ -3,24 +3,38 @@ from lxml import etree import sys + def format_title(title): """Put title in a box""" box = { - 'tl': '╔', 'tr': '╗', 'bl': '╚', 'br': '╝', 'h': '═', 'v': '║', + "tl": "╔", + "tr": "╗", + "bl": "╚", + "br": "╝", + "h": "═", + "v": "║", } - hline = box['h'] * (len(title) + 2) + hline = box["h"] * (len(title) + 2) + + return "\n".join( + [ + f"{box['tl']}{hline}{box['tr']}", + f"{box['v']} {title} {box['v']}", + f"{box['bl']}{hline}{box['br']}", + ] + ) - return '\n'.join([ - f"{box['tl']}{hline}{box['tr']}", - f"{box['v']} {title} {box['v']}", - f"{box['bl']}{hline}{box['br']}", - ]) # The log coloring causes the XML to be invalid, so set recover=True tree = etree.parse(sys.argv[1], etree.XMLParser(recover=True)) -for suite in tree.xpath('/testsuites/testsuite'): - skipped = suite.get('skipped') +for suite in tree.xpath("/testsuites/testsuite"): + skipped = suite.get("skipped") if int(skipped) != 0: - print(format_title('Tests were skipped when they should not have been. All the tests must be run in the CI'), - end='\n\n', flush=True) + print( + format_title( + "Tests were skipped when they should not have been. All the tests must be run in the CI" + ), + end="\n\n", + flush=True, + ) sys.exit(1) diff --git a/src/linux/integration-test.py b/src/linux/integration-test.py index 28a6851..020e6b7 100755 --- a/src/linux/integration-test.py +++ b/src/linux/integration-test.py @@ -34,109 +34,124 @@ edir = os.path.dirname(sys.argv[0]) try: import dbusmock except ImportError: - sys.stderr.write('Skipping tests, python-dbusmock not available (http://pypi.python.org/pypi/python-dbusmock).\n') + sys.stderr.write( + "Skipping tests, python-dbusmock not available (http://pypi.python.org/pypi/python-dbusmock).\n" + ) sys.exit(77) -UP = 'org.freedesktop.UPower' -UP_DEVICE = 'org.freedesktop.UPower.Device' -UP_DISPLAY_OBJECT_PATH = '/org/freedesktop/UPower/devices/DisplayDevice' +UP = "org.freedesktop.UPower" +UP_DEVICE = "org.freedesktop.UPower.Device" +UP_DISPLAY_OBJECT_PATH = "/org/freedesktop/UPower/devices/DisplayDevice" UP_DAEMON_ACTION_DELAY = 20 -UP_HISTORY_SAVE_INTERVAL = (10*60) +UP_HISTORY_SAVE_INTERVAL = 10 * 60 UP_HISTORY_SAVE_INTERVAL_LOW_POWER = 5 -DEVICE_IFACE = 'org.bluez.Device1' -BATTERY_IFACE = 'org.bluez.Battery1' +DEVICE_IFACE = "org.bluez.Device1" +BATTERY_IFACE = "org.bluez.Battery1" -(UP_DEVICE_STATE_UNKNOWN, - UP_DEVICE_STATE_CHARGING, - UP_DEVICE_STATE_DISCHARGING, - UP_DEVICE_STATE_EMPTY, - UP_DEVICE_STATE_FULLY_CHARGED, - UP_DEVICE_STATE_PENDING_CHARGE, - UP_DEVICE_STATE_PENDING_DISCHARGE) = range(7) +( + UP_DEVICE_STATE_UNKNOWN, + UP_DEVICE_STATE_CHARGING, + UP_DEVICE_STATE_DISCHARGING, + UP_DEVICE_STATE_EMPTY, + UP_DEVICE_STATE_FULLY_CHARGED, + UP_DEVICE_STATE_PENDING_CHARGE, + UP_DEVICE_STATE_PENDING_DISCHARGE, +) = range(7) -(UP_DEVICE_LEVEL_UNKNOWN, - UP_DEVICE_LEVEL_NONE, - UP_DEVICE_LEVEL_DISCHARGING, - UP_DEVICE_LEVEL_LOW, - UP_DEVICE_LEVEL_CRITICAL, - UP_DEVICE_LEVEL_ACTION, - UP_DEVICE_LEVEL_NORMAL, - UP_DEVICE_LEVEL_HIGH, - UP_DEVICE_LEVEL_FULL) = range(9) +( + UP_DEVICE_LEVEL_UNKNOWN, + UP_DEVICE_LEVEL_NONE, + UP_DEVICE_LEVEL_DISCHARGING, + UP_DEVICE_LEVEL_LOW, + UP_DEVICE_LEVEL_CRITICAL, + UP_DEVICE_LEVEL_ACTION, + UP_DEVICE_LEVEL_NORMAL, + UP_DEVICE_LEVEL_HIGH, + UP_DEVICE_LEVEL_FULL, +) = range(9) + +( + UP_DEVICE_KIND_UNKNOWN, + UP_DEVICE_KIND_LINE_POWER, + UP_DEVICE_KIND_BATTERY, + UP_DEVICE_KIND_UPS, + UP_DEVICE_KIND_MONITOR, + UP_DEVICE_KIND_MOUSE, + UP_DEVICE_KIND_KEYBOARD, + UP_DEVICE_KIND_PDA, + UP_DEVICE_KIND_PHONE, + UP_DEVICE_KIND_MEDIA_PLAYER, + UP_DEVICE_KIND_TABLET, + UP_DEVICE_KIND_COMPUTER, + UP_DEVICE_KIND_GAMING_INPUT, + UP_DEVICE_KIND_PEN, + UP_DEVICE_KIND_TOUCHPAD, + UP_DEVICE_KIND_MODEM, + UP_DEVICE_KIND_NETWORK, + UP_DEVICE_KIND_HEADSET, + UP_DEVICE_KIND_SPEAKERS, + UP_DEVICE_KIND_HEADPHONES, + UP_DEVICE_KIND_VIDEO, + UP_DEVICE_KIND_OTHER_AUDIO, + UP_DEVICE_KIND_REMOTE_CONTROL, + UP_DEVICE_KIND_PRINTER, + UP_DEVICE_KIND_SCANNER, + UP_DEVICE_KIND_CAMERA, + UP_DEVICE_KIND_WEARABLE, + UP_DEVICE_KIND_TOY, + UP_DEVICE_KIND_BLUETOOTH_GENERIC, +) = range(29) -(UP_DEVICE_KIND_UNKNOWN, - UP_DEVICE_KIND_LINE_POWER, - UP_DEVICE_KIND_BATTERY, - UP_DEVICE_KIND_UPS, - UP_DEVICE_KIND_MONITOR, - UP_DEVICE_KIND_MOUSE, - UP_DEVICE_KIND_KEYBOARD, - UP_DEVICE_KIND_PDA, - UP_DEVICE_KIND_PHONE, - UP_DEVICE_KIND_MEDIA_PLAYER, - UP_DEVICE_KIND_TABLET, - UP_DEVICE_KIND_COMPUTER, - UP_DEVICE_KIND_GAMING_INPUT, - UP_DEVICE_KIND_PEN, - UP_DEVICE_KIND_TOUCHPAD, - UP_DEVICE_KIND_MODEM, - UP_DEVICE_KIND_NETWORK, - UP_DEVICE_KIND_HEADSET, - UP_DEVICE_KIND_SPEAKERS, - UP_DEVICE_KIND_HEADPHONES, - UP_DEVICE_KIND_VIDEO, - UP_DEVICE_KIND_OTHER_AUDIO, - UP_DEVICE_KIND_REMOTE_CONTROL, - UP_DEVICE_KIND_PRINTER, - UP_DEVICE_KIND_SCANNER, - UP_DEVICE_KIND_CAMERA, - UP_DEVICE_KIND_WEARABLE, - UP_DEVICE_KIND_TOY, - UP_DEVICE_KIND_BLUETOOTH_GENERIC) = range(29) class Tests(dbusmock.DBusTestCase): @classmethod def setUpClass(cls): # run from local build tree if we are in one, otherwise use system instance - builddir = os.getenv('top_builddir', '.') - if os.access(os.path.join(builddir, 'src', 'upowerd'), os.X_OK): - cls.daemon_path = os.path.join(builddir, 'src', 'upowerd') - cls.upower_path = os.path.join(builddir, 'tools', 'upower') - print('Testing binaries from local build tree') + builddir = os.getenv("top_builddir", ".") + if os.access(os.path.join(builddir, "src", "upowerd"), os.X_OK): + cls.daemon_path = os.path.join(builddir, "src", "upowerd") + cls.upower_path = os.path.join(builddir, "tools", "upower") + print("Testing binaries from local build tree") cls.local_daemon = True - elif os.environ.get('UNDER_JHBUILD', False): - jhbuild_prefix = os.environ['JHBUILD_PREFIX'] - cls.daemon_path = os.path.join(jhbuild_prefix, 'libexec', 'upowerd') - cls.upower_path = os.path.join(jhbuild_prefix, 'bin', 'upower') - print('Testing binaries from JHBuild') + elif os.environ.get("UNDER_JHBUILD", False): + jhbuild_prefix = os.environ["JHBUILD_PREFIX"] + cls.daemon_path = os.path.join(jhbuild_prefix, "libexec", "upowerd") + cls.upower_path = os.path.join(jhbuild_prefix, "bin", "upower") + print("Testing binaries from JHBuild") cls.local_daemon = False else: - print('Testing installed system binaries') + print("Testing installed system binaries") cls.daemon_path = None - cls.upower_path = shutil.which('upower') - with open('/usr/share/dbus-1/system-services/org.freedesktop.UPower.service') as f: + cls.upower_path = shutil.which("upower") + with open( + "/usr/share/dbus-1/system-services/org.freedesktop.UPower.service" + ) as f: for line in f: - if line.startswith('Exec='): - cls.daemon_path = line.split('=', 1)[1].strip() + if line.startswith("Exec="): + cls.daemon_path = line.split("=", 1)[1].strip() break - assert cls.daemon_path, 'could not determine daemon path from D-BUS .service file' - assert cls.upower_path, 'could not determine upower path' + assert ( + cls.daemon_path + ), "could not determine daemon path from D-BUS .service file" + assert cls.upower_path, "could not determine upower path" cls.local_daemon = False # fail on CRITICALs on client side - GLib.log_set_always_fatal(GLib.LogLevelFlags.LEVEL_WARNING | - GLib.LogLevelFlags.LEVEL_ERROR | - GLib.LogLevelFlags.LEVEL_CRITICAL) + GLib.log_set_always_fatal( + GLib.LogLevelFlags.LEVEL_WARNING + | GLib.LogLevelFlags.LEVEL_ERROR + | GLib.LogLevelFlags.LEVEL_CRITICAL + ) # set up a fake system D-BUS cls.test_bus = Gio.TestDBus.new(Gio.TestDBusFlags.NONE) cls.test_bus.up() try: - del os.environ['DBUS_SESSION_BUS_ADDRESS'] + del os.environ["DBUS_SESSION_BUS_ADDRESS"] except KeyError: pass - os.environ['DBUS_SYSTEM_BUS_ADDRESS'] = cls.test_bus.get_bus_address() + os.environ["DBUS_SYSTEM_BUS_ADDRESS"] = cls.test_bus.get_bus_address() cls.dbus = Gio.bus_get_sync(Gio.BusType.SYSTEM, None) cls.dbus_con = cls.get_dbus(True) @@ -147,16 +162,16 @@ class Tests(dbusmock.DBusTestCase): dbusmock.DBusTestCase.tearDownClass() def setUp(self): - '''Set up a local umockdev testbed. + """Set up a local umockdev testbed. The testbed is initially empty. - ''' + """ self.testbed = UMockdev.Testbed.new() self.proxy = None self.daemon = None self.bluez = None - self.start_logind({'CanHybridSleep' : 'yes'}) + self.start_logind({"CanHybridSleep": "yes"}) self.start_polkitd({}) @classmethod @@ -165,7 +180,10 @@ class Tests(dbusmock.DBusTestCase): try: proc.wait(timeout) except: - print("Killing %d (%s) after timeout of %f seconds" % (proc.pid, proc.args[0], timeout)) + print( + "Killing %d (%s) after timeout of %f seconds" + % (proc.pid, proc.args[0], timeout) + ) proc.kill() proc.wait() @@ -178,42 +196,44 @@ class Tests(dbusmock.DBusTestCase): # def start_daemon(self, cfgfile=None, warns=False, history_dir_override=None): - '''Start daemon and create DBus proxy. + """Start daemon and create DBus proxy. Do this after adding the devices you want to test with. At the moment this only works with coldplugging, as we do not currently have a way to inject simulated uevents. When done, this sets self.proxy as the Gio.DBusProxy for upowerd. - ''' + """ env = os.environ.copy() if not cfgfile: - _, cfgfile = tempfile.mkstemp(prefix='upower-cfg-') + _, cfgfile = tempfile.mkstemp(prefix="upower-cfg-") self.addCleanup(os.unlink, cfgfile) - env['UPOWER_CONF_FILE_NAME'] = cfgfile + env["UPOWER_CONF_FILE_NAME"] = cfgfile if history_dir_override is not None: - self.upower_history_dir = env['UPOWER_HISTORY_DIR'] = history_dir_override - env['UPOWER_STATE_DIR'] = history_dir_override + self.upower_history_dir = env["UPOWER_HISTORY_DIR"] = history_dir_override + env["UPOWER_STATE_DIR"] = history_dir_override else: - self.upower_history_dir = env['UPOWER_HISTORY_DIR'] = tempfile.mkdtemp(prefix='upower-history-') - env['UPOWER_STATE_DIR'] = self.upower_history_dir - self.addCleanup(shutil.rmtree, env['UPOWER_HISTORY_DIR']) + self.upower_history_dir = env["UPOWER_HISTORY_DIR"] = tempfile.mkdtemp( + prefix="upower-history-" + ) + env["UPOWER_STATE_DIR"] = self.upower_history_dir + self.addCleanup(shutil.rmtree, env["UPOWER_HISTORY_DIR"]) - env['G_DEBUG'] = 'fatal-criticals' if warns else 'fatal-warnings' + env["G_DEBUG"] = "fatal-criticals" if warns else "fatal-warnings" # note: Python doesn't propagate the setenv from Testbed.new(), so we # have to do that ourselves - env['UMOCKDEV_DIR'] = self.testbed.get_root_dir() + env["UMOCKDEV_DIR"] = self.testbed.get_root_dir() # Hotfix for https://github.com/systemd/systemd/issues/23499 - env['SYSTEMD_DEVICE_VERIFY_SYSFS'] = '0' + env["SYSTEMD_DEVICE_VERIFY_SYSFS"] = "0" self.daemon_log = OutputChecker() - if os.getenv('VALGRIND') is not None: - daemon_path = ['valgrind', self.daemon_path, '-v', '-r'] + if os.getenv("VALGRIND") is not None: + daemon_path = ["valgrind", self.daemon_path, "-v", "-r"] else: - daemon_path = [self.daemon_path, '-v', '-r'] - self.daemon = subprocess.Popen(daemon_path, - env=env, stdout=self.daemon_log.fd, - stderr=subprocess.STDOUT) + daemon_path = [self.daemon_path, "-v", "-r"] + self.daemon = subprocess.Popen( + daemon_path, env=env, stdout=self.daemon_log.fd, stderr=subprocess.STDOUT + ) self.daemon_log.writer_attached() # wait until the daemon gets online timeout = 100 @@ -221,21 +241,27 @@ class Tests(dbusmock.DBusTestCase): time.sleep(0.1) timeout -= 1 try: - self.get_dbus_property('DaemonVersion') + self.get_dbus_property("DaemonVersion") break except GLib.GError: pass else: - self.fail('daemon did not start in 10 seconds') + self.fail("daemon did not start in 10 seconds") self.proxy = Gio.DBusProxy.new_sync( - self.dbus, Gio.DBusProxyFlags.DO_NOT_AUTO_START, None, UP, - '/org/freedesktop/UPower', UP, None) + self.dbus, + Gio.DBusProxyFlags.DO_NOT_AUTO_START, + None, + UP, + "/org/freedesktop/UPower", + UP, + None, + ) - self.assertEqual(self.daemon.poll(), None, 'daemon crashed') + self.assertEqual(self.daemon.poll(), None, "daemon crashed") def stop_daemon(self): - '''Stop the daemon if it is running.''' + """Stop the daemon if it is running.""" if self.daemon: try: @@ -255,87 +281,117 @@ class Tests(dbusmock.DBusTestCase): self.proxy = None def get_dbus_property(self, name): - '''Get property value from daemon D-Bus interface.''' + """Get property value from daemon D-Bus interface.""" - return self.dbus.call_sync(UP, '/org/freedesktop/UPower', - 'org.freedesktop.DBus.Properties', - 'Get', GLib.Variant('(ss)', (UP, name)), - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, None).unpack()[0] + return self.dbus.call_sync( + UP, + "/org/freedesktop/UPower", + "org.freedesktop.DBus.Properties", + "Get", + GLib.Variant("(ss)", (UP, name)), + None, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + None, + ).unpack()[0] def get_dbus_display_property(self, name): - '''Get property value from display device D-Bus interface.''' + """Get property value from display device D-Bus interface.""" - return self.dbus.call_sync(UP, UP_DISPLAY_OBJECT_PATH, - 'org.freedesktop.DBus.Properties', - 'Get', GLib.Variant('(ss)', (UP_DEVICE, name)), - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, None).unpack()[0] + return self.dbus.call_sync( + UP, + UP_DISPLAY_OBJECT_PATH, + "org.freedesktop.DBus.Properties", + "Get", + GLib.Variant("(ss)", (UP_DEVICE, name)), + None, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + None, + ).unpack()[0] def get_dbus_dev_property(self, device, name): - '''Get property value from an upower device D-Bus path.''' + """Get property value from an upower device D-Bus path.""" - return self.dbus.call_sync(UP, device, - 'org.freedesktop.DBus.Properties', - 'Get', GLib.Variant('(ss)', (UP_DEVICE, name)), - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, None).unpack()[0] + return self.dbus.call_sync( + UP, + device, + "org.freedesktop.DBus.Properties", + "Get", + GLib.Variant("(ss)", (UP_DEVICE, name)), + None, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + None, + ).unpack()[0] def get_dbus_dev_properties(self, device): - '''Get property values from an upower device D-Bus path.''' + """Get property values from an upower device D-Bus path.""" - return self.dbus.call_sync(UP, device, - 'org.freedesktop.DBus.Properties', - 'GetAll', GLib.Variant('(s)', (UP_DEVICE,)), - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, None).unpack()[0] + return self.dbus.call_sync( + UP, + device, + "org.freedesktop.DBus.Properties", + "GetAll", + GLib.Variant("(s)", (UP_DEVICE,)), + None, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + None, + ).unpack()[0] def enable_charge_limits(self, device, enable): - self.dbus.call_sync(UP, device, - 'org.freedesktop.UPower.Device', - 'EnableChargeThreshold', - GLib.Variant('(b)', (enable,)), - None, - Gio.DBusCallFlags.NO_AUTO_START, - -1, None) - + self.dbus.call_sync( + UP, + device, + "org.freedesktop.UPower.Device", + "EnableChargeThreshold", + GLib.Variant("(b)", (enable,)), + None, + Gio.DBusCallFlags.NO_AUTO_START, + -1, + None, + ) def assertDevs(self, expected): devs = self.proxy.EnumerateDevices() - names = sorted(n.split('/')[-1] for n in devs) + names = sorted(n.split("/")[-1] for n in devs) self.assertEqual(names, sorted(expected.keys())) for n in names: - props = self.get_dbus_dev_properties('/org/freedesktop/UPower/devices/' + n) + props = self.get_dbus_dev_properties("/org/freedesktop/UPower/devices/" + n) for k, v in expected[n].items(): - self.assertEqual(props[k], v, msg=f'Property "{k}" of "{n}" should be {v} but is {props[k]}') + self.assertEqual( + props[k], + v, + msg=f'Property "{k}" of "{n}" should be {v} but is {props[k]}', + ) def start_logind(self, parameters=None): - self.logind, self.logind_obj = self.spawn_server_template('logind', - parameters or {}) + self.logind, self.logind_obj = self.spawn_server_template( + "logind", parameters or {} + ) self.addCleanup(self.stop_process, self.logind) def start_bluez(self, parameters=None): - self.bluez, self.bluez_obj = self.spawn_server_template('bluez5', - parameters or {}) + self.bluez, self.bluez_obj = self.spawn_server_template( + "bluez5", parameters or {} + ) self.addCleanup(self.stop_process, self.bluez) def start_polkitd(self, parameters=None): - self.polkit, self.polkit_obj = self.spawn_server_template('polkitd', - parameters or {}) + self.polkit, self.polkit_obj = self.spawn_server_template( + "polkitd", parameters or {} + ) self.addCleanup(self.stop_process, self.polkit) def assertEventually(self, condition, message=None, timeout=50, value=True): - '''Assert that condition function eventually returns True. + """Assert that condition function eventually returns True. Timeout is in deciseconds, defaulting to 50 (5 seconds). message is printed on failure. - ''' + """ while timeout >= 0: context = GLib.MainContext.default() while context.iteration(False): @@ -345,7 +401,7 @@ class Tests(dbusmock.DBusTestCase): timeout -= 1 time.sleep(0.1) else: - self.fail(message or 'timed out waiting for ' + str(condition)) + self.fail(message or "timed out waiting for " + str(condition)) def wait_for_mainloop(self): ml = GLib.MainLoop() @@ -357,207 +413,315 @@ class Tests(dbusmock.DBusTestCase): # def test_daemon_version(self): - '''DaemonVersion property''' + """DaemonVersion property""" self.start_daemon() self.assertEqual(self.proxy.EnumerateDevices(), []) - self.assertRegex(self.get_dbus_property('DaemonVersion'), '^[0-9.]+$') + self.assertRegex(self.get_dbus_property("DaemonVersion"), "^[0-9.]+$") # without any devices we should assume AC - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_no_devices(self): - '''no devices''' + """no devices""" # without any devices we should assume AC self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_props_online_ac(self): - '''properties with online AC''' + """properties with online AC""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '1'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "1"], [] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) ac_up = devs[0] - self.assertTrue('line_power_AC' in ac_up) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(ac_up, 'PowerSupply'), True) - self.assertEqual(self.get_dbus_dev_property(ac_up, 'Type'), UP_DEVICE_KIND_LINE_POWER) - self.assertEqual(self.get_dbus_dev_property(ac_up, 'Online'), True) - self.assertEqual(self.get_dbus_dev_property(ac_up, 'NativePath'), 'AC') + self.assertTrue("line_power_AC" in ac_up) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(ac_up, "PowerSupply"), True) + self.assertEqual( + self.get_dbus_dev_property(ac_up, "Type"), UP_DEVICE_KIND_LINE_POWER + ) + self.assertEqual(self.get_dbus_dev_property(ac_up, "Online"), True) + self.assertEqual(self.get_dbus_dev_property(ac_up, "NativePath"), "AC") self.stop_daemon() def test_props_offline_ac(self): - '''properties with offline AC''' + """properties with offline AC""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) # we don't have any known online power device now, but still no battery - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(devs[0], 'Online'), False) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(devs[0], "Online"), False) self.stop_daemon() def test_macbook_capacity(self): - '''MacBooks have incorrect sysfs capacity''' + """MacBooks have incorrect sysfs capacity""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'capacity', '60', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) - self.testbed.add_device('virtual', 'virtual/dmi', None, - ['id/product_name', 'MacBookAir7,2'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "capacity", + "60", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) + self.testbed.add_device( + "virtual", "virtual/dmi", None, ["id/product_name", "MacBookAir7,2"], [] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 2) - if 'BAT' in devs[0] == ac_up: + if "BAT" in devs[0] == ac_up: (bat0_up, ac_up) = devs else: (ac_up, bat0_up) = devs - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 80) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 80) def test_macbook_uevent(self): - '''MacBooks sent uevent 5 seconds before battery updates''' + """MacBooks sent uevent 5 seconds before battery updates""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) - self.testbed.add_device('virtual', 'virtual/dmi', None, - ['id/product_name', 'MacBookAir7,2'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) + self.testbed.add_device( + "virtual", "virtual/dmi", None, ["id/product_name", "MacBookAir7,2"], [] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 2) - if 'BAT' in devs[0] == ac_up: + if "BAT" in devs[0] == ac_up: (bat0_up, ac_up) = devs else: (ac_up, bat0_up) = devs - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) - self.testbed.set_attribute(ac, 'online', '1') - self.testbed.uevent(ac, 'change') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) + self.testbed.set_attribute(ac, "online", "1") + self.testbed.uevent(ac, "change") + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) time.sleep(3) - self.testbed.set_attribute(bat0, 'status', 'Charging') + self.testbed.set_attribute(bat0, "status", "Charging") time.sleep(1) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_CHARGING) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_CHARGING + ) # We stopped polling now, so this update will *not* be read, even if # we send a new uevent, as the 'online' state does not change. - self.testbed.uevent(ac, 'change') + self.testbed.uevent(ac, "change") time.sleep(2) - self.testbed.set_attribute(bat0, 'status', 'Discharging') + self.testbed.set_attribute(bat0, "status", "Discharging") time.sleep(1) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_CHARGING) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_CHARGING + ) def test_battery_ac(self): - '''properties with dynamic battery/AC''' + """properties with dynamic battery/AC""" # offline AC + discharging battery - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 2) - if 'BAT' in devs[0] == ac_up: + if "BAT" in devs[0] == ac_up: (bat0_up, ac_up) = devs else: (ac_up, bat0_up) = devs # we don't have any known online power device now, but still no battery - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 80.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 48.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFull'), 60.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFullDesign'), 80.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Voltage'), 12.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'NativePath'), 'BAT0') + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 80.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 48.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFull"), 60.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 80.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "NativePath"), "BAT0") self.stop_daemon() # offline AC + discharging low battery - self.testbed.set_attribute(bat0, 'energy_now', '1500000') + self.testbed.set_attribute(bat0, "energy_now", "1500000") self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_CRITICAL) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 2.5) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_BATTERY) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_CRITICAL + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 2.5) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_BATTERY + ) self.stop_daemon() # now connect AC again - self.testbed.set_attribute(ac, 'online', '1') + self.testbed.set_attribute(ac, "online", "1") self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 2) # we don't have any known online power device now, but still no battery - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(ac_up, 'Online'), True) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(ac_up, "Online"), True) self.stop_daemon() def test_multiple_batteries(self): - '''Multiple batteries''' + """Multiple batteries""" # one well charged, one low - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) - self.testbed.add_device('power_supply', 'BAT1', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT1", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() @@ -565,97 +729,164 @@ class Tests(dbusmock.DBusTestCase): # as we have one which is well-charged, the summary state is "not low # battery" - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() # now set both to low - self.testbed.set_attribute(bat0, 'energy_now', '1500000') + self.testbed.set_attribute(bat0, "energy_now", "1500000") self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_CRITICAL) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_CRITICAL + ) self.stop_daemon() def test_unknown_battery_status_no_ac(self): - '''Unknown battery charge status, no AC''' + """Unknown battery charge status, no AC""" for i in range(2): - self.testbed.add_device('power_supply', f'BAT{i}', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + f"BAT{i}", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) # with no other power sources, the OnBattery value here is really # arbitrary, so don't test it. The only thing we know for sure is that # we aren't on low battery self.start_daemon() time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_DISCHARGING) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual( + self.get_dbus_display_property("State"), UP_DEVICE_STATE_DISCHARGING + ) self.stop_daemon() def test_unknown_battery_status_with_ac(self): - '''Unknown battery charge status, with AC''' + """Unknown battery charge status, with AC""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) for i in range(2): - self.testbed.add_device('power_supply', f'BAT{i}', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + f"BAT{i}", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) - self.testbed.set_attribute(ac, 'online', '0') + self.testbed.set_attribute(ac, "online", "0") self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_DISCHARGING) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual( + self.get_dbus_display_property("State"), UP_DEVICE_STATE_DISCHARGING + ) self.stop_daemon() - self.testbed.set_attribute(ac, 'online', '1') + self.testbed.set_attribute(ac, "online", "1") self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_CHARGING) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual( + self.get_dbus_display_property("State"), UP_DEVICE_STATE_CHARGING + ) self.stop_daemon() def test_battery_state_guessing(self): energy_now = 48000000 - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', str(energy_now), - 'voltage_now', '12000000'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + str(energy_now), + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() - self.assertDevs({ 'battery_BAT0': { 'State' : UP_DEVICE_STATE_UNKNOWN }, 'line_power_AC' : {} }) + self.assertDevs( + {"battery_BAT0": {"State": UP_DEVICE_STATE_UNKNOWN}, "line_power_AC": {}} + ) # Discharge for 20s: for i in range(25): time.sleep(1) # 1W usage over 1 second energy_now -= 1.0 * 1000000 / 3600 - self.testbed.set_attribute(bat0, 'energy_now', str(int(energy_now))) + self.testbed.set_attribute(bat0, "energy_now", str(int(energy_now))) - self.assertDevs({ 'battery_BAT0': { 'State' : UP_DEVICE_STATE_DISCHARGING }, 'line_power_AC' : {} }) + self.assertDevs( + { + "battery_BAT0": {"State": UP_DEVICE_STATE_DISCHARGING}, + "line_power_AC": {}, + } + ) # History is discarded, we have an unknown state # (the "online" state does not actually matter for the test) - self.testbed.set_attribute(bat0, 'online', '1') - self.testbed.uevent(ac, 'change') + self.testbed.set_attribute(bat0, "online", "1") + self.testbed.uevent(ac, "change") time.sleep(1) # FIXME: this does not get reset # https://gitlab.freedesktop.org/upower/upower/-/issues/230 @@ -666,83 +897,159 @@ class Tests(dbusmock.DBusTestCase): time.sleep(1) # 1W charge over 1 second energy_now += 1.0 * 1000000 / 3600 - self.testbed.set_attribute(bat0, 'energy_now', str(int(energy_now))) + self.testbed.set_attribute(bat0, "energy_now", str(int(energy_now))) - self.assertDevs({ 'battery_BAT0': { 'State' : UP_DEVICE_STATE_CHARGING }, 'line_power_AC' : {} }) + self.assertDevs( + {"battery_BAT0": {"State": UP_DEVICE_STATE_CHARGING}, "line_power_AC": {}} + ) self.stop_daemon() def test_display_pending_charge_one_battery(self): - '''One battery pending-charge''' + """One battery pending-charge""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Not charging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '40', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Not charging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "40", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_PENDING_CHARGE) + self.assertEqual( + self.get_dbus_display_property("State"), UP_DEVICE_STATE_PENDING_CHARGE + ) self.stop_daemon() def test_empty_guessing(self): - '''One empty batter not reporting a state''' + """One empty batter not reporting a state""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Unknown', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '0', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Unknown", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "0", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() - self.assertDevs({ 'battery_BAT0': { 'State' : UP_DEVICE_STATE_EMPTY } }) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_EMPTY) + self.assertDevs({"battery_BAT0": {"State": UP_DEVICE_STATE_EMPTY}}) + self.assertEqual(self.get_dbus_display_property("State"), UP_DEVICE_STATE_EMPTY) self.stop_daemon() def test_full_guessing(self): - '''One full batter not reporting a state''' + """One full batter not reporting a state""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Unknown', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '99', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Unknown", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "99", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() - self.assertDevs({ 'battery_BAT0': { 'State' : UP_DEVICE_STATE_FULLY_CHARGED } }) - self.assertEqual(self.get_dbus_display_property('State'), UP_DEVICE_STATE_FULLY_CHARGED) + self.assertDevs({"battery_BAT0": {"State": UP_DEVICE_STATE_FULLY_CHARGED}}) + self.assertEqual( + self.get_dbus_display_property("State"), UP_DEVICE_STATE_FULLY_CHARGED + ) self.stop_daemon() def test_display_state_aggregation(self): - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Not charging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '40', - 'voltage_now', '12000000'], []) - bat1 = self.testbed.add_device('power_supply', 'BAT1', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Not charging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '40', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Not charging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "40", + "voltage_now", + "12000000", + ], + [], + ) + bat1 = self.testbed.add_device( + "power_supply", + "BAT1", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Not charging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "40", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") # The unknown poll can cause issues for test synchronization config.write("[UPower]\n") config.write("NoPollBatteries=true\n") @@ -753,28 +1060,43 @@ class Tests(dbusmock.DBusTestCase): devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 2) - ANY = -1 - TBD = -2 - CONFLICT = -3 - UNKNOWN = UP_DEVICE_STATE_UNKNOWN - CHARGING = UP_DEVICE_STATE_CHARGING + ANY = -1 + TBD = -2 + CONFLICT = -3 + UNKNOWN = UP_DEVICE_STATE_UNKNOWN + CHARGING = UP_DEVICE_STATE_CHARGING DISCHARGING = UP_DEVICE_STATE_DISCHARGING - EMPTY = UP_DEVICE_STATE_EMPTY - FULL = UP_DEVICE_STATE_FULLY_CHARGED - P_CHARGE = UP_DEVICE_STATE_PENDING_CHARGE + EMPTY = UP_DEVICE_STATE_EMPTY + FULL = UP_DEVICE_STATE_FULLY_CHARGED + P_CHARGE = UP_DEVICE_STATE_PENDING_CHARGE P_DISCHARGE = UP_DEVICE_STATE_PENDING_DISCHARGE - states = [ 'Unknown', 'Charging', 'Discharging', 'Empty', 'Full', 'Not Charging' ] #, 'Pending Discharge' ] + states = [ + "Unknown", + "Charging", + "Discharging", + "Empty", + "Full", + "Not Charging", + ] # , 'Pending Discharge' ] # pending discharge does not exist on Linux. List it, but it is not tested display_device_state = [ # UNKNOWN , CHARGING , DISCHARGING, EMPTY , FULL , P_CHARGE , P_DISCHARGE - (ANY , CHARGING , DISCHARGING, ANY , ANY , TBD , ANY), - (CHARGING , CHARGING , CONFLICT , CHARGING , CHARGING , CHARGING , CHARGING), - (DISCHARGING, CONFLICT , DISCHARGING, DISCHARGING, DISCHARGING, DISCHARGING, DISCHARGING), - (ANY , CHARGING , DISCHARGING, EMPTY , ANY , TBD , ANY), - (ANY , CHARGING , DISCHARGING, ANY , ANY , TBD , ANY), - (TBD , CHARGING , DISCHARGING, TBD , TBD , P_CHARGE , ANY), - (ANY , CHARGING , DISCHARGING, ANY , ANY , ANY , ANY), + (ANY, CHARGING, DISCHARGING, ANY, ANY, TBD, ANY), + (CHARGING, CHARGING, CONFLICT, CHARGING, CHARGING, CHARGING, CHARGING), + ( + DISCHARGING, + CONFLICT, + DISCHARGING, + DISCHARGING, + DISCHARGING, + DISCHARGING, + DISCHARGING, + ), + (ANY, CHARGING, DISCHARGING, EMPTY, ANY, TBD, ANY), + (ANY, CHARGING, DISCHARGING, ANY, ANY, TBD, ANY), + (TBD, CHARGING, DISCHARGING, TBD, TBD, P_CHARGE, ANY), + (ANY, CHARGING, DISCHARGING, ANY, ANY, ANY, ANY), ] self.daemon_log.clear() @@ -783,23 +1105,27 @@ class Tests(dbusmock.DBusTestCase): # The table should be mirrored assert display_device_state[i][j] == display_device_state[j][i] - print(f'Test states are {states[i]} and {states[j]} expected state is {states[display_device_state[i][j]]}') + print( + f"Test states are {states[i]} and {states[j]} expected state is {states[display_device_state[i][j]]}" + ) - self.testbed.set_attribute(bat0, 'status', states[i]) - self.testbed.set_attribute(bat1, 'status', states[j]) - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "status", states[i]) + self.testbed.set_attribute(bat1, "status", states[j]) + self.testbed.uevent(bat0, "change") # We can't guarantee that both uevents are processed without # the idle handler running. So, lets wait for the idle handler # to calculate the composite battery state. - self.daemon_log.check_line('Calculating percentage', timeout=2.0) - self.testbed.uevent(bat1, 'change') + self.daemon_log.check_line("Calculating percentage", timeout=2.0) + self.testbed.uevent(bat1, "change") # TODO: Make this more elegant somehow - lines = self.daemon_log.check_line('Calculating percentage', timeout=2.0) + lines = self.daemon_log.check_line( + "Calculating percentage", timeout=2.0 + ) for l in lines: - found = bool(re.match(b".*Conflicting.*state.*", l)) - if found: - break + found = bool(re.match(b".*Conflicting.*state.*", l)) + if found: + break if display_device_state[i][j] == CONFLICT: self.assertTrue(found) @@ -807,153 +1133,252 @@ class Tests(dbusmock.DBusTestCase): self.assertFalse(found) if display_device_state[i][j] >= 0: - self.assertEqual(self.get_dbus_display_property('State'), display_device_state[i][j], - msg=f"Unexpected aggregate state for states {states[i]} and {states[j]}") + self.assertEqual( + self.get_dbus_display_property("State"), + display_device_state[i][j], + msg=f"Unexpected aggregate state for states {states[i]} and {states[j]}", + ) else: - self.assertIn(self.get_dbus_display_property('State'), ( - UP_DEVICE_STATE_UNKNOWN, - UP_DEVICE_STATE_CHARGING, - UP_DEVICE_STATE_DISCHARGING, - UP_DEVICE_STATE_EMPTY, - UP_DEVICE_STATE_FULLY_CHARGED, - UP_DEVICE_STATE_PENDING_CHARGE, - UP_DEVICE_STATE_PENDING_DISCHARGE), - msg=f"Invalid aggregate state for states {states[i]} and {states[j]}" + self.assertIn( + self.get_dbus_display_property("State"), + ( + UP_DEVICE_STATE_UNKNOWN, + UP_DEVICE_STATE_CHARGING, + UP_DEVICE_STATE_DISCHARGING, + UP_DEVICE_STATE_EMPTY, + UP_DEVICE_STATE_FULLY_CHARGED, + UP_DEVICE_STATE_PENDING_CHARGE, + UP_DEVICE_STATE_PENDING_DISCHARGE, + ), + msg=f"Invalid aggregate state for states {states[i]} and {states[j]}", ) self.stop_daemon() def test_map_pending_charge_to_fully_charged(self): - '''Map pending-charge to fully-charged''' + """Map pending-charge to fully-charged""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Not charging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '100', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Not charging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "100", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_FULLY_CHARGED) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_FULLY_CHARGED + ) self.stop_daemon() # and make sure we still return pending-charge below the threshold - self.testbed.set_attribute(bat0, 'capacity', '89') + self.testbed.set_attribute(bat0, "capacity", "89") self.start_daemon() - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_PENDING_CHARGE) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_PENDING_CHARGE + ) self.stop_daemon() def test_battery_charge(self): - '''battery which reports charge instead of energy + """battery which reports charge instead of energy energy_* is in uWh, while charge_* is in uAh. - ''' - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'charge_now', '7875000', - 'current_now', '787000', - 'voltage_now', '12000000'], []) + """ + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "charge_now", + "7875000", + "current_now", + "787000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 75.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 94.5) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFull'), 126.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFullDesign'), 132.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Voltage'), 12.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Temperature'), 0.0) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 75.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 94.5) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFull"), 126.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Temperature"), 0.0) self.stop_daemon() def test_battery_energy_charge_mixed(self): - '''battery which reports both current charge and energy''' + """battery which reports both current charge and energy""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'charge_now', '4200000', - 'energy_now', '9999999', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "charge_now", + "4200000", + "energy_now", + "9999999", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertAlmostEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 50.4) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFull'), 126.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFullDesign'), 132.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Voltage'), 12.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 40.0) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertAlmostEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 50.4) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFull"), 126.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 40.0) self.stop_daemon() def test_battery_capacity_and_charge(self): - '''battery which reports capacity and charge_full''' + """battery which reports capacity and charge_full""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'charge_full', '10500000', - 'charge_full_design', '11000000', - 'capacity', '40', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "charge_full", + "10500000", + "charge_full_design", + "11000000", + "capacity", + "40", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 40.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 50.4) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFull'), 126.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFullDesign'), 132.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Voltage'), 12.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_BATTERY) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 40.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 50.4) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFull"), 126.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_BATTERY + ) - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_battery_overfull(self): - '''battery which reports a > 100% percentage for a full battery''' + """battery which reports a > 100% percentage for a full battery""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Full', - 'capacity_level', 'Normal\n', - 'current_now', '1000', - 'charge_now', '11000000', - 'charge_full', '10000000', - 'charge_full_design', '11000000', - 'capacity', '110', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Full", + "capacity_level", + "Normal\n", + "current_now", + "1000", + "charge_now", + "11000000", + "charge_full", + "10000000", + "charge_full_design", + "11000000", + "capacity", + "110", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon(warns=True) devs = self.proxy.EnumerateDevices() @@ -961,94 +1386,164 @@ class Tests(dbusmock.DBusTestCase): bat0_up = devs[0] # should clamp percentage - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 100.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'State'), - UP_DEVICE_STATE_FULLY_CHARGED) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 100.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "IsPresent"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "State"), UP_DEVICE_STATE_FULLY_CHARGED + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 132.0) # should adjust EnergyFull to reality, not what the battery claims - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFull'), 132.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyFullDesign'), 132.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Voltage'), 12.0) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_BATTERY) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFull"), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyFullDesign"), 132.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Voltage"), 12.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_BATTERY + ) # capacity_level is unused because a 'capacity' attribute is present and used instead - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "BatteryLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_battery_temperature(self): - '''battery which reports temperature''' + """battery which reports temperature""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'temp', '254', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "temp", + "254", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Temperature'), 25.4) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 2.5) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 1.5) - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_CRITICAL) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Temperature"), 25.4) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 2.5) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 1.5) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_CRITICAL + ) self.stop_daemon() def test_battery_broken_name(self): - '''Battery with funky kernel name''' + """Battery with funky kernel name""" - self.testbed.add_device('power_supply', 'bq24735@5-0009', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "bq24735@5-0009", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() - self.assertEqual(self.get_dbus_display_property('IsPresent'), True) + self.assertEqual(self.get_dbus_display_property("IsPresent"), True) self.stop_daemon() def test_battery_charge_limit_multiple_batteries(self): - '''Battery with charge limits with multiple batteries''' + """Battery with charge limits with multiple batteries""" if not self.polkit: self.start_polkitd({}) - self.polkit_obj.SetAllowed(['org.freedesktop.UPower.enable-charging-limit']) + self.polkit_obj.SetAllowed(["org.freedesktop.UPower.enable-charging-limit"]) - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "70,80" + ) - self.testbed.add_device('power_supply', 'BAT1', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT1", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT1", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT1", "CHARGE_LIMIT", "70,80" + ) self.start_daemon() devs = self.proxy.EnumerateDevices() @@ -1057,52 +1552,98 @@ class Tests(dbusmock.DBusTestCase): bat1_up = devs[0] for bat in [bat0_up, bat1_up]: - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), False) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeStartThreshold'), 70) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeEndThreshold'), 80) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdEnabled"), False + ) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeStartThreshold"), 70 + ) + self.assertEqual(self.get_dbus_dev_property(bat, "ChargeEndThreshold"), 80) self.enable_charge_limits(bat0_up, True) self.enable_charge_limits(bat1_up, True) for bat in [bat0_up, bat1_up]: - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), True) - battery_name = bat.split('_')[-1] - with open(f'/sys/class/power_supply/{battery_name}/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '70') - with open(f'/sys/class/power_supply/{battery_name}/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '80') + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdEnabled"), True + ) + battery_name = bat.split("_")[-1] + with open( + f"/sys/class/power_supply/{battery_name}/charge_control_start_threshold" + ) as fp: + self.assertEqual(fp.read(), "70") + with open( + f"/sys/class/power_supply/{battery_name}/charge_control_end_threshold" + ) as fp: + self.assertEqual(fp.read(), "80") def test_battery_charge_limit_multiple_batteries_polkit_not_allowed(self): - '''Battery with charge limits with multiple batteries, but polkit isn't allowed''' + """Battery with charge limits with multiple batteries, but polkit isn't allowed""" if not self.polkit: self.start_polkitd({}) - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "70,80" + ) - self.testbed.add_device('power_supply', 'BAT1', None, - ['type', 'Battery', - 'present', '1', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT1", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT1", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT1", "CHARGE_LIMIT", "70,80" + ) self.start_daemon() devs = self.proxy.EnumerateDevices() @@ -1111,10 +1652,16 @@ class Tests(dbusmock.DBusTestCase): bat1_up = devs[0] for bat in [bat0_up, bat1_up]: - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), False) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeStartThreshold'), 70) - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeEndThreshold'), 80) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdEnabled"), False + ) + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeStartThreshold"), 70 + ) + self.assertEqual(self.get_dbus_dev_property(bat, "ChargeEndThreshold"), 80) with self.assertRaises(Exception) as cm: self.enable_charge_limits(bat0_up, True) @@ -1127,39 +1674,69 @@ class Tests(dbusmock.DBusTestCase): self.assertIn("Operation is not allowed", str(ex)) for bat in [bat0_up, bat1_up]: - self.assertEqual(self.get_dbus_dev_property(bat, 'ChargeThresholdEnabled'), False) - battery_name = bat.split('_')[-1] - with open(f'/sys/class/power_supply/{battery_name}/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '0') - with open(f'/sys/class/power_supply/{battery_name}/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + self.assertEqual( + self.get_dbus_dev_property(bat, "ChargeThresholdEnabled"), False + ) + battery_name = bat.split("_")[-1] + with open( + f"/sys/class/power_supply/{battery_name}/charge_control_start_threshold" + ) as fp: + self.assertEqual(fp.read(), "0") + with open( + f"/sys/class/power_supply/{battery_name}/charge_control_end_threshold" + ) as fp: + self.assertEqual(fp.read(), "100") def test_battery_charge_limit_supported(self): - '''Battery with charge_control_start/end_threshold supported''' + """Battery with charge_control_start/end_threshold supported""" if not self.polkit: self.start_polkitd({}) - self.polkit_obj.SetAllowed(['org.freedesktop.UPower.enable-charging-limit']) + self.polkit_obj.SetAllowed(["org.freedesktop.UPower.enable-charging-limit"]) - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'model_name', 'test', - 'serial_number', '12', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "model_name", + "test", + "serial_number", + "12", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "70,80" + ) def start_daemon(charge_threshold_value=None): - upower_history_dir_override = tempfile.mkdtemp(prefix='upower-history-') + upower_history_dir_override = tempfile.mkdtemp(prefix="upower-history-") if charge_threshold_value is not None: - with open(os.path.join(upower_history_dir_override, "charging-threshold-status") , 'w') as fp: + with open( + os.path.join( + upower_history_dir_override, "charging-threshold-status" + ), + "w", + ) as fp: fp.write(charge_threshold_value) self.start_daemon(history_dir_override=upower_history_dir_override) @@ -1168,25 +1745,35 @@ class Tests(dbusmock.DBusTestCase): return devs[0] bat0_up = start_daemon() - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 70) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 80) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeStartThreshold"), 70 + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "ChargeEndThreshold"), 80) self.enable_charge_limits(bat0_up, True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), True) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), True + ) # charge limits enabled? - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '70') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '80') + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "70") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "80") self.enable_charge_limits(bat0_up, False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '0') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "0") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "100") # TODO: Test changing CHARGE_LIMIT # self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '20,30') @@ -1199,43 +1786,75 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() # On startup with threshold set - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '90,100') - bat0_up = start_daemon(charge_threshold_value='1') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 90) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 100) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "90,100" + ) + bat0_up = start_daemon(charge_threshold_value="1") + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeStartThreshold"), 90 + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "ChargeEndThreshold"), 100) - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '90') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "90") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "100") def test_battery_charge_limit_supported_polkit_not_allowed(self): - '''Battery with charge_control_start/end_threshold supported''' + """Battery with charge_control_start/end_threshold supported""" if not self.polkit: self.start_polkitd({}) - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'model_name', 'test', - 'serial_number', '12', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '0', - 'charge_control_end_threshold', '100', - ], []) - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '70,80') + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "model_name", + "test", + "serial_number", + "12", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "0", + "charge_control_end_threshold", + "100", + ], + [], + ) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "70,80" + ) def start_daemon(charge_threshold_value=None): - upower_history_dir_override = tempfile.mkdtemp(prefix='upower-history-') + upower_history_dir_override = tempfile.mkdtemp(prefix="upower-history-") if charge_threshold_value is not None: - with open(os.path.join(upower_history_dir_override, "charging-threshold-status") , 'w') as fp: + with open( + os.path.join( + upower_history_dir_override, "charging-threshold-status" + ), + "w", + ) as fp: fp.write(charge_threshold_value) self.start_daemon(history_dir_override=upower_history_dir_override) @@ -1244,76 +1863,114 @@ class Tests(dbusmock.DBusTestCase): return devs[0] bat0_up = start_daemon() - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 70) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 80) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeStartThreshold"), 70 + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "ChargeEndThreshold"), 80) with self.assertRaises(Exception) as cm: self.enable_charge_limits(bat0_up, True) ex = cm.exception self.assertIn("Operation is not allowed", str(ex)) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) # charge limits enabled? - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '0') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "0") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "100") with self.assertRaises(Exception) as cm: self.enable_charge_limits(bat0_up, False) ex = cm.exception self.assertIn("Operation is not allowed", str(ex)) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '0') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "0") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "100") self.stop_daemon() # On startup with threshold set - self.testbed.set_property("/sys/class/power_supply/BAT0", 'CHARGE_LIMIT', '90,100') - bat0_up = start_daemon(charge_threshold_value='1') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), True) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeStartThreshold'), 90) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeEndThreshold'), 100) + self.testbed.set_property( + "/sys/class/power_supply/BAT0", "CHARGE_LIMIT", "90,100" + ) + bat0_up = start_daemon(charge_threshold_value="1") + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdSupported"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), True + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeStartThreshold"), 90 + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "ChargeEndThreshold"), 100) - with open('/sys/class/power_supply/BAT0/charge_control_start_threshold') as fp: - self.assertEqual(fp.read(), '90') - with open('/sys/class/power_supply/BAT0/charge_control_end_threshold') as fp: - self.assertEqual(fp.read(), '100') + with open("/sys/class/power_supply/BAT0/charge_control_start_threshold") as fp: + self.assertEqual(fp.read(), "90") + with open("/sys/class/power_supply/BAT0/charge_control_end_threshold") as fp: + self.assertEqual(fp.read(), "100") def test_battery_charge_threshold_unsupported(self): - '''Battery with only start_threshold supported''' + """Battery with only start_threshold supported""" if not self.polkit: self.start_polkitd({}) - self.polkit_obj.SetAllowed(['org.freedesktop.UPower.enable-charging-limit']) + self.polkit_obj.SetAllowed(["org.freedesktop.UPower.enable-charging-limit"]) - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'model_name', 'test', - 'serial_number', '12', - 'status', 'unknown', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000', - 'charge_control_start_threshold', '80', - ], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "model_name", + "test", + "serial_number", + "12", + "status", + "unknown", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + "charge_control_start_threshold", + "80", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdSupported'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'ChargeThresholdEnabled'), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdSupported"), False + ) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "ChargeThresholdEnabled"), False + ) with self.assertRaises(Exception) as cm: self.enable_charge_limits(bat0_up, True) @@ -1323,164 +1980,260 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_battery_zero_power_draw(self): - '''Battery with zero power draw, e.g. in a dual-battery system''' + """Battery with zero power draw, e.g. in a dual-battery system""" - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Full', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '60000000', - 'voltage_now', '12000000', - 'power_now', '0', - 'current_now', '787000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Full", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "60000000", + "voltage_now", + "12000000", + "power_now", + "0", + "current_now", + "787000", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'EnergyRate'), 0.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "EnergyRate"), 0.0) self.stop_daemon() def test_ups_no_ac(self): - '''UPS properties without AC''' + """UPS properties without AC""" # add a charging UPS - ups0 = self.testbed.add_device('usbmisc', 'hiddev0', None, [], - ['DEVNAME', 'null', 'UPOWER_VENDOR', 'APC', - 'UPOWER_BATTERY_TYPE', 'ups', - 'UPOWER_FAKE_DEVICE', '1', - 'UPOWER_FAKE_HID_CHARGING', '1', - 'UPOWER_FAKE_HID_PERCENTAGE', '70']) + ups0 = self.testbed.add_device( + "usbmisc", + "hiddev0", + None, + [], + [ + "DEVNAME", + "null", + "UPOWER_VENDOR", + "APC", + "UPOWER_BATTERY_TYPE", + "ups", + "UPOWER_FAKE_DEVICE", + "1", + "UPOWER_FAKE_HID_CHARGING", + "1", + "UPOWER_FAKE_HID_PERCENTAGE", + "70", + ], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) ups0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Vendor'), 'APC') - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Percentage'), 70.0) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'State'), UP_DEVICE_STATE_CHARGING) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'PowerSupply'), True) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Type'), UP_DEVICE_KIND_UPS) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "Vendor"), "APC") + self.assertEqual(self.get_dbus_dev_property(ups0_up, "IsPresent"), True) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "Percentage"), 70.0) + self.assertEqual( + self.get_dbus_dev_property(ups0_up, "State"), UP_DEVICE_STATE_CHARGING + ) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "PowerSupply"), True) + self.assertEqual( + self.get_dbus_dev_property(ups0_up, "Type"), UP_DEVICE_KIND_UPS + ) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() # now switch to discharging UPS - self.testbed.set_property(ups0, 'UPOWER_FAKE_HID_CHARGING', '0') + self.testbed.set_property(ups0, "UPOWER_FAKE_HID_CHARGING", "0") self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) self.assertEqual(devs[0], ups0_up) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'IsPresent'), True) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Percentage'), 70.0) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_DISCHARGING) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "IsPresent"), True) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "Percentage"), 70.0) + self.assertEqual( + self.get_dbus_dev_property(ups0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_DISCHARGING + ) self.stop_daemon() # low UPS charge - self.testbed.set_property(ups0, 'UPOWER_FAKE_HID_PERCENTAGE', '2') + self.testbed.set_property(ups0, "UPOWER_FAKE_HID_PERCENTAGE", "2") self.start_daemon() - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Percentage'), 2.0) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "Percentage"), 2.0) + self.assertEqual( + self.get_dbus_dev_property(ups0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) self.stop_daemon() def test_ups_offline_ac(self): - '''UPS properties with offline AC''' + """UPS properties with offline AC""" # add low charge UPS - ups0 = self.testbed.add_device('usbmisc', 'hiddev0', None, [], - ['DEVNAME', 'null', 'UPOWER_VENDOR', 'APC', - 'UPOWER_BATTERY_TYPE', 'ups', - 'UPOWER_FAKE_DEVICE', '1', - 'UPOWER_FAKE_HID_CHARGING', '0', - 'UPOWER_FAKE_HID_PERCENTAGE', '2']) + ups0 = self.testbed.add_device( + "usbmisc", + "hiddev0", + None, + [], + [ + "DEVNAME", + "null", + "UPOWER_VENDOR", + "APC", + "UPOWER_BATTERY_TYPE", + "ups", + "UPOWER_FAKE_DEVICE", + "1", + "UPOWER_FAKE_HID_CHARGING", + "0", + "UPOWER_FAKE_HID_PERCENTAGE", + "2", + ], + ) # add an offline AC, should still be on battery - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '0'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "0"], [] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() - if 'AC' in devs[0]: + if "AC" in devs[0]: ups0_up = devs[1] else: ups0_up = devs[0] self.assertEqual(len(devs), 2) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'Percentage'), 2.0) - self.assertEqual(self.get_dbus_dev_property(ups0_up, 'State'), UP_DEVICE_STATE_DISCHARGING) - self.assertEqual(self.get_dbus_property('OnBattery'), True) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual(self.get_dbus_dev_property(ups0_up, "Percentage"), 2.0) + self.assertEqual( + self.get_dbus_dev_property(ups0_up, "State"), UP_DEVICE_STATE_DISCHARGING + ) + self.assertEqual(self.get_dbus_property("OnBattery"), True) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) self.stop_daemon() # now plug in the AC, should switch to OnBattery=False - self.testbed.set_attribute(ac, 'online', '1') + self.testbed.set_attribute(ac, "online", "1") self.start_daemon() - self.assertEqual(self.get_dbus_property('OnBattery'), False) + self.assertEqual(self.get_dbus_property("OnBattery"), False) # FIXME this is completely wrong # The AC status doesn't change anything, the AC is what powers the UPS # and the UPS powers the desktop # # A plugged in UPS is always the one supplying the computer - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) self.stop_daemon() def test_refresh_after_sleep(self): - '''sleep/wake cycle to check we properly refresh the batteries''' + """sleep/wake cycle to check we properly refresh the batteries""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() - self.logind_obj.EmitSignal('', 'PrepareForSleep', 'b', [True]) + self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [True]) self.daemon_log.check_line("Polling will be paused", timeout=1) # simulate some battery drain during sleep for which we then # can check after we 'woke up' - self.testbed.set_attribute(bat0, 'energy_now', '40000000') + self.testbed.set_attribute(bat0, "energy_now", "40000000") - self.logind_obj.EmitSignal('', 'PrepareForSleep', 'b', [False]) + self.logind_obj.EmitSignal("", "PrepareForSleep", "b", [False]) self.daemon_log.check_line("Polling will be resumed", timeout=1) devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 40.0) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 40.0) self.stop_daemon() - @unittest.skipIf(parse_version(dbusmock.__version__) <= parse_version('0.23.1'), 'Not supported in dbusmock version') + @unittest.skipIf( + parse_version(dbusmock.__version__) <= parse_version("0.23.1"), + "Not supported in dbusmock version", + ) def test_prevent_sleep_until_critical_action_is_executed(self): - '''check that critical action is executed when trying to suspend''' + """check that critical action is executed when trying to suspend""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5.0\n") @@ -1497,32 +2250,52 @@ class Tests(dbusmock.DBusTestCase): bat0_up = devs[0] # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") # critical action is scheduled, a block inhibitor lock is taken besides a delay inhibitor lock time.sleep(0.5) - self.assertEventually(lambda: self.get_dbus_display_property('WarningLevel'), value=UP_DEVICE_LEVEL_ACTION) + self.assertEventually( + lambda: self.get_dbus_display_property("WarningLevel"), + value=UP_DEVICE_LEVEL_ACTION, + ) self.assertEqual(len(self.logind_obj.ListInhibitors()), 2) - self.daemon_log.check_line("About to call logind method Hibernate", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method Hibernate", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # block inhibitor lock is released self.assertEqual(len(self.logind_obj.ListInhibitors()), 1) def test_critical_action_is_taken_repeatedly(self): - '''check that critical action works repeatedly (eg. after resume)''' + """check that critical action works repeatedly (eg. after resume)""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5.0\n") @@ -1536,47 +2309,73 @@ class Tests(dbusmock.DBusTestCase): bat0_up = devs[0] # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method Hibernate", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method Hibernate", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # simulate that battery was charged to 100% during sleep - self.testbed.set_attribute(bat0, 'energy_now', '60000000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "60000000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) # simulate that battery was drained to 1% again - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method Hibernate", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method Hibernate", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) self.stop_daemon() os.unlink(config.name) def test_critical_action_is_suspend_and_AllowRiskyCriticalPowerAction_is_true(self): - '''check that critical action is suspend''' + """check that critical action is suspend""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5\n") @@ -1592,38 +2391,59 @@ class Tests(dbusmock.DBusTestCase): # check warning message when CriticalPowerAction=Suspend and AllowRiskyCriticalPowerAction=true self.daemon_log.check_line( - "The \"Suspend\" CriticalPowerAction setting is considered risky:" + 'The "Suspend" CriticalPowerAction setting is considered risky:' " abrupt power loss due to battery exhaustion may lead to data" " corruption. Use AllowRiskyCriticalPowerAction=false to disable" " support for risky settings.", - timeout=UP_DAEMON_ACTION_DELAY + 0.5) + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method Suspend", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method Suspend", timeout=UP_DAEMON_ACTION_DELAY + 0.5 + ) self.stop_daemon() os.unlink(config.name) - def test_critical_action_is_suspend_and_AllowRiskyCriticalPowerAction_is_false(self): - '''check that critical action is suspend''' + def test_critical_action_is_suspend_and_AllowRiskyCriticalPowerAction_is_false( + self, + ): + """check that critical action is suspend""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5\n") @@ -1639,39 +2459,59 @@ class Tests(dbusmock.DBusTestCase): # check warning message when CriticalPowerAction=Suspend and AllowRiskyCriticalPowerAction=false self.daemon_log.check_line( - "The \"Suspend\" CriticalPowerAction setting is considered risky:" + 'The "Suspend" CriticalPowerAction setting is considered risky:' " abrupt power loss due to battery exhaustion may lead to data" - " corruption. The system will perform \"HybridSleep\" instead." + ' corruption. The system will perform "HybridSleep" instead.' " Use AllowRiskyCriticalPowerAction=true to enable support for" " risky settings.", - timeout=UP_DAEMON_ACTION_DELAY + 0.5) + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method HybridSleep", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method HybridSleep", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) self.stop_daemon() os.unlink(config.name) def test_critical_action_is_ignore_and_AllowRiskyCriticalPowerAction_is_true(self): - '''check that critical action is ignore''' + """check that critical action is ignore""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5\n") @@ -1687,38 +2527,57 @@ class Tests(dbusmock.DBusTestCase): # check warning message when CriticalPowerAction=Ignore and AllowRiskyCriticalPowerAction=true self.daemon_log.check_line( - "The \"Ignore\" CriticalPowerAction setting is considered risky:" + 'The "Ignore" CriticalPowerAction setting is considered risky:' " abrupt power loss due to battery exhaustion may lead to data" " corruption. Use AllowRiskyCriticalPowerAction=false to disable" " support for risky settings.", - timeout=UP_DAEMON_ACTION_DELAY + 0.5) + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method Ignore", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method Ignore", timeout=UP_DAEMON_ACTION_DELAY + 0.5 + ) self.stop_daemon() os.unlink(config.name) def test_critical_action_is_ignore_and_AllowRiskyCriticalPowerAction_is_false(self): - '''check that critical action is ignore''' + """check that critical action is ignore""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") config.write("[UPower]\n") config.write("UsePercentageForPolicy=true\n") config.write("PercentageAction=5\n") @@ -1734,39 +2593,57 @@ class Tests(dbusmock.DBusTestCase): # check warning message when CriticalPowerAction=Ignore and AllowRiskyCriticalPowerAction=true self.daemon_log.check_line( - "The \"Ignore\" CriticalPowerAction setting is considered risky:" + 'The "Ignore" CriticalPowerAction setting is considered risky:' " abrupt power loss due to battery exhaustion may lead to data" - " corruption. The system will perform \"HybridSleep\" instead." + ' corruption. The system will perform "HybridSleep" instead.' " Use AllowRiskyCriticalPowerAction=true to enable support for" " risky settings.", - timeout=UP_DAEMON_ACTION_DELAY + 0.5) - + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) # simulate that battery has 1% (less than PercentageAction) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_ACTION) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_ACTION + ) - self.daemon_log.check_line("About to call logind method HybridSleep", timeout=UP_DAEMON_ACTION_DELAY + 0.5) + self.daemon_log.check_line( + "About to call logind method HybridSleep", + timeout=UP_DAEMON_ACTION_DELAY + 0.5, + ) self.stop_daemon() os.unlink(config.name) - def test_low_battery_changes_history_save_interval(self): - '''check that we save the history more quickly on low battery''' + """check that we save the history more quickly on low battery""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() @@ -1774,24 +2651,28 @@ class Tests(dbusmock.DBusTestCase): self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.daemon_log.check_line(f"saving in {UP_HISTORY_SAVE_INTERVAL} seconds", timeout=1) + self.daemon_log.check_line( + f"saving in {UP_HISTORY_SAVE_INTERVAL} seconds", timeout=1 + ) # simulate that battery has 1% (less than 10%) - self.testbed.set_attribute(bat0, 'energy_now', '600000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "600000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('Percentage'), 1) + self.assertEqual(self.get_dbus_display_property("Percentage"), 1) self.daemon_log.check_line("saving to disk earlier due to low power") - self.daemon_log.check_line(f"saving in {UP_HISTORY_SAVE_INTERVAL_LOW_POWER} seconds") + self.daemon_log.check_line( + f"saving in {UP_HISTORY_SAVE_INTERVAL_LOW_POWER} seconds" + ) # simulate that battery was charged to 100% during sleep - self.testbed.set_attribute(bat0, 'energy_now', '60000000') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_now", "60000000") + self.testbed.uevent(bat0, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_display_property('Percentage'), 100) + self.assertEqual(self.get_dbus_display_property("Percentage"), 100) # The 5 seconds were not up yet, and the shorter timeout sticks self.daemon_log.check_line("deferring as earlier timeout is already queued") @@ -1799,61 +2680,96 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_battery_id_change(self): - '''check that we save/load the history correctly when the ID changes''' + """check that we save/load the history correctly when the ID changes""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'manufacturer', 'FDO', - 'model_name', 'Fake Battery', - 'serial_number', '001', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '50000000', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "manufacturer", + "FDO", + "model_name", + "Fake Battery", + "serial_number", + "001", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "50000000", + "voltage_now", + "12000000", + ], + [], + ) self.start_daemon() self.daemon_log.check_line("using id: Fake_Battery-80-001", timeout=1) # Change the serial of the battery - self.testbed.set_attribute(bat0, 'energy_full_design', '90000000') - self.testbed.set_attribute(bat0, 'serial_number', '002') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "energy_full_design", "90000000") + self.testbed.set_attribute(bat0, "serial_number", "002") + self.testbed.uevent(bat0, "change") # This saves the old history, and then opens a new one - self.daemon_log.check_line_re("saved .*/history-time-empty-Fake_Battery-80-001.dat", timeout=1) + self.daemon_log.check_line_re( + "saved .*/history-time-empty-Fake_Battery-80-001.dat", timeout=1 + ) self.daemon_log.check_line("using id: Fake_Battery-90-002", timeout=1) # Only happens once self.daemon_log.check_no_line("using id:", wait=1.0) # Remove the battery - self.testbed.set_attribute(bat0, 'present', '0') - self.testbed.uevent(bat0, 'change') + self.testbed.set_attribute(bat0, "present", "0") + self.testbed.uevent(bat0, "change") # This saves the old history, and does *not* open a new one - self.daemon_log.check_line_re("saved .*/history-time-empty-Fake_Battery-90-002.dat", timeout=1) + self.daemon_log.check_line_re( + "saved .*/history-time-empty-Fake_Battery-90-002.dat", timeout=1 + ) self.daemon_log.check_no_line("using id:", wait=1.0) self.stop_daemon() - def test_percentage_low_icon_set(self): - '''Without battery level, PercentageLow is limit for icon change''' + """Without battery level, PercentageLow is limit for icon change""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '100000000', - 'energy_full_design', '100000000', - 'energy_now', '15000000', - 'capacity', '15', - 'voltage_now', '12000000'], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "100000000", + "energy_full_design", + "100000000", + "energy_now", + "15000000", + "capacity", + "15", + "voltage_now", + "12000000", + ], + [], + ) - config = tempfile.NamedTemporaryFile(delete=False, mode='w') + config = tempfile.NamedTemporaryFile(delete=False, mode="w") # Low, Critical and Action are all needed to avoid fallback to defaults config.write("[UPower]\n") config.write("PercentageLow=20.0\n") @@ -1867,128 +2783,173 @@ class Tests(dbusmock.DBusTestCase): bat0_up = devs[0] # capacity_level is unused because a 'capacity' attribute is present and used instead - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_NONE) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 15.0) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "BatteryLevel"), UP_DEVICE_LEVEL_NONE + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 15.0) # Battery below 20% from config, should set 'caution' icon even if over default (10%) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'IconName'), 'battery-caution-symbolic') + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "IconName"), "battery-caution-symbolic" + ) self.stop_daemon() os.unlink(config.name) def test_vendor_strings(self): - '''manufacturer/model_name/serial_number with valid and invalid strings''' + """manufacturer/model_name/serial_number with valid and invalid strings""" - bat0 = self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000', - # valid ASCII string - 'serial_number', '123ABC', - # valid UTF-8 string - 'manufacturer', '⍾ Batt Inc. ☢'], - []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + # valid ASCII string + "serial_number", + "123ABC", + # valid UTF-8 string + "manufacturer", + "⍾ Batt Inc. ☢", + ], + [], + ) # string with invalid chars - self.testbed.set_attribute_binary(bat0, 'model_name', b'AB\xFFC12\x013') + self.testbed.set_attribute_binary(bat0, "model_name", b"AB\xFFC12\x013") self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Serial'), '123ABC') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Vendor'), '⍾ Batt Inc. ☢') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), 'ABC123') - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Energy'), 1.5) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Serial"), "123ABC") + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Vendor"), "⍾ Batt Inc. ☢") + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), "ABC123") + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Energy"), 1.5) self.stop_daemon() def _add_bt_mouse(self): - '''Add a bluetooth mouse to testbed''' - - self.testbed.add_device('bluetooth', - 'usb1/bluetooth/hci0/hci0:01', - None, - [], []) + """Add a bluetooth mouse to testbed""" self.testbed.add_device( - 'input', - 'usb1/bluetooth/hci0/hci0:01/input2/mouse3', + "bluetooth", "usb1/bluetooth/hci0/hci0:01", None, [], [] + ) + + self.testbed.add_device( + "input", + "usb1/bluetooth/hci0/hci0:01/input2/mouse3", None, - ['uniq', '11:22:33:44:aa:bb'], - ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1']) + ["uniq", "11:22:33:44:aa:bb"], + ["DEVNAME", "input/mouse3", "ID_INPUT_MOUSE", "1"], + ) mousebat0 = self.testbed.add_device( - 'power_supply', - 'usb1/bluetooth/hci0/hci0:01/1/power_supply/hid-11:22:33:44:aa:bb-battery', + "power_supply", + "usb1/bluetooth/hci0/hci0:01/1/power_supply/hid-11:22:33:44:aa:bb-battery", None, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '30', - 'model_name', 'Fancy BT mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "30", + "model_name", + "Fancy BT mouse", + ], + [], + ) return mousebat0 def test_absent_device_battery(self): - '''absent battery''' - - self.testbed.add_device('bluetooth', - 'usb1/bluetooth/hci0/hci0:01', - None, - [], []) + """absent battery""" self.testbed.add_device( - 'input', - 'usb1/bluetooth/hci0/hci0:01/input2/mouse3', + "bluetooth", "usb1/bluetooth/hci0/hci0:01", None, [], [] + ) + + self.testbed.add_device( + "input", + "usb1/bluetooth/hci0/hci0:01/input2/mouse3", None, - ['uniq', '11:22:33:44:aa:bb'], - ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1']) + ["uniq", "11:22:33:44:aa:bb"], + ["DEVNAME", "input/mouse3", "ID_INPUT_MOUSE", "1"], + ) mousebat0 = self.testbed.add_device( - 'power_supply', - 'usb1/bluetooth/hci0/hci0:01/1/power_supply/hid-11:22:33:44:aa:bb-battery', + "power_supply", + "usb1/bluetooth/hci0/hci0:01/1/power_supply/hid-11:22:33:44:aa:bb-battery", None, - ['type', 'Battery', - 'scope', 'Device', - 'online', '1', - 'present', '0', - 'status', 'Discharging', - 'capacity', '0', - 'model_name', 'Fancy BT mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "online", + "1", + "present", + "0", + "status", + "Discharging", + "capacity", + "0", + "model_name", + "Fancy BT mouse", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy BT mouse') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'IsPresent'), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Fancy BT mouse" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "IsPresent"), False) - self.testbed.set_attribute(mousebat0, 'capacity', '100') - self.testbed.set_attribute(mousebat0, 'present', '1') - self.testbed.uevent(mousebat0, 'change') + self.testbed.set_attribute(mousebat0, "capacity", "100") + self.testbed.set_attribute(mousebat0, "present", "1") + self.testbed.uevent(mousebat0, "change") - self.assertEventually(lambda: self.get_dbus_dev_property(mousebat0_up, 'IsPresent'), value=True) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'IsPresent'), True) + self.assertEventually( + lambda: self.get_dbus_dev_property(mousebat0_up, "IsPresent"), value=True + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "IsPresent"), True) - self.testbed.set_attribute(mousebat0, 'capacity', '0') - self.testbed.set_attribute(mousebat0, 'present', '0') - self.testbed.uevent(mousebat0, 'change') + self.testbed.set_attribute(mousebat0, "capacity", "0") + self.testbed.set_attribute(mousebat0, "present", "0") + self.testbed.uevent(mousebat0, "change") - self.assertEventually(lambda: self.get_dbus_dev_property(mousebat0_up, 'IsPresent'), value=False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'IsPresent'), False) + self.assertEventually( + lambda: self.get_dbus_dev_property(mousebat0_up, "IsPresent"), value=False + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "IsPresent"), False) def test_bluetooth_mouse(self): - '''bluetooth mouse battery''' + """bluetooth mouse battery""" self._add_bt_mouse() @@ -1997,33 +2958,37 @@ class Tests(dbusmock.DBusTestCase): self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy BT mouse') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 30) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Fancy BT mouse" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 30) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_dup_bluetooth_mouse(self): - '''BT mouse that also supports HID++''' + """BT mouse that also supports HID++""" # power_supply interface self._add_bt_mouse() # BlueZ BATT service - alias = 'Arc Touch Mouse SE' + alias = "Arc Touch Mouse SE" battery_level = 99 - device_properties = { - 'Appearance': dbus.UInt16(0x03c2, variant_level=1) - } + device_properties = {"Appearance": dbus.UInt16(0x03C2, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) def test_dup_logitech_unifying_usb(self): - 'De-duplicate Logitech HID++ USB/Unifying mice' + "De-duplicate Logitech HID++ USB/Unifying mice" - self.testbed.add_from_file(os.path.join(edir, 'tests/logitech-g903.device')) + self.testbed.add_from_file(os.path.join(edir, "tests/logitech-g903.device")) self.start_daemon() devs = self.proxy.EnumerateDevices() @@ -2032,7 +2997,7 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_bluetooth_mouse_reconnect(self): - '''bluetooth mouse powerdown/reconnect''' + """bluetooth mouse powerdown/reconnect""" mb = self._add_bt_mouse() @@ -2040,17 +3005,17 @@ class Tests(dbusmock.DBusTestCase): devs_before = self.proxy.EnumerateDevices() self.assertEqual(len(devs_before), 1) - self.testbed.uevent(mb, 'remove') + self.testbed.uevent(mb, "remove") time.sleep(1) self.assertEqual(self.proxy.EnumerateDevices(), []) - self.testbed.uevent(mb, 'add') + self.testbed.uevent(mb, "add") time.sleep(0.5) devs_after = self.proxy.EnumerateDevices() self.assertEqual(devs_before, devs_after) # second add, which should be treated as change - self.testbed.uevent(mb, 'add') + self.testbed.uevent(mb, "add") time.sleep(0.5) devs_after = self.proxy.EnumerateDevices() @@ -2059,362 +3024,524 @@ class Tests(dbusmock.DBusTestCase): # with BT devices, original devices don't get removed on powerdown, but # on wakeup we'll get a new one which ought to replace the previous; # emulate that kernel bug - os.unlink(os.path.join(self.testbed.get_sys_dir(), 'class', - 'power_supply', 'hid-11:22:33:44:aa:bb-battery')) + os.unlink( + os.path.join( + self.testbed.get_sys_dir(), + "class", + "power_supply", + "hid-11:22:33:44:aa:bb-battery", + ) + ) mb1 = self.testbed.add_device( - 'power_supply', - 'usb1/bluetooth/hci0/hci0:01/2/power_supply/hid-11:22:33:44:aa:bb-battery', + "power_supply", + "usb1/bluetooth/hci0/hci0:01/2/power_supply/hid-11:22:33:44:aa:bb-battery", None, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '20', - 'model_name', 'Fancy BT mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "20", + "model_name", + "Fancy BT mouse", + ], + [], + ) - self.testbed.uevent(mb1, 'add') + self.testbed.uevent(mb1, "add") time.sleep(0.5) devs_after = self.proxy.EnumerateDevices() self.assertEqual(devs_before, devs_after) mb1_up = devs_after[0] - self.assertEqual(self.get_dbus_dev_property(mb1_up, 'Model'), 'Fancy BT mouse') - self.assertEqual(self.get_dbus_dev_property(mb1_up, 'Percentage'), 20) - self.assertEqual(self.get_dbus_dev_property(mb1_up, 'PowerSupply'), False) + self.assertEqual(self.get_dbus_dev_property(mb1_up, "Model"), "Fancy BT mouse") + self.assertEqual(self.get_dbus_dev_property(mb1_up, "Percentage"), 20) + self.assertEqual(self.get_dbus_dev_property(mb1_up, "PowerSupply"), False) self.stop_daemon() def test_hidpp_mouse(self): - '''HID++ mouse battery''' + """HID++ mouse battery""" - parent = self.testbed.add_device('usb', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2', - None, - [], []) - parent = self.testbed.add_device('hid', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009', - parent, - [], []) - dev = self.testbed.add_device('hid', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A', - parent, - [], []) + parent = self.testbed.add_device( + "usb", "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2", None, [], [] + ) + parent = self.testbed.add_device( + "hid", + "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009", + parent, + [], + [], + ) + dev = self.testbed.add_device( + "hid", + "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A", + parent, + [], + [], + ) parent = dev self.testbed.add_device( - 'input', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/input/input22', + "input", + "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/input/input22", parent, - [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1']) + [], + ["DEVNAME", "input/mouse3", "ID_INPUT_MOUSE", "1"], + ) self.testbed.add_device( - 'power_supply', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/power_supply/hidpp_battery_3', + "power_supply", + "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2/0003:046D:C52B.0009/0003:046D:4101.000A/power_supply/hidpp_battery_3", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '30', - 'serial_number', '123456', - 'model_name', 'Fancy Logitech mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "30", + "serial_number", + "123456", + "model_name", + "Fancy Logitech mouse", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy Logitech mouse') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 30) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Serial'), '123456') - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Fancy Logitech mouse" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 30) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Serial"), "123456") + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_usb_joypad(self): - '''DualShock 4 joypad connected via USB''' + """DualShock 4 joypad connected via USB""" - dev = self.testbed.add_device('usb', - '/devices/pci0000:00/0000:00:14.0/usb3/3-9', - None, - [], []) + dev = self.testbed.add_device( + "usb", "/devices/pci0000:00/0000:00:14.0/usb3/3-9", None, [], [] + ) parent = dev self.testbed.add_device( - 'input', - '/devices/pci0000:00/0000:00:14.0/usb3/3-9/3-9:1.3/0003:054C:09CC.0007/input/input51', + "input", + "/devices/pci0000:00/0000:00:14.0/usb3/3-9/3-9:1.3/0003:054C:09CC.0007/input/input51", parent, - ['name', 'Sony Interactive Entertainment Wireless Controller', - 'uniq', 'ff:ff:ff:ff:ff:ff'], - ['ID_INPUT', '1', - 'ID_INPUT_JOYSTICK', '1']) + [ + "name", + "Sony Interactive Entertainment Wireless Controller", + "uniq", + "ff:ff:ff:ff:ff:ff", + ], + ["ID_INPUT", "1", "ID_INPUT_JOYSTICK", "1"], + ) dev = self.testbed.add_device( - 'power_supply', - '/devices/pci0000:00/0000:00:14.0/usb3/3-9/3-9:1.3/0003:054C:09CC.0007/power_supply/sony_controller_battery_ff:ff:ff:ff:ff:ff', + "power_supply", + "/devices/pci0000:00/0000:00:14.0/usb3/3-9/3-9:1.3/0003:054C:09CC.0007/power_supply/sony_controller_battery_ff:ff:ff:ff:ff:ff", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'status', 'Charging', - 'capacity', '20',], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "status", + "Charging", + "capacity", + "20", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) joypadbat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(joypadbat0_up, 'Model'), 'Sony Interactive Entertainment Wireless Controller') - self.assertEqual(self.get_dbus_dev_property(joypadbat0_up, 'Serial'), 'ff:ff:ff:ff:ff:ff') - self.assertEqual(self.get_dbus_dev_property(joypadbat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(joypadbat0_up, 'Type'), UP_DEVICE_KIND_GAMING_INPUT) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(joypadbat0_up, "Model"), + "Sony Interactive Entertainment Wireless Controller", + ) + self.assertEqual( + self.get_dbus_dev_property(joypadbat0_up, "Serial"), "ff:ff:ff:ff:ff:ff" + ) + self.assertEqual( + self.get_dbus_dev_property(joypadbat0_up, "PowerSupply"), False + ) + self.assertEqual( + self.get_dbus_dev_property(joypadbat0_up, "Type"), + UP_DEVICE_KIND_GAMING_INPUT, + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) def test_hidpp_touchpad_race(self): - '''HID++ touchpad with input node that appears later''' + """HID++ touchpad with input node that appears later""" - parent = self.testbed.add_device('usb', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2', - None, - [], []) - parent = self.testbed.add_device('hid', - '0003:046D:C52B.0009', - parent, - [], []) - dev = self.testbed.add_device('hid', - '0003:046D:4101.000A', - parent, - [], []) + parent = self.testbed.add_device( + "usb", "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2", None, [], [] + ) + parent = self.testbed.add_device("hid", "0003:046D:C52B.0009", parent, [], []) + dev = self.testbed.add_device("hid", "0003:046D:4101.000A", parent, [], []) parent = dev batt_dev = self.testbed.add_device( - 'power_supply', - 'power_supply/hidpp_battery_3', + "power_supply", + "power_supply/hidpp_battery_3", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity_level', 'Full\n', - 'serial_number', '123456', - 'model_name', 'Logitech T650'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity_level", + "Full\n", + "serial_number", + "123456", + "model_name", + "Logitech T650", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Logitech T650') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_BATTERY) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Serial'), '123456') - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Logitech T650" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_BATTERY + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Serial"), "123456") + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) # Now test all the levels - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 100) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_FULL) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 100) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_FULL, + ) self.testbed.add_device( - 'input', - 'input/input22', + "input", + "input/input22", parent, - [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_TOUCHPAD', '1', 'ID_INPUT_MOUSE', '1']) - self.testbed.uevent(batt_dev, 'change') + [], + [ + "DEVNAME", + "input/mouse3", + "ID_INPUT_TOUCHPAD", + "1", + "ID_INPUT_MOUSE", + "1", + ], + ) + self.testbed.uevent(batt_dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_TOUCHPAD) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_TOUCHPAD + ) def test_hidpp_touchpad(self): - '''HID++ touchpad battery with 5 capacity levels''' + """HID++ touchpad battery with 5 capacity levels""" - parent = self.testbed.add_device('usb', - '/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2', - None, - [], []) - parent = self.testbed.add_device('hid', - '0003:046D:C52B.0009', - parent, - [], []) - dev = self.testbed.add_device('hid', - '0003:046D:4101.000A', - parent, - [], []) + parent = self.testbed.add_device( + "usb", "/devices/pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2", None, [], [] + ) + parent = self.testbed.add_device("hid", "0003:046D:C52B.0009", parent, [], []) + dev = self.testbed.add_device("hid", "0003:046D:4101.000A", parent, [], []) parent = dev self.testbed.add_device( - 'input', - 'input/input22', + "input", + "input/input22", parent, - [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_TOUCHPAD', '1', 'ID_INPUT_MOUSE', '1']) + [], + [ + "DEVNAME", + "input/mouse3", + "ID_INPUT_TOUCHPAD", + "1", + "ID_INPUT_MOUSE", + "1", + ], + ) dev = self.testbed.add_device( - 'power_supply', - 'power_supply/hidpp_battery_3', + "power_supply", + "power_supply/hidpp_battery_3", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity_level', 'Full\n', - 'serial_number', '123456', - 'model_name', 'Logitech T650'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity_level", + "Full\n", + "serial_number", + "123456", + "model_name", + "Logitech T650", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Logitech T650') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_TOUCHPAD) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Serial'), '123456') - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Logitech T650" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_TOUCHPAD + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Serial"), "123456") + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) # Now test all the levels - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 100) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_FULL) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 100) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_FULL, + ) - self.testbed.set_attribute(dev, 'capacity_level', 'Critical\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "Critical\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_CRITICAL) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'WarningLevel'), UP_DEVICE_LEVEL_CRITICAL) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 5) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_CRITICAL, + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "WarningLevel"), + UP_DEVICE_LEVEL_CRITICAL, + ) - self.testbed.set_attribute(dev, 'capacity_level', 'Low\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "Low\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 10) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_LOW) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'WarningLevel'), UP_DEVICE_LEVEL_LOW) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 10) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_LOW, + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "WarningLevel"), + UP_DEVICE_LEVEL_LOW, + ) - self.testbed.set_attribute(dev, 'capacity_level', 'High\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "High\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 70) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_HIGH) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 70) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_HIGH, + ) - self.testbed.set_attribute(dev, 'capacity_level', 'Normal\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "Normal\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 55) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_NORMAL) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 55) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_NORMAL, + ) - self.testbed.set_attribute(dev, 'capacity_level', 'Unknown\n') - self.testbed.set_attribute(dev, 'status', 'Charging\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "Unknown\n") + self.testbed.set_attribute(dev, "status", "Charging\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 50.0) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_UNKNOWN) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'State'), UP_DEVICE_STATE_CHARGING) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'IconName'), 'battery-good-charging-symbolic') + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 50.0) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_UNKNOWN, + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "State"), UP_DEVICE_STATE_CHARGING + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "IconName"), + "battery-good-charging-symbolic", + ) - self.testbed.set_attribute(dev, 'capacity_level', 'Full\n') - self.testbed.set_attribute(dev, 'status', 'Full\n') - self.testbed.uevent(dev, 'change') + self.testbed.set_attribute(dev, "capacity_level", "Full\n") + self.testbed.set_attribute(dev, "status", "Full\n") + self.testbed.uevent(dev, "change") time.sleep(0.5) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 100) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'BatteryLevel'), UP_DEVICE_LEVEL_FULL) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'State'), UP_DEVICE_STATE_FULLY_CHARGED) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'IconName'), 'battery-full-charged-symbolic') + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 100) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "BatteryLevel"), + UP_DEVICE_LEVEL_FULL, + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "State"), + UP_DEVICE_STATE_FULLY_CHARGED, + ) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "IconName"), + "battery-full-charged-symbolic", + ) self.stop_daemon() def test_bluetooth_hid_mouse(self): - '''bluetooth HID mouse battery''' + """bluetooth HID mouse battery""" dev = self.testbed.add_device( - 'bluetooth', - '/devices/pci0000:00/0000:00:14.0/usb2/2-7/2-7:1.0/bluetooth/hci0', + "bluetooth", + "/devices/pci0000:00/0000:00:14.0/usb2/2-7/2-7:1.0/bluetooth/hci0", None, - [], []) + [], + [], + ) parent = dev dev = self.testbed.add_device( - 'bluetooth', - 'hci0:256', - parent, - [], ['DEVTYPE', 'link']) + "bluetooth", "hci0:256", parent, [], ["DEVTYPE", "link"] + ) parent = dev dev = self.testbed.add_device( - 'hid', - '0005:046D:B00D.0002', - parent, - [], ['HID_NAME', 'Fancy BT Mouse']) + "hid", "0005:046D:B00D.0002", parent, [], ["HID_NAME", "Fancy BT Mouse"] + ) parent = dev self.testbed.add_device( - 'power_supply', - 'power_supply/hid-00:1f:20:96:33:47-battery', + "power_supply", + "power_supply/hid-00:1f:20:96:33:47-battery", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '30', - 'model_name', 'Fancy BT mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "30", + "model_name", + "Fancy BT mouse", + ], + [], + ) dev = self.testbed.add_device( - 'input', - 'input/input22', - parent, - [], ['ID_INPUT_MOUSE', '1']) + "input", "input/input22", parent, [], ["ID_INPUT_MOUSE", "1"] + ) parent = dev - self.testbed.add_device( - 'input', - 'mouse1', - parent, - [], ['ID_INPUT_MOUSE', '1']) + self.testbed.add_device("input", "mouse1", parent, [], ["ID_INPUT_MOUSE", "1"]) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy BT mouse') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 30) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Fancy BT mouse" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 30) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_virtual_unparented_device(self): - '''Unparented virtual input device''' + """Unparented virtual input device""" - dev = self.testbed.add_device( - 'input', - 'virtual/input/input18', - None, - [], []) + dev = self.testbed.add_device("input", "virtual/input/input18", None, [], []) - acpi = self.testbed.add_device('acpi', 'PNP0C0A:00', None, [], []) - bat0 = self.testbed.add_device('power_supply', 'BAT0', acpi, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + acpi = self.testbed.add_device("acpi", "PNP0C0A:00", None, [], []) + bat0 = self.testbed.add_device( + "power_supply", + "BAT0", + acpi, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) # Generated a critical in older versions of upower self.start_daemon() @@ -2422,188 +3549,261 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_bluetooth_hid_mouse_no_legacy_subdevice(self): - '''bluetooth HID mouse battery''' + """bluetooth HID mouse battery""" dev = self.testbed.add_device( - 'bluetooth', - '/devices/pci0000:00/0000:00:14.0/usb2/2-7/2-7:1.0/bluetooth/hci0', + "bluetooth", + "/devices/pci0000:00/0000:00:14.0/usb2/2-7/2-7:1.0/bluetooth/hci0", None, - [], []) + [], + [], + ) parent = dev dev = self.testbed.add_device( - 'bluetooth', - 'hci0:256', - parent, - [], ['DEVTYPE', 'link']) + "bluetooth", "hci0:256", parent, [], ["DEVTYPE", "link"] + ) parent = dev dev = self.testbed.add_device( - 'hid', - '0005:046D:B00D.0002', - parent, - [], ['HID_NAME', 'Fancy BT Mouse']) + "hid", "0005:046D:B00D.0002", parent, [], ["HID_NAME", "Fancy BT Mouse"] + ) parent = dev self.testbed.add_device( - 'power_supply', - 'power_supply/hid-00:1f:20:96:33:47-battery', + "power_supply", + "power_supply/hid-00:1f:20:96:33:47-battery", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '30', - 'model_name', 'Fancy BT mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "30", + "model_name", + "Fancy BT mouse", + ], + [], + ) self.testbed.add_device( - 'input', - 'input/input22', - parent, - [], ['ID_INPUT_MOUSE', '1']) + "input", "input/input22", parent, [], ["ID_INPUT_MOUSE", "1"] + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) mousebat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Model'), 'Fancy BT mouse') - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Percentage'), 30) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mousebat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Model"), "Fancy BT mouse" + ) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "Percentage"), 30) + self.assertEqual(self.get_dbus_dev_property(mousebat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(mousebat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_bluetooth_keyboard(self): - '''bluetooth keyboard battery''' + """bluetooth keyboard battery""" - dev = self.testbed.add_device('bluetooth', - 'usb2/bluetooth/hci0/hci0:1', - None, - [], []) + dev = self.testbed.add_device( + "bluetooth", "usb2/bluetooth/hci0/hci0:1", None, [], [] + ) parent = dev self.testbed.add_device( - 'input', - 'input3/event4', + "input", + "input3/event4", parent, - [], ['DEVNAME', 'input/event4', 'ID_INPUT_KEYBOARD', '1']) + [], + ["DEVNAME", "input/event4", "ID_INPUT_KEYBOARD", "1"], + ) self.testbed.add_device( - 'power_supply', - 'power_supply/hid-00:22:33:44:55:66-battery', + "power_supply", + "power_supply/hid-00:22:33:44:55:66-battery", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '40', - 'model_name', 'Monster Typist'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "40", + "model_name", + "Monster Typist", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) kbdbat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Model'), 'Monster Typist') - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Percentage'), 40) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Type'), UP_DEVICE_KIND_KEYBOARD) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Model"), "Monster Typist" + ) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "Percentage"), 40) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Type"), UP_DEVICE_KIND_KEYBOARD + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_bluetooth_mouse_with_keyboard(self): - '''mouse with a few keys (but not a keyboard)''' + """mouse with a few keys (but not a keyboard)""" - dev = self.testbed.add_device('bluetooth', - 'usb2/bluetooth/hci0/hci0:1', - None, - [], []) + dev = self.testbed.add_device( + "bluetooth", "usb2/bluetooth/hci0/hci0:1", None, [], [] + ) parent = dev self.testbed.add_device( - 'input', - 'input3/event3', + "input", + "input3/event3", parent, - [], ['DEVNAME', 'input/event3', 'ID_INPUT_KEYBOARD', '1', 'ID_INPUT_MOUSE', '1']) + [], + [ + "DEVNAME", + "input/event3", + "ID_INPUT_KEYBOARD", + "1", + "ID_INPUT_MOUSE", + "1", + ], + ) self.testbed.add_device( - 'power_supply', - 'power_supply/hid-00:22:33:44:55:66-battery', + "power_supply", + "power_supply/hid-00:22:33:44:55:66-battery", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '40', - 'model_name', 'Monster Mouse'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "40", + "model_name", + "Monster Mouse", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) kbdbat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Model'), 'Monster Mouse') - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Percentage'), 40) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Model"), "Monster Mouse" + ) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "Percentage"), 40) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def test_bluetooth_mouse_and_keyboard(self): - '''keyboard/mouse combo battery''' + """keyboard/mouse combo battery""" - dev = self.testbed.add_device('bluetooth', - 'usb2/bluetooth/hci0/hci0:1', - None, - [], []) + dev = self.testbed.add_device( + "bluetooth", "usb2/bluetooth/hci0/hci0:1", None, [], [] + ) parent = dev self.testbed.add_device( - 'input', - 'input3/event3', + "input", + "input3/event3", parent, - [], ['DEVNAME', 'input/event3', 'ID_INPUT_MOUSE', '1']) + [], + ["DEVNAME", "input/event3", "ID_INPUT_MOUSE", "1"], + ) self.testbed.add_device( - 'input', - 'input3/event4', + "input", + "input3/event4", parent, - [], ['DEVNAME', 'input/event4', 'ID_INPUT_KEYBOARD', '1']) + [], + ["DEVNAME", "input/event4", "ID_INPUT_KEYBOARD", "1"], + ) self.testbed.add_device( - 'power_supply', - 'power_supply/hid-00:22:33:44:55:66-battery', + "power_supply", + "power_supply/hid-00:22:33:44:55:66-battery", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '40', - 'model_name', 'Monster Typist Mouse/Keyboard Combo'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "40", + "model_name", + "Monster Typist Mouse/Keyboard Combo", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) kbdbat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Model'), 'Monster Typist Mouse/Keyboard Combo') - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Percentage'), 40) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, 'Type'), UP_DEVICE_KIND_KEYBOARD) - self.assertEqual(self.get_dbus_property('OnBattery'), False) - self.assertEqual(self.get_dbus_display_property('WarningLevel'), UP_DEVICE_LEVEL_NONE) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Model"), + "Monster Typist Mouse/Keyboard Combo", + ) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "Percentage"), 40) + self.assertEqual(self.get_dbus_dev_property(kbdbat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(kbdbat0_up, "Type"), UP_DEVICE_KIND_KEYBOARD + ) + self.assertEqual(self.get_dbus_property("OnBattery"), False) + self.assertEqual( + self.get_dbus_display_property("WarningLevel"), UP_DEVICE_LEVEL_NONE + ) self.stop_daemon() def _add_bluez_battery_device(self, alias, device_properties, battery_level): @@ -2611,21 +3811,20 @@ class Tests(dbusmock.DBusTestCase): self.start_bluez() # Add an adapter to both bluez and udev - adapter_name = 'hci0' - path = self.bluez_obj.AddAdapter(adapter_name, 'my-computer') - self.assertEqual(path, '/org/bluez/' + adapter_name) + adapter_name = "hci0" + path = self.bluez_obj.AddAdapter(adapter_name, "my-computer") + self.assertEqual(path, "/org/bluez/" + adapter_name) - dev = self.testbed.add_device('bluetooth', - 'usb2/bluetooth/hci0/hci0:1', - None, - [], []) + dev = self.testbed.add_device( + "bluetooth", "usb2/bluetooth/hci0/hci0:1", None, [], [] + ) # Add a device to bluez - address = '11:22:33:44:AA:BB' + address = "11:22:33:44:AA:BB" path = self.bluez_obj.AddDevice(adapter_name, address, alias) - device = self.dbus_con.get_object('org.bluez', path) + device = self.dbus_con.get_object("org.bluez", path) if device_properties: try: @@ -2635,16 +3834,20 @@ class Tests(dbusmock.DBusTestCase): device.AddProperties(DEVICE_IFACE, device_properties) battery_properties = { - 'Percentage': dbus.Byte(battery_level, variant_level=1), + "Percentage": dbus.Byte(battery_level, variant_level=1), } device.AddProperties(BATTERY_IFACE, battery_properties) - bluez_manager = self.dbus_con.get_object('org.bluez', '/') - bluez_manager.EmitSignal(dbusmock.OBJECT_MANAGER_IFACE, 'InterfacesAdded', - 'oa{sa{sv}}', [ - dbus.ObjectPath(path, variant_level=1), - {BATTERY_IFACE: battery_properties}, - ]) + bluez_manager = self.dbus_con.get_object("org.bluez", "/") + bluez_manager.EmitSignal( + dbusmock.OBJECT_MANAGER_IFACE, + "InterfacesAdded", + "oa{sa{sv}}", + [ + dbus.ObjectPath(path, variant_level=1), + {BATTERY_IFACE: battery_properties}, + ], + ) if not self.daemon: self.start_daemon() @@ -2656,142 +3859,164 @@ class Tests(dbusmock.DBusTestCase): return self.proxy.EnumerateDevices() def test_bluetooth_le_mouse(self): - '''Bluetooth LE mouse''' + """Bluetooth LE mouse""" - alias = 'Arc Touch Mouse SE' + alias = "Arc Touch Mouse SE" battery_level = 99 - device_properties = { - 'Appearance': dbus.UInt16(0x03c2, variant_level=1) - } + device_properties = {"Appearance": dbus.UInt16(0x03C2, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) mouse_bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'UpdateTime') != 0, True) + self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "Percentage"), battery_level + ) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "PowerSupply"), False + ) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "UpdateTime") != 0, True + ) self.stop_daemon() def test_bluetooth_le_device(self): - '''Bluetooth LE Device''' - '''See https://gitlab.freedesktop.org/upower/upower/issues/100''' + """Bluetooth LE Device""" + """See https://gitlab.freedesktop.org/upower/upower/issues/100""" - alias = 'Satechi M1 Mouse' + alias = "Satechi M1 Mouse" battery_level = 99 - device_properties = { - 'Class': dbus.UInt32(0, variant_level=1) - } + device_properties = {"Class": dbus.UInt32(0, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) mouse_bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, 'Type'), UP_DEVICE_KIND_BLUETOOTH_GENERIC) + self.assertEqual(self.get_dbus_dev_property(mouse_bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "Percentage"), battery_level + ) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "PowerSupply"), False + ) + self.assertEqual( + self.get_dbus_dev_property(mouse_bat0_up, "Type"), + UP_DEVICE_KIND_BLUETOOTH_GENERIC, + ) self.stop_daemon() def test_bluetooth_headphones(self): - '''Bluetooth Headphones''' + """Bluetooth Headphones""" - alias = 'WH-1000XM3' + alias = "WH-1000XM3" battery_level = 99 - device_properties = { - 'Class': dbus.UInt32(0x240404, variant_level=1) - } + device_properties = {"Class": dbus.UInt32(0x240404, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_HEADSET) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Percentage"), battery_level + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_HEADSET + ) self.stop_daemon() def test_bluetooth_wireless_earbuds(self): - '''Bluetooth Wireless Earbuds''' + """Bluetooth Wireless Earbuds""" - alias = 'QCY-qs2_R' + alias = "QCY-qs2_R" battery_level = 99 - device_properties = { - 'Class': dbus.UInt32(0x240418, variant_level=1) - } + device_properties = {"Class": dbus.UInt32(0x240418, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_HEADPHONES) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Percentage"), battery_level + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_HEADPHONES + ) self.stop_daemon() def test_bluetooth_phone(self): - '''Bluetooth Phone''' + """Bluetooth Phone""" - alias = 'Phone' + alias = "Phone" battery_level = 99 - device_properties = { - 'Class': dbus.UInt32(0x5a020c, variant_level=1) - } + device_properties = {"Class": dbus.UInt32(0x5A020C, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_PHONE) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Percentage"), battery_level + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_PHONE + ) self.stop_daemon() def test_bluetooth_computer(self): - '''Bluetooth Computer''' + """Bluetooth Computer""" - alias = 'Computer' + alias = "Computer" battery_level = 99 - device_properties = { - 'Class': dbus.UInt32(0x6c010c, variant_level=1) - } + device_properties = {"Class": dbus.UInt32(0x6C010C, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_COMPUTER) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Percentage"), battery_level + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_COMPUTER + ) self.stop_daemon() def test_bluetooth_heart_rate_monitor(self): - '''Bluetooth Heart Rate Monitor''' + """Bluetooth Heart Rate Monitor""" - alias = 'Polar H7' + alias = "Polar H7" battery_level = 99 - device_properties = { - 'Appearance': dbus.UInt16(0x0341, variant_level=1) - } + device_properties = {"Appearance": dbus.UInt16(0x0341, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) self.assertEqual(len(devs), 1) bat0_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), battery_level) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_BLUETOOTH_GENERIC) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Percentage"), battery_level + ) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), + UP_DEVICE_KIND_BLUETOOTH_GENERIC, + ) self.stop_daemon() def test_bluetooth_hidpp_mouse(self): - '''Logitech Bluetooth LE mouse with HID++ kernel support''' + """Logitech Bluetooth LE mouse with HID++ kernel support""" self.start_bluez() self.start_daemon() @@ -2799,84 +4024,96 @@ class Tests(dbusmock.DBusTestCase): udevs = [] # Add Bluetooth LE device - alias = 'Logitech Bluetooth Name' + alias = "Logitech Bluetooth Name" battery_level = 99 - device_properties = { - 'Appearance': dbus.UInt16(0x03c2, variant_level=1) - } + device_properties = {"Appearance": dbus.UInt16(0x03C2, variant_level=1)} devs = self._add_bluez_battery_device(alias, device_properties, battery_level) - bluez_dev_path = '/org/bluez/hci0/dev_11_22_33_44_AA_BB' + bluez_dev_path = "/org/bluez/hci0/dev_11_22_33_44_AA_BB" self.assertEqual(len(devs), 1) # Add HID++ kernel device - parent = self.testbed.add_device('usb', - 'pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2', - None, - [], []) + parent = self.testbed.add_device( + "usb", "pci0000:00/0000:00:14.0/usb3/3-10/3-10:1.2", None, [], [] + ) udevs.insert(0, parent) - parent = self.testbed.add_device('hid', - '0003:046D:C52B.0009', - parent, - [], []) + parent = self.testbed.add_device("hid", "0003:046D:C52B.0009", parent, [], []) udevs.insert(0, parent) - dev = self.testbed.add_device('hid', - '0003:046D:4101.000A', - parent, - [], []) + dev = self.testbed.add_device("hid", "0003:046D:4101.000A", parent, [], []) udevs.insert(0, dev) parent = dev _dev = self.testbed.add_device( - 'input', - 'input/input22', + "input", + "input/input22", parent, - [], ['DEVNAME', 'input/mouse3', 'ID_INPUT_MOUSE', '1']) + [], + ["DEVNAME", "input/mouse3", "ID_INPUT_MOUSE", "1"], + ) udevs.insert(0, _dev) _dev = self.testbed.add_device( - 'power_supply', - 'power_supply/hidpp_battery_3', + "power_supply", + "power_supply/hidpp_battery_3", parent, - ['type', 'Battery', - 'scope', 'Device', - 'present', '1', - 'online', '1', - 'status', 'Discharging', - 'capacity', '30', - 'serial_number', '11:22:33:44:aa:bb', - 'model_name', 'Logitech HID++ name'], - []) + [ + "type", + "Battery", + "scope", + "Device", + "present", + "1", + "online", + "1", + "status", + "Discharging", + "capacity", + "30", + "serial_number", + "11:22:33:44:aa:bb", + "model_name", + "Logitech HID++ name", + ], + [], + ) udevs.insert(0, _dev) devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) bat0_up = devs[0] # Check we have the Bluetooth name - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Model'), alias) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Model"), alias) # Check we have the kernel percentage - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Percentage'), 30) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'PowerSupply'), False) - self.assertEqual(self.get_dbus_dev_property(bat0_up, 'Type'), UP_DEVICE_KIND_MOUSE) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "Percentage"), 30) + self.assertEqual(self.get_dbus_dev_property(bat0_up, "PowerSupply"), False) + self.assertEqual( + self.get_dbus_dev_property(bat0_up, "Type"), UP_DEVICE_KIND_MOUSE + ) - bluez_dev = self.dbus_con.get_object('org.bluez', bluez_dev_path) - bluez_dev.UpdateProperties(DEVICE_IFACE, { 'ServicesResolved': dbus.Boolean(False, variant_level=1) }) + bluez_dev = self.dbus_con.get_object("org.bluez", bluez_dev_path) + bluez_dev.UpdateProperties( + DEVICE_IFACE, {"ServicesResolved": dbus.Boolean(False, variant_level=1)} + ) # Remove device from kernel # process = subprocess.Popen(['find', os.path.join(self.testbed.get_root_dir())]) for path in udevs: - self.testbed.uevent(path, 'remove') + self.testbed.uevent(path, "remove") self.testbed.remove_device(path) # Remove device from bluez - bluez_manager = self.dbus_con.get_object('org.bluez', '/') - bluez_manager.EmitSignal(dbusmock.OBJECT_MANAGER_IFACE, 'InterfacesRemoved', - 'oas', [ - dbus.ObjectPath(bluez_dev_path, variant_level=1), - [BATTERY_IFACE], - ]) + bluez_manager = self.dbus_con.get_object("org.bluez", "/") + bluez_manager.EmitSignal( + dbusmock.OBJECT_MANAGER_IFACE, + "InterfacesRemoved", + "oas", + [ + dbus.ObjectPath(bluez_dev_path, variant_level=1), + [BATTERY_IFACE], + ], + ) - adapter = self.dbus_con.get_object('org.bluez', '/org/bluez/hci0') + adapter = self.dbus_con.get_object("org.bluez", "/org/bluez/hci0") adapter.RemoveDevice(bluez_dev_path) time.sleep(0.5) @@ -2886,136 +4123,211 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_charge_cycles(self): - '''Charge cycles''' + """Charge cycles""" # one well charged, one low - self.testbed.add_device('power_supply', 'BAT0', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '48000000', - 'voltage_now', '12000000'], []) + self.testbed.add_device( + "power_supply", + "BAT0", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "48000000", + "voltage_now", + "12000000", + ], + [], + ) - self.testbed.add_device('power_supply', 'BAT1', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000', - 'cycle_count', '2000'], []) + self.testbed.add_device( + "power_supply", + "BAT1", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + "cycle_count", + "2000", + ], + [], + ) - self.testbed.add_device('power_supply', 'BAT2', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000', - 'cycle_count', '0'], []) + self.testbed.add_device( + "power_supply", + "BAT2", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + "cycle_count", + "0", + ], + [], + ) - self.testbed.add_device('power_supply', 'BAT3', None, - ['type', 'Battery', - 'present', '1', - 'status', 'Discharging', - 'energy_full', '60000000', - 'energy_full_design', '80000000', - 'energy_now', '1500000', - 'voltage_now', '12000000', - 'cycle_count', '-1'], []) + self.testbed.add_device( + "power_supply", + "BAT3", + None, + [ + "type", + "Battery", + "present", + "1", + "status", + "Discharging", + "energy_full", + "60000000", + "energy_full_design", + "80000000", + "energy_now", + "1500000", + "voltage_now", + "12000000", + "cycle_count", + "-1", + ], + [], + ) self.start_daemon() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 4) - self.assertEqual(self.get_dbus_dev_property(devs[0], 'ChargeCycles'), -1) - self.assertEqual(self.get_dbus_dev_property(devs[1], 'ChargeCycles'), 2000) - self.assertEqual(self.get_dbus_dev_property(devs[2], 'ChargeCycles'), -1) - self.assertEqual(self.get_dbus_dev_property(devs[3], 'ChargeCycles'), -1) + self.assertEqual(self.get_dbus_dev_property(devs[0], "ChargeCycles"), -1) + self.assertEqual(self.get_dbus_dev_property(devs[1], "ChargeCycles"), 2000) + self.assertEqual(self.get_dbus_dev_property(devs[2], "ChargeCycles"), -1) + self.assertEqual(self.get_dbus_dev_property(devs[3], "ChargeCycles"), -1) self.stop_daemon() def test_wacom_dongle(self): - 'Wacom tablet connected through wireless USB dongle' + "Wacom tablet connected through wireless USB dongle" self.start_daemon() - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-dongle-waiting.device')) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-dongle-waiting.device") + ) time.sleep(0.5) self.assertDevs({}) - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-dongle-active.device')) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-dongle-active.device") + ) time.sleep(0.5) - self.assertDevs({ - 'battery_wacom_battery_11': { - 'NativePath': 'wacom_battery_11', - 'Model': 'Wacom Intuos5 touch M (WL)', - 'Type': UP_DEVICE_KIND_TABLET, - 'PowerSupply': False, - 'HasHistory': True, - 'Online': False, - 'Percentage': 19.0, - 'IsPresent': True, - 'State': UP_DEVICE_STATE_CHARGING, - 'IsRechargeable': True, + self.assertDevs( + { + "battery_wacom_battery_11": { + "NativePath": "wacom_battery_11", + "Model": "Wacom Intuos5 touch M (WL)", + "Type": UP_DEVICE_KIND_TABLET, + "PowerSupply": False, + "HasHistory": True, + "Online": False, + "Percentage": 19.0, + "IsPresent": True, + "State": UP_DEVICE_STATE_CHARGING, + "IsRechargeable": True, + } } - }) + ) def test_headset_detection(self): - 'Detect USB wireless headsets and other audio devices' + "Detect USB wireless headsets and other audio devices" - self.testbed.add_from_file(os.path.join(edir, 'tests/usb-headset.device')) + self.testbed.add_from_file(os.path.join(edir, "tests/usb-headset.device")) self.start_daemon() - self.assertDevs({ - 'battery_hidpp_battery_0': { - 'NativePath': 'hidpp_battery_0', - 'Model': 'G935 Gaming Headset', - 'Type': UP_DEVICE_KIND_HEADSET, - 'PowerSupply': False, - 'HasHistory': True, - 'Percentage': 3.0, - 'IsPresent': True, - 'State': UP_DEVICE_STATE_DISCHARGING, - 'IsRechargeable': True, + self.assertDevs( + { + "battery_hidpp_battery_0": { + "NativePath": "hidpp_battery_0", + "Model": "G935 Gaming Headset", + "Type": UP_DEVICE_KIND_HEADSET, + "PowerSupply": False, + "HasHistory": True, + "Percentage": 3.0, + "IsPresent": True, + "State": UP_DEVICE_STATE_DISCHARGING, + "IsRechargeable": True, + } } - }) + ) self.stop_daemon() def test_headset_hotplug(self): - 'Detect USB headset when hotplugged' + "Detect USB headset when hotplugged" self.start_daemon() - self.testbed.add_from_file(os.path.join(edir, 'tests/steelseries-headset.device')) - card = '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/sound/card1' + self.testbed.add_from_file( + os.path.join(edir, "tests/steelseries-headset.device") + ) + card = "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/sound/card1" self.wait_for_mainloop() devs = self.proxy.EnumerateDevices() self.assertEqual(len(devs), 1) headset_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(headset_up, 'Type'), UP_DEVICE_KIND_BATTERY) + self.assertEqual( + self.get_dbus_dev_property(headset_up, "Type"), UP_DEVICE_KIND_BATTERY + ) - self.testbed.set_property(card, 'SOUND_INITIALIZED', '1') - self.testbed.set_property(card, 'SOUND_FORM_FACTOR', 'headset') - self.testbed.uevent(card, 'change') - self.assertEqual(self.get_dbus_dev_property(headset_up, 'Type'), UP_DEVICE_KIND_HEADSET) + self.testbed.set_property(card, "SOUND_INITIALIZED", "1") + self.testbed.set_property(card, "SOUND_FORM_FACTOR", "headset") + self.testbed.uevent(card, "change") + self.assertEqual( + self.get_dbus_dev_property(headset_up, "Type"), UP_DEVICE_KIND_HEADSET + ) self.stop_daemon() def test_headset_wireless_status(self): - 'Hide devices when wireless_status is disconnected' + "Hide devices when wireless_status is disconnected" - self.testbed.add_from_file(os.path.join(edir, 'tests/steelseries-headset.device')) - card = '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/sound/card1' - self.testbed.set_property(card, 'SOUND_INITIALIZED', '1') - self.testbed.set_property(card, 'SOUND_FORM_FACTOR', 'headset') - intf = '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.3' - self.testbed.set_attribute(intf, 'wireless_status', 'connected') + self.testbed.add_from_file( + os.path.join(edir, "tests/steelseries-headset.device") + ) + card = "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.0/sound/card1" + self.testbed.set_property(card, "SOUND_INITIALIZED", "1") + self.testbed.set_property(card, "SOUND_FORM_FACTOR", "headset") + intf = "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-5/1-5:1.3" + self.testbed.set_attribute(intf, "wireless_status", "connected") num_devices = 0 @@ -3025,50 +4337,50 @@ class Tests(dbusmock.DBusTestCase): num_devices = len(devs) self.assertEqual(num_devices, 1) headset_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(headset_up, 'Percentage'), 69.0) + self.assertEqual(self.get_dbus_dev_property(headset_up, "Percentage"), 69.0) client = UPowerGlib.Client.new() def device_added_cb(client, device): nonlocal num_devices num_devices += 1 + def device_removed_cb(client, path): nonlocal num_devices num_devices -= 1 - client.connect('device-added', device_added_cb) - client.connect('device-removed', device_removed_cb) + client.connect("device-added", device_added_cb) + client.connect("device-removed", device_removed_cb) - self.testbed.set_attribute(intf, 'wireless_status', 'disconnected') - self.testbed.uevent(intf, 'change') + self.testbed.set_attribute(intf, "wireless_status", "disconnected") + self.testbed.uevent(intf, "change") self.wait_for_mainloop() self.assertEqual(num_devices, 0) - self.testbed.set_attribute(intf, 'wireless_status', 'connected') - self.testbed.uevent(intf, 'change') + self.testbed.set_attribute(intf, "wireless_status", "connected") + self.testbed.uevent(intf, "change") self.wait_for_mainloop() self.assertEqual(num_devices, 1) devs = self.proxy.EnumerateDevices() headset_up = devs[0] - self.assertEqual(self.get_dbus_dev_property(headset_up, 'Percentage'), 69.0) + self.assertEqual(self.get_dbus_dev_property(headset_up, "Percentage"), 69.0) self.stop_daemon() def test_daemon_restart(self): - - self.testbed.add_from_file(os.path.join(edir, 'tests/usb-headset.device')) - bat = '/sys/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.3/0003:046D:0A87.0004/power_supply/hidpp_battery_0' + self.testbed.add_from_file(os.path.join(edir, "tests/usb-headset.device")) + bat = "/sys/devices/pci0000:00/0000:00:14.0/usb1/1-8/1-8:1.3/0003:046D:0A87.0004/power_supply/hidpp_battery_0" self.start_daemon() - process = subprocess.Popen([self.upower_path, '-m']) + process = subprocess.Popen([self.upower_path, "-m"]) for i in range(10): # Replace daemon self.start_daemon() - self.testbed.uevent(bat, 'change') + self.testbed.uevent(bat, "change") # Check that upower is still running self.assertIsNone(process.returncode) @@ -3077,142 +4389,226 @@ class Tests(dbusmock.DBusTestCase): self.stop_daemon() def test_remove(self): - 'Test removing when parent ID lookup stops working' + "Test removing when parent ID lookup stops working" - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-dongle-waiting.device')) - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-dongle-active.device')) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-dongle-waiting.device") + ) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-dongle-active.device") + ) self.start_daemon() - self.assertDevs({ 'battery_wacom_battery_11': {} }) + self.assertDevs({"battery_wacom_battery_11": {}}) # Destroy sysfs enough to break the parent ID lookup - os.unlink(os.path.join(self.testbed.get_root_dir(), - 'sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/0003:056A:0084.001F', - 'subsystem')) + os.unlink( + os.path.join( + self.testbed.get_root_dir(), + "sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/0003:056A:0084.001F", + "subsystem", + ) + ) - self.get_dbus_dev_property('/org/freedesktop/UPower/devices/battery_wacom_battery_11', 'State') + self.get_dbus_dev_property( + "/org/freedesktop/UPower/devices/battery_wacom_battery_11", "State" + ) # This should remove all devices that UPower tracks - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/0003:056A:0084.001F/power_supply/wacom_battery_11', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1/0003:056A:0084.0020/input/input125', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1/0003:056A:0084.0020/input/input127', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.2/0003:056A:0084.0021/input/input129', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.2', - 'remove') - self.testbed.uevent('/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1', - 'remove') - self.daemon_log.check_line('No devices with parent /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1 left', timeout=2) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0/0003:056A:0084.001F/power_supply/wacom_battery_11", + "remove", + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1/0003:056A:0084.0020/input/input125", + "remove", + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1/0003:056A:0084.0020/input/input127", + "remove", + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.2/0003:056A:0084.0021/input/input129", + "remove", + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.0", "remove" + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.1", "remove" + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1/1-1.1:1.2", "remove" + ) + self.testbed.uevent( + "/sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1", "remove" + ) + self.daemon_log.check_line( + "No devices with parent /sys/devices/pci0000:00/0000:00:1a.0/usb1/1-1/1-1.1 left", + timeout=2, + ) # Ensure the object is really gone from the bus, # the second case could happen if a reference is leaked. self.assertDevs({}) - with self.assertRaisesRegex(GLib.Error, 'Object does not exist at path'): - self.get_dbus_dev_property('/org/freedesktop/UPower/devices/battery_wacom_battery_11', 'State') + with self.assertRaisesRegex(GLib.Error, "Object does not exist at path"): + self.get_dbus_dev_property( + "/org/freedesktop/UPower/devices/battery_wacom_battery_11", "State" + ) self.stop_daemon() def test_wacom_bluetooth(self): - 'Wacom tablet connected through wireless USB dongle' + "Wacom tablet connected through wireless USB dongle" self.start_daemon() - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-bluetooth-active.device')) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-bluetooth-active.device") + ) time.sleep(0.5) - self.assertDevs({ - 'battery_wacom_battery_10': { - 'NativePath': 'wacom_battery_10', - 'Model': 'Wacom Intuos5 touch M (WL)', - 'Type': UP_DEVICE_KIND_TABLET, - 'PowerSupply': False, - 'HasHistory': True, - 'Online': False, - 'Percentage': 100.0, - 'IsPresent': True, - # XXX: This is "Discharging" in sysfs - 'State': UP_DEVICE_STATE_FULLY_CHARGED, - 'IsRechargeable': True, + self.assertDevs( + { + "battery_wacom_battery_10": { + "NativePath": "wacom_battery_10", + "Model": "Wacom Intuos5 touch M (WL)", + "Type": UP_DEVICE_KIND_TABLET, + "PowerSupply": False, + "HasHistory": True, + "Online": False, + "Percentage": 100.0, + "IsPresent": True, + # XXX: This is "Discharging" in sysfs + "State": UP_DEVICE_STATE_FULLY_CHARGED, + "IsRechargeable": True, + } } - }) + ) self.stop_daemon() def test_sibling_priority_no_overwrite(self): - 'Test siblings using the fallback device do not overwrite previous guesses' + "Test siblings using the fallback device do not overwrite previous guesses" - self.testbed.add_from_file(os.path.join(edir, 'tests/wacom-pen-digitiser.device')) + self.testbed.add_from_file( + os.path.join(edir, "tests/wacom-pen-digitiser.device") + ) self.start_daemon() - self.assertDevs({ - 'battery_wacom_battery_0': { - 'NativePath': 'wacom_battery_0', - 'Model': 'Wacom HID 52D5', - 'Type': UP_DEVICE_KIND_TABLET, - 'PowerSupply': False, - 'HasHistory': True, - 'Percentage': 100.0, - 'IsPresent': True, - 'State': UP_DEVICE_STATE_FULLY_CHARGED, - 'IsRechargeable': True, + self.assertDevs( + { + "battery_wacom_battery_0": { + "NativePath": "wacom_battery_0", + "Model": "Wacom HID 52D5", + "Type": UP_DEVICE_KIND_TABLET, + "PowerSupply": False, + "HasHistory": True, + "Percentage": 100.0, + "IsPresent": True, + "State": UP_DEVICE_STATE_FULLY_CHARGED, + "IsRechargeable": True, + } } - }) + ) self.stop_daemon() def test_ignore_unknown_power_supply_type(self): - ''' + """ Ignore devices with unknown power supply type and doesn't look like a charger. - ''' + """ # Sample data taken from Fairphone 4, running Linux kernel 4.19 w/ # vendor patches (abbreviated). # Actual battery. - battery = self.testbed.add_device('power_supply', 'battery', None, - ['capacity', '77', - 'charging_enabled', '1', - 'health', 'Good', - 'present', '1', - 'status', 'Charging', - 'technology', 'Li-ion', - 'type', 'Battery', - 'voltage_max', '4400000', - 'voltage_now', '4268584'], []) + battery = self.testbed.add_device( + "power_supply", + "battery", + None, + [ + "capacity", + "77", + "charging_enabled", + "1", + "health", + "Good", + "present", + "1", + "status", + "Charging", + "technology", + "Li-ion", + "type", + "Battery", + "voltage_max", + "4400000", + "voltage_now", + "4268584", + ], + [], + ) # BMS (should be ignored) - bms = self.testbed.add_device('power_supply', 'bms', None, - ['type', 'BMS', - 'capacity', '77', - 'capacity_raw', '7685', - 'current_avg', '-1677247', - 'current_now', '-1543885', - 'power_avg', '29886557', - 'power_now', '52842898', - 'real_capacity', '77', - 'temp', '300', - 'voltage_avg', '4322887', - 'voltage_max', '4400000', - 'voltage_min', '3400000', - 'voltage_now', '4298363', - 'voltage_ocv', '4102200'], []) + bms = self.testbed.add_device( + "power_supply", + "bms", + None, + [ + "type", + "BMS", + "capacity", + "77", + "capacity_raw", + "7685", + "current_avg", + "-1677247", + "current_now", + "-1543885", + "power_avg", + "29886557", + "power_now", + "52842898", + "real_capacity", + "77", + "temp", + "300", + "voltage_avg", + "4322887", + "voltage_max", + "4400000", + "voltage_min", + "3400000", + "voltage_now", + "4298363", + "voltage_ocv", + "4102200", + ], + [], + ) # "Charge pump master" (not sure what it is either, should be ignored) charge_pump_master = self.testbed.add_device( - 'power_supply', 'charge_pump_master', None, - ['chip_version', '3', - 'min_icl', '1000000', - 'model_name', 'SMB1398_V2', - 'parallel_mode', '1', - 'parallel_output_mode', '2', - 'type', 'Nothing attached'], []) + "power_supply", + "charge_pump_master", + None, + [ + "chip_version", + "3", + "min_icl", + "1000000", + "model_name", + "SMB1398_V2", + "parallel_mode", + "1", + "parallel_output_mode", + "2", + "type", + "Nothing attached", + ], + [], + ) self.start_daemon(warns=True) devs = self.proxy.EnumerateDevices() @@ -3226,28 +4622,29 @@ class Tests(dbusmock.DBusTestCase): # def test_lib_daemon_properties(self): - '''library GI: daemon properties''' + """library GI: daemon properties""" self.start_daemon() client = UPowerGlib.Client.new() - self.assertRegex(client.get_daemon_version(), '^[0-9.]+$') + self.assertRegex(client.get_daemon_version(), "^[0-9.]+$") self.assertIn(client.get_lid_is_present(), [False, True]) self.assertIn(client.get_lid_is_closed(), [False, True]) self.assertEqual(client.get_on_battery(), False) - self.assertEqual(client.get_critical_action(), 'HybridSleep') + self.assertEqual(client.get_critical_action(), "HybridSleep") self.stop_daemon() def test_lib_up_client_async(self): - '''Test up_client_async_new()''' + """Test up_client_async_new()""" - ac = self.testbed.add_device('power_supply', 'AC', None, - ['type', 'Mains', 'online', '1'], []) + ac = self.testbed.add_device( + "power_supply", "AC", None, ["type", "Mains", "online", "1"], [] + ) self.start_daemon() def client_new_cb(obj, res): nonlocal ml, client client = UPowerGlib.Client.new_finish(res) - self.assertRegex(client.get_daemon_version(), '^[0-9.]+$') + self.assertRegex(client.get_daemon_version(), "^[0-9.]+$") ml.quit() def get_devices_cb(obj, res): @@ -3272,34 +4669,41 @@ class Tests(dbusmock.DBusTestCase): @classmethod def _props_to_str(cls, properties): - '''Convert a properties dictionary to uevent text representation.''' + """Convert a properties dictionary to uevent text representation.""" - prop_str = '' + prop_str = "" if properties: for k, v in properties.items(): - prop_str += '%s=%s\n' % (k, v) + prop_str += "%s=%s\n" % (k, v) return prop_str -if __name__ == '__main__': + +if __name__ == "__main__": try: import gi from gi.repository import GLib from gi.repository import Gio - gi.require_version('UPowerGlib', '1.0') + + gi.require_version("UPowerGlib", "1.0") from gi.repository import UPowerGlib except ImportError as e: - sys.stderr.write('Skipping tests, PyGobject not available for Python 3, or missing GI typelibs: %s\n' % str(e)) + sys.stderr.write( + "Skipping tests, PyGobject not available for Python 3, or missing GI typelibs: %s\n" + % str(e) + ) sys.exit(77) try: - gi.require_version('UMockdev', '1.0') + gi.require_version("UMockdev", "1.0") from gi.repository import UMockdev except ImportError: - sys.stderr.write('Skipping tests, umockdev not available (https://github.com/martinpitt/umockdev)\n') + sys.stderr.write( + "Skipping tests, umockdev not available (https://github.com/martinpitt/umockdev)\n" + ) sys.exit(77) # run ourselves under umockdev - if 'umockdev' not in os.environ.get('LD_PRELOAD', ''): - os.execvp('umockdev-wrapper', ['umockdev-wrapper'] + sys.argv) + if "umockdev" not in os.environ.get("LD_PRELOAD", ""): + os.execvp("umockdev-wrapper", ["umockdev-wrapper"] + sys.argv) unittest.main() diff --git a/src/linux/output_checker.py b/src/linux/output_checker.py index d1a8c4c..037e248 100644 --- a/src/linux/output_checker.py +++ b/src/linux/output_checker.py @@ -26,21 +26,27 @@ import threading import select import errno -class OutputChecker(object): +class OutputChecker(object): def __init__(self, out=sys.stdout): self._output = out self._pipe_fd_r, self._pipe_fd_w = os.pipe() - self._partial_buf = b'' + self._partial_buf = b"" self._lines_sem = threading.Semaphore() self._lines = [] self._reader_io = io.StringIO() # Just to be sure, shouldn't be a problem even if we didn't set it - fcntl.fcntl(self._pipe_fd_r, fcntl.F_SETFL, - fcntl.fcntl(self._pipe_fd_r, fcntl.F_GETFL) | os.O_CLOEXEC | os.O_NONBLOCK) - fcntl.fcntl(self._pipe_fd_w, fcntl.F_SETFL, - fcntl.fcntl(self._pipe_fd_w, fcntl.F_GETFL) | os.O_CLOEXEC) + fcntl.fcntl( + self._pipe_fd_r, + fcntl.F_SETFL, + fcntl.fcntl(self._pipe_fd_r, fcntl.F_GETFL) | os.O_CLOEXEC | os.O_NONBLOCK, + ) + fcntl.fcntl( + self._pipe_fd_w, + fcntl.F_SETFL, + fcntl.fcntl(self._pipe_fd_w, fcntl.F_GETFL) | os.O_CLOEXEC, + ) # Start copier thread self._thread = threading.Thread(target=self._copy, daemon=True) @@ -73,7 +79,7 @@ class OutputChecker(object): self._lines_sem.release() return - l = r.split(b'\n') + l = r.split(b"\n") l[0] = self._partial_buf + l[0] self._lines.extend(l[:-1]) self._partial_buf = l[-1] @@ -86,7 +92,7 @@ class OutputChecker(object): deadline = time.time() + timeout if isinstance(needle_re, str): - needle_re = needle_re.encode('ascii') + needle_re = needle_re.encode("ascii") r = re.compile(needle_re) ret = [] @@ -98,16 +104,23 @@ class OutputChecker(object): # EOF, throw error if self._pipe_fd_r == -1: if failmsg: - raise AssertionError("No further messages: " % failmsg) from None + raise AssertionError( + "No further messages: " % failmsg + ) from None else: - raise AssertionError('No client waiting for needle %s' % (str(needle_re))) from None + raise AssertionError( + "No client waiting for needle %s" % (str(needle_re)) + ) from None # Check if should wake up - if not self._lines_sem.acquire(timeout = deadline - time.time()): + if not self._lines_sem.acquire(timeout=deadline - time.time()): if failmsg: raise AssertionError(failmsg) from None else: - raise AssertionError('Timed out waiting for needle %s (timeout: %0.2f)' % (str(needle_re), timeout)) from None + raise AssertionError( + "Timed out waiting for needle %s (timeout: %0.2f)" + % (str(needle_re), timeout) + ) from None continue ret.append(l) @@ -116,7 +129,7 @@ class OutputChecker(object): def check_line(self, needle, timeout=0, failmsg=None): if isinstance(needle, str): - needle = needle.encode('ascii') + needle = needle.encode("ascii") needle_re = re.escape(needle) @@ -126,7 +139,7 @@ class OutputChecker(object): deadline = time.time() + wait if isinstance(needle_re, str): - needle_re = needle_re.encode('ascii') + needle_re = needle_re.encode("ascii") r = re.compile(needle_re) ret = [] @@ -140,7 +153,7 @@ class OutputChecker(object): break # Check if should wake up - if not self._lines_sem.acquire(timeout = deadline - time.time()): + if not self._lines_sem.acquire(timeout=deadline - time.time()): # Timed out, so everything is good break continue @@ -150,13 +163,16 @@ class OutputChecker(object): if failmsg: raise AssertionError(failmsg) else: - raise AssertionError('Found needle %s but shouldn\'t have been there (timeout: %0.2f)' % (str(needle_re), wait)) + raise AssertionError( + "Found needle %s but shouldn't have been there (timeout: %0.2f)" + % (str(needle_re), wait) + ) return ret def check_no_line(self, needle, wait=0, failmsg=None): if isinstance(needle, str): - needle = needle.encode('ascii') + needle = needle.encode("ascii") needle_re = re.escape(needle) @@ -174,7 +190,6 @@ class OutputChecker(object): raise AssertionError("OutputCheck: Write side has not been closed yet!") def force_close(self): - fd = self._pipe_fd_r self._pipe_fd_r = -1 if fd >= 0: diff --git a/src/linux/unittest_inspector.py b/src/linux/unittest_inspector.py index 0d5d3a6..db595a4 100755 --- a/src/linux/unittest_inspector.py +++ b/src/linux/unittest_inspector.py @@ -22,23 +22,25 @@ import inspect import os import unittest + def list_tests(module): tests = [] for name, obj in inspect.getmembers(module): if inspect.isclass(obj) and issubclass(obj, unittest.TestCase): cases = unittest.defaultTestLoader.getTestCaseNames(obj) - tests += [ (obj, '{}.{}'.format(name, t)) for t in cases ] + tests += [(obj, "{}.{}".format(name, t)) for t in cases] return tests -if __name__ == '__main__': +if __name__ == "__main__": parser = argparse.ArgumentParser() - parser.add_argument('unittest_source', type=argparse.FileType('r')) + parser.add_argument("unittest_source", type=argparse.FileType("r")) args = parser.parse_args() source_path = args.unittest_source.name spec = importlib.util.spec_from_file_location( - os.path.basename(source_path), source_path) + os.path.basename(source_path), source_path + ) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module)