Skip to content

Commit

Permalink
Refine String() for schema with unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
vt128 committed Oct 14, 2023
1 parent 726370c commit 6c28ea1
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 11 deletions.
97 changes: 97 additions & 0 deletions helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"fmt"
"image/color"
"testing"
"time"

b1 "github.com/b1ug/blink1-go"
)
Expand Down Expand Up @@ -67,3 +68,99 @@ func TestRandomColor(t *testing.T) {
t.Errorf("RandomColor(*) = %v, want different colors", lc)
}
}

func TestStringer(t *testing.T) {
tests := []struct {
typ fmt.Stringer
exp string
}{
// as baseline
{
typ: time.Millisecond,
exp: "1ms",
},
// for LEDIndex
{
typ: b1.LED1,
exp: "LED 1",
},
{
typ: b1.LED2,
exp: "LED 2",
},
{
typ: b1.LEDAll,
exp: "All LED",
},
// device things
{
typ: b1.DevicePatternState{IsPlaying: true, CurrentPos: 1, LoopStartPos: 2, LoopEndPos: 3, RepeatTimes: 4},
exp: "▶️{playing=true cur=1 loop=[2,3) left=4}",
},
{
typ: b1.DevicePatternState{IsPlaying: false, CurrentPos: 10, LoopStartPos: 20, LoopEndPos: 30, RepeatTimes: 40},
exp: "⏸{playing=false cur=10 loop=[20,30) left=40}",
},
{
typ: b1.DeviceLightState{R: 1, G: 2, B: 3, LED: b1.LED1, FadeTimeMsec: 4},
exp: "🎨{color=#010203 led=1 fade=4ms}",
},
{
typ: b1.DeviceLightState{R: 10, G: 20, B: 30, LED: b1.LEDAll, FadeTimeMsec: 1000},
exp: "🎨{color=#0A141E led=0 fade=1000ms}",
},
// controller things
{
typ: b1.PatternState{IsPlaying: true, CurrentPosition: 1, StartPosition: 2, EndPosition: 3, RepeatTimes: 4},
exp: "▶️(playing=true cur=1 loop=[2,3) left=4)",
},
{
typ: b1.PatternState{IsPlaying: false, CurrentPosition: 10, StartPosition: 20, EndPosition: 30, RepeatTimes: 40},
exp: "⏸(playing=false cur=10 loop=[20,30) left=40)",
},
{
typ: b1.LightState{Color: color.RGBA{R: 1, G: 2, B: 3, A: 0xff}, LED: b1.LED1, FadeTime: time.Millisecond},
exp: "🎨(color=#010203 led=1 fade=1ms)",
},
{
typ: b1.LightState{Color: color.RGBA{R: 10, G: 20, B: 30, A: 0xff}, LED: b1.LEDAll, FadeTime: time.Second},
exp: "🎨(color=#0A141E led=0 fade=1s)",
},
// pattern things
{
typ: b1.Pattern{
StartPosition: 0,
EndPosition: 10,
RepeatTimes: 1,
States: []b1.LightState{
{
Color: color.RGBA{255, 0, 0, 255},
LED: b1.LED1,
FadeTime: 1 * time.Second,
},
{
Color: color.RGBA{0, 255, 0, 255},
LED: b1.LED2,
FadeTime: 2 * time.Second,
},
},
},
exp: "🎼(loop=[0,10] repeat=1 states=2)",
},
{
typ: b1.Pattern{
StartPosition: 10,
EndPosition: 20,
RepeatTimes: 0,
},
exp: "🎼(loop=[10,20] repeat=∞ states=0)",
},
}
for _, tc := range tests {
t.Run(tc.exp, func(t *testing.T) {
if got := tc.typ.String(); got != tc.exp {
t.Errorf("Stringer.String(%v) = %v, want %v", tc.typ, got, tc.exp)
}
})
}
}
45 changes: 34 additions & 11 deletions schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package blink1
import (
"fmt"
"image/color"
"strconv"
"time"
)

Expand All @@ -26,6 +27,18 @@ func (l LEDIndex) ToByte() byte {
return byte(l)
}

// String returns a string representation of LEDIndex.
func (l LEDIndex) String() string {
switch l {
case LED1:
return "LED 1"
case LED2:
return "LED 2"
default:
return "All LED"
}
}

// DevicePatternState is a blink(1) pattern playing state for low-level APIs.
type DevicePatternState struct {
IsPlaying bool // Is playing
Expand All @@ -39,6 +52,19 @@ func (st DevicePatternState) String() string {
return fmt.Sprintf("%s{playing=%t cur=%d loop=[%d,%d) left=%d}", convPlayingToEmoji(st.IsPlaying), st.IsPlaying, st.CurrentPos, st.LoopStartPos, st.LoopEndPos, st.RepeatTimes)
}

// PatternState represents a blink(1) pattern playing state for high-level APIs.
type PatternState struct {
IsPlaying bool // Is playing
CurrentPosition uint // Current position
StartPosition uint // Loop start position, inclusive
EndPosition uint // Loop end position, exclusive
RepeatTimes uint // Remaining times to repeat
}

func (st PatternState) String() string {
return fmt.Sprintf("%s(playing=%t cur=%d loop=[%d,%d) left=%d)", convPlayingToEmoji(st.IsPlaying), st.IsPlaying, st.CurrentPosition, st.StartPosition, st.EndPosition, st.RepeatTimes)
}

// DeviceLightState is a blink(1) light state for low-level APIs.
type DeviceLightState struct {
R, G, B byte // RGB values
Expand Down Expand Up @@ -69,15 +95,12 @@ type Pattern struct {
States []LightState // Slice of states to execute in pattern, non-empty patterns will be set to the device automatically
}

// PatternState represents a blink(1) pattern playing state for high-level APIs.
type PatternState struct {
IsPlaying bool // Is playing
CurrentPosition uint // Current position
StartPosition uint // Loop start position, inclusive
EndPosition uint // Loop end position, exclusive
RepeatTimes uint // Remaining times to repeat
}

func (st PatternState) String() string {
return fmt.Sprintf("%s(playing=%t cur=%d loop=[%d,%d) left=%d)", convPlayingToEmoji(st.IsPlaying), st.IsPlaying, st.CurrentPosition, st.StartPosition, st.EndPosition, st.RepeatTimes)
func (p Pattern) String() string {
var repeat string
if p.RepeatTimes == 0 {
repeat = "∞"
} else {
repeat = strconv.Itoa(int(p.RepeatTimes))
}
return fmt.Sprintf("🎼(loop=[%d,%d] repeat=%s states=%d)", p.StartPosition, p.EndPosition, repeat, len(p.States))
}

0 comments on commit 6c28ea1

Please sign in to comment.