From 46a28fda7a69bab33c93feb8d5a905dcdec1e12c Mon Sep 17 00:00:00 2001 From: Anna Rose Wiggins Date: Fri, 18 Jul 2025 16:42:22 +0000 Subject: [PATCH] Add tests for EventBuffer (#7) Reviewed-on: https://git.annabunches.net/anna/joyful/pulls/7 Co-authored-by: Anna Rose Wiggins Co-committed-by: Anna Rose Wiggins --- .vscode/tasks.json | 12 ++- cmd/joyful/main.go | 2 +- internal/virtualdevice/eventbuffer.go | 27 +++++-- internal/virtualdevice/eventbuffer_test.go | 88 ++++++++++++++++++++++ internal/virtualdevice/interfaces.go | 7 ++ readme.md | 6 +- 6 files changed, 129 insertions(+), 13 deletions(-) create mode 100644 internal/virtualdevice/eventbuffer_test.go create mode 100644 internal/virtualdevice/interfaces.go diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 6ed2c5b..ad0bca5 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -16,12 +16,18 @@ "build", "-o", "build/", - "./cmd/joyful", + "./..." ], "group": { "kind": "build", - "isDefault": true, + "isDefault": true }, - }, + "options": { + "env": { + "CGO_ENABLED": "0" + } + }, + "problemMatcher": [] + } ], } \ No newline at end of file diff --git a/cmd/joyful/main.go b/cmd/joyful/main.go index e504372..7e5a807 100644 --- a/cmd/joyful/main.go +++ b/cmd/joyful/main.go @@ -41,7 +41,7 @@ func initVirtualBuffers(config *config.ConfigParser) (map[string]*virtualdevice. func getVirtualDevices(buffers map[string]*virtualdevice.EventBuffer) map[string]*evdev.InputDevice { devices := make(map[string]*evdev.InputDevice) for name, buffer := range buffers { - devices[name] = buffer.Device + devices[name] = buffer.Device.(*evdev.InputDevice) } return devices } diff --git a/internal/virtualdevice/eventbuffer.go b/internal/virtualdevice/eventbuffer.go index e95c099..9a46341 100644 --- a/internal/virtualdevice/eventbuffer.go +++ b/internal/virtualdevice/eventbuffer.go @@ -10,12 +10,12 @@ import ( type EventBuffer struct { events []*evdev.InputEvent - Device *evdev.InputDevice + Device VirtualDevice } -func NewEventBuffer(device *evdev.InputDevice) *EventBuffer { +func NewEventBuffer(device VirtualDevice) *EventBuffer { return &EventBuffer{ - events: make([]*evdev.InputEvent, 0), + events: make([]*evdev.InputEvent, 0, 100), Device: device, } } @@ -24,20 +24,33 @@ func (buffer *EventBuffer) AddEvent(event *evdev.InputEvent) { buffer.events = append(buffer.events, event) } -func (buffer *EventBuffer) SendEvents() { +func (buffer *EventBuffer) SendEvents() []error { eventTime := syscall.NsecToTimeval(int64(time.Now().Nanosecond())) + writeErrors := make([]error, 0) + + if len(buffer.events) == 0 { + return writeErrors + } for i := 0; i < len(buffer.events); i++ { buffer.events[i].Time = eventTime - buffer.Device.WriteOne(buffer.events[i]) + err := buffer.Device.WriteOne(buffer.events[i]) + if err != nil { + writeErrors = append(writeErrors, err) + } } - buffer.Device.WriteOne(&evdev.InputEvent{ + err := buffer.Device.WriteOne(&evdev.InputEvent{ Time: eventTime, Type: evdev.EV_SYN, Code: evdev.SYN_REPORT, Value: 0, }) - buffer.events = make([]*evdev.InputEvent, 0) + if err != nil { + writeErrors = append(writeErrors, err) + } + + buffer.events = make([]*evdev.InputEvent, 0, 100) + return writeErrors } diff --git a/internal/virtualdevice/eventbuffer_test.go b/internal/virtualdevice/eventbuffer_test.go new file mode 100644 index 0000000..515de5f --- /dev/null +++ b/internal/virtualdevice/eventbuffer_test.go @@ -0,0 +1,88 @@ +package virtualdevice + +import ( + "errors" + "testing" + + "github.com/holoplot/go-evdev" + "github.com/stretchr/testify/mock" + "github.com/stretchr/testify/suite" +) + +type EventBufferTests struct { + suite.Suite + device *VirtualDeviceMock + writeOneCall *mock.Call +} + +type VirtualDeviceMock struct { + mock.Mock +} + +func (m *VirtualDeviceMock) WriteOne(event *evdev.InputEvent) error { + args := m.Called() + return args.Error(0) +} + +func TestRunnerEventBufferTests(t *testing.T) { + suite.Run(t, new(EventBufferTests)) +} + +func (t *EventBufferTests) SetupTest() { + t.device = new(VirtualDeviceMock) +} + +func (t *EventBufferTests) SetupSubTest() { + t.device = new(VirtualDeviceMock) + t.writeOneCall = t.device.On("WriteOne").Return(nil) +} + +func (t *EventBufferTests) TearDownSubTest() { + t.writeOneCall.Unset() +} + +func (t *EventBufferTests) TestNewEventBuffer() { + buffer := NewEventBuffer(t.device) + t.Equal(t.device, buffer.Device) + t.Len(buffer.events, 0) +} + +func (t *EventBufferTests) TestEventBufferAddEvent() { + buffer := NewEventBuffer(t.device) + buffer.AddEvent(&evdev.InputEvent{}) + buffer.AddEvent(&evdev.InputEvent{}) + buffer.AddEvent(&evdev.InputEvent{}) + t.Len(buffer.events, 3) +} + +func (t *EventBufferTests) TestEventBufferSendEvents() { + t.Run("3 Events", func() { + buffer := NewEventBuffer(t.device) + buffer.AddEvent(&evdev.InputEvent{}) + buffer.AddEvent(&evdev.InputEvent{}) + buffer.AddEvent(&evdev.InputEvent{}) + errs := buffer.SendEvents() + + t.Len(errs, 0) + t.device.AssertNumberOfCalls(t.T(), "WriteOne", 4) + }) + + t.Run("No Events", func() { + buffer := NewEventBuffer(t.device) + errs := buffer.SendEvents() + + t.Len(errs, 0) + t.device.AssertNumberOfCalls(t.T(), "WriteOne", 0) + }) + + t.Run("Bad Event", func() { + t.writeOneCall.Unset() + t.writeOneCall = t.device.On("WriteOne").Return(errors.New("Fail")) + + buffer := NewEventBuffer(t.device) + buffer.AddEvent(&evdev.InputEvent{}) + errs := buffer.SendEvents() + t.Len(errs, 2) + }) + +} diff --git a/internal/virtualdevice/interfaces.go b/internal/virtualdevice/interfaces.go new file mode 100644 index 0000000..561c1bc --- /dev/null +++ b/internal/virtualdevice/interfaces.go @@ -0,0 +1,7 @@ +package virtualdevice + +import "github.com/holoplot/go-evdev" + +type VirtualDevice interface { + WriteOne(*evdev.InputEvent) error +} diff --git a/readme.md b/readme.md index cfe3fff..f8cb94f 100644 --- a/readme.md +++ b/readme.md @@ -26,6 +26,8 @@ Joyful is ideal for Linux gamers who enjoy space and flight sims and miss the fe * Output keyboard button presses * Explicit input and output from gamepad-like devices. * HIDRAW support for more button options. +* Specify different config directories for multiple sets of mappings. +* Positional and percentage-based deadzones. ## Configuration @@ -37,14 +39,14 @@ Configuration can be fairly complicated and repetitive. If anyone wants to creat ## Technical details -Joyful is written in golang, and uses evdev/uinput to manage devices. +Joyful is written in golang, and uses evdev/uinput to manage devices. ### Building To build joyful, install `go` via your package manager, then run: ``` -go build -o build/ ./... +CGO_ENABLED=0 go build -o build/ ./... ``` Look for binaries in the `build/` directory.