- store/sqlite: 75.4% (repos + db coverage) - host/sub2api: 80.8% (httptest mock server, pure function tests) - app: 74.2% (handler error paths, NewActionSet closures) - pack: 72.4% - provision: 75.2% - access: 77.3% - config: 94.7% (lookup mock tests) All tests pass: build, vet, race, coverage gates.
92 lines
2.9 KiB
Go
92 lines
2.9 KiB
Go
package access
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
|
|
"sub2api-cn-relay-manager/internal/host/sub2api"
|
|
)
|
|
|
|
func TestValidateRejectsMissingProbeAPIKeyForSelfService(t *testing.T) {
|
|
err := Validate(ClosureRequest{Mode: "self_service"})
|
|
if err == nil {
|
|
t.Fatal("Validate() error = nil, want validation error")
|
|
}
|
|
}
|
|
|
|
func TestValidateRejectsMissingSubscriptionsForSubscriptionMode(t *testing.T) {
|
|
err := Validate(ClosureRequest{Mode: "subscription", ProbeAPIKey: "user-key"})
|
|
if err == nil {
|
|
t.Fatal("Validate() error = nil, want validation error")
|
|
}
|
|
}
|
|
|
|
func TestServiceCloseAssignsSubscriptionsAndProbesGateway(t *testing.T) {
|
|
host := &fakeClosureHost{
|
|
gatewayResult: sub2api.GatewayAccessResult{OK: true, StatusCode: 200, HasExpectedModel: true, Models: []string{"deepseek-chat"}},
|
|
}
|
|
service := NewService(host)
|
|
result, err := service.Close(context.Background(), ClosureRequest{
|
|
Mode: "subscription",
|
|
ProbeAPIKey: "user-key",
|
|
GroupID: "group-1",
|
|
ExpectedModel: "deepseek-chat",
|
|
Subscriptions: []SubscriptionTarget{{UserID: "user-1", DurationDays: 30}},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("Close() error = %v", err)
|
|
}
|
|
if len(host.assigned) != 1 {
|
|
t.Fatalf("assigned subscriptions = %d, want 1", len(host.assigned))
|
|
}
|
|
if host.gatewayProbe.APIKey != "user-key" || host.gatewayProbe.ExpectedModel != "deepseek-chat" {
|
|
t.Fatalf("gateway probe = %+v, want api key + expected model", host.gatewayProbe)
|
|
}
|
|
if !result.OK || !result.HasExpectedModel {
|
|
t.Fatalf("gateway result = %+v, want success", result)
|
|
}
|
|
}
|
|
|
|
func TestServiceCloseReturnsSubscriptionErrorBeforeGatewayProbe(t *testing.T) {
|
|
host := &fakeClosureHost{assignErr: errors.New("assign failed")}
|
|
service := NewService(host)
|
|
_, err := service.Close(context.Background(), ClosureRequest{
|
|
Mode: "subscription",
|
|
ProbeAPIKey: "user-key",
|
|
GroupID: "group-1",
|
|
ExpectedModel: "deepseek-chat",
|
|
Subscriptions: []SubscriptionTarget{{UserID: "user-1", DurationDays: 30}},
|
|
})
|
|
if err == nil {
|
|
t.Fatal("Close() error = nil, want subscription failure")
|
|
}
|
|
if host.gatewayProbe.APIKey != "" {
|
|
t.Fatalf("gateway probe should not run after subscription error, got %+v", host.gatewayProbe)
|
|
}
|
|
}
|
|
|
|
type fakeClosureHost struct {
|
|
assigned []sub2api.AssignSubscriptionRequest
|
|
assignErr error
|
|
gatewayProbe sub2api.GatewayAccessCheckRequest
|
|
gatewayResult sub2api.GatewayAccessResult
|
|
gatewayErr error
|
|
}
|
|
|
|
func (f *fakeClosureHost) AssignSubscription(_ context.Context, req sub2api.AssignSubscriptionRequest) (sub2api.SubscriptionRef, error) {
|
|
if f.assignErr != nil {
|
|
return sub2api.SubscriptionRef{}, f.assignErr
|
|
}
|
|
f.assigned = append(f.assigned, req)
|
|
return sub2api.SubscriptionRef{ID: "sub-1"}, nil
|
|
}
|
|
|
|
func (f *fakeClosureHost) CheckGatewayAccess(_ context.Context, req sub2api.GatewayAccessCheckRequest) (sub2api.GatewayAccessResult, error) {
|
|
f.gatewayProbe = req
|
|
if f.gatewayErr != nil {
|
|
return sub2api.GatewayAccessResult{}, f.gatewayErr
|
|
}
|
|
return f.gatewayResult, nil
|
|
}
|