initial config manager
This commit is contained in:
@@ -0,0 +1,200 @@
|
||||
package confmgr
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func fptr(f float64) *float64 { return &f }
|
||||
|
||||
func sampleSet() ConfigSet {
|
||||
return ConfigSet{
|
||||
Name: "PSU",
|
||||
Description: "power supply config",
|
||||
Parameters: []Parameter{
|
||||
{Key: "voltage", DS: "epics", Signal: "PSU:V", Type: TypeFloat, Default: 12.0, Mandatory: true, Min: fptr(0), Max: fptr(48)},
|
||||
{Key: "enabled", DS: "epics", Signal: "PSU:EN", Type: TypeBool, Default: false},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateAndGetSet(t *testing.T) {
|
||||
s, err := New(t.TempDir())
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
out, err := s.CreateSet(sampleSet(), "initial")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.ID == "" {
|
||||
t.Fatal("expected generated ID")
|
||||
}
|
||||
if out.Version != 1 {
|
||||
t.Errorf("version: want 1, got %d", out.Version)
|
||||
}
|
||||
got, err := s.GetSet(out.ID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if got.Name != "PSU" || len(got.Parameters) != 2 {
|
||||
t.Errorf("round-trip mismatch: %+v", got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetVersioning(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
created, _ := s.CreateSet(sampleSet(), "")
|
||||
id := created.ID
|
||||
|
||||
// Update -> v2.
|
||||
upd := sampleSet()
|
||||
upd.Description = "edited"
|
||||
v2, err := s.UpdateSet(id, upd, "edit")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v2.Version != 2 {
|
||||
t.Fatalf("version after update: want 2, got %d", v2.Version)
|
||||
}
|
||||
|
||||
versions, err := s.Versions(KindSet, id)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(versions) != 2 {
|
||||
t.Fatalf("want 2 versions, got %d", len(versions))
|
||||
}
|
||||
if !versions[0].Current || versions[0].Version != 2 {
|
||||
t.Errorf("newest should be current v2: %+v", versions[0])
|
||||
}
|
||||
|
||||
// Old version still retrievable.
|
||||
old, err := s.GetSetVersion(id, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if old.Description != "power supply config" {
|
||||
t.Errorf("v1 description changed: %q", old.Description)
|
||||
}
|
||||
|
||||
// Promote v1 -> becomes v3 with original content.
|
||||
if err := s.Promote(KindSet, id, 1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cur, _ := s.GetSet(id)
|
||||
if cur.Version != 3 || cur.Description != "power supply config" {
|
||||
t.Errorf("after promote: want v3 original desc, got v%d %q", cur.Version, cur.Description)
|
||||
}
|
||||
}
|
||||
|
||||
func TestForkSet(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
created, _ := s.CreateSet(sampleSet(), "")
|
||||
_, _ = s.UpdateSet(created.ID, sampleSet(), "")
|
||||
|
||||
newID, err := s.Fork(KindSet, created.ID, 1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
forked, err := s.GetSet(newID)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if forked.ID == created.ID {
|
||||
t.Error("fork should have a new ID")
|
||||
}
|
||||
if forked.Version != 1 {
|
||||
t.Errorf("fork version: want 1, got %d", forked.Version)
|
||||
}
|
||||
if forked.Tag != "" {
|
||||
t.Errorf("fork tag should be cleared, got %q", forked.Tag)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteSetSoftDeletes(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
created, _ := s.CreateSet(sampleSet(), "")
|
||||
if err := s.Delete(KindSet, created.ID); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := s.GetSet(created.ID); err == nil {
|
||||
t.Error("expected set to be gone after delete")
|
||||
}
|
||||
// Deleting again is a not-found.
|
||||
if err := s.Delete(KindSet, created.ID); err != ErrNotFound {
|
||||
t.Errorf("want ErrNotFound, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetValidation(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
bad := ConfigSet{Name: "", Parameters: nil}
|
||||
if _, err := s.CreateSet(bad, ""); err == nil {
|
||||
t.Error("expected empty-name validation error")
|
||||
}
|
||||
dup := ConfigSet{Name: "x", Parameters: []Parameter{
|
||||
{Key: "a", DS: "d", Signal: "s", Type: TypeFloat},
|
||||
{Key: "a", DS: "d", Signal: "s2", Type: TypeFloat},
|
||||
}}
|
||||
if _, err := s.CreateSet(dup, ""); err == nil {
|
||||
t.Error("expected duplicate-key validation error")
|
||||
}
|
||||
defaultOOR := ConfigSet{Name: "x", Parameters: []Parameter{
|
||||
{Key: "a", DS: "d", Signal: "s", Type: TypeFloat, Default: 100.0, Max: fptr(10)},
|
||||
}}
|
||||
if _, err := s.CreateSet(defaultOOR, ""); err == nil {
|
||||
t.Error("expected out-of-range default validation error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstanceLifecycle(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
set, _ := s.CreateSet(sampleSet(), "")
|
||||
|
||||
inst := ConfigInstance{
|
||||
Name: "nominal",
|
||||
SetID: set.ID,
|
||||
Values: map[string]any{"voltage": 24.0, "enabled": true},
|
||||
}
|
||||
out, err := s.CreateInstance(inst, "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if out.Version != 1 {
|
||||
t.Errorf("instance version: want 1, got %d", out.Version)
|
||||
}
|
||||
|
||||
// Update value -> v2.
|
||||
out.Values["voltage"] = 36.0
|
||||
v2, err := s.UpdateInstance(out.ID, out, "bump")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v2.Version != 2 {
|
||||
t.Errorf("instance version after update: want 2, got %d", v2.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInstanceValidation(t *testing.T) {
|
||||
s, _ := New(t.TempDir())
|
||||
set, _ := s.CreateSet(sampleSet(), "")
|
||||
|
||||
// voltage is mandatory with a default, so omitting it is OK; but an
|
||||
// out-of-range value must fail.
|
||||
bad := ConfigInstance{Name: "x", SetID: set.ID, Values: map[string]any{"voltage": 999.0}}
|
||||
if _, err := s.CreateInstance(bad, ""); err == nil {
|
||||
t.Error("expected out-of-range value error")
|
||||
}
|
||||
|
||||
// Unknown parameter key must fail.
|
||||
unknown := ConfigInstance{Name: "x", SetID: set.ID, Values: map[string]any{"nope": 1.0}}
|
||||
if _, err := s.CreateInstance(unknown, ""); err == nil {
|
||||
t.Error("expected unknown-parameter error")
|
||||
}
|
||||
|
||||
// Unknown set must fail.
|
||||
missing := ConfigInstance{Name: "x", SetID: "does-not-exist", Values: map[string]any{}}
|
||||
if _, err := s.CreateInstance(missing, ""); err == nil {
|
||||
t.Error("expected missing-set error")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user