Expand coverage for runtime and sqlite paths
This commit is contained in:
@@ -8,6 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"sub2api-cn-relay-manager/internal/host/sub2api"
|
||||
"sub2api-cn-relay-manager/internal/pack"
|
||||
"sub2api-cn-relay-manager/internal/store/sqlite"
|
||||
)
|
||||
|
||||
@@ -382,6 +383,127 @@ func TestStoredResourcesForReconcileMergesCurrentBatchAndSharedScaffoldingOnly(t
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileValidatesTopLevelRequest(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
req := Request{}
|
||||
if _, err := NewService(nil, &reconcileHostStub{}).Reconcile(context.Background(), req); err == nil || err.Error() != "store is required" {
|
||||
t.Fatalf("Reconcile(nil store) error = %v, want store is required", err)
|
||||
}
|
||||
|
||||
store := openReconcileTestStore(t)
|
||||
defer closeReconcileTestStore(t, store)
|
||||
|
||||
if _, err := NewService(store, nil).Reconcile(context.Background(), req); err == nil || err.Error() != "host adapter is required" {
|
||||
t.Fatalf("Reconcile(nil host) error = %v, want host adapter is required", err)
|
||||
}
|
||||
if _, err := NewService(store, &reconcileHostStub{}).Reconcile(context.Background(), req); err == nil || err.Error() != "host_id is required" {
|
||||
t.Fatalf("Reconcile(missing host_id) error = %v, want host_id is required", err)
|
||||
}
|
||||
if _, err := NewService(store, &reconcileHostStub{}).Reconcile(context.Background(), Request{HostID: "host-1"}); err == nil || err.Error() != "host_base_url is required" {
|
||||
t.Fatalf("Reconcile(missing host_base_url) error = %v, want host_base_url is required", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcileRejectsNonReconcilableLatestBatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
store := openReconcileTestStore(t)
|
||||
defer closeReconcileTestStore(t, store)
|
||||
|
||||
fixture := seedReconcileFixture(t, store)
|
||||
mustExecReconcileSQL(t, store, `UPDATE import_batches SET batch_status = 'failed' WHERE id = ?`, fixture.batchID)
|
||||
|
||||
_, err := NewService(store, &reconcileHostStub{}).Reconcile(context.Background(), Request{
|
||||
HostID: "host-1",
|
||||
HostBaseURL: "https://sub2api.example.com",
|
||||
AccessProbeAPIKey: "user-key",
|
||||
Pack: pack.LoadedPack{
|
||||
Manifest: pack.Manifest{PackID: "openai-cn-pack", Version: "1.0.0", TargetHost: "sub2api"},
|
||||
},
|
||||
Provider: pack.ProviderManifest{
|
||||
ProviderID: "deepseek",
|
||||
SmokeTestModel: "deepseek-chat",
|
||||
},
|
||||
})
|
||||
if err == nil || err.Error() != "latest import batch is failed; run import again before reconcile" {
|
||||
t.Fatalf("Reconcile() error = %v, want non-reconcilable batch error", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReconcilePersistsActiveRunForHealthySnapshot(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
store := openReconcileTestStore(t)
|
||||
defer closeReconcileTestStore(t, store)
|
||||
|
||||
fixture := seedReconcileFixture(t, store)
|
||||
mustCreateImportBatchItem(t, store, fixture.batchID, "fp-1", `{"account_id":"account-1"}`)
|
||||
mustCreateManagedResource(t, store, fixture.batchID, fixture.hostPK, "group", "group-1", "group one")
|
||||
mustCreateManagedResource(t, store, fixture.batchID, fixture.hostPK, "account", "account-1", "account one")
|
||||
mustCreateAndLoadAccessClosures(t, store, fixture.batchID, sqlite.AccessClosureRecord{
|
||||
BatchID: fixture.batchID,
|
||||
ClosureType: accessModeSelfService,
|
||||
Status: accessStatusSelfServiceReady,
|
||||
})
|
||||
|
||||
host := &reconcileHostStub{
|
||||
testResults: map[string]sub2api.ProbeResult{
|
||||
"account-1": {OK: true, Status: accountStatusPassed, Message: "ok"},
|
||||
},
|
||||
models: map[string][]sub2api.AccountModel{
|
||||
"account-1": {{ID: "deepseek-chat"}},
|
||||
},
|
||||
gatewayResult: sub2api.GatewayAccessResult{
|
||||
OK: true,
|
||||
StatusCode: 200,
|
||||
HasExpectedModel: true,
|
||||
CompletionOK: true,
|
||||
Models: []string{"deepseek-chat"},
|
||||
},
|
||||
completionResults: []sub2api.GatewayCompletionResult{
|
||||
{OK: true, StatusCode: 200},
|
||||
},
|
||||
managedResourceSnapshot: sub2api.ManagedResourceSnapshot{
|
||||
Groups: []sub2api.NamedResource{{ID: "group-1", Name: "group one"}},
|
||||
Accounts: []sub2api.NamedResource{{ID: "account-1", Name: "account one"}},
|
||||
},
|
||||
}
|
||||
|
||||
result, err := NewService(store, host).Reconcile(context.Background(), Request{
|
||||
HostID: "host-1",
|
||||
HostBaseURL: "https://sub2api.example.com",
|
||||
AccessProbeAPIKey: "user-key",
|
||||
Pack: pack.LoadedPack{
|
||||
Manifest: pack.Manifest{PackID: "openai-cn-pack", Version: "1.0.0", TargetHost: "sub2api"},
|
||||
},
|
||||
Provider: pack.ProviderManifest{
|
||||
ProviderID: "deepseek",
|
||||
SmokeTestModel: "deepseek-chat",
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Reconcile() error = %v", err)
|
||||
}
|
||||
if result.Status != "active" {
|
||||
t.Fatalf("result.Status = %q, want active", result.Status)
|
||||
}
|
||||
if result.MissingCount != 0 || result.ExtraCount != 0 || result.ProbeFailureCount != 0 {
|
||||
t.Fatalf("result = %+v, want no drift and no probe failures", result)
|
||||
}
|
||||
if result.AccessStatus != accessStatusSelfServiceReady {
|
||||
t.Fatalf("result.AccessStatus = %q, want %q", result.AccessStatus, accessStatusSelfServiceReady)
|
||||
}
|
||||
|
||||
runs, err := store.ReconcileRuns().GetByBatchID(context.Background(), fixture.batchID)
|
||||
if err != nil {
|
||||
t.Fatalf("ReconcileRuns().GetByBatchID() error = %v", err)
|
||||
}
|
||||
if len(runs) != 1 || runs[0].Status != "active" {
|
||||
t.Fatalf("persisted reconcile runs = %+v, want single active run", runs)
|
||||
}
|
||||
}
|
||||
|
||||
type reconcileFixture struct {
|
||||
hostPK int64
|
||||
packPK int64
|
||||
@@ -512,6 +634,13 @@ func mustCreateAndLoadAccessClosures(t *testing.T, store *sqlite.DB, batchID int
|
||||
return loaded
|
||||
}
|
||||
|
||||
func mustExecReconcileSQL(t *testing.T, store *sqlite.DB, query string, args ...any) {
|
||||
t.Helper()
|
||||
if _, err := store.SQLDB().Exec(query, args...); err != nil {
|
||||
t.Fatalf("Exec(%q) error = %v", query, err)
|
||||
}
|
||||
}
|
||||
|
||||
type reconcileHostStub struct {
|
||||
disableResponsesErr error
|
||||
gatewayErr error
|
||||
@@ -525,6 +654,8 @@ type reconcileHostStub struct {
|
||||
completionCalls int
|
||||
disableResponsesCalls int
|
||||
disabledResponsesAccounts []string
|
||||
managedResourceSnapshot sub2api.ManagedResourceSnapshot
|
||||
listManagedResourcesErr error
|
||||
}
|
||||
|
||||
func (h *reconcileHostStub) GetHostVersion(context.Context) (string, error) {
|
||||
@@ -632,5 +763,8 @@ func (h *reconcileHostStub) DisableOpenAIResponsesAPI(_ context.Context, account
|
||||
}
|
||||
|
||||
func (h *reconcileHostStub) ListManagedResources(context.Context, sub2api.ListManagedResourcesRequest) (sub2api.ManagedResourceSnapshot, error) {
|
||||
return sub2api.ManagedResourceSnapshot{}, nil
|
||||
if h.listManagedResourcesErr != nil {
|
||||
return sub2api.ManagedResourceSnapshot{}, h.listManagedResourcesErr
|
||||
}
|
||||
return h.managedResourceSnapshot, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user