From 0fca3a582830c60277701292b2b9251a7c962ca4 Mon Sep 17 00:00:00 2001 From: Tobi <28510156+sezanzeb@users.noreply.github.com> Date: Sun, 12 Jan 2025 10:15:45 +0100 Subject: [PATCH] Split test_macros (#1032) --- tests/unit/test_macros/macro_test_base.py | 8 + tests/unit/test_macros/test_add.py | 71 +++++++ tests/unit/test_macros/test_hold.py | 6 + tests/unit/test_macros/test_hold_keys.py | 6 + tests/unit/test_macros/test_if_eq.py | 143 ++++++++------ tests/unit/test_macros/test_if_single.py | 6 + tests/unit/test_macros/test_if_tap.py | 10 + tests/unit/test_macros/test_key.py | 123 ++++++++++++ tests/unit/test_macros/test_leds.py | 10 + tests/unit/test_macros/test_macros.py | 231 +--------------------- tests/unit/test_macros/test_modify.py | 62 ++++++ tests/unit/test_macros/test_mouse.py | 8 + tests/unit/test_macros/test_parsing.py | 115 +---------- tests/unit/test_macros/test_repeat.py | 140 +++++++++++++ tests/unit/test_macros/test_set.py | 101 ++++++++++ tests/unit/test_macros/test_wait.py | 5 + 16 files changed, 641 insertions(+), 404 deletions(-) create mode 100644 tests/unit/test_macros/test_add.py create mode 100644 tests/unit/test_macros/test_key.py create mode 100644 tests/unit/test_macros/test_modify.py create mode 100644 tests/unit/test_macros/test_repeat.py create mode 100644 tests/unit/test_macros/test_set.py diff --git a/tests/unit/test_macros/macro_test_base.py b/tests/unit/test_macros/macro_test_base.py index 6f2ce631..24291b23 100644 --- a/tests/unit/test_macros/macro_test_base.py +++ b/tests/unit/test_macros/macro_test_base.py @@ -23,9 +23,11 @@ import unittest from inputremapper.configs.preset import Preset +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.context import Context from inputremapper.injection.global_uinputs import GlobalUInputs, UInput from inputremapper.injection.macros.macro import Macro, macro_variables +from inputremapper.injection.macros.parse import Parser from inputremapper.injection.mapping_handlers.mapping_parser import MappingParser from tests.lib.fixtures import fixtures from tests.lib.logger import logger @@ -101,6 +103,12 @@ def count_tasks(self, macro) -> int: count += self.count_tasks(child_macro) return count + def expect_string_in_error(self, string: str, macro: str): + with self.assertRaises(MacroError) as cm: + Parser.parse(macro, self.context) + error = str(cm.exception) + self.assertIn(string, error) + class DummyMapping: macro_key_sleep_ms = 10 diff --git a/tests/unit/test_macros/test_add.py b/tests/unit/test_macros/test_add.py new file mode 100644 index 00000000..de916c45 --- /dev/null +++ b/tests/unit/test_macros/test_add.py @@ -0,0 +1,71 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# input-remapper - GUI for device specific keyboard mappings +# Copyright (C) 2024 sezanzeb +# +# This file is part of input-remapper. +# +# input-remapper is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# input-remapper is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with input-remapper. If not, see . + + +import unittest + +from inputremapper.configs.validation_errors import MacroError +from inputremapper.injection.macros.macro import macro_variables +from inputremapper.injection.macros.parse import Parser +from tests.lib.test_setup import test_setup +from tests.unit.test_macros.macro_test_base import DummyMapping, MacroTestBase + + +@test_setup +class TestAdd(MacroTestBase): + async def test_add(self): + await Parser.parse("set(a, 1).add(a, 1)", self.context, DummyMapping).run( + self.handler + ) + self.assertEqual(macro_variables.get("a"), 2) + + await Parser.parse("set(b, 1).add(b, -1)", self.context, DummyMapping).run( + self.handler + ) + self.assertEqual(macro_variables.get("b"), 0) + + await Parser.parse("set(c, -1).add(c, 500)", self.context, DummyMapping).run( + self.handler + ) + self.assertEqual(macro_variables.get("c"), 499) + + await Parser.parse("add(d, 500)", self.context, DummyMapping).run(self.handler) + self.assertEqual(macro_variables.get("d"), 500) + + async def test_add_invalid(self): + # For invalid input it should do nothing (except to log to the console) + await Parser.parse('set(e, "foo").add(e, 1)', self.context, DummyMapping).run( + self.handler + ) + self.assertEqual(macro_variables.get("e"), "foo") + + await Parser.parse('set(e, "2").add(e, 3)', self.context, DummyMapping).run( + self.handler + ) + self.assertEqual(macro_variables.get("e"), "2") + + async def test_raises_error(self): + Parser.parse("add(a, 1)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "add(a, b)", self.context) + self.assertRaises(MacroError, Parser.parse, 'add(a, "1")', self.context) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_macros/test_hold.py b/tests/unit/test_macros/test_hold.py index 4f5dcb10..0fd2abe2 100644 --- a/tests/unit/test_macros/test_hold.py +++ b/tests/unit/test_macros/test_hold.py @@ -25,6 +25,7 @@ from evdev.ecodes import EV_KEY from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping @@ -180,6 +181,11 @@ async def test_hold_variable(self): ], ) + async def test_raises_error(self): + self.assertRaises(MacroError, Parser.parse, "h(1, 1)", self.context) + self.assertRaises(MacroError, Parser.parse, "h(hold(h(1, 1)))", self.context) + self.assertRaises(MacroError, Parser.parse, "hold(key(a)key(b))", self.context) + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_hold_keys.py b/tests/unit/test_macros/test_hold_keys.py index cce07480..fe3b8fc0 100644 --- a/tests/unit/test_macros/test_hold_keys.py +++ b/tests/unit/test_macros/test_hold_keys.py @@ -25,6 +25,7 @@ from evdev.ecodes import EV_KEY from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping @@ -119,6 +120,11 @@ async def test_run_plus_syntax(self): self.assertEqual(self.result[6], (EV_KEY, keyboard_layout.get("b"), 0)) self.assertEqual(self.result[7], (EV_KEY, keyboard_layout.get("a"), 0)) + async def test_raises_error(self): + self.assertRaises( + MacroError, Parser.parse, "hold_keys(a, broken, b)", self.context + ) + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_if_eq.py b/tests/unit/test_macros/test_if_eq.py index 5caf8ec4..593eb697 100644 --- a/tests/unit/test_macros/test_if_eq.py +++ b/tests/unit/test_macros/test_if_eq.py @@ -28,6 +28,7 @@ ) from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.macro import macro_variables from inputremapper.injection.macros.parse import Parser from tests.lib.logger import logger @@ -37,69 +38,6 @@ @test_setup class TestIfEq(MacroTestBase): - async def test_ifeq_runs(self): - # deprecated ifeq function, but kept for compatibility reasons - macro = Parser.parse( - "set(foo, 2).ifeq(foo, 2, key(a), key(b))", - self.context, - DummyMapping, - ) - code_a = keyboard_layout.get("a") - code_b = keyboard_layout.get("b") - - await macro.run(self.handler) - self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) - self.assertEqual(self.count_child_macros(macro), 2) - - async def test_ifeq_none(self): - code_a = keyboard_layout.get("a") - - # first param None - macro = Parser.parse( - "set(foo, 2).ifeq(foo, 2, None, key(b))", self.context, DummyMapping - ) - self.assertEqual(self.count_child_macros(macro), 1) - await macro.run(self.handler) - self.assertListEqual(self.result, []) - - # second param None - self.result = [] - macro = Parser.parse( - "set(foo, 2).ifeq(foo, 2, key(a), None)", self.context, DummyMapping - ) - self.assertEqual(self.count_child_macros(macro), 1) - await macro.run(self.handler) - self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) - - """Old syntax, use None instead""" - - # first param "" - self.result = [] - macro = Parser.parse( - "set(foo, 2).ifeq(foo, 2, , key(b))", self.context, DummyMapping - ) - self.assertEqual(self.count_child_macros(macro), 1) - await macro.run(self.handler) - self.assertListEqual(self.result, []) - - # second param "" - self.result = [] - macro = Parser.parse( - "set(foo, 2).ifeq(foo, 2, key(a), )", self.context, DummyMapping - ) - self.assertEqual(self.count_child_macros(macro), 1) - await macro.run(self.handler) - self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) - - async def test_ifeq_unknown_key(self): - macro = Parser.parse("ifeq(qux, 2, key(a), key(b))", self.context, DummyMapping) - code_a = keyboard_layout.get("a") - code_b = keyboard_layout.get("b") - - await macro.run(self.handler) - self.assertListEqual(self.result, [(EV_KEY, code_b, 1), (EV_KEY, code_b, 0)]) - self.assertEqual(self.count_child_macros(macro), 2) - async def test_if_eq(self): """new version of ifeq""" code_a = keyboard_layout.get("a") @@ -193,6 +131,85 @@ def set_foo(value): ], ) + async def test_raises_error(self): + Parser.parse("if_eq(2, $a, k(a),)", self.context) # no error + Parser.parse("if_eq(2, $a, , else=k(a))", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "if_eq(2, $a, 1,)", self.context) + self.assertRaises(MacroError, Parser.parse, "if_eq(2, $a, , 2)", self.context) + self.expect_string_in_error("blub", "if_eq(2, $a, key(a), blub=a)") + + +class TestIfEqDeprecated(MacroTestBase): + async def test_ifeq_runs(self): + # deprecated ifeq function, but kept for compatibility reasons + macro = Parser.parse( + "set(foo, 2).ifeq(foo, 2, key(a), key(b))", + self.context, + DummyMapping, + ) + code_a = keyboard_layout.get("a") + code_b = keyboard_layout.get("b") + + await macro.run(self.handler) + self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) + self.assertEqual(self.count_child_macros(macro), 2) + + async def test_ifeq_none(self): + code_a = keyboard_layout.get("a") + + # first param None + macro = Parser.parse( + "set(foo, 2).ifeq(foo, 2, None, key(b))", self.context, DummyMapping + ) + self.assertEqual(self.count_child_macros(macro), 1) + await macro.run(self.handler) + self.assertListEqual(self.result, []) + + # second param None + self.result = [] + macro = Parser.parse( + "set(foo, 2).ifeq(foo, 2, key(a), None)", self.context, DummyMapping + ) + self.assertEqual(self.count_child_macros(macro), 1) + await macro.run(self.handler) + self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) + + """Old syntax, use None instead""" + + # first param "" + self.result = [] + macro = Parser.parse( + "set(foo, 2).ifeq(foo, 2, , key(b))", self.context, DummyMapping + ) + self.assertEqual(self.count_child_macros(macro), 1) + await macro.run(self.handler) + self.assertListEqual(self.result, []) + + # second param "" + self.result = [] + macro = Parser.parse( + "set(foo, 2).ifeq(foo, 2, key(a), )", self.context, DummyMapping + ) + self.assertEqual(self.count_child_macros(macro), 1) + await macro.run(self.handler) + self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) + + async def test_ifeq_unknown_key(self): + macro = Parser.parse("ifeq(qux, 2, key(a), key(b))", self.context, DummyMapping) + code_a = keyboard_layout.get("a") + code_b = keyboard_layout.get("b") + + await macro.run(self.handler) + self.assertListEqual(self.result, [(EV_KEY, code_b, 1), (EV_KEY, code_b, 0)]) + self.assertEqual(self.count_child_macros(macro), 2) + + async def test_raises_error(self): + Parser.parse("ifeq(a, 2, k(a),)", self.context) # no error + Parser.parse("ifeq(a, 2, , k(a))", self.context) # no error + Parser.parse("ifeq(a, 2, None, k(a))", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "ifeq(a, 2, 1,)", self.context) + self.assertRaises(MacroError, Parser.parse, "ifeq(a, 2, , 2)", self.context) + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_if_single.py b/tests/unit/test_macros/test_if_single.py index d3dd86e7..dbd9a57a 100644 --- a/tests/unit/test_macros/test_if_single.py +++ b/tests/unit/test_macros/test_if_single.py @@ -28,6 +28,7 @@ ) from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.parse import Parser from inputremapper.input_event import InputEvent from tests.lib.test_setup import test_setup @@ -181,6 +182,11 @@ async def test_if_single_ignores_joystick(self): self.assertFalse(macro.running) self.assertListEqual(self.result, [(EV_KEY, code_a, 1), (EV_KEY, code_a, 0)]) + async def test_raises_error(self): + Parser.parse("if_single(k(a),)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "if_single(1,)", self.context) + self.assertRaises(MacroError, Parser.parse, "if_single(,1)", self.context) + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_if_tap.py b/tests/unit/test_macros/test_if_tap.py index afe9896e..b7afa248 100644 --- a/tests/unit/test_macros/test_if_tap.py +++ b/tests/unit/test_macros/test_if_tap.py @@ -29,6 +29,7 @@ ) from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup from tests.unit.test_macros.macro_test_base import DummyMapping, MacroTestBase @@ -175,6 +176,15 @@ async def test_if_not_tap_named(self): self.assertListEqual(self.result, [(EV_KEY, y, 1), (EV_KEY, y, 0)]) self.assertFalse(macro.running) + async def test_raises_error(self): + Parser.parse("if_tap(, k(a), 1000)", self.context) # no error + Parser.parse("if_tap(, k(a), timeout=1000)", self.context) # no error + Parser.parse("if_tap(, k(a), $timeout)", self.context) # no error + Parser.parse("if_tap(, k(a), timeout=$t)", self.context) # no error + Parser.parse("if_tap(, key(a))", self.context) # no error + Parser.parse("if_tap(k(a),)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "if_tap(k(a), b)", self.context) + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_key.py b/tests/unit/test_macros/test_key.py new file mode 100644 index 00000000..34749f5a --- /dev/null +++ b/tests/unit/test_macros/test_key.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# input-remapper - GUI for device specific keyboard mappings +# Copyright (C) 2024 sezanzeb +# +# This file is part of input-remapper. +# +# input-remapper is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# input-remapper is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with input-remapper. If not, see . + + +import unittest + +from evdev.ecodes import EV_KEY + +from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import ( + MacroError, + SymbolNotAvailableInTargetError, +) +from inputremapper.injection.macros.parse import Parser +from tests.lib.test_setup import test_setup +from tests.unit.test_macros.macro_test_base import DummyMapping, MacroTestBase + + +@test_setup +class TestKey(MacroTestBase): + async def test_1(self): + macro = Parser.parse("key(1)", self.context, DummyMapping, True) + one_code = keyboard_layout.get("1") + + await macro.run(self.handler) + self.assertListEqual( + self.result, + [(EV_KEY, one_code, 1), (EV_KEY, one_code, 0)], + ) + self.assertEqual(self.count_child_macros(macro), 0) + + async def test_named_parameter(self): + macro = Parser.parse("key(symbol=1)", self.context, DummyMapping, True) + one_code = keyboard_layout.get("1") + + await macro.run(self.handler) + self.assertListEqual( + self.result, + [(EV_KEY, one_code, 1), (EV_KEY, one_code, 0)], + ) + self.assertEqual(self.count_child_macros(macro), 0) + + async def test_2(self): + macro = Parser.parse('key(1).key("KEY_A").key(3)', self.context, DummyMapping) + + await macro.run(self.handler) + self.assertListEqual( + self.result, + [ + (EV_KEY, keyboard_layout.get("1"), 1), + (EV_KEY, keyboard_layout.get("1"), 0), + (EV_KEY, keyboard_layout.get("a"), 1), + (EV_KEY, keyboard_layout.get("a"), 0), + (EV_KEY, keyboard_layout.get("3"), 1), + (EV_KEY, keyboard_layout.get("3"), 0), + ], + ) + self.assertEqual(self.count_child_macros(macro), 0) + + async def test_key_down_up(self): + code_a = keyboard_layout.get("a") + code_b = keyboard_layout.get("b") + macro = Parser.parse( + "set(foo, b).key_down($foo).key_up($foo).key_up(a).key_down(a)", + self.context, + DummyMapping, + ) + await macro.run(self.handler) + self.assertListEqual( + self.result, + [ + (EV_KEY, code_b, 1), + (EV_KEY, code_b, 0), + (EV_KEY, code_a, 0), + (EV_KEY, code_a, 1), + ], + ) + + async def test_raises_error(self): + Parser.parse("k(1).h(k(a)).k(3)", self.context) # No error + self.expect_string_in_error("bracket", "key((1)") + self.expect_string_in_error("bracket", "k(1))") + self.assertRaises(MacroError, Parser.parse, "k((1).k)", self.context) + self.assertRaises(MacroError, Parser.parse, "key(foo=a)", self.context) + self.assertRaises( + MacroError, Parser.parse, "key(symbol=a, foo=b)", self.context + ) + self.assertRaises(MacroError, Parser.parse, "k()", self.context) + self.assertRaises(MacroError, Parser.parse, "key(invalidkey)", self.context) + self.assertRaises(MacroError, Parser.parse, 'key("invalidkey")', self.context) + Parser.parse("key(1)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "k(1, 1)", self.context) + Parser.parse("key($a)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "key(a)key(b)", self.context) + # wrong target for BTN_A + self.assertRaises( + SymbolNotAvailableInTargetError, + Parser.parse, + "key(BTN_A)", + self.context, + DummyMapping, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_macros/test_leds.py b/tests/unit/test_macros/test_leds.py index 719357c4..507a70e7 100644 --- a/tests/unit/test_macros/test_leds.py +++ b/tests/unit/test_macros/test_leds.py @@ -109,6 +109,16 @@ async def test_if_capslock_no_then(self): await macro.run(self.handler) self.assertListEqual(self.result, [(EV_KEY, KEY_1, 1), (EV_KEY, KEY_1, 0)]) + async def test_raises_error(self): + Parser.parse("if_capslock(else=key(KEY_A))", self.context) # no error + Parser.parse("if_capslock(key(KEY_A), None)", self.context) # no error + Parser.parse("if_capslock(key(KEY_A))", self.context) # no error + Parser.parse("if_capslock(then=key(KEY_A))", self.context) # no error + Parser.parse("if_numlock(else=key(KEY_A))", self.context) # no error + Parser.parse("if_numlock(key(KEY_A), None)", self.context) # no error + Parser.parse("if_numlock(key(KEY_A))", self.context) # no error + Parser.parse("if_numlock(then=key(KEY_A))", self.context) # no error + if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_macros.py b/tests/unit/test_macros/test_macros.py index c72236b6..d80f70b8 100644 --- a/tests/unit/test_macros/test_macros.py +++ b/tests/unit/test_macros/test_macros.py @@ -28,10 +28,7 @@ ) from inputremapper.configs.keyboard_layout import keyboard_layout -from inputremapper.configs.validation_errors import ( - MacroError, -) -from inputremapper.injection.macros.macro import Macro, macro_variables +from inputremapper.injection.macros.macro import Macro from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping @@ -39,164 +36,7 @@ @test_setup class TestMacros(MacroTestBase): - async def test_0(self): - macro = Parser.parse("key(1)", self.context, DummyMapping, True) - one_code = keyboard_layout.get("1") - - await macro.run(self.handler) - self.assertListEqual( - self.result, - [(EV_KEY, one_code, 1), (EV_KEY, one_code, 0)], - ) - self.assertEqual(self.count_child_macros(macro), 0) - - async def test_named_parameter(self): - macro = Parser.parse("key(symbol=1)", self.context, DummyMapping, True) - one_code = keyboard_layout.get("1") - - await macro.run(self.handler) - self.assertListEqual( - self.result, - [(EV_KEY, one_code, 1), (EV_KEY, one_code, 0)], - ) - self.assertEqual(self.count_child_macros(macro), 0) - - async def test_1(self): - macro = Parser.parse('key(1).key("KEY_A").key(3)', self.context, DummyMapping) - - await macro.run(self.handler) - self.assertListEqual( - self.result, - [ - (EV_KEY, keyboard_layout.get("1"), 1), - (EV_KEY, keyboard_layout.get("1"), 0), - (EV_KEY, keyboard_layout.get("a"), 1), - (EV_KEY, keyboard_layout.get("a"), 0), - (EV_KEY, keyboard_layout.get("3"), 1), - (EV_KEY, keyboard_layout.get("3"), 0), - ], - ) - self.assertEqual(self.count_child_macros(macro), 0) - - async def test_key(self): - code_a = keyboard_layout.get("a") - code_b = keyboard_layout.get("b") - macro = Parser.parse("set(foo, b).key($foo).key(a)", self.context, DummyMapping) - await macro.run(self.handler) - self.assertListEqual( - self.result, - [ - (EV_KEY, code_b, 1), - (EV_KEY, code_b, 0), - (EV_KEY, code_a, 1), - (EV_KEY, code_a, 0), - ], - ) - - async def test_key_down_up(self): - code_a = keyboard_layout.get("a") - code_b = keyboard_layout.get("b") - macro = Parser.parse( - "set(foo, b).key_down($foo).key_up($foo).key_up(a).key_down(a)", - self.context, - DummyMapping, - ) - await macro.run(self.handler) - self.assertListEqual( - self.result, - [ - (EV_KEY, code_b, 1), - (EV_KEY, code_b, 0), - (EV_KEY, code_a, 0), - (EV_KEY, code_a, 1), - ], - ) - - async def test_modify(self): - code_a = keyboard_layout.get("a") - code_b = keyboard_layout.get("b") - code_c = keyboard_layout.get("c") - macro = Parser.parse( - "set(foo, b).modify($foo, modify(a, key(c)))", - self.context, - DummyMapping, - ) - await macro.run(self.handler) - self.assertListEqual( - self.result, - [ - (EV_KEY, code_b, 1), - (EV_KEY, code_a, 1), - (EV_KEY, code_c, 1), - (EV_KEY, code_c, 0), - (EV_KEY, code_a, 0), - (EV_KEY, code_b, 0), - ], - ) - - async def test_2(self): - start = time.time() - repeats = 20 - - macro = Parser.parse( - f"repeat({repeats}, key(k)).repeat(1, key(k))", - self.context, - DummyMapping, - ) - k_code = keyboard_layout.get("k") - - await macro.run(self.handler) - keystroke_sleep = DummyMapping.macro_key_sleep_ms - sleep_time = 2 * repeats * keystroke_sleep / 1000 - self.assertGreater(time.time() - start, sleep_time * 0.9) - self.assertLess(time.time() - start, sleep_time * 1.3) - - self.assertListEqual( - self.result, - [(EV_KEY, k_code, 1), (EV_KEY, k_code, 0)] * (repeats + 1), - ) - - self.assertEqual(self.count_child_macros(macro), 2) - - self.assertEqual(len(macro.tasks[0].child_macros), 1) - self.assertEqual(len(macro.tasks[0].child_macros[0].tasks), 1) - self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[0].child_macros), 0) - - self.assertEqual(len(macro.tasks[1].child_macros), 1) - self.assertEqual(len(macro.tasks[1].child_macros[0].tasks), 1) - self.assertEqual(len(macro.tasks[1].child_macros[0].tasks[0].child_macros), 0) - - async def test_3(self): - start = time.time() - macro = Parser.parse("repeat(3, key(m).w(100))", self.context, DummyMapping) - m_code = keyboard_layout.get("m") - await macro.run(self.handler) - - keystroke_time = 6 * DummyMapping.macro_key_sleep_ms - total_time = keystroke_time + 300 - total_time /= 1000 - - self.assertGreater(time.time() - start, total_time * 0.9) - self.assertLess(time.time() - start, total_time * 1.2) - self.assertListEqual( - self.result, - [ - (EV_KEY, m_code, 1), - (EV_KEY, m_code, 0), - (EV_KEY, m_code, 1), - (EV_KEY, m_code, 0), - (EV_KEY, m_code, 1), - (EV_KEY, m_code, 0), - ], - ) - self.assertEqual(self.count_child_macros(macro), 1) - self.assertEqual(len(macro.tasks), 1) - self.assertEqual(len(macro.tasks[0].child_macros), 1) - self.assertEqual(len(macro.tasks[0].child_macros[0].tasks), 2) - self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[0].child_macros), 0) - self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[1].child_macros), 0) - - async def test_4(self): + async def test_newlines(self): macro = Parser.parse( " repeat(2,\nkey(\nr ).key(minus\n )).key(m) ", self.context, @@ -226,7 +66,7 @@ async def test_4(self): self.assertEqual(self.count_child_macros(macro), 1) self.assertEqual(self.count_tasks(macro), 4) - async def test_5(self): + async def test_various(self): start = time.time() macro = Parser.parse( "w(200).repeat(2,modify(w,\nrepeat(2,\tkey(BtN_LeFt))).w(10).key(k))", @@ -257,7 +97,7 @@ async def test_5(self): expected *= 2 self.assertListEqual(self.result, expected) - async def test_6(self): + async def test_not_run(self): # does nothing without .run macro = Parser.parse("key(a).repeat(3, key(b))", self.context) self.assertIsInstance(macro, Macro) @@ -322,69 +162,6 @@ async def test_duplicate_run(self): ] * 2 self.assertListEqual(self.result, expected) - async def test_macro_breaks(self): - # the first parameter for `repeat` requires an integer, not "foo", - # which makes `repeat` throw - macro = Parser.parse( - 'set(a, "foo").repeat($a, key(KEY_A)).key(KEY_B)', - self.context, - DummyMapping, - ) - - try: - await macro.run(self.handler) - except MacroError as e: - self.assertIn("foo", str(e)) - - self.assertFalse(macro.running) - - # key(KEY_B) is not executed, the macro stops - self.assertListEqual(self.result, []) - - async def test_set(self): - """await Parser.parse('set(a, "foo")', self.context, DummyMapping).run(self.handler) - self.assertEqual(macro_variables.get("a"), "foo") - - await Parser.parse('set( \t"b" \n, "1")', self.context, DummyMapping).run(self.handler) - self.assertEqual(macro_variables.get("b"), "1")""" - - await Parser.parse("set(a, 1)", self.context, DummyMapping).run(self.handler) - self.assertEqual(macro_variables.get("a"), 1) - - """await Parser.parse("set(a, )", self.context, DummyMapping).run(self.handler) - self.assertEqual(macro_variables.get("a"), None)""" - - async def test_add(self): - await Parser.parse("set(a, 1).add(a, 1)", self.context, DummyMapping).run( - self.handler - ) - self.assertEqual(macro_variables.get("a"), 2) - - await Parser.parse("set(b, 1).add(b, -1)", self.context, DummyMapping).run( - self.handler - ) - self.assertEqual(macro_variables.get("b"), 0) - - await Parser.parse("set(c, -1).add(c, 500)", self.context, DummyMapping).run( - self.handler - ) - self.assertEqual(macro_variables.get("c"), 499) - - await Parser.parse("add(d, 500)", self.context, DummyMapping).run(self.handler) - self.assertEqual(macro_variables.get("d"), 500) - - async def test_add_invalid(self): - # For invalid input it should do nothing (except to log to the console) - await Parser.parse('set(e, "foo").add(e, 1)', self.context, DummyMapping).run( - self.handler - ) - self.assertEqual(macro_variables.get("e"), "foo") - - await Parser.parse('set(e, "2").add(e, 3)', self.context, DummyMapping).run( - self.handler - ) - self.assertEqual(macro_variables.get("e"), "2") - if __name__ == "__main__": unittest.main() diff --git a/tests/unit/test_macros/test_modify.py b/tests/unit/test_macros/test_modify.py new file mode 100644 index 00000000..5d9ebf14 --- /dev/null +++ b/tests/unit/test_macros/test_modify.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# input-remapper - GUI for device specific keyboard mappings +# Copyright (C) 2024 sezanzeb +# +# This file is part of input-remapper. +# +# input-remapper is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# input-remapper is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with input-remapper. If not, see . + + +import unittest + +from evdev.ecodes import EV_KEY + +from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError +from inputremapper.injection.macros.parse import Parser +from tests.lib.test_setup import test_setup +from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping + + +@test_setup +class TestModify(MacroTestBase): + async def test_modify(self): + code_a = keyboard_layout.get("a") + code_b = keyboard_layout.get("b") + code_c = keyboard_layout.get("c") + macro = Parser.parse( + "set(foo, b).modify($foo, modify(a, key(c)))", + self.context, + DummyMapping, + ) + await macro.run(self.handler) + self.assertListEqual( + self.result, + [ + (EV_KEY, code_b, 1), + (EV_KEY, code_a, 1), + (EV_KEY, code_c, 1), + (EV_KEY, code_c, 0), + (EV_KEY, code_a, 0), + (EV_KEY, code_b, 0), + ], + ) + + async def test_raises_error(self): + self.assertRaises(MacroError, Parser.parse, "modify(asdf, k(a))", self.context) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_macros/test_mouse.py b/tests/unit/test_macros/test_mouse.py index e952ea39..4ef17484 100644 --- a/tests/unit/test_macros/test_mouse.py +++ b/tests/unit/test_macros/test_mouse.py @@ -33,6 +33,7 @@ EV_KEY, ) +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup from tests.unit.test_macros.macro_test_base import DummyMapping, MacroTestBase @@ -206,6 +207,13 @@ async def test_wheel_releases(self): await self._run_macro(f"wheel(down, 1).key(a)", 0.1) self.assertEqual(self.result[-2:], [(EV_KEY, KEY_A, 1), (EV_KEY, KEY_A, 0)]) + async def test_raises_error(self): + Parser.parse("mouse(up, 3)", self.context) # no error + Parser.parse("mouse(up, speed=$a)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "mouse(3, up)", self.context) + Parser.parse("wheel(left, 3)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "wheel(3, left)", self.context) + def _get_x_movement(self): return [event for event in self.result if event[1] == REL_X] diff --git a/tests/unit/test_macros/test_parsing.py b/tests/unit/test_macros/test_parsing.py index da6c0c7c..c4ed60cf 100644 --- a/tests/unit/test_macros/test_parsing.py +++ b/tests/unit/test_macros/test_parsing.py @@ -26,7 +26,6 @@ from inputremapper.configs.validation_errors import ( MacroError, - SymbolNotAvailableInTargetError, ) from inputremapper.injection.macros.argument import Argument, ArgumentConfig from inputremapper.injection.macros.parse import Parser @@ -289,119 +288,7 @@ def test(value, types): Variable("foo", const=False), ) - async def test_raises_error(self): - def expect_string_in_error(string: str, macro: str): - with self.assertRaises(MacroError) as cm: - Parser.parse(macro, self.context) - error = str(cm.exception) - self.assertIn(string, error) - - Parser.parse("k(1).h(k(a)).k(3)", self.context) # No error - expect_string_in_error("bracket", "key((1)") - expect_string_in_error("bracket", "k(1))") - self.assertRaises(MacroError, Parser.parse, "k((1).k)", self.context) - self.assertRaises(MacroError, Parser.parse, "key(foo=a)", self.context) - self.assertRaises( - MacroError, Parser.parse, "key(symbol=a, foo=b)", self.context - ) - self.assertRaises(MacroError, Parser.parse, "k()", self.context) - self.assertRaises(MacroError, Parser.parse, "key(invalidkey)", self.context) - self.assertRaises(MacroError, Parser.parse, 'key("invalidkey")', self.context) - Parser.parse("key(1)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "k(1, 1)", self.context) - Parser.parse("key($a)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "h(1, 1)", self.context) - self.assertRaises(MacroError, Parser.parse, "h(hold(h(1, 1)))", self.context) - self.assertRaises(MacroError, Parser.parse, "r(1)", self.context) - self.assertRaises(MacroError, Parser.parse, "repeat(a, k(1))", self.context) - Parser.parse("repeat($a, k(1))", self.context) # no error - Parser.parse("repeat(2, k(1))", self.context) # no error - self.assertRaises(MacroError, Parser.parse, 'repeat("2", k(1))', self.context) - self.assertRaises(MacroError, Parser.parse, "r(1, 1)", self.context) - self.assertRaises(MacroError, Parser.parse, "r(k(1), 1)", self.context) - Parser.parse("r(1, macro=k(1))", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "r(a=1, b=k(1))", self.context) - self.assertRaises( - MacroError, - Parser.parse, - "r(repeats=1, macro=k(1), a=2)", - self.context, - ) - self.assertRaises( - MacroError, - Parser.parse, - "r(repeats=1, macro=k(1), repeats=2)", - self.context, - ) - self.assertRaises(MacroError, Parser.parse, "modify(asdf, k(a))", self.context) - Parser.parse("if_tap(, k(a), 1000)", self.context) # no error - Parser.parse("if_tap(, k(a), timeout=1000)", self.context) # no error - Parser.parse("if_tap(, k(a), $timeout)", self.context) # no error - Parser.parse("if_tap(, k(a), timeout=$t)", self.context) # no error - Parser.parse("if_tap(, key(a))", self.context) # no error - Parser.parse("if_tap(k(a),)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "if_tap(k(a), b)", self.context) - Parser.parse("if_single(k(a),)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "if_single(1,)", self.context) - self.assertRaises(MacroError, Parser.parse, "if_single(,1)", self.context) - Parser.parse("mouse(up, 3)", self.context) # no error - Parser.parse("mouse(up, speed=$a)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "mouse(3, up)", self.context) - Parser.parse("wheel(left, 3)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "wheel(3, left)", self.context) - Parser.parse("w(2)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "wait(a)", self.context) - Parser.parse("ifeq(a, 2, k(a),)", self.context) # no error - Parser.parse("ifeq(a, 2, , k(a))", self.context) # no error - Parser.parse("ifeq(a, 2, None, k(a))", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "ifeq(a, 2, 1,)", self.context) - self.assertRaises(MacroError, Parser.parse, "ifeq(a, 2, , 2)", self.context) - Parser.parse("if_eq(2, $a, k(a),)", self.context) # no error - Parser.parse("if_eq(2, $a, , else=k(a))", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "if_eq(2, $a, 1,)", self.context) - self.assertRaises(MacroError, Parser.parse, "if_eq(2, $a, , 2)", self.context) - - expect_string_in_error("blub", "if_eq(2, $a, key(a), blub=a)") - - expect_string_in_error("foo", "foo(a)") - - self.assertRaises(MacroError, Parser.parse, "set($a, 1)", self.context) - self.assertRaises(MacroError, Parser.parse, "set(1, 2)", self.context) - self.assertRaises(MacroError, Parser.parse, "set(+, 2)", self.context) - self.assertRaises(MacroError, Parser.parse, "set(a(), 2)", self.context) - self.assertRaises(MacroError, Parser.parse, "set('b,c', 2)", self.context) - self.assertRaises(MacroError, Parser.parse, 'set("b,c", 2)', self.context) - Parser.parse("set(A, 2)", self.context) # no error - - self.assertRaises(MacroError, Parser.parse, "key(a)key(b)", self.context) - self.assertRaises(MacroError, Parser.parse, "hold(key(a)key(b))", self.context) - - self.assertRaises( - MacroError, Parser.parse, "hold_keys(a, broken, b)", self.context - ) - - Parser.parse("add(a, 1)", self.context) # no error - self.assertRaises(MacroError, Parser.parse, "add(a, b)", self.context) - self.assertRaises(MacroError, Parser.parse, 'add(a, "1")', self.context) - - Parser.parse("if_capslock(else=key(KEY_A))", self.context) # no error - Parser.parse("if_capslock(key(KEY_A), None)", self.context) # no error - Parser.parse("if_capslock(key(KEY_A))", self.context) # no error - Parser.parse("if_capslock(then=key(KEY_A))", self.context) # no error - Parser.parse("if_numlock(else=key(KEY_A))", self.context) # no error - Parser.parse("if_numlock(key(KEY_A), None)", self.context) # no error - Parser.parse("if_numlock(key(KEY_A))", self.context) # no error - Parser.parse("if_numlock(then=key(KEY_A))", self.context) # no error - - # wrong target for BTN_A - self.assertRaises( - SymbolNotAvailableInTargetError, - Parser.parse, - "key(BTN_A)", - self.context, - DummyMapping, - ) - + async def test_string_not_a_macro(self): # passing a string parameter. This is not a macro, even though # it might look like it without the string quotes. Everything with # explicit quotes around it has to be treated as a string. diff --git a/tests/unit/test_macros/test_repeat.py b/tests/unit/test_macros/test_repeat.py new file mode 100644 index 00000000..d20dcd16 --- /dev/null +++ b/tests/unit/test_macros/test_repeat.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# input-remapper - GUI for device specific keyboard mappings +# Copyright (C) 2024 sezanzeb +# +# This file is part of input-remapper. +# +# input-remapper is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# input-remapper is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with input-remapper. If not, see . +import time +import unittest + +from evdev.ecodes import EV_KEY + +from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError +from inputremapper.injection.macros.parse import Parser +from tests.lib.test_setup import test_setup +from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping + + +@test_setup +class TestRepeat(MacroTestBase): + async def test_1(self): + start = time.time() + repeats = 20 + + macro = Parser.parse( + f"repeat({repeats}, key(k)).repeat(1, key(k))", + self.context, + DummyMapping, + ) + k_code = keyboard_layout.get("k") + + await macro.run(self.handler) + keystroke_sleep = DummyMapping.macro_key_sleep_ms + sleep_time = 2 * repeats * keystroke_sleep / 1000 + self.assertGreater(time.time() - start, sleep_time * 0.9) + self.assertLess(time.time() - start, sleep_time * 1.3) + + self.assertListEqual( + self.result, + [(EV_KEY, k_code, 1), (EV_KEY, k_code, 0)] * (repeats + 1), + ) + + self.assertEqual(self.count_child_macros(macro), 2) + + self.assertEqual(len(macro.tasks[0].child_macros), 1) + self.assertEqual(len(macro.tasks[0].child_macros[0].tasks), 1) + self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[0].child_macros), 0) + + self.assertEqual(len(macro.tasks[1].child_macros), 1) + self.assertEqual(len(macro.tasks[1].child_macros[0].tasks), 1) + self.assertEqual(len(macro.tasks[1].child_macros[0].tasks[0].child_macros), 0) + + async def test_2(self): + start = time.time() + macro = Parser.parse("repeat(3, key(m).w(100))", self.context, DummyMapping) + m_code = keyboard_layout.get("m") + await macro.run(self.handler) + + keystroke_time = 6 * DummyMapping.macro_key_sleep_ms + total_time = keystroke_time + 300 + total_time /= 1000 + + self.assertGreater(time.time() - start, total_time * 0.9) + self.assertLess(time.time() - start, total_time * 1.2) + self.assertListEqual( + self.result, + [ + (EV_KEY, m_code, 1), + (EV_KEY, m_code, 0), + (EV_KEY, m_code, 1), + (EV_KEY, m_code, 0), + (EV_KEY, m_code, 1), + (EV_KEY, m_code, 0), + ], + ) + self.assertEqual(self.count_child_macros(macro), 1) + self.assertEqual(len(macro.tasks), 1) + self.assertEqual(len(macro.tasks[0].child_macros), 1) + self.assertEqual(len(macro.tasks[0].child_macros[0].tasks), 2) + self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[0].child_macros), 0) + self.assertEqual(len(macro.tasks[0].child_macros[0].tasks[1].child_macros), 0) + + async def test_not_an_int(self): + # the first parameter for `repeat` requires an integer, not "foo", + # which makes `repeat` throw + macro = Parser.parse( + 'set(a, "foo").repeat($a, key(KEY_A)).key(KEY_B)', + self.context, + DummyMapping, + ) + + try: + await macro.run(self.handler) + except MacroError as e: + self.assertIn("foo", str(e)) + + self.assertFalse(macro.running) + + # key(KEY_B) is not executed, the macro stops + self.assertListEqual(self.result, []) + + async def test_raises_error(self): + self.assertRaises(MacroError, Parser.parse, "r(1)", self.context) + self.assertRaises(MacroError, Parser.parse, "repeat(a, k(1))", self.context) + Parser.parse("repeat($a, k(1))", self.context) # no error + Parser.parse("repeat(2, k(1))", self.context) # no error + self.assertRaises(MacroError, Parser.parse, 'repeat("2", k(1))', self.context) + self.assertRaises(MacroError, Parser.parse, "r(1, 1)", self.context) + self.assertRaises(MacroError, Parser.parse, "r(k(1), 1)", self.context) + Parser.parse("r(1, macro=k(1))", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "r(a=1, b=k(1))", self.context) + self.assertRaises( + MacroError, + Parser.parse, + "r(repeats=1, macro=k(1), a=2)", + self.context, + ) + self.assertRaises( + MacroError, + Parser.parse, + "r(repeats=1, macro=k(1), repeats=2)", + self.context, + ) + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_macros/test_set.py b/tests/unit/test_macros/test_set.py new file mode 100644 index 00000000..def8ab16 --- /dev/null +++ b/tests/unit/test_macros/test_set.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# input-remapper - GUI for device specific keyboard mappings +# Copyright (C) 2024 sezanzeb +# +# This file is part of input-remapper. +# +# input-remapper is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# input-remapper is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with input-remapper. If not, see . + + +import unittest + +from evdev.ecodes import EV_KEY + +from inputremapper.configs.keyboard_layout import keyboard_layout +from inputremapper.configs.validation_errors import MacroError +from inputremapper.injection.macros.macro import macro_variables +from inputremapper.injection.macros.parse import Parser +from tests.lib.test_setup import test_setup +from tests.unit.test_macros.macro_test_base import MacroTestBase, DummyMapping + + +@test_setup +class TestSet(MacroTestBase): + async def test_set_key(self): + code_b = keyboard_layout.get("b") + macro = Parser.parse("set(foo, b).key($foo)", self.context, DummyMapping) + await macro.run(self.handler) + self.assertListEqual( + self.result, + [ + (EV_KEY, code_b, 1), + (EV_KEY, code_b, 0), + ], + ) + + async def test_int_is_explicit_string(self): + await Parser.parse( + 'set( \t"b" \n, "1")', + self.context, + DummyMapping, + ).run(self.handler) + self.assertEqual(macro_variables.get("b"), "1") + + async def test_int_is_int(self): + await Parser.parse( + "set(a, 1)", + self.context, + DummyMapping, + ).run(self.handler) + self.assertEqual(macro_variables.get("a"), 1) + + async def test_none(self): + await Parser.parse( + "set(a, )", + self.context, + DummyMapping, + ).run(self.handler) + self.assertEqual(macro_variables.get("a"), None) + + async def test_set_case_sensitive_1(self): + await Parser.parse( + 'set(a, "foo")', + self.context, + DummyMapping, + ).run(self.handler) + self.assertEqual(macro_variables.get("a"), "foo") + self.assertEqual(macro_variables.get("A"), None) + + async def test_set_case_sensitive_2(self): + await Parser.parse( + 'set(A, "foo")', + self.context, + DummyMapping, + ).run(self.handler) + self.assertEqual(macro_variables.get("A"), "foo") + self.assertEqual(macro_variables.get("a"), None) + + async def test_raises_error(self): + self.assertRaises(MacroError, Parser.parse, "set($a, 1)", self.context) + self.assertRaises(MacroError, Parser.parse, "set(1, 2)", self.context) + self.assertRaises(MacroError, Parser.parse, "set(+, 2)", self.context) + self.assertRaises(MacroError, Parser.parse, "set(a(), 2)", self.context) + self.assertRaises(MacroError, Parser.parse, "set('b,c', 2)", self.context) + self.assertRaises(MacroError, Parser.parse, 'set("b,c", 2)', self.context) + Parser.parse("set(A, 2)", self.context) # no error + + +if __name__ == "__main__": + unittest.main() diff --git a/tests/unit/test_macros/test_wait.py b/tests/unit/test_macros/test_wait.py index 11df0abb..375fe397 100644 --- a/tests/unit/test_macros/test_wait.py +++ b/tests/unit/test_macros/test_wait.py @@ -22,6 +22,7 @@ import time import unittest +from inputremapper.configs.validation_errors import MacroError from inputremapper.injection.macros.macro import Macro from inputremapper.injection.macros.parse import Parser from tests.lib.test_setup import test_setup @@ -79,6 +80,10 @@ async def test_wait_4_ranged_double_get(self): ) await self.assert_time_randomized(macro, 0.02, 0.08) + async def test_raises_error(self): + Parser.parse("w(2)", self.context) # no error + self.assertRaises(MacroError, Parser.parse, "wait(a)", self.context) + if __name__ == "__main__": unittest.main()