package gotelem import ( "log/slog" "os" "reflect" "sync" "testing" "time" "github.com/kschamplin/gotelem/skylab" ) func makeEvent() skylab.BusEvent { var pkt skylab.Packet = &skylab.BmsMeasurement{ BatteryVoltage: 12000, AuxVoltage: 24000, Current: 1.23, } return skylab.BusEvent{ Timestamp: time.Now(), Name: pkt.String(), Data: pkt, } } func TestBroker(t *testing.T) { t.Parallel() t.Run("test send", func(t *testing.T) { flog := slog.New(slog.NewTextHandler(os.Stderr, nil)) broker := NewBroker(10, flog) sub, err := broker.Subscribe("testSub") if err != nil { t.Fatalf("error subscribing: %v", err) } testEvent := makeEvent() go func() { time.Sleep(time.Millisecond * 1) broker.Publish("other", testEvent) }() var recvEvent skylab.BusEvent select { case recvEvent = <-sub: if !reflect.DeepEqual(recvEvent.Data, testEvent.Data) { t.Fatalf("mismatched data, want %v got %v", testEvent.Data, recvEvent.Data) } if !testEvent.Timestamp.Equal(recvEvent.Timestamp) { t.Fatalf("mismatched timestamp, want %v got %v", testEvent.Timestamp, recvEvent.Timestamp) } case <-time.After(1 * time.Second): t.Fatalf("timeout waiting for packet") } }) t.Run("multiple broadcast", func(t *testing.T) { flog := slog.New(slog.NewTextHandler(os.Stderr, nil)) broker := NewBroker(10, flog) testEvent := makeEvent() wg := sync.WaitGroup{} clientFn := func(name string) { sub, err := broker.Subscribe(name) if err != nil { t.Log(err) return } <-sub wg.Done() } wg.Add(2) go clientFn("client1") go clientFn("client2") // yes this is stupid. otherwise we race. time.Sleep(10 * time.Millisecond) broker.Publish("sender", testEvent) done := make(chan bool) go func() { wg.Wait() done <- true }() select { case <-done: case <-time.After(1 * time.Second): t.Fatal("timeout waiting for clients") } }) t.Run("name collision", func(t *testing.T) { flog := slog.New(slog.NewTextHandler(os.Stderr, nil)) broker := NewBroker(10, flog) _, err := broker.Subscribe("collide") if err != nil { t.Fatal(err) } _, err = broker.Subscribe("collide") if err == nil { t.Fatal("expected error, got nil") } }) t.Run("unsubscribe", func(t *testing.T) { flog := slog.New(slog.NewTextHandler(os.Stderr, nil)) broker := NewBroker(10, flog) ch, err := broker.Subscribe("test") if err != nil { t.Fatal(err) } broker.Unsubscribe("test") _, ok := <-ch if ok { t.Fatal("expected dead channel, but channel returned result") } }) }