You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
94 lines
2.9 KiB
94 lines
2.9 KiB
|
2 months ago
|
package greenled
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"os"
|
||
|
|
"path/filepath"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
)
|
||
|
|
|
||
|
|
func TestSysfsControllerMapsSerialChannelsInOrder(t *testing.T) {
|
||
|
|
root := t.TempDir()
|
||
|
|
for channel := 1; channel <= ChannelCount; channel++ {
|
||
|
|
state, err := stateForChannel(channel)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("map channel %d: %v", channel, err)
|
||
|
|
}
|
||
|
|
if err := os.MkdirAll(filepath.Join(root, state.LEDName), 0o755); err != nil {
|
||
|
|
t.Fatalf("create %s: %v", state.LEDName, err)
|
||
|
|
}
|
||
|
|
if err := os.WriteFile(filepath.Join(root, state.LEDName, "brightness"), []byte("0\n"), 0o644); err != nil {
|
||
|
|
t.Fatalf("seed %s: %v", state.LEDName, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
controller := NewSysfsController(root)
|
||
|
|
states, err := controller.States(context.Background())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("list states: %v", err)
|
||
|
|
}
|
||
|
|
if len(states) != ChannelCount {
|
||
|
|
t.Fatalf("state count = %d, want %d", len(states), ChannelCount)
|
||
|
|
}
|
||
|
|
for index, state := range states {
|
||
|
|
channel := index + 1
|
||
|
|
if state.Channel != "CH"+twoDigits(channel) || state.I2CBus != 3 || state.I2CAddress != expectedAddress(channel) || state.GPIOOffset != (channel-1)%8 || !state.Available || state.Forced {
|
||
|
|
t.Fatalf("state for serial CH%02d = %#v", channel, state)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSysfsControllerForcesAndPulsesThenReleases(t *testing.T) {
|
||
|
|
root := t.TempDir()
|
||
|
|
state, err := stateForChannel(9)
|
||
|
|
if err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
if err := os.MkdirAll(filepath.Join(root, state.LEDName), 0o755); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
brightnessPath := filepath.Join(root, state.LEDName, "brightness")
|
||
|
|
if err := os.WriteFile(brightnessPath, []byte("0\n"), 0o644); err != nil {
|
||
|
|
t.Fatal(err)
|
||
|
|
}
|
||
|
|
|
||
|
|
controller := NewSysfsController(root)
|
||
|
|
forced, err := controller.SetForce(context.Background(), "ch09", true)
|
||
|
|
if err != nil || !forced.Forced || forced.Channel != "CH09" {
|
||
|
|
t.Fatalf("force CH09 = %#v, %v", forced, err)
|
||
|
|
}
|
||
|
|
if value, err := os.ReadFile(brightnessPath); err != nil || string(value) != "1\n" {
|
||
|
|
t.Fatalf("brightness after force = %q, %v", value, err)
|
||
|
|
}
|
||
|
|
|
||
|
|
released, err := controller.Pulse(context.Background(), "CH09", MinPulseDuration)
|
||
|
|
if err != nil || released.Forced {
|
||
|
|
t.Fatalf("pulse CH09 = %#v, %v", released, err)
|
||
|
|
}
|
||
|
|
if value, err := os.ReadFile(brightnessPath); err != nil || string(value) != "0\n" {
|
||
|
|
t.Fatalf("brightness after pulse = %q, %v", value, err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestSysfsControllerRejectsInvalidChannelAndPulseDuration(t *testing.T) {
|
||
|
|
controller := NewSysfsController(t.TempDir())
|
||
|
|
if _, err := controller.SetForce(context.Background(), "CH49", true); err == nil {
|
||
|
|
t.Fatal("CH49 force unexpectedly succeeded")
|
||
|
|
}
|
||
|
|
if _, err := controller.Pulse(context.Background(), "CH01", 99*time.Millisecond); err == nil {
|
||
|
|
t.Fatal("short pulse unexpectedly succeeded")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func twoDigits(value int) string {
|
||
|
|
if value < 10 {
|
||
|
|
return "0" + string(rune('0'+value))
|
||
|
|
}
|
||
|
|
return string(rune('0'+value/10)) + string(rune('0'+value%10))
|
||
|
|
}
|
||
|
|
|
||
|
|
func expectedAddress(channel int) string {
|
||
|
|
return "0x" + []string{"20", "21", "22", "23", "24", "25"}[(channel-1)/8]
|
||
|
|
}
|