internal/budget/cost_basis_test.go
Rama main · réplica de lectura del repositorio original.
package budget
import (
"context"
"path/filepath"
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.mongodb.org/mongo-driver/v2/bson"
"go.mongodb.org/mongo-driver/v2/mongo"
"github.com/enterpilot/gomodel/config"
"github.com/enterpilot/gomodel/internal/storage"
"github.com/enterpilot/gomodel/internal/storage/mongotest"
"github.com/enterpilot/gomodel/internal/storage/sqlx"
"github.com/enterpilot/gomodel/internal/storage/sqlx/sqlxtest"
"github.com/enterpilot/gomodel/internal/usage"
)
func TestNormalizeCostBasis(t *testing.T) {
tests := []struct {
raw string
want CostBasis
wantErr bool
}{
{raw: "", want: CostBasisProvider},
{raw: "provider", want: CostBasisProvider},
{raw: " Billed ", want: CostBasisBilled},
{raw: "billed", want: CostBasisBilled},
{raw: "invoice", wantErr: true},
}
for _, tt := range tests {
t.Run(tt.raw, func(t *testing.T) {
got, err := NormalizeCostBasis(tt.raw)
if tt.wantErr {
require.ErrorContains(t, err, "cost_basis must be one of provider, billed")
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
}
func TestNormalizeBudgetDefaultsCostBasisToProvider(t *testing.T) {
got, err := NormalizeBudget(Budget{Subject: "/team", PeriodSeconds: PeriodDailySeconds, Amount: 1})
require.NoError(t, err)
assert.Equal(t, CostBasisProvider, got.CostBasis)
_, err = NormalizeBudget(Budget{Subject: "/team", PeriodSeconds: PeriodDailySeconds, Amount: 1, CostBasis: "gross"})
require.Error(t, err)
}
func TestServiceRejectsBilledBudgetWritesWhenDisabled(t *testing.T) {
ctx := context.Background()
billed := Budget{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 100,
}
store := &fakeStore{}
service, err := NewService(ctx, store, WithBilledBudgets(false))
require.NoError(t, err)
err = service.UpsertBudgets(ctx, []Budget{billed})
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
err = service.ReplaceConfigBudgets(ctx, []Budget{billed})
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
require.Equal(t, 0, store.replaceCalls)
// Provider-cost budgets are unaffected by the gate.
provider := billed
provider.CostBasis = CostBasisProvider
require.NoError(t, service.UpsertBudgets(ctx, []Budget{provider}))
}
// A stored billed budget must not stop the gateway when billed budgets become
// unavailable: it keeps limiting spend, on provider cost.
func TestServiceEnforcesStoredBilledBudgetOnProviderCostWhenDisabled(t *testing.T) {
ctx := context.Background()
store := &fakeStore{
budgets: []Budget{{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 100, Source: SourceManual,
}},
sum: func(SpendWindow) (float64, bool, error) { return 100, true, nil },
}
service, err := NewService(ctx, store, WithBilledBudgets(false), WithBilledCacheHits(true))
require.NoError(t, err)
budgets := service.Budgets()
require.Len(t, budgets, 1)
assert.Equal(t, CostBasisBilled, budgets[0].CostBasis, "the stored basis is kept")
assert.Equal(t, CostBasisProvider, budgets[0].EnforcedBasis())
err = service.Check(ctx, Subjects{UserPath: "/", Labels: []string{"acme"}}, time.Now())
var exceeded *ExceededError
require.ErrorAs(t, err, &exceeded)
require.Len(t, store.lastWindows, 1)
assert.Equal(t, CostBasisProvider, store.lastWindows[0].CostBasis)
// Enforced on provider cost, the budget no longer gates cache hits.
store.sumCalls = 0
require.NoError(t, service.CheckCacheHit(ctx, Subjects{UserPath: "/", Labels: []string{"acme"}}, time.Now()))
assert.Zero(t, store.sumCalls)
}
func TestServiceKeepsStoredBilledBasisOnEditWhenDisabled(t *testing.T) {
ctx := context.Background()
store := &fakeStore{budgets: []Budget{{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 100, Source: SourceManual,
}}}
service, err := NewService(ctx, store, WithBilledBudgets(false))
require.NoError(t, err)
assert.True(t, service.StoredAsBilled(ScopeLabel, "acme", PeriodMonthlySeconds))
assert.False(t, service.StoredAsBilled(ScopeLabel, "acme", PeriodDailySeconds))
assert.False(t, service.StoredAsBilled(ScopeLabel, "other", PeriodMonthlySeconds))
// Editing the amount keeps the stored billed basis.
require.NoError(t, service.UpsertBudgets(ctx, []Budget{{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 200, Source: SourceManual,
}}))
// A new billed budget still needs the capability.
err = service.UpsertBudgets(ctx, []Budget{{
Scope: ScopeLabel, Subject: "other", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 200, Source: SourceManual,
}})
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
// Config budgets get the full check, even for a stored billed key.
err = service.ReplaceConfigBudgets(ctx, []Budget{{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 200, Source: SourceConfig,
}})
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
assert.Zero(t, store.replaceCalls)
}
func TestServicePassesCostBasisToSpendWindows(t *testing.T) {
ctx := context.Background()
store := &fakeStore{budgets: []Budget{
{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10},
{Scope: ScopeUserPath, Subject: "/", CostBasis: CostBasisProvider, PeriodSeconds: PeriodDailySeconds, Amount: 10},
}}
service, err := NewService(ctx, store)
require.NoError(t, err)
_, err = service.CheckWithResults(ctx, Subjects{UserPath: "/team", Labels: []string{"acme"}}, time.Now())
require.NoError(t, err)
require.Len(t, store.lastWindows, 2)
bases := map[Scope]CostBasis{}
for _, window := range store.lastWindows {
bases[window.Scope] = window.CostBasis
}
assert.Equal(t, CostBasisBilled, bases[ScopeLabel])
assert.Equal(t, CostBasisProvider, bases[ScopeUserPath])
}
func TestServiceCheckCacheHit(t *testing.T) {
billedLabel := Budget{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10}
providerLabel := Budget{Scope: ScopeLabel, Subject: "acme", PeriodSeconds: PeriodDailySeconds, Amount: 10}
billedProvider := Budget{Scope: ScopeProvider, Subject: "openai", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10}
billedOther := Budget{Scope: ScopeLabel, Subject: "other", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10}
tests := []struct {
name string
budgets []Budget
billedCacheHits bool
wantExceeded bool
wantStoreCall bool
}{
{name: "billed budget exhausted", budgets: []Budget{billedLabel}, billedCacheHits: true, wantExceeded: true, wantStoreCall: true},
{name: "cache hits not billed", budgets: []Budget{billedLabel}},
{name: "provider cost budget", budgets: []Budget{providerLabel}, billedCacheHits: true},
{name: "billed provider-scope budget", budgets: []Budget{billedProvider}, billedCacheHits: true},
{name: "billed budget for another label", budgets: []Budget{billedOther}, billedCacheHits: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
store := &fakeStore{
budgets: tt.budgets,
sum: func(SpendWindow) (float64, bool, error) { return 10, true, nil },
}
service, err := NewService(ctx, store, WithBilledCacheHits(tt.billedCacheHits))
require.NoError(t, err)
err = service.CheckCacheHit(ctx, Subjects{UserPath: "/team", Labels: []string{"acme"}, Provider: "openai"}, time.Now())
if tt.wantExceeded {
var exceeded *ExceededError
require.ErrorAs(t, err, &exceeded)
assert.Equal(t, "acme", exceeded.Result.Budget.Subject)
} else {
require.NoError(t, err)
}
assert.Equal(t, tt.wantStoreCall, store.sumCalls > 0)
})
}
}
func TestSeedConfiguredBudgetsCarriesCostBasis(t *testing.T) {
ctx := context.Background()
store := &fakeStore{}
err := seedConfiguredBudgets(ctx, store, config.BudgetsConfig{
Labels: []config.BudgetLabelConfig{{Label: "acme", Limits: []config.BudgetLimitConfig{
{Period: "monthly", Amount: 500, CostBasis: "billed"},
{Period: "daily", Amount: 20},
}}},
}, allCapabilities)
require.NoError(t, err)
require.Len(t, store.replacedBudgets, 2)
assert.Equal(t, CostBasisBilled, store.replacedBudgets[0].CostBasis)
assert.Equal(t, CostBasisProvider, store.replacedBudgets[1].CostBasis)
err = seedConfiguredBudgets(ctx, store, config.BudgetsConfig{
Labels: []config.BudgetLabelConfig{{Label: "acme", Limits: []config.BudgetLimitConfig{
{Period: "monthly", Amount: 500, CostBasis: "billed"},
}}},
}, capabilities{quotaTemplates: true})
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
assert.Equal(t, 1, store.replaceCalls)
}
func newSQLiteStorage(t *testing.T) storage.Storage {
t.Helper()
shared, err := storage.NewSQLite(storage.SQLiteConfig{Path: filepath.Join(t.TempDir(), "budgets.db")})
require.NoError(t, err)
t.Cleanup(func() { _ = shared.Close() })
return shared
}
func billedLabelConfig(basis string) []config.BudgetLabelConfig {
return []config.BudgetLabelConfig{{Label: "acme", Limits: []config.BudgetLimitConfig{
{Period: "monthly", Amount: 500, CostBasis: basis},
}}}
}
// A billed budget in the current config aborts startup unless the capability
// is present and markups are enabled, mirroring per-child quota templates.
func TestNewGatesConfiguredBilledBudgets(t *testing.T) {
tests := []struct {
name string
capability bool
markups bool
wantErr bool
}{
{name: "capability and markups", capability: true, markups: true},
{name: "no capability", capability: false, markups: true, wantErr: true},
{name: "markups disabled", capability: true, markups: false, wantErr: true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
cfg := &config.Config{}
cfg.Budgets.Enabled = true
cfg.Pricing.MarkupsEnabled = tt.markups
cfg.Budgets.Labels = billedLabelConfig("billed")
result, err := New(context.Background(), cfg, newSQLiteStorage(t), false, tt.capability)
if tt.wantErr {
require.ErrorIs(t, err, ErrBilledBudgetsUnavailable)
return
}
require.NoError(t, err)
t.Cleanup(func() { _ = result.Close() })
budgets := result.Service.Budgets()
require.Len(t, budgets, 1)
assert.Equal(t, CostBasisBilled, budgets[0].CostBasis)
})
}
}
// Restarting after billed budgets become unavailable must start: a config
// change that drops or switches the billed budget applies, and a manual billed
// budget keeps limiting spend on provider cost.
func TestNewStartsWithStoredBilledBudgetsAfterEntitlementLoss(t *testing.T) {
tests := []struct {
name string
nextLabel []config.BudgetLabelConfig
manual bool
stored []CostBasis
enforced []CostBasis
}{
{name: "config budget switched to provider", nextLabel: billedLabelConfig("provider"), stored: []CostBasis{CostBasisProvider}, enforced: []CostBasis{CostBasisProvider}},
{name: "config budget removed"},
{name: "manual billed budget", manual: true, stored: []CostBasis{CostBasisBilled}, enforced: []CostBasis{CostBasisProvider}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
ctx := context.Background()
shared := newSQLiteStorage(t)
cfg := &config.Config{}
cfg.Budgets.Enabled = true
cfg.Pricing.MarkupsEnabled = true
if !tt.manual {
cfg.Budgets.Labels = billedLabelConfig("billed")
}
first, err := New(ctx, cfg, shared, false, true)
require.NoError(t, err)
if tt.manual {
require.NoError(t, first.Service.UpsertBudgets(ctx, []Budget{{
Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled,
PeriodSeconds: PeriodMonthlySeconds, Amount: 500, Source: SourceManual,
}}))
}
require.NoError(t, first.Close())
cfg.Pricing.MarkupsEnabled = false
cfg.Budgets.Labels = tt.nextLabel
next, err := New(ctx, cfg, shared, false, false)
require.NoError(t, err)
t.Cleanup(func() { _ = next.Close() })
var stored, enforced []CostBasis
for _, item := range next.Service.Budgets() {
stored = append(stored, item.CostBasis)
enforced = append(enforced, item.EnforcedBasis())
}
assert.Equal(t, tt.stored, stored)
assert.Equal(t, tt.enforced, enforced)
})
}
}
// billedSpendEntries covers every row shape a billed window must handle: a
// marked-up row, a row written before markups were enabled (no billed cost), a
// billed and an unbilled response-cache hit, a pre-markup cache hit, and a row
// of unknown cost.
func billedSpendEntries(now time.Time) []*usage.UsageEntry {
withBilled := func(entry *usage.UsageEntry, billed float64) *usage.UsageEntry {
entry.BilledCost = &billed
return entry
}
unknown := usageEntryWithCost("unknown", "/acme", "", now, 0, "acme")
unknown.InputCost, unknown.OutputCost, unknown.TotalCost = nil, nil, nil
return []*usage.UsageEntry{
withBilled(usageEntryWithCost("marked-up", "/acme", "", now, 1, "acme"), 1.25),
usageEntryWithCost("pre-markup", "/acme", "", now, 2, "acme"),
withBilled(usageEntryWithCost("billed-hit", "/acme", usage.CacheTypeExact, now, 4, "acme"), 4.5),
withBilled(usageEntryWithCost("free-hit", "/acme", usage.CacheTypeSemantic, now, 8, "acme"), 0),
usageEntryWithCost("pre-markup-hit", "/acme", usage.CacheTypeExact, now, 16, "acme"),
unknown,
withBilled(usageEntryWithCost("only-free-hit", "/cache-only", usage.CacheTypeExact, now, 3, "cache-only"), 0),
}
}
// assertBilledSpend checks provider and billed windows over billedSpendEntries
// in one batch, so a mixed batch is covered too.
func assertBilledSpend(t *testing.T, store Store, now time.Time) {
t.Helper()
start, end := now.Add(-time.Hour), now.Add(time.Hour)
windows := []SpendWindow{
{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisProvider, Start: start, End: end},
{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled, Start: start, End: end},
{Scope: ScopeUserPath, Subject: "/acme", CostBasis: CostBasisBilled, Start: start, End: end},
{Scope: ScopeLabel, Subject: "cache-only", CostBasis: CostBasisProvider, Start: start, End: end},
{Scope: ScopeLabel, Subject: "cache-only", CostBasis: CostBasisBilled, Start: start, End: end},
{Scope: ScopeLabel, Subject: "absent", CostBasis: CostBasisBilled, Start: start, End: end},
{Scope: ScopeProvider, Subject: "test", CostBasis: CostBasisBilled, Start: start, End: end},
{Scope: ScopeProvider, Subject: "test", CostBasis: CostBasisBilled, Start: start, End: end, ExcludeCacheHits: true},
{Scope: ScopeLabel, Subject: "cache-only", CostBasis: CostBasisBilled, Start: start, End: end, ExcludeCacheHits: true},
}
want := []Spend{
{Total: 3, HasUsage: true}, // provider: uncached marked-up + pre-markup
{Total: 7.75, HasUsage: true}, // billed: 1.25 + 2 (fallback) + 4.5 (billed hit) + 0
{Total: 7.75, HasUsage: true}, // same rows by user path
{}, // provider never counts cache hits
{Total: 0, HasUsage: true}, // an unbilled hit is billed usage worth 0
{},
{Total: 7.75, HasUsage: true}, // billed provider budget counts billed hits by default
{Total: 3.25, HasUsage: true}, // without them: 1.25 + 2 (fallback)
{}, // nothing left once the only rows are hits
}
got, err := store.SumSpend(context.Background(), windows)
require.NoError(t, err)
require.Len(t, got, len(want))
for i := range want {
assert.Equal(t, want[i].HasUsage, got[i].HasUsage, "spend[%d] has usage", i)
assert.InDelta(t, want[i].Total, got[i].Total, 1e-9, "spend[%d] total", i)
}
}
func TestServiceExcludesBilledCacheHitsFromProviderBudgetsWhenConfigured(t *testing.T) {
budgets := []Budget{
{Scope: ScopeProvider, Subject: "openai", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10},
{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled, PeriodSeconds: PeriodDailySeconds, Amount: 10},
}
for _, tt := range []struct {
name string
options []ServiceOption
exclude map[Scope]bool
}{
{name: "default counts hits", exclude: map[Scope]bool{ScopeProvider: false, ScopeLabel: false}},
{name: "disabled excludes provider hits", options: []ServiceOption{WithProviderBilledCacheHits(false)}, exclude: map[Scope]bool{ScopeProvider: true, ScopeLabel: false}},
} {
t.Run(tt.name, func(t *testing.T) {
store := &fakeStore{budgets: budgets}
options := append([]ServiceOption{WithBilledBudgets(true)}, tt.options...)
service, err := NewService(context.Background(), store, options...)
require.NoError(t, err)
_, err = service.Statuses(context.Background(), time.Now())
require.NoError(t, err)
got := map[Scope]bool{}
for _, window := range store.lastWindows {
got[window.Scope] = window.ExcludeCacheHits
}
assert.Equal(t, tt.exclude, got)
})
}
}
func TestSQLStoreSumSpendOnBilledCost(t *testing.T) {
sqlxtest.Run(t, func(t *testing.T, db sqlx.DB) {
ctx := context.Background()
usageStore, err := usage.NewSQLStore(ctx, db, 0)
require.NoError(t, err)
now := time.Date(2026, time.April, 25, 12, 0, 0, 0, time.UTC)
require.NoError(t, usageStore.WriteBatch(ctx, billedSpendEntries(now)))
store, err := NewSQLStore(ctx, db)
require.NoError(t, err)
assertBilledSpend(t, store, now)
})
}
func TestMongoDBStoreSumSpendOnBilledCost(t *testing.T) {
mongotest.Run(t, func(t *testing.T, db *mongo.Database) {
ctx := context.Background()
usageStore, err := usage.NewMongoDBStore(db, 0)
require.NoError(t, err)
now := time.Date(2026, time.April, 25, 12, 0, 0, 0, time.UTC)
require.NoError(t, usageStore.WriteBatch(ctx, billedSpendEntries(now)))
store, err := NewMongoDBStore(ctx, db)
require.NoError(t, err)
assertBilledSpend(t, store, now)
})
}
func TestSQLStoreRoundTripsCostBasis(t *testing.T) {
runSQLStoreTest(t, func(t *testing.T, store *SQLStore) {
assertStoreRoundTripsCostBasis(t, store)
})
}
func TestMongoDBStoreRoundTripsCostBasis(t *testing.T) {
mongotest.Run(t, func(t *testing.T, db *mongo.Database) {
store, err := NewMongoDBStore(context.Background(), db)
require.NoError(t, err)
assertStoreRoundTripsCostBasis(t, store)
})
}
// assertStoreRoundTripsCostBasis persists both bases, then checks that a
// config re-seed leaves a manual budget's basis alone while updating a
// config-sourced one.
func assertStoreRoundTripsCostBasis(t *testing.T, store Store) {
t.Helper()
ctx := context.Background()
err := store.UpsertBudgets(ctx, []Budget{
{Scope: ScopeLabel, Subject: "acme", CostBasis: CostBasisBilled, PeriodSeconds: PeriodMonthlySeconds, Amount: 100, Source: SourceManual},
{Scope: ScopeLabel, Subject: "beta", PeriodSeconds: PeriodMonthlySeconds, Amount: 50, Source: SourceConfig},
})
require.NoError(t, err)
err = store.ReplaceConfigBudgets(ctx, []Budget{
{Scope: ScopeLabel, Subject: "acme", PeriodSeconds: PeriodMonthlySeconds, Amount: 1},
{Scope: ScopeLabel, Subject: "beta", CostBasis: CostBasisBilled, PeriodSeconds: PeriodMonthlySeconds, Amount: 50},
})
require.NoError(t, err)
budgets, err := store.ListBudgets(ctx)
require.NoError(t, err)
bases := map[string]CostBasis{}
for _, item := range budgets {
bases[item.Subject] = item.CostBasis
}
assert.Equal(t, map[string]CostBasis{"acme": CostBasisBilled, "beta": CostBasisBilled}, bases)
err = store.UpsertBudgets(ctx, []Budget{
{Scope: ScopeLabel, Subject: "acme", PeriodSeconds: PeriodMonthlySeconds, Amount: 100, Source: SourceManual},
})
require.NoError(t, err)
budgets, err = store.ListBudgets(ctx)
require.NoError(t, err)
for _, item := range budgets {
if item.Subject == "acme" {
assert.Equal(t, CostBasisProvider, item.CostBasis)
}
}
}
// Budgets stored before cost bases existed keep limiting provider cost.
func TestSQLStoreMigratesPreCostBasisRows(t *testing.T) {
sqlxtest.Run(t, func(t *testing.T, db sqlx.DB) {
ctx := context.Background()
err := db.Schema(ctx, `CREATE TABLE budgets (
scope TEXT NOT NULL DEFAULT 'user_path',
subject TEXT NOT NULL,
per_child `+sqlx.TypeBool+` NOT NULL DEFAULT FALSE,
period_seconds `+sqlx.TypeInt64+` NOT NULL,
amount `+sqlx.TypeFloat+` NOT NULL,
source TEXT NOT NULL DEFAULT '',
last_reset_at `+sqlx.TypeInt64+`,
created_at `+sqlx.TypeInt64+` NOT NULL,
updated_at `+sqlx.TypeInt64+` NOT NULL,
PRIMARY KEY (scope, subject, period_seconds)
)`)
require.NoError(t, err)
_, err = db.Exec(ctx, `
INSERT INTO budgets (scope, subject, period_seconds, amount, source, created_at, updated_at)
VALUES (?, ?, ?, ?, ?, ?, ?)
`, ScopeUserPath, "/legacy", PeriodDailySeconds, 10.0, SourceManual, int64(1), int64(1))
require.NoError(t, err)
store, err := NewSQLStore(ctx, db)
require.NoError(t, err)
budgets, err := store.ListBudgets(ctx)
require.NoError(t, err)
require.Len(t, budgets, 1)
assert.Equal(t, CostBasisProvider, budgets[0].CostBasis)
})
}
func TestMongoDBStoreReadsPreCostBasisDocumentsAsProvider(t *testing.T) {
mongotest.Run(t, func(t *testing.T, db *mongo.Database) {
ctx := context.Background()
now := time.Date(2026, time.April, 25, 12, 0, 0, 0, time.UTC)
_, err := db.Collection("budgets").InsertOne(ctx, bson.D{
{Key: "scope", Value: string(ScopeUserPath)}, {Key: "subject", Value: "/legacy"},
{Key: "period_seconds", Value: PeriodDailySeconds}, {Key: "amount", Value: 10.0},
{Key: "source", Value: SourceManual}, {Key: "created_at", Value: now}, {Key: "updated_at", Value: now},
})
require.NoError(t, err)
store, err := NewMongoDBStore(ctx, db)
require.NoError(t, err)
budgets, err := store.ListBudgets(ctx)
require.NoError(t, err)
require.Len(t, budgets, 1)
assert.Equal(t, CostBasisProvider, budgets[0].CostBasis)
})
}