Add tests for EventBuffer #7

Merged
anna merged 3 commits from eventbuffer-tests into main 2025-07-18 16:42:22 +00:00
6 changed files with 129 additions and 13 deletions

12
.vscode/tasks.json vendored
View file

@ -16,12 +16,18 @@
"build", "build",
"-o", "-o",
"build/", "build/",
"./cmd/joyful", "./..."
], ],
"group": { "group": {
"kind": "build", "kind": "build",
"isDefault": true, "isDefault": true
}, },
}, "options": {
"env": {
"CGO_ENABLED": "0"
}
},
"problemMatcher": []
}
], ],
} }

View file

@ -41,7 +41,7 @@ func initVirtualBuffers(config *config.ConfigParser) (map[string]*virtualdevice.
func getVirtualDevices(buffers map[string]*virtualdevice.EventBuffer) map[string]*evdev.InputDevice { func getVirtualDevices(buffers map[string]*virtualdevice.EventBuffer) map[string]*evdev.InputDevice {
devices := make(map[string]*evdev.InputDevice) devices := make(map[string]*evdev.InputDevice)
for name, buffer := range buffers { for name, buffer := range buffers {
devices[name] = buffer.Device devices[name] = buffer.Device.(*evdev.InputDevice)
} }
return devices return devices
} }

View file

@ -10,12 +10,12 @@ import (
type EventBuffer struct { type EventBuffer struct {
events []*evdev.InputEvent events []*evdev.InputEvent
Device *evdev.InputDevice Device VirtualDevice
} }
func NewEventBuffer(device *evdev.InputDevice) *EventBuffer { func NewEventBuffer(device VirtualDevice) *EventBuffer {
return &EventBuffer{ return &EventBuffer{
events: make([]*evdev.InputEvent, 0), events: make([]*evdev.InputEvent, 0, 100),
Device: device, Device: device,
} }
} }
@ -24,20 +24,33 @@ func (buffer *EventBuffer) AddEvent(event *evdev.InputEvent) {
buffer.events = append(buffer.events, event) buffer.events = append(buffer.events, event)
} }
func (buffer *EventBuffer) SendEvents() { func (buffer *EventBuffer) SendEvents() []error {
eventTime := syscall.NsecToTimeval(int64(time.Now().Nanosecond())) 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++ { for i := 0; i < len(buffer.events); i++ {
buffer.events[i].Time = eventTime 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, Time: eventTime,
Type: evdev.EV_SYN, Type: evdev.EV_SYN,
Code: evdev.SYN_REPORT, Code: evdev.SYN_REPORT,
Value: 0, Value: 0,
}) })
buffer.events = make([]*evdev.InputEvent, 0) if err != nil {
writeErrors = append(writeErrors, err)
}
buffer.events = make([]*evdev.InputEvent, 0, 100)
return writeErrors
} }

View file

@ -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)
})
}

View file

@ -0,0 +1,7 @@
package virtualdevice
import "github.com/holoplot/go-evdev"
type VirtualDevice interface {
WriteOne(*evdev.InputEvent) error
}

View file

@ -26,6 +26,8 @@ Joyful is ideal for Linux gamers who enjoy space and flight sims and miss the fe
* Output keyboard button presses * Output keyboard button presses
* Explicit input and output from gamepad-like devices. * Explicit input and output from gamepad-like devices.
* HIDRAW support for more button options. * HIDRAW support for more button options.
* Specify different config directories for multiple sets of mappings.
* Positional and percentage-based deadzones.
## Configuration ## Configuration
@ -37,14 +39,14 @@ Configuration can be fairly complicated and repetitive. If anyone wants to creat
## Technical details ## 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 ### Building
To build joyful, install `go` via your package manager, then run: 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. Look for binaries in the `build/` directory.