From 951aad3b4970060b6e171e4d7c0ed6be875a56d6 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 8 Mar 2024 10:06:57 -0800 Subject: [PATCH 1/3] Actually don't load uninitialized data from EEPROM clobbering defaults --- .../src/kaleidoscope/plugin/EEPROM-Settings.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/Kaleidoscope-EEPROM-Settings/src/kaleidoscope/plugin/EEPROM-Settings.h b/plugins/Kaleidoscope-EEPROM-Settings/src/kaleidoscope/plugin/EEPROM-Settings.h index d8c7291404..efac2d9e1f 100644 --- a/plugins/Kaleidoscope-EEPROM-Settings/src/kaleidoscope/plugin/EEPROM-Settings.h +++ b/plugins/Kaleidoscope-EEPROM-Settings/src/kaleidoscope/plugin/EEPROM-Settings.h @@ -88,8 +88,8 @@ class EEPROMSettings : public kaleidoscope::Plugin { *startAddress = start; // Load the data if the slice is initialized - Runtime.storage().get(start, *data); // Directly load data into the provided address if (!Runtime.storage().isSliceUninitialized(start, size)) { + Runtime.storage().get(start, *data); // Directly load data into the provided address return true; } From f695791487c98a1778ab8ad669a5dea7b1ad13a3 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 8 Mar 2024 10:16:38 -0800 Subject: [PATCH 2/3] Add two test scripts for mouse keys and sticky keys behaviour --- .../mouse_keys_defaults.py | 68 +++++++++++++++++++ .../sticky_off_after_reboot_and_reset.py | 68 +++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py create mode 100644 testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py diff --git a/testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py b/testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py new file mode 100644 index 0000000000..9441fb85e5 --- /dev/null +++ b/testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py @@ -0,0 +1,68 @@ +import subprocess +import unittest +import time +def run_focus_command(command, hide_stderr=False): + """Execute a focus send command, print the command and its output, and return its output.""" + stderr_setting = subprocess.DEVNULL if hide_stderr else subprocess.PIPE + print(f"Running command: {command}") + completed_process = subprocess.run(f"focus send {command}", shell=True, stdout=subprocess.PIPE, stderr=stderr_setting, text=True) + print(f"Result: {completed_process.stdout.strip()}") + if completed_process.returncode != 0 and not hide_stderr: + print(f"Error: {completed_process.stderr.strip()}" if completed_process.stderr else "Command failed with no error output.") + return completed_process.stdout.strip(), completed_process.returncode + +class TestFocusCommands(unittest.TestCase): + def test_mousekeys_base_speed_persistence(self): + _, _ = run_focus_command("version") + + # Initially try to erase eeprom and expect an error + _, returncode = run_focus_command("eeprom.erase", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Eeprom erase should fail but did not.") + + #erasing eeprom takes a moment + time.sleep(5) + + # Verify initial mousekeys.base_speed is '1' + initial_mode, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(initial_mode, '50', "Initial mousekeys.base_speed should be '50'") + + # Change mousekeys.base_speed to 50 and verify + run_focus_command("mousekeys.base_speed 60") + mode_after_setting_to_60, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(mode_after_setting_to_60, '60', "mousekeys.base_speed should be '60' after setting to 60") + + # Reset device and expect an error + _, returncode = run_focus_command("device.reset", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Device reset should fail but did not.") + time.sleep(5) # Wait for the device to potentially reset + + # Verify mousekeys.base_speed is still 0 after reset + mode_after_reset, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(mode_after_reset, '60', "mousekeys.base_speed should remain '60' after reset") + + # Change mousekeys.base_speed to 1 and verify + run_focus_command("mousekeys.base_speed 250") + mode_after_setting_to_250, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(mode_after_setting_to_250, '250', "mousekeys.base_speed should be '250' after setting to 250") + + # Reset device again and expect an error + _, returncode = run_focus_command("device.reset", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Device reset should fail but did not.") + time.sleep(5) # Wait for the device to potentially reset + + # Verify mousekeys.base_speed is still 1 after reset + mode_final, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(mode_final, '250', "mousekeys.base_speed should remain '250' after final reset") + + # Try to erase eeprom again and expect an error + _, returncode = run_focus_command("eeprom.erase", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Eeprom erase should fail but did not.") + + time.sleep(5) # Wait for the device to potentially reset + + # Verify mousekeys.base_speed is still 1 after attempting to erase eeprom + mode_after_erase, _ = run_focus_command("mousekeys.base_speed") + self.assertEqual(mode_after_erase, '50', "mousekeys.base_speed should remain '50' after attempting to erase eeprom") + +if __name__ == '__main__': + unittest.main() diff --git a/testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py b/testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py new file mode 100644 index 0000000000..d9a32a56e1 --- /dev/null +++ b/testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py @@ -0,0 +1,68 @@ +import subprocess +import unittest +import time +def run_focus_command(command, hide_stderr=False): + """Execute a focus send command, print the command and its output, and return its output.""" + stderr_setting = subprocess.DEVNULL if hide_stderr else subprocess.PIPE + print(f"Running command: {command}") + completed_process = subprocess.run(f"focus send {command}", shell=True, stdout=subprocess.PIPE, stderr=stderr_setting, text=True) + print(f"Result: {completed_process.stdout.strip()}") + if completed_process.returncode != 0 and not hide_stderr: + print(f"Error: {completed_process.stderr.strip()}" if completed_process.stderr else "Command failed with no error output.") + return completed_process.stdout.strip(), completed_process.returncode + +class TestFocusCommands(unittest.TestCase): + def test_oneshot_auto_mods_persistence(self): + _, _ = run_focus_command("version") + + # Initially try to erase eeprom and expect an error + _, returncode = run_focus_command("eeprom.erase", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Eeprom erase should fail but did not.") + + #erasing eeprom takes a moment + time.sleep(5) + + # Verify initial oneshot.auto_mods is '1' + initial_mode, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(initial_mode, '0', "Initial oneshot.auto_mods should be '0'") + + # Change oneshot.auto_mods to 0 and verify + run_focus_command("oneshot.auto_mods 0") + mode_after_setting_to_0, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(mode_after_setting_to_0, '0', "oneshot.auto_mods should be '0' after setting to 0") + + # Reset device and expect an error + _, returncode = run_focus_command("device.reset", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Device reset should fail but did not.") + time.sleep(5) # Wait for the device to potentially reset + + # Verify oneshot.auto_mods is still 0 after reset + mode_after_reset, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(mode_after_reset, '0', "oneshot.auto_mods should remain '0' after reset") + + # Change oneshot.auto_mods to 1 and verify + run_focus_command("oneshot.auto_mods 1") + mode_after_setting_to_1, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(mode_after_setting_to_1, '1', "oneshot.auto_mods should be '1' after setting to 1") + + # Reset device again and expect an error + _, returncode = run_focus_command("device.reset", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Device reset should fail but did not.") + time.sleep(5) # Wait for the device to potentially reset + + # Verify oneshot.auto_mods is still 1 after reset + mode_final, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(mode_final, '1', "oneshot.auto_mods should remain '1' after final reset") + + # Try to erase eeprom again and expect an error + _, returncode = run_focus_command("eeprom.erase", hide_stderr=True) + self.assertNotEqual(returncode, 0, "Eeprom erase should fail but did not.") + + time.sleep(5) # Wait for the device to potentially reset + + # Verify oneshot.auto_mods is still 1 after attempting to erase eeprom + mode_after_erase, _ = run_focus_command("oneshot.auto_mods") + self.assertEqual(mode_after_erase, '0', "oneshot.auto_mods should remain '0' after attempting to erase eeprom") + +if __name__ == '__main__': + unittest.main() From 849c67e719a0aaf7155ec27ee13d9d85b0ee8c53 Mon Sep 17 00:00:00 2001 From: Jesse Vincent Date: Fri, 8 Mar 2024 10:25:52 -0800 Subject: [PATCH 3/3] Add more on-device tests and a test harness --- testing/device-testing/.gitignore | 1 + testing/device-testing/Makefile | 20 +++++++++++++++++++ .../{mouse_keys_defaults.py => test.py} | 0 ..._off_after_reboot_and_reset.py => test.py} | 0 ..._off_after_reboot_and_reset.py => test.py} | 0 5 files changed, 21 insertions(+) create mode 100644 testing/device-testing/.gitignore create mode 100644 testing/device-testing/Makefile rename testing/device-testing/mouse-keys-defaults/{mouse_keys_defaults.py => test.py} (100%) rename testing/device-testing/spacecadet-off/{space_cadet_off_after_reboot_and_reset.py => test.py} (100%) rename testing/device-testing/sticky-keys-off/{sticky_off_after_reboot_and_reset.py => test.py} (100%) diff --git a/testing/device-testing/.gitignore b/testing/device-testing/.gitignore new file mode 100644 index 0000000000..c18dd8d83c --- /dev/null +++ b/testing/device-testing/.gitignore @@ -0,0 +1 @@ +__pycache__/ diff --git a/testing/device-testing/Makefile b/testing/device-testing/Makefile new file mode 100644 index 0000000000..bde80127a1 --- /dev/null +++ b/testing/device-testing/Makefile @@ -0,0 +1,20 @@ +# Makefile for running Python tests + +# Shell to use with Make +SHELL := /bin/bash + +# Find all Python test scripts +TEST_SCRIPTS := $(shell find . -type f -name 'test.py' ) + +.PHONY: test + +test-on-hardware-wiping-your-device: + @for script in $(TEST_SCRIPTS) ; do \ + echo "Running $$script..." ; \ + python -m unittest $$script ; \ + if [ $$? -ne 0 ]; then \ + echo "Test failed: $$script" ; \ + exit 1 ; \ + fi ; \ + done + diff --git a/testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py b/testing/device-testing/mouse-keys-defaults/test.py similarity index 100% rename from testing/device-testing/mouse-keys-defaults/mouse_keys_defaults.py rename to testing/device-testing/mouse-keys-defaults/test.py diff --git a/testing/device-testing/spacecadet-off/space_cadet_off_after_reboot_and_reset.py b/testing/device-testing/spacecadet-off/test.py similarity index 100% rename from testing/device-testing/spacecadet-off/space_cadet_off_after_reboot_and_reset.py rename to testing/device-testing/spacecadet-off/test.py diff --git a/testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py b/testing/device-testing/sticky-keys-off/test.py similarity index 100% rename from testing/device-testing/sticky-keys-off/sticky_off_after_reboot_and_reset.py rename to testing/device-testing/sticky-keys-off/test.py