mirror of
https://github.com/jwetzell/showbridge-go.git
synced 2026-04-27 13:25:40 +00:00
standardize processor instance creation in tests
This commit is contained in:
@@ -71,12 +71,15 @@ func TestGoodArtnetPacketFilter(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
opCode uint16
|
||||
expected artnet.ArtNetPacket
|
||||
}{
|
||||
{
|
||||
name: "tiemcode packet with matching opCode",
|
||||
params: map[string]any{
|
||||
"opCode": float64(artnet.OpTimeCode),
|
||||
},
|
||||
payload: &artnet.ArtTimeCode{
|
||||
ID: []byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpTimeCode,
|
||||
@@ -90,7 +93,6 @@ func TestGoodArtnetPacketFilter(t *testing.T) {
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
},
|
||||
opCode: artnet.OpTimeCode,
|
||||
expected: &artnet.ArtTimeCode{
|
||||
ID: []byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpTimeCode,
|
||||
@@ -106,7 +108,10 @@ func TestGoodArtnetPacketFilter(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "tiemcode packet with mismatching opCode",
|
||||
name: "timecode packet with mismatching opCode",
|
||||
params: map[string]any{
|
||||
"opCode": float64(artnet.OpDmx),
|
||||
},
|
||||
payload: &artnet.ArtTimeCode{
|
||||
ID: []byte{'A', 'r', 't', '-', 'N', 'e', 't', 0x00},
|
||||
OpCode: artnet.OpTimeCode,
|
||||
@@ -120,17 +125,27 @@ func TestGoodArtnetPacketFilter(t *testing.T) {
|
||||
Hours: 0,
|
||||
Type: 0,
|
||||
},
|
||||
opCode: artnet.OpDmx,
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
artnetPacketFilter := processor.ArtNetPacketFilter{
|
||||
OpCode: test.opCode,
|
||||
registration, ok := processor.ProcessorRegistry["artnet.packet.filter"]
|
||||
if !ok {
|
||||
t.Fatalf("artnet.packet.filter processor not registered")
|
||||
}
|
||||
got, err := artnetPacketFilter.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "artnet.packet.filter",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("artnet.packet.filter failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("artnet.packet.filter failed: %s", err)
|
||||
@@ -158,8 +173,8 @@ func TestGoodArtnetPacketFilter(t *testing.T) {
|
||||
func TestBadArtnetPacketFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload any
|
||||
params map[string]any
|
||||
payload any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -80,37 +80,55 @@ func TestFloatParseGoodConfig(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGoodFloatParse(t *testing.T) {
|
||||
floatParser := processor.FloatParse{}
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
bitSize int
|
||||
expected float64
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected float64
|
||||
}{
|
||||
{
|
||||
name: "positive number",
|
||||
name: "positive number",
|
||||
params: map[string]any{
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "12345.67",
|
||||
bitSize: 64,
|
||||
expected: 12345.67,
|
||||
},
|
||||
{
|
||||
name: "negative number",
|
||||
name: "negative number",
|
||||
params: map[string]any{
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "-12345.67",
|
||||
bitSize: 64,
|
||||
expected: -12345.67,
|
||||
},
|
||||
{
|
||||
name: "zero",
|
||||
name: "zero",
|
||||
params: map[string]any{
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "0",
|
||||
bitSize: 64,
|
||||
expected: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := floatParser.Process(t.Context(), test.payload)
|
||||
registration, ok := processor.ProcessorRegistry["float.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("float.parse processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "float.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("float.parse failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotFloat, ok := got.(float64)
|
||||
if !ok {
|
||||
@@ -128,38 +146,50 @@ func TestGoodFloatParse(t *testing.T) {
|
||||
|
||||
func TestBadFloatParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
bitSize int
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "non-string input",
|
||||
name: "non-string input",
|
||||
params: map[string]any{
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: []byte{0x01},
|
||||
bitSize: 64,
|
||||
errorString: "float.parse processor only accepts a string",
|
||||
},
|
||||
{
|
||||
name: "not float string",
|
||||
name: "not float string",
|
||||
params: map[string]any{
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "abcd",
|
||||
bitSize: 64,
|
||||
errorString: "strconv.ParseFloat: parsing \"abcd\": invalid syntax",
|
||||
},
|
||||
{
|
||||
name: "bit size overflow",
|
||||
name: "bit size overflow",
|
||||
params: map[string]any{
|
||||
"bitSize": 32.0,
|
||||
},
|
||||
payload: "1.79e+64",
|
||||
bitSize: 32,
|
||||
errorString: "strconv.ParseFloat: parsing \"1.79e+64\": value out of range",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
floatParser := processor.FloatParse{
|
||||
BitSize: test.bitSize,
|
||||
registration, ok := processor.ProcessorRegistry["float.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("float.parse processor not registered")
|
||||
}
|
||||
got, err := floatParser.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "float.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("float.parse expected to fail but succeeded, got: %v", got)
|
||||
|
||||
@@ -100,58 +100,75 @@ func TestIntParseGoodConfig(t *testing.T) {
|
||||
|
||||
func TestGoodIntParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
expected int64
|
||||
base int
|
||||
bitSize int
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected int64
|
||||
}{
|
||||
{
|
||||
name: "positive number",
|
||||
name: "positive number",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "12345",
|
||||
expected: 12345,
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "negative number",
|
||||
name: "negative number",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "-12345",
|
||||
expected: -12345,
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "zero",
|
||||
name: "zero",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "0",
|
||||
expected: 0,
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "binary",
|
||||
name: "binary",
|
||||
params: map[string]any{
|
||||
"base": 2.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "1010101",
|
||||
expected: 85,
|
||||
base: 2,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "hex",
|
||||
name: "hex",
|
||||
params: map[string]any{
|
||||
"base": 16.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "15F",
|
||||
expected: 351,
|
||||
base: 16,
|
||||
bitSize: 64,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
intParser := processor.IntParse{
|
||||
Base: test.base,
|
||||
BitSize: test.bitSize,
|
||||
registration, ok := processor.ProcessorRegistry["int.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("int.parse processor not registered")
|
||||
}
|
||||
|
||||
got, err := intParser.Process(t.Context(), test.payload)
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "int.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("int.parse failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotInt, ok := got.(int64)
|
||||
if !ok {
|
||||
@@ -169,43 +186,53 @@ func TestGoodIntParse(t *testing.T) {
|
||||
|
||||
func TestBadIntParse(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
base int
|
||||
bitSize int
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "non-string input",
|
||||
name: "non-string input",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: []byte{0x01},
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
errorString: "int.parse processor only accepts a string",
|
||||
},
|
||||
{
|
||||
name: "not int string",
|
||||
name: "not int string",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 64.0,
|
||||
},
|
||||
payload: "123.46",
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
errorString: "strconv.ParseInt: parsing \"123.46\": invalid syntax",
|
||||
},
|
||||
{
|
||||
name: "bit overflow",
|
||||
name: "bit overflow",
|
||||
params: map[string]any{
|
||||
"base": 10.0,
|
||||
"bitSize": 32.0,
|
||||
},
|
||||
payload: "12345678901234567890",
|
||||
base: 10,
|
||||
bitSize: 32,
|
||||
errorString: "strconv.ParseInt: parsing \"12345678901234567890\": value out of range",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
intParser := processor.IntParse{
|
||||
Base: test.base,
|
||||
BitSize: test.bitSize,
|
||||
registration, ok := processor.ProcessorRegistry["int.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("int.parse processor not registered")
|
||||
}
|
||||
got, err := intParser.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "int.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("int.parse expected to fail but succeeded, got: %v", got)
|
||||
|
||||
@@ -67,27 +67,37 @@ func TestIntRandomGoodConfig(t *testing.T) {
|
||||
|
||||
func TestGoodIntRandom(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
min int
|
||||
max int
|
||||
name string
|
||||
payload any
|
||||
params map[string]any
|
||||
}{
|
||||
{
|
||||
name: "1-10",
|
||||
name: "1-10",
|
||||
params: map[string]any{
|
||||
"min": 1.0,
|
||||
"max": 10.0,
|
||||
},
|
||||
payload: "12345",
|
||||
min: 1,
|
||||
max: 10,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
intRandom := processor.IntRandom{
|
||||
Min: test.min,
|
||||
Max: test.max,
|
||||
registration, ok := processor.ProcessorRegistry["int.random"]
|
||||
if !ok {
|
||||
t.Fatalf("int.random processor not registered")
|
||||
}
|
||||
got, err := intRandom.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "int.random",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("int.random failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
gotInt, ok := got.(int)
|
||||
if !ok {
|
||||
t.Fatalf("int.random returned a %T payload: %s", got, got)
|
||||
@@ -95,8 +105,18 @@ func TestGoodIntRandom(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("int.random failed: %s", err)
|
||||
}
|
||||
if gotInt < test.min || gotInt > test.max {
|
||||
t.Fatalf("int.random got %d, expected between %d and %d", gotInt, test.min, test.max)
|
||||
|
||||
minNum, ok := test.params["min"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("int.random test min param is not a number: %s", test.params["min"])
|
||||
}
|
||||
maxNum, ok := test.params["max"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("int.random test max param is not a number: %s", test.params["max"])
|
||||
}
|
||||
|
||||
if gotInt < int(minNum) || gotInt > int(maxNum) {
|
||||
t.Fatalf("int.random got %d, expected between %d and %d", gotInt, int(minNum), int(maxNum))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package processor_test
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"github.com/jwetzell/showbridge-go/internal/processor"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
)
|
||||
|
||||
func TestMIDIMessageEncodeFromRegistry(t *testing.T) {
|
||||
@@ -25,3 +27,63 @@ func TestMIDIMessageEncodeFromRegistry(t *testing.T) {
|
||||
t.Fatalf("midi.message.encode processor has wrong type: %s", processorInstance.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoodMIDIMessageEncode(t *testing.T) {
|
||||
midiMessageEncoder := processor.MIDIMessageEncode{}
|
||||
tests := []struct {
|
||||
name string
|
||||
payload any
|
||||
expected []byte
|
||||
}{
|
||||
{
|
||||
name: "note on message",
|
||||
payload: midi.NoteOn(1, 60, 127),
|
||||
expected: []byte{0x91, 0x3c, 0x7f},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := midiMessageEncoder.Process(t.Context(), test.payload)
|
||||
|
||||
gotBytes, ok := got.([]byte)
|
||||
if !ok {
|
||||
t.Fatalf("midi.message.encode returned a %T payload: %s", got, got)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("midi.message.encode failed: %s", err)
|
||||
}
|
||||
if !slices.Equal(gotBytes, test.expected) {
|
||||
t.Fatalf("midi.message.encode got %+v, expected %+v", got, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadMIDIMessageEncode(t *testing.T) {
|
||||
midiMessageEncoder := processor.MIDIMessageEncode{}
|
||||
tests := []struct {
|
||||
name string
|
||||
payload any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "non-midi message input",
|
||||
payload: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
|
||||
errorString: "midi.message.encode processor only accepts a midi.Message",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := midiMessageEncoder.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("midi.message.encode expected to fail but got payload: %s", got)
|
||||
}
|
||||
if err.Error() != test.errorString {
|
||||
t.Fatalf("midi.message.encode got error '%s', expected '%s'", err.Error(), test.errorString)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
package processor_test
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"github.com/jwetzell/showbridge-go/internal/processor"
|
||||
"gitlab.com/gomidi/midi/v2"
|
||||
)
|
||||
|
||||
func TestMIDIMessageFilterFromRegistry(t *testing.T) {
|
||||
@@ -28,3 +30,128 @@ func TestMIDIMessageFilterFromRegistry(t *testing.T) {
|
||||
t.Fatalf("midi.message.filter processor has wrong type: %s", processorInstance.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func TestGoodMIDIMessageFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
params map[string]any
|
||||
payload midi.Message
|
||||
expected midi.Message
|
||||
}{
|
||||
{
|
||||
name: "matches pattern",
|
||||
payload: midi.NoteOn(1, 60, 127),
|
||||
params: map[string]any{"type": "NoteOn"},
|
||||
expected: midi.NoteOn(1, 60, 127),
|
||||
},
|
||||
{
|
||||
name: "does not match pattern",
|
||||
payload: midi.NoteOn(1, 60, 127),
|
||||
params: map[string]any{"type": "NoteOff"},
|
||||
expected: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
registration, ok := processor.ProcessorRegistry["midi.message.filter"]
|
||||
if !ok {
|
||||
t.Fatalf("midi.message.filter processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "midi.message.filter",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("midi.message.filter failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("midi.message.filter failed: %s", err)
|
||||
}
|
||||
|
||||
if test.expected == nil {
|
||||
if got != nil {
|
||||
t.Fatalf("midi.message.filter got %+v, expected nil", got)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
gotMIDIMessage, ok := got.(midi.Message)
|
||||
if !ok {
|
||||
t.Fatalf("midi.message.filter returned a %T payload: %s", got, got)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(gotMIDIMessage, test.expected) {
|
||||
t.Fatalf("midi.message.filter got %+v, expected %+v", gotMIDIMessage, test.expected)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadMIDIMessageFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "no type param",
|
||||
params: map[string]any{},
|
||||
payload: midi.NoteOn(1, 60, 127),
|
||||
errorString: "midi.message.filter requires a type parameter",
|
||||
},
|
||||
{
|
||||
name: "non-string type param",
|
||||
params: map[string]any{
|
||||
"type": 123,
|
||||
},
|
||||
payload: "hello",
|
||||
errorString: "midi.message.filter type must be a string",
|
||||
},
|
||||
{
|
||||
name: "non-midi message input",
|
||||
params: map[string]any{
|
||||
"type": "NoteOn",
|
||||
},
|
||||
payload: []byte{0x68, 0x65, 0x6c, 0x6c, 0x6f},
|
||||
errorString: "midi.message.filter processor only accepts a midi.Message",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
registration, ok := processor.ProcessorRegistry["midi.message.filter"]
|
||||
if !ok {
|
||||
t.Fatalf("midi.message.filter processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "midi.message.filter",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if test.errorString != err.Error() {
|
||||
t.Fatalf("midi.message.filter got error '%s', expected '%s'", err.Error(), test.errorString)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("midi.message.filter expected to fail but got payload: %s", got)
|
||||
}
|
||||
|
||||
if err.Error() != test.errorString {
|
||||
t.Fatalf("midi.message.filter got error '%s', expected '%s'", err.Error(), test.errorString)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package processor_test
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/expr-lang/expr"
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"github.com/jwetzell/showbridge-go/internal/processor"
|
||||
)
|
||||
@@ -83,14 +82,16 @@ func TestScriptExprBadConfigNonCompilingExpression(t *testing.T) {
|
||||
|
||||
func TestGoodScriptExpr(t *testing.T) {
|
||||
tests := []struct {
|
||||
program string
|
||||
name string
|
||||
params map[string]any
|
||||
payload map[string]any
|
||||
expected any
|
||||
}{
|
||||
{
|
||||
program: "foo + bar",
|
||||
name: "number",
|
||||
name: "number",
|
||||
params: map[string]any{
|
||||
"expression": "foo + bar",
|
||||
},
|
||||
payload: map[string]any{
|
||||
"foo": 1,
|
||||
"bar": 1,
|
||||
@@ -98,8 +99,10 @@ func TestGoodScriptExpr(t *testing.T) {
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
program: "foo + bar",
|
||||
name: "string",
|
||||
name: "string",
|
||||
params: map[string]any{
|
||||
"expression": "foo + bar",
|
||||
},
|
||||
payload: map[string]any{
|
||||
"foo": "1",
|
||||
"bar": "1",
|
||||
@@ -110,14 +113,21 @@ func TestGoodScriptExpr(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
program, err := expr.Compile(test.program)
|
||||
if err != nil {
|
||||
t.Fatalf("script.expr failed to compile program: %s", err)
|
||||
registration, ok := processor.ProcessorRegistry["script.expr"]
|
||||
if !ok {
|
||||
t.Fatalf("script.expr processor not registered")
|
||||
}
|
||||
|
||||
exprProcessor := &processor.ScriptExpr{Program: program}
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "script.expr",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := exprProcessor.Process(t.Context(), test.payload)
|
||||
if err != nil {
|
||||
t.Fatalf("script.expr failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("script.expr failed: %s", err)
|
||||
@@ -133,14 +143,16 @@ func TestGoodScriptExpr(t *testing.T) {
|
||||
|
||||
func TestBadScriptExpr(t *testing.T) {
|
||||
tests := []struct {
|
||||
program string
|
||||
name string
|
||||
params map[string]any
|
||||
payload map[string]any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "accessing missing field",
|
||||
program: "foo + bar",
|
||||
name: "accessing missing field",
|
||||
params: map[string]any{
|
||||
"expression": "foo + bar",
|
||||
},
|
||||
payload: map[string]any{
|
||||
"foo": 1,
|
||||
},
|
||||
@@ -150,14 +162,17 @@ func TestBadScriptExpr(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
program, err := expr.Compile(test.program)
|
||||
if err != nil {
|
||||
t.Fatalf("script.expr failed to compile program: %s", err)
|
||||
registration, ok := processor.ProcessorRegistry["script.expr"]
|
||||
if !ok {
|
||||
t.Fatalf("script.expr processor not registered")
|
||||
}
|
||||
|
||||
exprProcessor := &processor.ScriptExpr{Program: program}
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "script.expr",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := exprProcessor.Process(t.Context(), test.payload)
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("script.expr expected to fail but succeeded, got: %v", got)
|
||||
|
||||
@@ -79,40 +79,48 @@ func TestScriptJSBadConfigWrongProgramType(t *testing.T) {
|
||||
|
||||
func TestGoodScriptJS(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
expected any
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected any
|
||||
}{
|
||||
{
|
||||
name: "number",
|
||||
processor: &processor.ScriptJS{Program: `
|
||||
payload = payload + 1
|
||||
`},
|
||||
params: map[string]any{
|
||||
"program": `
|
||||
payload = payload + 1
|
||||
`,
|
||||
},
|
||||
payload: 1,
|
||||
expected: 2,
|
||||
},
|
||||
{
|
||||
name: "string",
|
||||
processor: &processor.ScriptJS{Program: `
|
||||
payload = payload + "1"
|
||||
`},
|
||||
params: map[string]any{
|
||||
"program": `
|
||||
payload = payload + "1"
|
||||
`,
|
||||
},
|
||||
payload: "1",
|
||||
expected: "11",
|
||||
},
|
||||
{
|
||||
name: "object",
|
||||
processor: &processor.ScriptJS{Program: `
|
||||
payload = { key: payload }
|
||||
`},
|
||||
params: map[string]any{
|
||||
"program": `
|
||||
payload = { key: payload }
|
||||
`,
|
||||
},
|
||||
payload: "1",
|
||||
expected: map[string]any{"key": "1"},
|
||||
},
|
||||
{
|
||||
name: "nil",
|
||||
processor: &processor.ScriptJS{Program: `
|
||||
payload = undefined
|
||||
`},
|
||||
params: map[string]any{
|
||||
"program": `
|
||||
payload = undefined
|
||||
`,
|
||||
},
|
||||
payload: "1",
|
||||
expected: nil,
|
||||
},
|
||||
@@ -120,7 +128,21 @@ func TestGoodScriptJS(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := test.processor.Process(t.Context(), test.payload)
|
||||
registration, ok := processor.ProcessorRegistry["script.js"]
|
||||
if !ok {
|
||||
t.Fatalf("script.js processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "script.js",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("script.js failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("script.js process failed: %s", err)
|
||||
@@ -151,13 +173,17 @@ func TestGoodScriptJS(t *testing.T) {
|
||||
func TestBadScriptJS(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
processor processor.Processor
|
||||
params map[string]any
|
||||
payload any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "accessing not defined variable",
|
||||
processor: &processor.ScriptJS{Program: `paylod = foo`},
|
||||
name: "accessing not defined variable",
|
||||
params: map[string]any{
|
||||
"program": `
|
||||
paylod = foo
|
||||
`,
|
||||
},
|
||||
payload: 0,
|
||||
errorString: "ReferenceError: 'foo' is not defined",
|
||||
},
|
||||
@@ -165,7 +191,17 @@ func TestBadScriptJS(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := test.processor.Process(t.Context(), test.payload)
|
||||
registration, ok := processor.ProcessorRegistry["script.js"]
|
||||
if !ok {
|
||||
t.Fatalf("script.js processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "script.js",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("script.js expected to fail but succeeded, got: %v", got)
|
||||
|
||||
@@ -2,7 +2,6 @@ package processor_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"text/template"
|
||||
|
||||
"github.com/jwetzell/showbridge-go/internal/config"
|
||||
"github.com/jwetzell/showbridge-go/internal/processor"
|
||||
@@ -53,37 +52,37 @@ func TestGoodStringCreate(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
template string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
name: "string payload",
|
||||
template: "{{.}}",
|
||||
params: map[string]any{"template": "{{.}}"},
|
||||
payload: "hello",
|
||||
expected: "hello",
|
||||
},
|
||||
{
|
||||
name: "number payload",
|
||||
template: "{{.}}",
|
||||
params: map[string]any{"template": "{{.}}"},
|
||||
payload: 4,
|
||||
expected: "4",
|
||||
},
|
||||
{
|
||||
name: "boolean payload",
|
||||
template: "{{.}}",
|
||||
params: map[string]any{"template": "{{.}}"},
|
||||
payload: true,
|
||||
expected: "true",
|
||||
},
|
||||
{
|
||||
name: "struct payload - field",
|
||||
template: "{{.Data}}",
|
||||
params: map[string]any{"template": "{{.Data}}"},
|
||||
payload: TestStruct{Data: "test"},
|
||||
expected: "test",
|
||||
},
|
||||
{
|
||||
name: "struct payload - method",
|
||||
template: "{{.GetData}}",
|
||||
params: map[string]any{"template": "{{.GetData}}"},
|
||||
payload: TestStruct{Data: "test"},
|
||||
expected: "test",
|
||||
},
|
||||
@@ -91,14 +90,21 @@ func TestGoodStringCreate(t *testing.T) {
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
template, err := template.New("template").Parse(test.template)
|
||||
if err != nil {
|
||||
t.Fatalf("string.create template parsing failed: %s", err)
|
||||
registration, ok := processor.ProcessorRegistry["string.create"]
|
||||
if !ok {
|
||||
t.Fatalf("string.create processor not registered")
|
||||
}
|
||||
|
||||
processor := &processor.StringCreate{Template: template}
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "string.create",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processor.Process(t.Context(), test.payload)
|
||||
if err != nil {
|
||||
t.Fatalf("string.create failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotStrings, ok := got.(string)
|
||||
if !ok {
|
||||
|
||||
@@ -118,8 +118,8 @@ func TestGoodStringFilter(t *testing.T) {
|
||||
func TestBadStringFilter(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
payload any
|
||||
params map[string]any
|
||||
payload any
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
|
||||
@@ -49,22 +49,36 @@ func TestStringSplitFromRegistry(t *testing.T) {
|
||||
|
||||
func TestGoodStringSplit(t *testing.T) {
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
expected []string
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected []string
|
||||
}{
|
||||
{
|
||||
processor: &processor.StringSplit{Separator: ","},
|
||||
name: "comma separated",
|
||||
payload: "part1,part2,part3",
|
||||
expected: []string{"part1", "part2", "part3"},
|
||||
name: "comma separated",
|
||||
params: map[string]any{"separator": ","},
|
||||
payload: "part1,part2,part3",
|
||||
expected: []string{"part1", "part2", "part3"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := test.processor.Process(t.Context(), test.payload)
|
||||
registration, ok := processor.ProcessorRegistry["string.split"]
|
||||
if !ok {
|
||||
t.Fatalf("string.split processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "string.split",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("string.split failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotStrings, ok := got.([]string)
|
||||
if !ok {
|
||||
|
||||
@@ -28,3 +28,36 @@ func TestTimeSleepFromRegistry(t *testing.T) {
|
||||
t.Fatalf("time.sleep processor has wrong type: %s", processorInstance.Type())
|
||||
}
|
||||
}
|
||||
|
||||
func TestBadTimeSleep(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
errorString string
|
||||
}{}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
registration, ok := processor.ProcessorRegistry["time.sleep"]
|
||||
if !ok {
|
||||
t.Fatalf("time.sleep processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "time.sleep",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("time.sleep expected to fail but succeeded, got: %v", got)
|
||||
|
||||
}
|
||||
if err.Error() != test.errorString {
|
||||
t.Fatalf("time.sleep got error '%s', expected '%s'", err.Error(), test.errorString)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,50 +101,54 @@ func TestUintParseGoodConfig(t *testing.T) {
|
||||
func TestGoodUintParse(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
expected uint64
|
||||
base int
|
||||
bitSize int
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
expected uint64
|
||||
}{
|
||||
{
|
||||
name: "positive number",
|
||||
params: map[string]any{"base": 10.0, "bitSize": 64.0},
|
||||
payload: "12345",
|
||||
expected: 12345,
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "zero",
|
||||
params: map[string]any{"base": 10.0, "bitSize": 64.0},
|
||||
payload: "0",
|
||||
expected: 0,
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "binary",
|
||||
params: map[string]any{"base": 2.0, "bitSize": 64.0},
|
||||
payload: "1010101",
|
||||
expected: 85,
|
||||
base: 2,
|
||||
bitSize: 64,
|
||||
},
|
||||
{
|
||||
name: "hex",
|
||||
params: map[string]any{"base": 16.0, "bitSize": 64.0},
|
||||
payload: "15F",
|
||||
expected: 351,
|
||||
base: 16,
|
||||
bitSize: 64,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
uintParser := processor.UintParse{
|
||||
Base: test.base,
|
||||
BitSize: test.bitSize,
|
||||
registration, ok := processor.ProcessorRegistry["uint.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("uint.parse processor not registered")
|
||||
}
|
||||
got, err := uintParser.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "uint.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("uint.parse failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotUint, ok := got.(uint64)
|
||||
if !ok {
|
||||
@@ -161,41 +165,45 @@ func TestGoodUintParse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestBadUintParse(t *testing.T) {
|
||||
uintParser := processor.UintParse{}
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
base int
|
||||
bitSize int
|
||||
errorString string
|
||||
}{
|
||||
{
|
||||
name: "non-string input",
|
||||
params: map[string]any{"base": 10.0, "bitSize": 64.0},
|
||||
payload: []byte{0x01},
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
errorString: "uint.parse processor only accepts a string",
|
||||
},
|
||||
{
|
||||
name: "not uint string",
|
||||
params: map[string]any{"base": 10.0, "bitSize": 64.0},
|
||||
payload: "-1234",
|
||||
base: 10,
|
||||
bitSize: 64,
|
||||
errorString: "strconv.ParseUint: parsing \"-1234\": invalid syntax",
|
||||
},
|
||||
{
|
||||
name: "bit overflow",
|
||||
params: map[string]any{"base": 10.0, "bitSize": 32.0},
|
||||
payload: "123456789012345678901234567",
|
||||
base: 10,
|
||||
bitSize: 32,
|
||||
errorString: "strconv.ParseUint: parsing \"123456789012345678901234567\": value out of range",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := uintParser.Process(t.Context(), test.payload)
|
||||
registration, ok := processor.ProcessorRegistry["uint.parse"]
|
||||
if !ok {
|
||||
t.Fatalf("uint.parse processor not registered")
|
||||
}
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "uint.parse",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
if err == nil {
|
||||
t.Fatalf("uint.parse expected to fail but succeeded, got: %v", got)
|
||||
|
||||
@@ -68,27 +68,34 @@ func TestUintRandomGoodConfig(t *testing.T) {
|
||||
func TestGoodUintRandom(t *testing.T) {
|
||||
|
||||
tests := []struct {
|
||||
processor processor.Processor
|
||||
name string
|
||||
payload any
|
||||
min uint
|
||||
max uint
|
||||
name string
|
||||
params map[string]any
|
||||
payload any
|
||||
}{
|
||||
{
|
||||
name: "1-10",
|
||||
params: map[string]any{"min": 1.0, "max": 10.0},
|
||||
payload: "12345",
|
||||
min: 1,
|
||||
max: 10,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
uintRandom := processor.UintRandom{
|
||||
Min: test.min,
|
||||
Max: test.max,
|
||||
registration, ok := processor.ProcessorRegistry["uint.random"]
|
||||
if !ok {
|
||||
t.Fatalf("uint.random processor not registered")
|
||||
}
|
||||
got, err := uintRandom.Process(t.Context(), test.payload)
|
||||
|
||||
processorInstance, err := registration.New(config.ProcessorConfig{
|
||||
Type: "uint.random",
|
||||
Params: test.params,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("uint.random failed to create processor: %s", err)
|
||||
}
|
||||
|
||||
got, err := processorInstance.Process(t.Context(), test.payload)
|
||||
|
||||
gotUint, ok := got.(uint)
|
||||
if !ok {
|
||||
@@ -97,8 +104,16 @@ func TestGoodUintRandom(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatalf("uint.random failed: %s", err)
|
||||
}
|
||||
if gotUint < test.min || gotUint > test.max {
|
||||
t.Fatalf("uint.random got %d, expected between %d and %d", gotUint, test.min, test.max)
|
||||
minNum, ok := test.params["min"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("uint.random test min param is not a number")
|
||||
}
|
||||
maxNum, ok := test.params["max"].(float64)
|
||||
if !ok {
|
||||
t.Fatalf("uint.random test max param is not a number")
|
||||
}
|
||||
if gotUint < uint(minNum) || gotUint > uint(maxNum) {
|
||||
t.Fatalf("uint.random got %d, expected between %d and %d", gotUint, uint(minNum), uint(maxNum))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user