Initial go port of epics
This commit is contained in:
@@ -0,0 +1,210 @@
|
||||
package stub_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/uopi/uopi/internal/datasource"
|
||||
"github.com/uopi/uopi/internal/datasource/stub"
|
||||
)
|
||||
|
||||
func newStub(t *testing.T) *stub.Stub {
|
||||
t.Helper()
|
||||
s := stub.New()
|
||||
if err := s.Connect(context.Background()); err != nil {
|
||||
t.Fatalf("Connect: %v", err)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
if stub.New().Name() != "stub" {
|
||||
t.Error("Name() should return 'stub'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestListSignals(t *testing.T) {
|
||||
s := newStub(t)
|
||||
sigs, err := s.ListSignals(context.Background())
|
||||
if err != nil {
|
||||
t.Fatalf("ListSignals: %v", err)
|
||||
}
|
||||
if len(sigs) == 0 {
|
||||
t.Fatal("expected at least one signal")
|
||||
}
|
||||
names := make(map[string]bool)
|
||||
for _, m := range sigs {
|
||||
names[m.Name] = true
|
||||
}
|
||||
for _, want := range []string{"sine_1hz", "ramp_10s", "toggle_1hz", "noise", "setpoint"} {
|
||||
if !names[want] {
|
||||
t.Errorf("signal %q not in ListSignals", want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMetadata(t *testing.T) {
|
||||
s := newStub(t)
|
||||
m, err := s.GetMetadata(context.Background(), "sine_1hz")
|
||||
if err != nil {
|
||||
t.Fatalf("GetMetadata: %v", err)
|
||||
}
|
||||
if m.Type != datasource.TypeFloat64 {
|
||||
t.Errorf("Type = %v, want TypeFloat64", m.Type)
|
||||
}
|
||||
if m.Unit == "" {
|
||||
t.Error("expected non-empty Unit")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetMetadataNotFound(t *testing.T) {
|
||||
s := newStub(t)
|
||||
_, err := s.GetMetadata(context.Background(), "no:such:pv")
|
||||
if err != datasource.ErrNotFound {
|
||||
t.Errorf("want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeReceivesValues(t *testing.T) {
|
||||
s := newStub(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ch := make(chan datasource.Value, 4)
|
||||
stop, err := s.Subscribe(ctx, "sine_1hz", ch)
|
||||
if err != nil {
|
||||
t.Fatalf("Subscribe: %v", err)
|
||||
}
|
||||
defer stop()
|
||||
|
||||
select {
|
||||
case v := <-ch:
|
||||
if v.Quality != datasource.QualityGood {
|
||||
t.Errorf("Quality = %v, want Good", v.Quality)
|
||||
}
|
||||
if _, ok := v.Data.(float64); !ok {
|
||||
t.Errorf("Data type = %T, want float64", v.Data)
|
||||
}
|
||||
if v.Timestamp.IsZero() {
|
||||
t.Error("Timestamp is zero")
|
||||
}
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timeout waiting for first value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeUnknown(t *testing.T) {
|
||||
s := newStub(t)
|
||||
_, err := s.Subscribe(context.Background(), "no:such", make(chan datasource.Value, 1))
|
||||
if err != datasource.ErrNotFound {
|
||||
t.Errorf("want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSubscribeCancel(t *testing.T) {
|
||||
s := newStub(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ch := make(chan datasource.Value, 4)
|
||||
stop, err := s.Subscribe(ctx, "ramp_10s", ch)
|
||||
if err != nil {
|
||||
t.Fatalf("Subscribe: %v", err)
|
||||
}
|
||||
|
||||
// Drain one value to confirm it's running.
|
||||
select {
|
||||
case <-ch:
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timeout waiting for first value")
|
||||
}
|
||||
|
||||
stop() // cancel subscription
|
||||
|
||||
// Drain remaining buffered values then confirm channel goes quiet.
|
||||
time.Sleep(200 * time.Millisecond)
|
||||
for len(ch) > 0 {
|
||||
<-ch
|
||||
}
|
||||
time.Sleep(300 * time.Millisecond)
|
||||
if len(ch) > 0 {
|
||||
t.Error("channel still receiving after stop()")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteSetpoint(t *testing.T) {
|
||||
s := newStub(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
if err := s.Write(context.Background(), "setpoint", float64(99.0)); err != nil {
|
||||
t.Fatalf("Write: %v", err)
|
||||
}
|
||||
|
||||
ch := make(chan datasource.Value, 4)
|
||||
stop, err := s.Subscribe(ctx, "setpoint", ch)
|
||||
if err != nil {
|
||||
t.Fatalf("Subscribe: %v", err)
|
||||
}
|
||||
defer stop()
|
||||
|
||||
select {
|
||||
case v := <-ch:
|
||||
f, ok := v.Data.(float64)
|
||||
if !ok {
|
||||
t.Fatalf("Data type = %T, want float64", v.Data)
|
||||
}
|
||||
if f != 99.0 {
|
||||
t.Errorf("setpoint value = %g, want 99.0", f)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timeout waiting for setpoint value")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteReadOnly(t *testing.T) {
|
||||
s := newStub(t)
|
||||
err := s.Write(context.Background(), "sine_1hz", float64(0))
|
||||
if err != datasource.ErrNotWritable {
|
||||
t.Errorf("want ErrNotWritable, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteNotFound(t *testing.T) {
|
||||
s := newStub(t)
|
||||
err := s.Write(context.Background(), "no:such", float64(0))
|
||||
if err != datasource.ErrNotFound {
|
||||
t.Errorf("want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHistory(t *testing.T) {
|
||||
s := newStub(t)
|
||||
_, err := s.History(context.Background(), "sine_1hz", time.Now().Add(-time.Hour), time.Now(), 100)
|
||||
if err != datasource.ErrHistoryUnavailable {
|
||||
t.Errorf("want ErrHistoryUnavailable, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestToggleBool(t *testing.T) {
|
||||
s := newStub(t)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
|
||||
defer cancel()
|
||||
|
||||
ch := make(chan datasource.Value, 4)
|
||||
stop, err := s.Subscribe(ctx, "toggle_1hz", ch)
|
||||
if err != nil {
|
||||
t.Fatalf("Subscribe: %v", err)
|
||||
}
|
||||
defer stop()
|
||||
|
||||
select {
|
||||
case v := <-ch:
|
||||
if _, ok := v.Data.(bool); !ok {
|
||||
t.Errorf("toggle_1hz Data type = %T, want bool", v.Data)
|
||||
}
|
||||
case <-ctx.Done():
|
||||
t.Fatal("timeout")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user