139 lines
3.7 KiB
Go
139 lines
3.7 KiB
Go
|
|
package store
|
||
|
|
|
||
|
|
import (
|
||
|
|
"context"
|
||
|
|
"errors"
|
||
|
|
"testing"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"basicstack.de/proofedmesh/services/admin-api/internal/model"
|
||
|
|
)
|
||
|
|
|
||
|
|
func d(s string) time.Time {
|
||
|
|
t, err := time.Parse("2006-01-02", s)
|
||
|
|
if err != nil {
|
||
|
|
panic(err)
|
||
|
|
}
|
||
|
|
return t
|
||
|
|
}
|
||
|
|
|
||
|
|
func rateDE(validFrom, validTo string) model.NewRateInput {
|
||
|
|
in := model.NewRateInput{
|
||
|
|
Country: "DE", Currency: "EUR",
|
||
|
|
FullDay: "28.00", PartialDayMin8h: "14.00",
|
||
|
|
ArrivalDay: "14.00", DepartureDay: "14.00",
|
||
|
|
ValidFrom: d(validFrom),
|
||
|
|
SourceRegulation: "test",
|
||
|
|
}
|
||
|
|
if validTo != "" {
|
||
|
|
t := d(validTo)
|
||
|
|
in.ValidTo = &t
|
||
|
|
}
|
||
|
|
return in
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_CreateAndGet(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
r, err := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("create: %v", err)
|
||
|
|
}
|
||
|
|
if r.RateID != "PDR-1" {
|
||
|
|
t.Errorf("expected PDR-1, got %s", r.RateID)
|
||
|
|
}
|
||
|
|
got, err := m.Get(ctx, "PDR-1")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("get: %v", err)
|
||
|
|
}
|
||
|
|
if got.FullDay != "28.00" {
|
||
|
|
t.Errorf("roundtrip full_day: %s", got.FullDay)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_Get_NotFound(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
_, err := m.Get(context.Background(), "PDR-999")
|
||
|
|
if !errors.Is(err, ErrNotFound) {
|
||
|
|
t.Fatalf("expected ErrNotFound, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_OverlapRejected(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
if _, err := m.Create(ctx, rateDE("2026-01-01", "2026-12-31"), "admin", time.Now()); err != nil {
|
||
|
|
t.Fatalf("first create: %v", err)
|
||
|
|
}
|
||
|
|
// Overlap on the last day of 2026
|
||
|
|
_, err := m.Create(ctx, rateDE("2026-12-31", ""), "admin", time.Now())
|
||
|
|
if !errors.Is(err, ErrOverlap) {
|
||
|
|
t.Fatalf("expected ErrOverlap, got %v", err)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_RetireChangesValidTo(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
updated, err := m.Retire(ctx, r.RateID, d("2026-06-30"), "admin2", time.Now())
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("retire: %v", err)
|
||
|
|
}
|
||
|
|
if updated.ValidTo == nil || !updated.ValidTo.Equal(d("2026-06-30")) {
|
||
|
|
t.Errorf("valid_to not set to 2026-06-30: %v", updated.ValidTo)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_Retire_BeforeValidFrom_Rejected(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
_, err := m.Retire(ctx, r.RateID, d("2025-12-01"), "admin2", time.Now())
|
||
|
|
if err == nil {
|
||
|
|
t.Fatal("expected error for valid_to before valid_from")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_AttachAttestation(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
err := m.AttachAttestation(ctx, r.RateID, "sha256:0000000000000000000000000000000000000000000000000000000000000001")
|
||
|
|
if err != nil {
|
||
|
|
t.Fatalf("attach: %v", err)
|
||
|
|
}
|
||
|
|
got, _ := m.Get(ctx, r.RateID)
|
||
|
|
if got.RateChangeAttestationRef == nil {
|
||
|
|
t.Fatal("expected attestation ref to be set")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_AttachAttestation_BadRef_Rejected(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
r, _ := m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
err := m.AttachAttestation(ctx, r.RateID, "not-a-hash")
|
||
|
|
if err == nil {
|
||
|
|
t.Fatal("expected error for malformed attestation ref")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func TestMemory_List_FilterByCountry(t *testing.T) {
|
||
|
|
m := NewMemory()
|
||
|
|
ctx := context.Background()
|
||
|
|
_, _ = m.Create(ctx, rateDE("2026-01-01", ""), "admin", time.Now())
|
||
|
|
fr := rateDE("2026-01-01", "")
|
||
|
|
fr.Country = "FR"
|
||
|
|
_, _ = m.Create(ctx, fr, "admin", time.Now())
|
||
|
|
|
||
|
|
all, _ := m.List(ctx, ListFilter{})
|
||
|
|
if len(all) != 2 {
|
||
|
|
t.Fatalf("expected 2 total, got %d", len(all))
|
||
|
|
}
|
||
|
|
de, _ := m.List(ctx, ListFilter{Country: "DE"})
|
||
|
|
if len(de) != 1 || de[0].Country != "DE" {
|
||
|
|
t.Fatalf("country filter failed: %+v", de)
|
||
|
|
}
|
||
|
|
}
|