#!/usr/bin/env python3 # # This file is part of libratbag. # # Copyright 2017 Red Hat, Inc. # # Permission is hereby granted, free of charge, to any person obtaining a # copy of this software and associated documentation files (the "Software"), # to deal in the Software without restriction, including without limitation # the rights to use, copy, modify, merge, publish, distribute, sublicense, # and/or sell copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice (including the next # paragraph) shall be included in all copies or substantial portions of the # Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER # DEALINGS IN THE SOFTWARE. import argparse import io import os import resource import subprocess import sys import time import toolbox import unittest run_ratbagctl_in_subprocess = False class TestRatbagCtl(unittest.TestCase): json = None @classmethod def setUpClass(cls): super().setUpClass() # it's a lot easier to debug a validation failure here than # with ratbagd failing if cls.json is not None: import json json.loads(cls.json) if cls.json is not None: cls.load_test_device(cls.json) cls.find_test_device() @classmethod def run_ratbagctl_subprocess(cls, params): ratbagctl = subprocess.Popen( " ".join([toolbox.RATBAGCTL_PATH, params]), stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, env={"RATBAG_TEST": "1"}, ) (stdout, stderr) = ratbagctl.communicate() return ( ratbagctl.returncode, stdout.decode("utf-8").rstrip("\n"), stderr.decode("utf-8").rstrip("\n"), ) @classmethod def run_ratbagctl_fast(cls, params): global parser, ratbagd stdout = sys.stdout stderr = sys.stderr returncode = 0 sys.stdout = io.StringIO() sys.stderr = io.StringIO() try: cmd = parser.parse(params.split()) cmd.func(ratbagd, cmd) except SystemExit as e: returncode = e.code except AttributeError: returncode = 2 except ValueError: returncode = 2 except argparse.ArgumentTypeError: returncode = 2 output = sys.stdout.getvalue() error = sys.stderr.getvalue() sys.stdout = stdout sys.stderr = stderr # Small delay as we may not get an updated state on time from ratbagd. time.sleep(0.001) toolbox.sync_dbus() return returncode, output.rstrip("\n"), error.rstrip("\n") @classmethod def run_ratbagctl(cls, params): params = params.replace("test_device", cls.test_device) if run_ratbagctl_in_subprocess: return cls.run_ratbagctl_subprocess(params) return cls.run_ratbagctl_fast(params) @classmethod def reset_test_device(cls): global ratbagd ratbagd._dbus_call("ResetTestDevice", "") toolbox.sync_dbus() @classmethod def load_test_device(cls, json): global ratbagd rc = ratbagd._dbus_call("LoadTestDevice", "s", json) assert rc == 0 toolbox.sync_dbus() @classmethod def find_test_device(cls): rc, stdout, stderr = cls.run_ratbagctl_subprocess("list") testdevice = None for line in stdout.split("\n"): if "Test device" in line: testdevice = line.split(":")[0] break assert testdevice is not None cls.test_device = testdevice def launch_good_test(self, params): returncode, stdout, stderr = self.run_ratbagctl(params) self.assertEqual(returncode, 0, msg=stderr + stdout) self.maxDiff = None self.assertEqual(stderr, "") return stdout def launch_fail_test(self, params): returncode, stdout, stderr = self.run_ratbagctl(params) self.assertNotEqual(returncode, 0, msg=stderr + stdout) return stdout def launch_fail_with_exception_test(self, params, exception): global run_ratbagctl_in_subprocess if run_ratbagctl_in_subprocess: return "" with self.assertRaises(exception): returncode, stdout, stderr = self.run_ratbagctl(params) return "" @classmethod def setProfile(cls, profile): cls.run_ratbagctl(f"test_device profile active set {profile}") class TestRatbagCtlList(TestRatbagCtl): def test_list(self): r = self.launch_good_test("list") self.assertIn(self.test_device, r) self.launch_fail_test("test_device list") self.launch_fail_test("list test_device") class TestRatbagCtlInfo(TestRatbagCtl): def test_info(self): self.launch_good_test("test_device info") self.launch_fail_test("test_device info X") self.launch_fail_test("info X") class TestRatbagCtlName(TestRatbagCtl): def test_get(self): r = self.launch_good_test("test_device name") self.assertEqual(r, "Test device") self.launch_fail_test("test_device name X") self.launch_fail_test("name X") class TestRatbagCtlProfile(TestRatbagCtl): json = """ { "profiles": [ { "is_active": false, "capabilities": [102] }, { "name": "test profile x2", "is_active": false, "capabilities": [102] }, { "is_active": true, "capabilities": [102] }, { "is_active": false, "is_disabled": true, "capabilities": [102] } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_profile_name_get(self): command = "profile 1 name get" r = self.launch_good_test("test_device " + command) self.assertEqual(r, "test profile x2") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device profile name get") def test_profile_name_set(self): r = self.launch_good_test("test_device profile 1 name get") self.assertEqual(r, "test profile x2") self.launch_good_test("test_device profile 1 name set banana") r = self.launch_good_test("test_device profile 1 name get") self.assertEqual(r, "banana") # profile 0 doesn't have the capability RATBAG_PROFILE_CAP_WRITABLE_NAME self.launch_fail_with_exception_test( "test_device profile 0 name set kiwi", toolbox.RatbagCapabilityError ) # better be safe than sorry, checking that the previous actually failed :) r = self.launch_good_test("test_device profile 0 name get") self.assertNotEqual(r, "kiwi") self.launch_fail_test("profile 1 name set blah") self.launch_fail_test("test_device profile 1 name set blah X") self.launch_fail_test("test_device profile name set blah") def test_profile_active_get(self): command = "profile active get" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r), 2) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") def test_profile_active_set(self): command = "profile active set" r = self.launch_good_test("test_device " + command + " 1") self.assertEqual(r, "") r = self.launch_good_test("test_device profile active get") self.assertEqual(int(r), 1) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 1 X") def test_profile_n(self): r0 = self.launch_good_test("test_device profile 0 get") r1 = self.launch_good_test("test_device profile 1 get") self.assertNotEqual(r0, r1) self.launch_fail_test("profile 0 get") self.launch_fail_test("test_device profile 0") self.launch_fail_test("test_device profile 0 get X") self.launch_fail_test("test_device profile 10 get") def test_profile_enable(self): r = self.launch_good_test("test_device profile 0 get") self.assertNotIn("Profile 0: (disabled)", r) r = self.launch_good_test("test_device profile 3 get") self.assertIn("Profile 3: (disabled)", r) self.launch_good_test("test_device profile 3 enable") r = self.launch_good_test("test_device profile 3 get") self.assertNotIn("Profile 3: (disabled)", r) self.launch_fail_test("profile enable") self.launch_fail_test("test_device profile X enable") self.launch_fail_test("test_device profile 1 enable X") self.launch_fail_test("test_device profile 10 enable") def test_profile_disable(self): r = self.launch_good_test("test_device profile 2 get") self.assertNotIn("Profile 2: (disabled)", r) self.launch_good_test("test_device profile 2 disable") r = self.launch_good_test("test_device profile 2 get") self.assertEqual("Profile 2: (disabled)", r) self.launch_fail_test("profile disable") self.launch_fail_test("test_device profile X disable") self.launch_fail_test("test_device profile 1 disable X") self.launch_fail_test("test_device profile 10 disable") class TestRatbagCtlResolution(TestRatbagCtl): json = """ { "profiles": [ { "is_active": false }, { "is_active": false }, { "is_active": true, "resolutions": [ { "xres": 800, "is_active": false, "is_default": true }, { "xres": 1200, "yres": 1300, "capabilities": [1], "is_default": false, "is_active": false }, { "xres": 2300, "yres": 2400, "capabilities": [1], "is_active": true, "is_default": false }, { "xres": 400, "capabilities": [2], "is_active": false, "is_disabled": false, "is_default": false } ] }, { "is_active": false, "is_disabled": true } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_resolution_n_get(self): r = self.launch_good_test("test_device resolution 1 get") self.assertEqual(r, "1: 1200x1300dpi (default)") self.launch_fail_test("test_device resolution 10 get") self.launch_fail_test("test_device resolution 1 get X") self.launch_fail_test("resolution 1 get X") def test_profile_resolution(self): r = self.launch_good_test("test_device profile 2 resolution 1 get") self.assertEqual(r, "1: 1200x1300dpi") def test_resolution_active_get(self): command = "resolution active get" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r), 2) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 10") def test_resolution_active_set(self): command = "resolution active set" r = self.launch_good_test("test_device resolution active get") self.assertEqual(int(r), 2) r = self.launch_good_test("test_device " + command + " 0") self.assertEqual(r, "") r = self.launch_good_test("test_device resolution active get") self.assertEqual(int(r), 0) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 1 X") def test_resolution_disabled_get(self): command = "disabled get" r = self.launch_good_test("test_device resolution 3 " + command) self.assertEqual(r, "False") self.launch_fail_test("test_device resolution 10 " + command) self.launch_fail_test("test_device resolution 3 " + command + " X") def test_resolution_disabled_set(self): command = "disabled set" self.launch_good_test("test_device resolution 3 " + command) r = self.launch_good_test("test_device resolution 3 disabled get") self.assertEqual(r, "True") self.launch_fail_test("resolution " + command) self.launch_fail_test("test_device resolution 10 " + command) self.launch_fail_test("test_device resolution 3 " + command + " X") def test_resolution_enabled_get(self): command = "enabled get" r = self.launch_good_test("test_device resolution 3 " + command) self.assertEqual(r, "False") self.launch_fail_test("test_device resolution 10 " + command) self.launch_fail_test("test_device resolution 3 " + command + " X") def test_resolution_enabled_set(self): command = "enabled set" self.launch_good_test("test_device resolution 3 " + command) r = self.launch_good_test("test_device resolution 3 enabled get") self.assertEqual(r, "True") self.launch_fail_test("resolution " + command) self.launch_fail_test("test_device resolution 10 " + command) self.launch_fail_test("test_device resolution 3 " + command + " X") def test_resolution_default_get(self): command = "resolution default get" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r), 0) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 10") def test_resolution_default_set(self): command = "resolution default set" self.launch_good_test("test_device " + command + " 2") r = self.launch_good_test("test_device resolution default get") self.assertEqual(int(r), 2) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 1 X") # Reset for other tests self.launch_good_test("test_device " + command + " 1") class TestRatbagCtlDPI(TestRatbagCtl): json = """ { "profiles": [ { "is_active": true, "resolutions": [ { "xres": 200, "is_active": true, "dpi_min": 50, "dpi_max": 5000 }, { "xres": 250, "is_active": false }, { "xres": 300, "is_active": false } ] }, { "is_active": false, "resolutions": [ { "xres": 1000, "yres": 1100, "capabilities": [1], "is_active": false }, { "xres": 1300, "yres": 1400, "capabilities": [1], "is_active": true } ] }, { "is_active": false, "resolutions": [ { "xres": 2100, "yres": 2200, "capabilities": [1], "is_active": true}, { "xres": 2200, "yres": 2300, "capabilities": [1], "is_active": false } ] } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_dpi_get(self): command = "dpi get" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r[:-3]), 200) # drop 'dpi' suffix self.setProfile(1) r = self.launch_good_test("test_device " + command) self.assertEqual(r, "1300x1400dpi") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " 1") self.launch_fail_test("test_device " + command + " X") def test_dpi_get_all(self): dpi_list = ( "50 100 150 200 250 300 350 400 450 500 550 600 650 700 750 800 850 900 950" " 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300" " 2400 2500 2600 2800 3000 3200 3400 3600 3800 4000 4200 4400 4600 4800" " 5000" ) command = "dpi get-all" r = self.launch_good_test("test_device " + command) self.assertEqual(r, dpi_list) self.setProfile(1) r = self.launch_good_test("test_device " + command) self.assertEqual(r, dpi_list) def test_dpi_set(self): command = "dpi set" self.setProfile(0) r = self.launch_good_test("test_device dpi get ") res = int(r[:-3]) + 50 # drop 'dpi' suffix r = self.launch_good_test("test_device " + command + f" {res}") self.assertEqual(r, "") r = self.launch_good_test("test_device dpi get") self.assertEqual(int(r[:-3]), res) # drop 'dpi' suffix self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 100 X") def test_dpi_set_xy(self): command = "dpi set" self.setProfile(2) r = self.launch_good_test("test_device dpi get") self.assertEqual(r, "2100x2200dpi") self.launch_good_test("test_device " + command + " 1300x1400") r = self.launch_good_test("test_device dpi get") self.assertEqual(r, "1300x1400dpi") self.launch_good_test("test_device " + command + " 2300x2400dpi") r = self.launch_good_test("test_device dpi get") self.assertEqual(r, "2300x2400dpi") self.launch_good_test("test_device " + command + " 2300") r = self.launch_good_test("test_device dpi get") self.assertEqual(r, "2300x2300dpi") self.launch_fail_test("test_device " + command + " 2300dpi") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 100 X") def test_prefix_dpi(self): self.setProfile(0) r = self.launch_good_test("test_device profile 1 dpi get") self.assertEqual(r, "1300x1400dpi") r = self.launch_good_test("test_device profile 2 resolution 1 dpi get") self.assertEqual(r, "2200x2300dpi") r = self.launch_good_test("test_device resolution 2 dpi get") self.assertEqual(int(r[:-3]), 300) # drop 'dpi' suffix self.launch_fail_test("test_device profile 1 profile 1 dpi get") self.launch_fail_test("test_device profile 1 resolution 1 resolution 2 dpi get") class TestRatbagCtlReportRate(TestRatbagCtl): json = """ { "profiles": [ { "is_active": true, "rate": 1000, "report_rates": [500, 1000] }, { "is_active": false, "rate": 2000 }, { "is_active": false, "rate": 3000 } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_rate_get(self): command = "rate get" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r), 1000) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " 1") self.launch_fail_test("test_device " + command + " X") def test_rate_get_all(self): rate_list = "500 1000" command = "rate get-all" r = self.launch_good_test("test_device " + command) self.assertEqual(r, rate_list) self.setProfile(1) r = self.launch_good_test("test_device " + command) self.assertEqual(r, rate_list) def test_rate_set(self): command = "rate set" r = self.launch_good_test("test_device rate get") res = int(r) + 500 r = self.launch_good_test("test_device " + command + f" {res}") self.assertEqual(r, "") r = self.launch_good_test("test_device rate get") self.assertEqual(int(r), res) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 100 X") def test_prefix_rate(self): r = self.launch_good_test("test_device rate get") self.assertEqual(int(r), 1000) r = self.launch_good_test("test_device profile 1 rate get") self.assertEqual(int(r), 2000) r = self.launch_good_test("test_device profile 2 rate get") self.assertEqual(int(r), 3000) self.launch_fail_test("test_device profile 1 profile 1 rate get") self.launch_fail_test("test_device profile 1 resolution 0 rate get") self.launch_fail_test( "test_device profile 1 resolution 1 resolution 2 rate get" ) class TestRatbagCtlButton(TestRatbagCtl): json = """ { "profiles": [ { "is_active": true, "buttons": [ { "button": 0 }, { "action_type": "none" }, { "action_type": "special", "special": "profile-cycle-up" }, { "action_type": "macro", "macro": [ "+B", "-B", "t300" ] } ] }, { "is_active": false }, { "is_active": false, "buttons": [ { "action_type": "special", "special": "profile-cycle-up" }, { "action_type": "special" }, { "button": 2, "action_type": "button" }, { "button": 3, "action_type": "button" } ] } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_button_count(self): command = "button count" r = self.launch_good_test("test_device " + command) self.assertEqual(int(r), 4) self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " 1") self.launch_fail_test("test_device " + command + " X") def test_button_n_get(self): self.setProfile(0) r = self.launch_good_test("test_device button 0 get") self.assertEqual(r, "Button: 0 is mapped to 'button 0'") r = self.launch_good_test("test_device button 1 get") self.assertEqual(r, "Button: 1 is mapped to none") r = self.launch_good_test("test_device button 2 get") self.assertEqual(r, "Button: 2 is mapped to 'profile-cycle-up'") r = self.launch_good_test("test_device button 3 get") self.assertEqual(r, "Button: 3 is mapped to macro '↕KEY_B 300ms'") self.launch_fail_test("test_device button 1 get 10") self.launch_fail_test("test_device button 10 get") self.launch_fail_test("test_device button 1 get X") def test_button_n_action_get(self): self.setProfile(0) r = self.launch_good_test("test_device button 0 action get") self.assertEqual(r, "Button: 0 is mapped to 'button 0'") self.launch_fail_test("test_device button 1 action get 10") self.launch_fail_test("test_device button 10 action get") self.launch_fail_test("test_device button 1 action get X") def test_button_n_action_set_button(self): self.setProfile(2) command = "button 2 action set button" r = self.launch_good_test("test_device button 2 action get") self.assertEqual(r, "Button: 2 is mapped to 'button 2'") r = self.launch_good_test("test_device " + command + " 1") self.assertEqual(r, "") r = self.launch_good_test("test_device button 2 action get") self.assertEqual(r, "Button: 2 is mapped to 'button 1'") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 100 X") def test_button_n_action_set_special(self): self.setProfile(2) command = "button 0 action set special " r = self.launch_good_test("test_device button 0 action get") self.assertEqual(r, "Button: 0 is mapped to 'profile-cycle-up'") r = self.launch_good_test("test_device " + command + " second-mode") self.assertEqual(r, "") r = self.launch_good_test("test_device button 0 action get") self.assertEqual(r, "Button: 0 is mapped to 'second-mode'") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " X") self.launch_fail_test("test_device " + command + " 100 X") def test_button_n_action_set_macro(self): command = "button 2 action set macro " self.launch_good_test("test_device " + command + "+KEY_B KEY_A -KEY_B KEY_C") r = self.launch_good_test("test_device button 2 get") self.assertEqual( r, "Button: 2 is mapped to macro '↓KEY_B ↕KEY_A ↑KEY_B ↕KEY_C'" ) self.launch_good_test("test_device " + command + "t100 t200") r = self.launch_good_test("test_device button 2 get") self.assertEqual(r, "Button: 2 is mapped to macro '100ms 200ms'") self.launch_good_test("test_device " + command + "KeY_z") r = self.launch_good_test("test_device button 2 get") self.assertEqual(r, "Button: 2 is mapped to macro '↕KEY_Z'") self.launch_good_test("test_device " + command) r = self.launch_good_test("test_device button 2 get") self.assertEqual(r, "Button: 2 is mapped to macro 'None'") self.launch_fail_test(command) self.launch_fail_test("test_device " + command + " KEY_A X") def test_prefix_button(self): r = self.launch_good_test("test_device profile 2 button 3 get") self.assertEqual(r, "Button: 3 is mapped to 'button 3'") self.launch_fail_test("test_device profile 2 profile 2 button 3 get") self.launch_fail_test("test_device profile 2 resolution 2 button 3 get") class TestRatbagCtlLED(TestRatbagCtl): json = """ { "profiles": [ { "is_active": true, "leds": [ { "mode": 0, "duration": 1000, "brightness": 20 }, { "mode": 1, "duration": 333, "brightness": 40, "color": [255, 0, 0] }, { "mode": 2, "duration": 333, "brightness": 40 } ] }, { "leds": [ { "mode": 1 }, { "mode": 0 }, { "mode": 1 } ] }, { "leds": [ { "mode": 1, "color": [255, 0, 0], "duration": 1000 }, { "mode": 2, "brightness": 40, "duration": 333 }, { "mode": 1 } ] } ] } """ @classmethod def setUpClass(cls): super().setUpClass() def test_led_n_get(self): self.setProfile(0) r = self.launch_good_test("test_device led 0 get") self.assertEqual(r, "LED: 0, depth: rgb, mode: off") r = self.launch_good_test("test_device led 1 get") self.assertEqual(r, "LED: 1, depth: rgb, mode: on, color: ff0000") r = self.launch_good_test("test_device led 2 get") self.assertEqual( r, "LED: 2, depth: rgb, mode: cycle, duration: 333, brightness: 40" ) self.launch_fail_test("test_device led 0 get 10") self.launch_fail_test("test_device led 10 get") self.launch_fail_test("test_device led 0 get X") def test_led_n_set_mode(self): self.setProfile(0) r = self.launch_good_test("test_device led 0 get") self.assertEqual(r, "LED: 0, depth: rgb, mode: off") r = self.launch_good_test("test_device led 0 set mode cycle") self.assertEqual(r, "") r = self.launch_good_test("test_device led 0 get") self.assertEqual( r, "LED: 0, depth: rgb, mode: cycle, duration: 1000, brightness: 20" ) self.launch_fail_test("test_device led 0 set mode bicycle") self.launch_fail_test("test_device led 0 set mode") self.launch_fail_test("test_device led 0 set mode cycle X") def test_led_n_set_color(self): self.setProfile(0) r = self.launch_good_test("test_device led 1 get") self.assertEqual(r, "LED: 1, depth: rgb, mode: on, color: ff0000") r = self.launch_good_test("test_device led 1 set color 00ff00") self.assertEqual(r, "") r = self.launch_good_test("test_device led 1 get") self.assertEqual(r, "LED: 1, depth: rgb, mode: on, color: 00ff00") r = self.launch_good_test("test_device led 1 set color 0x0000ff") self.assertEqual(r, "") r = self.launch_good_test("test_device led 1 get") self.assertEqual(r, "LED: 1, depth: rgb, mode: on, color: 0000ff") self.launch_fail_test("test_device led 1 set color g0ff00") self.launch_fail_test("test_device led 1 set color") self.launch_fail_test("test_device led 1 set color 00ff00 X") def test_led_n_set_duration(self): self.setProfile(0) r = self.launch_good_test("test_device led 2 get") self.assertEqual( r, "LED: 2, depth: rgb, mode: cycle, duration: 333, brightness: 40" ) r = self.launch_good_test("test_device led 2 set duration 10") self.assertEqual(r, "") r = self.launch_good_test("test_device led 2 get") self.assertEqual( r, "LED: 2, depth: rgb, mode: cycle, duration: 10, brightness: 40" ) self.launch_fail_test("test_device led 2 set duration this_is_not_an_int") self.launch_fail_test("test_device led 2 set duration") self.launch_fail_test("test_device led 2 set duration 100 X") def test_led_n_set_brightness(self): self.setProfile(2) r = self.launch_good_test("test_device led 1 get") self.assertEqual( r, "LED: 1, depth: rgb, mode: cycle, duration: 333, brightness: 40" ) r = self.launch_good_test("test_device led 1 set brightness 100") self.assertEqual(r, "") r = self.launch_good_test("test_device led 1 get") self.assertEqual( r, "LED: 1, depth: rgb, mode: cycle, duration: 333, brightness: 100" ) self.launch_fail_test("test_device led 1 set brightness this_is_not_an_int") self.launch_fail_test("test_device led 1 set brightness") self.launch_fail_test("test_device led 1 set brightness 100 X") self.launch_fail_test("test_device led 1 set brightness this_is_not_an_int") self.launch_fail_test("test_device led 1 set brightness 256") self.launch_fail_test("test_device led 1 set brightness -10") def test_led_n_set_combination(self): self.setProfile(2) r = self.launch_good_test("test_device led 0 get") self.assertEqual(r, "LED: 0, depth: rgb, mode: on, color: ff0000") r = self.launch_good_test("test_device led 0 set mode cycle brightness 100") r = self.launch_good_test("test_device led 0 get") self.assertEqual( r, "LED: 0, depth: rgb, mode: cycle, duration: 1000, brightness: 100" ) r = self.launch_good_test( "test_device led 0 set mode cycle duration 100 brightness 255" ) r = self.launch_good_test("test_device led 0 get") self.assertEqual( r, "LED: 0, depth: rgb, mode: cycle, duration: 100, brightness: 255" ) r = self.launch_good_test("test_device led 0 set mode on color 00ff00") r = self.launch_good_test("test_device led 0 get") self.assertEqual(r, "LED: 0, depth: rgb, mode: on, color: 00ff00") r = self.launch_good_test( "test_device led 0 set duration 100 brightness 200 mode cycle" ) r = self.launch_good_test("test_device led 0 get") self.assertEqual( r, "LED: 0, depth: rgb, mode: cycle, duration: 100, brightness: 200" ) r = self.launch_good_test( "test_device led 0 set duration 100 brightness 200 mode cycle" " brightness 100" ) r = self.launch_good_test("test_device led 0 get") self.assertEqual( r, "LED: 0, depth: rgb, mode: cycle, duration: 100, brightness: 100" ) self.launch_fail_test("test_device led 0 set brightness 10 mode bicycle") def test_prefix_led(self): self.setProfile(2) r = self.launch_good_test("test_device profile 1 led 1 get") self.assertEqual(r, "LED: 1, depth: rgb, mode: off") self.launch_fail_test("test_device profile 1 profile 2 led 1 get") self.launch_fail_test("test_device profile 1 resolution 2 led 1 get") def test_led_capabilities(self): r = self.launch_good_test("test_device led 0 capabilities") self.assertEqual(r, "Modes: breathing, cycle, off, on") r = self.launch_good_test("test_device led 1 capabilities") self.assertEqual(r, "Modes: breathing, cycle, off, on") def setUpModule(): global ratbagd_process, ratbagd, parser ratbagd_process = None if start_ratbagd: ratbagd_process = toolbox.start_ratbagd() assert ratbagd_process is not None try: ratbagd = toolbox.open_ratbagd(ratbagd_process) assert ratbagd is not None except Exception as e: if ratbagd_process is not None: toolbox.terminate_ratbagd(ratbagd_process) raise e parser = toolbox.get_parser() def tearDownModule(): global ratbagd_process if start_ratbagd: toolbox.terminate_ratbagd(ratbagd_process) def parse(input_string): global run_ratbagctl_in_subprocess, start_ratbagd parser_test = argparse.ArgumentParser( description="Testsuite for ratbagd/ratbagctl", add_help=False ) parser_test.add_argument("--subprocess", action="store_true", default=False) parser_test.add_argument( "--use-existing-ratbagd", dest="use_existing", action="store_true", default=False, help="Don't start up ratbagd.devel, connect to the already running one", ) ns, rest = parser_test.parse_known_args(input_string) run_ratbagctl_in_subprocess = ns.subprocess start_ratbagd = not ns.use_existing if start_ratbagd and os.geteuid() != 0: print("Script must be run as root", file=sys.stderr) sys.exit(77) return rest def main(argv): os.environ["RATBAG_TEST"] = "1" os.environ["LIBRATBAG_DATA_DIR"] = "@LIBRATBAG_DATA_DIR@" resource.setrlimit(resource.RLIMIT_CORE, (0, 0)) args = parse(argv) unittest.main(argv=[sys.argv[0], *args]) if __name__ == "__main__": main(sys.argv[1:])