Skip to content

Commit 2b4b035

Browse files
michaelmcneesclaude
andcommitted
test(budget): add team hard block, provider usage error, and upper-bound clamp tests
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 10306ca commit 2b4b035

2 files changed

Lines changed: 62 additions & 1 deletion

File tree

internal/budget/budget_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,55 @@ func TestChecker_Check_FailOpenOnGetTeamBudgetError(t *testing.T) {
150150
assert.False(t, result.Warning)
151151
}
152152

153+
func TestChecker_Check_FailOpenOnGetProviderUsageError(t *testing.T) {
154+
checker := &budget.Checker{
155+
ResetMode: "calendar",
156+
ResetDay: 1,
157+
GetTotalUsage: func(ctx context.Context, period time.Time) (int64, error) {
158+
return 0, nil
159+
},
160+
GetProviderUsage: func(ctx context.Context, teamID, provider string, period time.Time) (int64, error) {
161+
return 0, fmt.Errorf("provider usage query failed")
162+
},
163+
GetTeamBudget: func(ctx context.Context, teamID, provider string) (*budget.TeamBudget, error) {
164+
return &budget.TeamBudget{MonthlyTokenLimit: 5000, Enforcement: "hard"}, nil
165+
},
166+
}
167+
168+
result := checker.Check(context.Background(), budget.CheckInput{
169+
TeamID: "team-1",
170+
Provider: "openai",
171+
})
172+
173+
assert.False(t, result.Blocked)
174+
assert.False(t, result.Warning)
175+
}
176+
177+
func TestChecker_Check_TeamHardBlock(t *testing.T) {
178+
checker := &budget.Checker{
179+
ResetMode: "calendar",
180+
ResetDay: 1,
181+
GetTotalUsage: func(ctx context.Context, period time.Time) (int64, error) {
182+
return 0, nil
183+
},
184+
GetProviderUsage: func(ctx context.Context, teamID, provider string, period time.Time) (int64, error) {
185+
return 5001, nil
186+
},
187+
GetTeamBudget: func(ctx context.Context, teamID, provider string) (*budget.TeamBudget, error) {
188+
return &budget.TeamBudget{MonthlyTokenLimit: 5000, Enforcement: "hard"}, nil
189+
},
190+
}
191+
192+
result := checker.Check(context.Background(), budget.CheckInput{
193+
TeamID: "team-1",
194+
Provider: "openai",
195+
})
196+
197+
assert.True(t, result.Blocked)
198+
assert.Equal(t, "team", result.BlockedBy)
199+
assert.Contains(t, result.Message, "team budget exceeded")
200+
}
201+
153202
func TestChecker_CheckExecutionBudget(t *testing.T) {
154203
result := budget.CheckExecutionBudget(50000, 50001)
155204
assert.True(t, result.Blocked)

internal/config/config_test.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func TestLoad_BudgetResetDay_RollingInvalid(t *testing.T) {
226226
}
227227

228228
func TestLoad_BudgetResetDay_CalendarClamps(t *testing.T) {
229-
// Invalid ResetDay with calendar mode should silently clamp to 1
229+
// Invalid ResetDay with calendar mode should silently clamp to 1 (lower bound)
230230
t.Setenv("MANTLE_ENGINE_BUDGET_RESET_MODE", "calendar")
231231
t.Setenv("MANTLE_ENGINE_BUDGET_RESET_DAY", "0")
232232

@@ -235,3 +235,15 @@ func TestLoad_BudgetResetDay_CalendarClamps(t *testing.T) {
235235
require.NoError(t, err)
236236
assert.Equal(t, 1, cfg.Engine.Budget.ResetDay)
237237
}
238+
239+
func TestLoad_BudgetResetDay_CalendarClampsUpperBound(t *testing.T) {
240+
// ResetDay >28 with calendar mode should silently clamp to 1
241+
// (calendar mode ignores reset_day entirely, so any invalid value is safe to clamp)
242+
t.Setenv("MANTLE_ENGINE_BUDGET_RESET_MODE", "calendar")
243+
t.Setenv("MANTLE_ENGINE_BUDGET_RESET_DAY", "100")
244+
245+
cmd := newTestCommand()
246+
cfg, err := Load(cmd)
247+
require.NoError(t, err)
248+
assert.Equal(t, 1, cfg.Engine.Budget.ResetDay)
249+
}

0 commit comments

Comments
 (0)