package serial import ( "context" "sync" "testing" "time" ) type changingLinkSource struct { mu sync.Mutex state string calls int } func (s *changingLinkSource) LinkStates(context.Context) ([]LinkState, error) { s.mu.Lock() defer s.mu.Unlock() s.calls++ return []LinkState{{Channel: "CH08", State: s.state, Signal: "cts", Available: true, EverUp: s.state == "up"}}, nil } func (s *changingLinkSource) set(state string) { s.mu.Lock() s.state = state s.mu.Unlock() } func TestLinkMonitorRefreshesInBackgroundAndServesCache(t *testing.T) { source := &changingLinkSource{state: "down"} monitor, err := NewLinkMonitor(source, LinkMonitorOptions{Interval: 100 * time.Millisecond}) if err != nil { t.Fatal(err) } ctx, cancel := context.WithCancel(context.Background()) defer cancel() go monitor.Run(ctx) waitForState := func(want string) { t.Helper() deadline := time.Now().Add(time.Second) for time.Now().Before(deadline) { states, err := monitor.LinkStates(context.Background()) if err == nil && len(states) == 1 && states[0].State == want { return } time.Sleep(10 * time.Millisecond) } t.Fatalf("cached link state did not become %s", want) } waitForState("down") source.set("up") waitForState("up") }