mirror of
https://github.com/libratbag/libratbag.git
synced 2026-11-07 15:14:38 +01:00
944 lines
34 KiB
Python
Executable File
944 lines
34 KiB
Python
Executable File
#!/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:])
|