diff --git a/keyboard.go b/keyboard.go index 9c52eb8..15da476 100644 --- a/keyboard.go +++ b/keyboard.go @@ -45,14 +45,17 @@ func CreateKeyboard(path string, name []byte) (Keyboard, error) { // KeyPress will issue a single key press (push down a key and then immediately release it). func (vk vKeyboard) KeyPress(key int) error { + if !keyCodeInRange(key) { + return fmt.Errorf("failed to perform KeyPress. Code %d is not in range", key) + } err := sendBtnEvent(vk.deviceFile, key, btnStatePressed) if err != nil { - return fmt.Errorf("Failed to issue the KeyDown event: %v", err) + return fmt.Errorf("failed to issue the KeyDown event: %v", err) } err = sendBtnEvent(vk.deviceFile, key, btnStateReleased) if err != nil { - return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + return fmt.Errorf("failed to issue the KeyUp event: %v", err) } err = syncEvents(vk.deviceFile) @@ -66,9 +69,12 @@ func (vk vKeyboard) KeyPress(key int) error { // event is sent to the device, the key will remain pressed and therefore input will continuously be generated. Therefore, // do not forget to call "KeyUp" afterwards. func (vk vKeyboard) KeyDown(key int) error { + if !keyCodeInRange(key) { + return fmt.Errorf("failed to perform KeyDown. Code %d is not in range", key) + } err := sendBtnEvent(vk.deviceFile, key, btnStatePressed) if err != nil { - return fmt.Errorf("Failed to issue the KeyDown event: %v", err) + return fmt.Errorf("failed to issue the KeyDown event: %v", err) } err = syncEvents(vk.deviceFile) @@ -82,9 +88,13 @@ func (vk vKeyboard) KeyDown(key int) error { // cases it is recommended to call this function immediately after the "KeyDown" function in order to only issue a // single key press. func (vk vKeyboard) KeyUp(key int) error { + if !keyCodeInRange(key) { + return fmt.Errorf("failed to perform KeyUp. Code %d is not in range", key) + } + err := sendBtnEvent(vk.deviceFile, key, btnStateReleased) if err != nil { - return fmt.Errorf("Failed to issue the KeyUp event: %v", err) + return fmt.Errorf("failed to issue the KeyUp event: %v", err) } err = syncEvents(vk.deviceFile) @@ -130,3 +140,7 @@ func createVKeyboardDevice(path string, name []byte) (fd *os.File, err error) { Product: 0x0815, Version: 1}}) } + +func keyCodeInRange(key int) bool { + return key >= keyReserved && key <= keyMax +} diff --git a/keyboard_test.go b/keyboard_test.go index cbb2e6c..d939b4d 100644 --- a/keyboard_test.go +++ b/keyboard_test.go @@ -7,23 +7,38 @@ import "testing" // keyboard devices is working. All other keys, defined in keycodes.go should work as well if this test passes. // Another thing to keep in mind is that there are certain key codes that might not be great candidates for // unit testing, as they may create unwanted side effects, like logging out the current user, etc... -func TestBasicKeyboard(t *testing.T) { +func TestKeysInValidRangeWork(t *testing.T) { vk, err := CreateKeyboard("/dev/uinput", []byte("Test Basic Keyboard")) if err != nil { t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err) } - err = vk.KeyPress(Key1) + err = vk.KeyPress(keyReserved) if err != nil { t.Fatalf("Failed to send key press. Last error was: %s\n", err) } - err = vk.KeyDown(Key1) + err = vk.KeyDown(keyReserved) if err != nil { t.Fatalf("Failed to send key down event. Last error was: %s\n", err) } - err = vk.KeyUp(Key1) + err = vk.KeyUp(keyReserved) + if err != nil { + t.Fatalf("Failed to send key up event. Last error was: %s\n", err) + } + + err = vk.KeyPress(keyMax) + if err != nil { + t.Fatalf("Failed to send key press. Last error was: %s\n", err) + } + + err = vk.KeyDown(keyMax) + if err != nil { + t.Fatalf("Failed to send key down event. Last error was: %s\n", err) + } + + err = vk.KeyUp(keyMax) if err != nil { t.Fatalf("Failed to send key up event. Last error was: %s\n", err) } @@ -34,3 +49,61 @@ func TestBasicKeyboard(t *testing.T) { t.Fatalf("Failed to close device. Last error was: %s\n", err) } } + +func TestKeyOutsideOfRangeKeyPressFails(t *testing.T) { + vk, err := CreateKeyboard("/dev/uinput", []byte("Test Basic Keyboard")) + if err != nil { + t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err) + } + defer vk.Close() + + err = vk.KeyPress(249) + if err == nil { + t.Fatalf("Expected key press to fail due to invalid key code, but got no error.") + } + + err = vk.KeyPress(-1) + if err == nil { + t.Fatalf("Expected key press to fail due to invalid key code, but got no error.") + } + +} + +func TestKeyPressFailsIfDeviceIsClosed(t *testing.T) { + vk, err := CreateKeyboard("/dev/uinput", []byte("Test Basic Keyboard")) + if err != nil { + t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err) + } + vk.Close() + + err = vk.KeyPress(Key1) + if err == nil { + t.Fatalf("Expected KeyPress to fail, but no error was returned.") + } +} + +func TestKeyUpFailsIfDeviceIsClosed(t *testing.T) { + vk, err := CreateKeyboard("/dev/uinput", []byte("Test Basic Keyboard")) + if err != nil { + t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err) + } + vk.Close() + + err = vk.KeyUp(Key1) + if err == nil { + t.Fatalf("Expected KeyPress to fail, but no error was returned.") + } +} + +func TestKeyDownFailsIfDeviceIsClosed(t *testing.T) { + vk, err := CreateKeyboard("/dev/uinput", []byte("Test Basic Keyboard")) + if err != nil { + t.Fatalf("Failed to create the virtual keyboard. Last error was: %s\n", err) + } + vk.Close() + + err = vk.KeyDown(Key1) + if err == nil { + t.Fatalf("Expected KeyPress to fail, but no error was returned.") + } +}