package plans import ( "context" "errors" "testing" "time" "github.com/carlosframework/platform/internal/domains" "github.com/carlosframework/platform/internal/release" ) func TestRecordKey(t *testing.T) { if got := LimitsKey("abc"); got != "accounts/abc/limits.json" { t.Fatalf("LimitsKey = %q", got) } } func sampleRecord(sqid string) *Record { return &Record{ Account: sqid, CatalogID: "v1@0123456789ab", Plan: "free", Source: "default", Revision: 1, Limits: Limits{RunningThings: 3, IdleSeconds: 90, MemoryTier: MemorySmall}, IssuedAt: time.Unix(1_800_000_000, 0).UTC(), } } func TestRecordRoundTrip(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) sqid := domains.Sqid(42) want := sampleRecord(sqid) etag, err := PutLimits(ctx, s, want, "") if err != nil || etag == "" { t.Fatalf("put: %q, %v", etag, err) } got, getEtag, err := GetLimits(ctx, s, sqid) if err != nil { t.Fatal(err) } if getEtag == "" || got.Schema != RecordSchema { t.Fatalf("etag %q, schema %d", getEtag, got.Schema) } want.Schema = RecordSchema if *got != *want { t.Fatalf("got %+v, want %+v", got, want) } } func TestGetRecordAbsent(t *testing.T) { got, etag, err := GetLimits(context.Background(), release.NewDirStore(t.TempDir()), domains.Sqid(42)) if got != nil || etag != "" || err != nil { t.Fatalf("got %+v, %q, %v; want nil, \"\", nil", got, etag, err) } } func TestParseRecordRefuses(t *testing.T) { cases := map[string]string{ "schema 2": `{"schema": 2, "account": "abc"}`, "wrong account": `{"schema": 1, "account": "other"}`, "malformed": `{"schema": 1,`, } for name, body := range cases { if _, err := ParseLimits([]byte(body), "abc"); err == nil { t.Errorf("%s: accepted", name) } } } func TestParseRecordIgnoresUnknownFields(t *testing.T) { r, err := ParseLimits([]byte(`{"schema": 1, "account": "abc", "plan": "free", "throttled": true}`), "abc") if err != nil || r.Plan != "free" { t.Fatalf("got %+v, %v", r, err) } } func TestPutRecordIsCAS(t *testing.T) { ctx := context.Background() s := release.NewDirStore(t.TempDir()) sqid := domains.Sqid(42) first, err := PutLimits(ctx, s, sampleRecord(sqid), "") if err != nil { t.Fatal(err) } if _, err := PutLimits(ctx, s, sampleRecord(sqid), ""); !errors.Is(err, release.ErrCASConflict) { t.Fatalf("second create-only put: %v", err) } r := sampleRecord(sqid) r.Revision = 2 if _, err := PutLimits(ctx, s, r, first); err != nil { t.Fatalf("put with the current etag: %v", err) } if _, err := PutLimits(ctx, s, r, first); !errors.Is(err, release.ErrCASConflict) { t.Fatalf("put with a stale etag: %v", err) } } func TestPutRecordRefusesAnInvalidAccount(t *testing.T) { r := sampleRecord("../escape") if _, err := PutLimits(context.Background(), release.NewDirStore(t.TempDir()), r, ""); err == nil { t.Fatal("accepted an invalid account") } }