Add more tests (#4)
This also refactors some of the code parsing logic. Reviewed-on: #4 Co-authored-by: Anna Rose Wiggins <annabunches@gmail.com> Co-committed-by: Anna Rose Wiggins <annabunches@gmail.com>
This commit is contained in:
parent
a05dc9126d
commit
712dcdbc07
7 changed files with 198 additions and 83 deletions
62
internal/config/codes.go
Normal file
62
internal/config/codes.go
Normal file
|
@ -0,0 +1,62 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/holoplot/go-evdev"
|
||||
)
|
||||
|
||||
func parseCode(code, prefix string) (evdev.EvCode, error) {
|
||||
code = strings.ToUpper(code)
|
||||
|
||||
var codeLookup map[string]evdev.EvCode
|
||||
|
||||
switch prefix {
|
||||
case CodePrefixButton:
|
||||
codeLookup = evdev.KEYFromString
|
||||
case CodePrefixAxis:
|
||||
codeLookup = evdev.ABSFromString
|
||||
case CodePrefixRelaxis:
|
||||
codeLookup = evdev.RELFromString
|
||||
default:
|
||||
return 0, fmt.Errorf("invalid EvCode prefix '%s'", prefix)
|
||||
}
|
||||
|
||||
switch {
|
||||
case strings.HasPrefix(code, prefix+"_"):
|
||||
eventCode, ok := codeLookup[code]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("invalid keycode specification '%s'", code)
|
||||
}
|
||||
|
||||
return eventCode, nil
|
||||
|
||||
case strings.HasPrefix(code, "0X"):
|
||||
codeInt, err := strconv.ParseUint(code[2:], 16, 0)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return evdev.EvCode(codeInt), nil
|
||||
|
||||
case prefix == CodePrefixButton && !hasError(strconv.Atoi(code)):
|
||||
index, err := strconv.Atoi(code)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
if index >= len(ButtonFromIndex) {
|
||||
return 0, fmt.Errorf("button index '%d' out of bounds", index)
|
||||
}
|
||||
|
||||
return ButtonFromIndex[index], nil
|
||||
|
||||
default:
|
||||
eventCode, ok := codeLookup[prefix+"_"+code]
|
||||
if !ok {
|
||||
return 0, fmt.Errorf("invalid keycode specification '%s'", code)
|
||||
}
|
||||
return eventCode, nil
|
||||
}
|
||||
}
|
63
internal/config/devices_test.go
Normal file
63
internal/config/devices_test.go
Normal file
|
@ -0,0 +1,63 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/holoplot/go-evdev"
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type DevicesConfigTests struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestRunnerDevicesConfig(t *testing.T) {
|
||||
suite.Run(t, new(DevicesConfigTests))
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeAxes() {
|
||||
t.Run("8 axes", func() {
|
||||
axes := makeAxes(8)
|
||||
t.Equal(8, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Z))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_RX))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_RY))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_RZ))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_THROTTLE))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_RUDDER))
|
||||
})
|
||||
|
||||
t.Run("9 axes is truncated", func() {
|
||||
axes := makeAxes(9)
|
||||
t.Equal(8, len(axes))
|
||||
})
|
||||
|
||||
t.Run("3 axes", func() {
|
||||
axes := makeAxes(3)
|
||||
t.Equal(3, len(axes))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_X))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Y))
|
||||
t.Contains(axes, evdev.EvCode(evdev.ABS_Z))
|
||||
})
|
||||
}
|
||||
|
||||
func (t *DevicesConfigTests) TestMakeButtons() {
|
||||
t.Run("Maximum buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons)
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("Truncated buttons", func() {
|
||||
buttons := makeButtons(VirtualDeviceMaxButtons + 1)
|
||||
t.Equal(VirtualDeviceMaxButtons, len(buttons))
|
||||
})
|
||||
|
||||
t.Run("16 buttons", func() {
|
||||
buttons := makeButtons(16)
|
||||
t.Equal(16, len(buttons))
|
||||
t.Contains(buttons, evdev.EvCode(evdev.BTN_DEAD))
|
||||
t.NotContains(buttons, evdev.EvCode(evdev.BTN_TRIGGER_HAPPY))
|
||||
})
|
||||
}
|
|
@ -3,8 +3,6 @@ package config
|
|||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.annabunches.net/annabunches/joyful/internal/mappingrules"
|
||||
"github.com/holoplot/go-evdev"
|
||||
|
@ -16,39 +14,9 @@ func makeRuleTargetButton(targetConfig RuleTargetConfig, devs map[string]*evdev.
|
|||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
var eventCode evdev.EvCode
|
||||
buttonConfig := strings.ToUpper(targetConfig.Button)
|
||||
switch {
|
||||
case strings.HasPrefix(buttonConfig, "BTN_"):
|
||||
eventCode, ok = evdev.KEYFromString[buttonConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid button specification '%s'", buttonConfig)
|
||||
}
|
||||
|
||||
case strings.HasPrefix(buttonConfig, "0X"):
|
||||
codeInt, err := strconv.ParseUint(buttonConfig[2:], 16, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eventCode = evdev.EvCode(codeInt)
|
||||
|
||||
case !hasError(strconv.Atoi(buttonConfig)):
|
||||
index, err := strconv.Atoi(buttonConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if index >= len(ButtonFromIndex) {
|
||||
return nil, fmt.Errorf("button index '%d' out of bounds", index)
|
||||
}
|
||||
|
||||
eventCode = ButtonFromIndex[index]
|
||||
|
||||
default:
|
||||
eventCode, ok = evdev.KEYFromString["BTN_"+buttonConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid button specification '%s'", buttonConfig)
|
||||
}
|
||||
eventCode, err := parseCode(targetConfig.Button, "BTN")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mappingrules.NewRuleTargetButton(
|
||||
|
@ -69,27 +37,9 @@ func makeRuleTargetAxis(targetConfig RuleTargetConfig, devs map[string]*evdev.In
|
|||
return nil, errors.New("deadzone_end must be greater than deadzone_start")
|
||||
}
|
||||
|
||||
var eventCode evdev.EvCode
|
||||
axisConfig := strings.ToUpper(targetConfig.Axis)
|
||||
switch {
|
||||
case strings.HasPrefix(axisConfig, "ABS_"):
|
||||
eventCode, ok = evdev.ABSFromString[axisConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid axis code '%s'", axisConfig)
|
||||
}
|
||||
|
||||
case strings.HasPrefix(axisConfig, "0X"):
|
||||
codeInt, err := strconv.ParseUint(axisConfig[2:], 16, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eventCode = evdev.EvCode(codeInt)
|
||||
|
||||
default:
|
||||
eventCode, ok = evdev.ABSFromString["ABS_"+axisConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid axis code '%s'", axisConfig)
|
||||
}
|
||||
eventCode, err := parseCode(targetConfig.Axis, "ABS")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mappingrules.NewRuleTargetAxis(
|
||||
|
@ -108,28 +58,11 @@ func makeRuleTargetRelaxis(targetConfig RuleTargetConfig, devs map[string]*evdev
|
|||
return nil, fmt.Errorf("non-existent device '%s'", targetConfig.Device)
|
||||
}
|
||||
|
||||
var eventCode evdev.EvCode
|
||||
axisConfig := strings.ToUpper(targetConfig.Axis)
|
||||
switch {
|
||||
case strings.HasPrefix(axisConfig, "REL_"):
|
||||
eventCode, ok = evdev.RELFromString[axisConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid axis code '%s'", axisConfig)
|
||||
}
|
||||
|
||||
case strings.HasPrefix(axisConfig, "0X"):
|
||||
codeInt, err := strconv.ParseUint(axisConfig[2:], 16, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
eventCode = evdev.EvCode(codeInt)
|
||||
|
||||
default:
|
||||
eventCode, ok = evdev.RELFromString["REL_"+axisConfig]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid axis code '%s'", axisConfig)
|
||||
}
|
||||
eventCode, err := parseCode(targetConfig.Axis, "REL")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return mappingrules.NewRuleTargetRelaxis(
|
||||
targetConfig.Device,
|
||||
device,
|
||||
|
|
|
@ -12,6 +12,10 @@ type MakeRuleTargetsTests struct {
|
|||
devs map[string]*evdev.InputDevice
|
||||
}
|
||||
|
||||
func TestRunnerMakeRuleTargets(t *testing.T) {
|
||||
suite.Run(t, new(MakeRuleTargetsTests))
|
||||
}
|
||||
|
||||
func (t *MakeRuleTargetsTests) SetupSuite() {
|
||||
t.devs = map[string]*evdev.InputDevice{
|
||||
"test": {},
|
||||
|
@ -141,7 +145,3 @@ func (t *MakeRuleTargetsTests) TestMakeRuleTargetRelaxis() {
|
|||
t.NotNil(err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestRunnerMakeRuleTargets(t *testing.T) {
|
||||
suite.Run(t, new(MakeRuleTargetsTests))
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@ const (
|
|||
RuleTypeAxisToButton = "axis-to-button"
|
||||
RuleTypeAxisToRelaxis = "axis-to-relaxis"
|
||||
|
||||
CodePrefixButton = "BTN"
|
||||
CodePrefixAxis = "ABS"
|
||||
CodePrefixRelaxis = "REL"
|
||||
|
||||
VirtualDeviceMaxButtons = 74
|
||||
)
|
||||
|
||||
|
|
53
internal/mappingrules/mapping_rule_base_test.go
Normal file
53
internal/mappingrules/mapping_rule_base_test.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package mappingrules
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type MappingRuleBaseTests struct {
|
||||
suite.Suite
|
||||
}
|
||||
|
||||
func TestRunnerMappingRuleBaseTests(t *testing.T) {
|
||||
suite.Run(t, new(MappingRuleBaseTests))
|
||||
}
|
||||
|
||||
func (t *MappingRuleBaseTests) TestNewMappingRuleBase() {
|
||||
t.Run("No Modes", func() {
|
||||
base := NewMappingRuleBase("foo", []string{})
|
||||
t.Equal("foo", base.Name)
|
||||
t.EqualValues([]string{"*"}, base.Modes)
|
||||
})
|
||||
|
||||
t.Run("Has Modes", func() {
|
||||
base := NewMappingRuleBase("foo", []string{"bar", "baz"})
|
||||
t.Equal("foo", base.Name)
|
||||
t.Contains(base.Modes, "bar")
|
||||
t.Contains(base.Modes, "baz")
|
||||
t.NotContains(base.Modes, "*")
|
||||
})
|
||||
}
|
||||
|
||||
func (t *MappingRuleBaseTests) TestModeCheck() {
|
||||
t.Run("* works on all modes", func() {
|
||||
base := NewMappingRuleBase("", []string{})
|
||||
mode := "bar"
|
||||
t.True(base.modeCheck(&mode))
|
||||
mode = "baz"
|
||||
t.True(base.modeCheck(&mode))
|
||||
})
|
||||
|
||||
t.Run("single mode only works in that mode", func() {
|
||||
base := NewMappingRuleBase("", []string{"bar"})
|
||||
mode := "bar"
|
||||
t.True(base.modeCheck(&mode))
|
||||
mode = "baz"
|
||||
t.False(base.modeCheck(&mode))
|
||||
})
|
||||
|
||||
t.Run("multiple modes work in each mode", func() {
|
||||
|
||||
})
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue