Files
sub2api-cn-relay-manager/internal/store/sqlite/import_batches_repo_test.go
2026-05-23 10:55:57 +08:00

750 lines
28 KiB
Go

package sqlite
import (
"context"
"testing"
)
func TestImportBatchesRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
hostID := createTestHost(t, store)
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
id, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
if id <= 0 {
t.Fatalf("Create() id = %d, want positive", id)
}
got, _ := store.ImportBatches().GetByID(context.Background(), id)
if got.Mode != "partial" || got.BatchStatus != "running" {
t.Fatalf("GetByID() = %+v, want running batch", got)
}
}
func TestImportBatchesRepoUpdateStatus(t *testing.T) {
store := openTestDB(t)
hostID := createTestHost(t, store)
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
id, _ := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
})
err := store.ImportBatches().UpdateStatus(context.Background(), id, "succeeded", "subscription_ready")
if err != nil {
t.Fatalf("UpdateStatus() error = %v", err)
}
got, _ := store.ImportBatches().GetByID(context.Background(), id)
if got.BatchStatus != "succeeded" || got.AccessStatus != "subscription_ready" {
t.Fatalf("status = %+v, want succeeded/subscription_ready", got)
}
}
func TestImportBatchesRepoGetLatestByProviderID(t *testing.T) {
store := openTestDB(t)
hostID := createTestHost(t, store)
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
})
id2, _ := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
got, _ := store.ImportBatches().GetLatestByProviderID(context.Background(), providerID)
if got.ID != id2 {
t.Fatalf("latest id = %d, want %d", got.ID, id2)
}
}
func TestImportBatchesRepoListByProviderID(t *testing.T) {
store := openTestDB(t)
hostID := createTestHost(t, store)
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
olderID, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
})
if err != nil {
t.Fatalf("Create older batch error = %v", err)
}
newerID, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostID, PackID: packID, ProviderID: providerID,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create newer batch error = %v", err)
}
batches, err := store.ImportBatches().ListByProviderID(context.Background(), providerID)
if err != nil {
t.Fatalf("ListByProviderID() error = %v", err)
}
if len(batches) != 2 {
t.Fatalf("ListByProviderID() len = %d, want 2", len(batches))
}
if batches[0].ID != newerID || batches[1].ID != olderID {
t.Fatalf("ListByProviderID() ids = [%d %d], want [%d %d]", batches[0].ID, batches[1].ID, newerID, olderID)
}
}
func TestImportBatchesRepoGetLatestByProviderIDAndHostID(t *testing.T) {
store := openTestDB(t)
hostA := createTestHost(t, store)
hostB := createTestHostWithBaseURL(t, store, "host-b-"+sanitizeTestName(t.Name()), "https://host-b.example.com")
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
}); err != nil {
t.Fatalf("Create(hostA older) error = %v", err)
}
latestA, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packID, ProviderID: providerID,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create(hostA newer) error = %v", err)
}
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "partially_succeeded", AccessStatus: "degraded",
}); err != nil {
t.Fatalf("Create(hostB) error = %v", err)
}
got, err := store.ImportBatches().GetLatestByProviderIDAndHostID(context.Background(), providerID, hostA)
if err != nil {
t.Fatalf("GetLatestByProviderIDAndHostID() error = %v", err)
}
if got.ID != latestA {
t.Fatalf("GetLatestByProviderIDAndHostID() id = %d, want %d", got.ID, latestA)
}
}
func TestImportBatchesRepoListByProviderIDAndHostID(t *testing.T) {
store := openTestDB(t)
hostA := createTestHost(t, store)
hostB := createTestHostWithBaseURL(t, store, "host-b-"+sanitizeTestName(t.Name()), "https://host-b2.example.com")
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
olderA, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
})
if err != nil {
t.Fatalf("Create(hostA older) error = %v", err)
}
newerA, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packID, ProviderID: providerID,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create(hostA newer) error = %v", err)
}
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packID, ProviderID: providerID,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
}); err != nil {
t.Fatalf("Create(hostB) error = %v", err)
}
batches, err := store.ImportBatches().ListByProviderIDAndHostID(context.Background(), providerID, hostA)
if err != nil {
t.Fatalf("ListByProviderIDAndHostID() error = %v", err)
}
if len(batches) != 2 {
t.Fatalf("ListByProviderIDAndHostID() len = %d, want 2", len(batches))
}
if batches[0].ID != newerA || batches[1].ID != olderA {
t.Fatalf("ListByProviderIDAndHostID() ids = [%d %d], want [%d %d]", batches[0].ID, batches[1].ID, newerA, olderA)
}
}
func TestImportBatchesRepoListLatestReconcilable(t *testing.T) {
store := openTestDB(t)
hostA := createTestHost(t, store)
hostB := createTestHostWithBaseURL(t, store, "host-b-"+sanitizeTestName(t.Name()), "https://host-b3.example.com")
packAID := createTestPack(t, store)
packBID := createTestPackWithSuffix(t, store, "reconcile")
providerA := createTestProviderWithPack(t, store, packAID)
providerB := createTestProviderWithPack(t, store, packBID)
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packAID, ProviderID: providerA,
Mode: "partial", BatchStatus: "running", AccessStatus: "pending",
}); err != nil {
t.Fatalf("Create(providerA older) error = %v", err)
}
latestA, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packAID, ProviderID: providerA,
Mode: "strict", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create(providerA latest) error = %v", err)
}
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packBID, ProviderID: providerB,
Mode: "strict", BatchStatus: "partially_succeeded", AccessStatus: "degraded",
}); err != nil {
t.Fatalf("Create(providerB latest) error = %v", err)
}
if _, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packBID, ProviderID: providerB,
Mode: "strict", BatchStatus: "failed", AccessStatus: "broken",
}); err != nil {
t.Fatalf("Create(providerB newer failed) error = %v", err)
}
batches, err := store.ImportBatches().ListLatestReconcilable(context.Background())
if err != nil {
t.Fatalf("ListLatestReconcilable() error = %v", err)
}
if len(batches) != 1 {
t.Fatalf("ListLatestReconcilable() len = %d, want 1 because providerB latest batch is not reconcilable", len(batches))
}
if batches[0].ID != latestA {
t.Fatalf("ListLatestReconcilable() id = %d, want %d", batches[0].ID, latestA)
}
batchID, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packBID, ProviderID: providerB,
Mode: "strict", BatchStatus: "partially_succeeded", AccessStatus: "degraded",
})
if err != nil {
t.Fatalf("Create(providerB new reconcilable) error = %v", err)
}
batches, err = store.ImportBatches().ListLatestReconcilable(context.Background())
if err != nil {
t.Fatalf("ListLatestReconcilable() second call error = %v", err)
}
if len(batches) != 2 {
t.Fatalf("ListLatestReconcilable() second len = %d, want 2", len(batches))
}
if batches[0].ID != batchID || batches[1].ID != latestA {
t.Fatalf("ListLatestReconcilable() ids = [%d %d], want [%d %d]", batches[0].ID, batches[1].ID, batchID, latestA)
}
}
func TestImportBatchesRepoGetByIDNotFound(t *testing.T) {
store := openTestDB(t)
_, err := store.ImportBatches().GetByID(context.Background(), 999)
if err == nil {
t.Fatal("GetByID(999) error = nil, want error")
}
}
func TestImportBatchesRepoCreateValidationErrors(t *testing.T) {
store := openTestDB(t)
for _, tt := range []struct {
name string
batch ImportBatch
}{
{"host_id zero", ImportBatch{HostID: 0, PackID: 1, ProviderID: 1, Mode: "m", BatchStatus: "s", AccessStatus: "s"}},
{"pack_id zero", ImportBatch{HostID: 1, PackID: 0, ProviderID: 1, Mode: "m", BatchStatus: "s", AccessStatus: "s"}},
{"provider_id zero", ImportBatch{HostID: 1, PackID: 1, ProviderID: 0, Mode: "m", BatchStatus: "s", AccessStatus: "s"}},
{"empty mode", ImportBatch{HostID: 1, PackID: 1, ProviderID: 1, Mode: "", BatchStatus: "s", AccessStatus: "s"}},
{"empty batch_status", ImportBatch{HostID: 1, PackID: 1, ProviderID: 1, Mode: "m", BatchStatus: "", AccessStatus: "s"}},
{"empty access_status", ImportBatch{HostID: 1, PackID: 1, ProviderID: 1, Mode: "m", BatchStatus: "s", AccessStatus: ""}},
} {
t.Run(tt.name, func(t *testing.T) {
_, err := store.ImportBatches().Create(context.Background(), tt.batch)
if err == nil {
t.Fatal("Create() error = nil")
}
})
}
}
func TestImportBatchesRepoUpdateStatusValidation(t *testing.T) {
store := openTestDB(t)
if err := store.ImportBatches().UpdateStatus(context.Background(), 0, "s", "s"); err == nil {
t.Fatal("UpdateStatus id=0 error = nil")
}
if err := store.ImportBatches().UpdateStatus(context.Background(), 1, "", "s"); err == nil {
t.Fatal("UpdateStatus empty batch_status error = nil")
}
}
// --- ImportBatchItems Repo Tests ---
func TestImportBatchItemsRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
id, err := store.ImportBatchItems().Create(context.Background(), ImportBatchItem{
BatchID: batchID,
KeyFingerprint: "sha256:abc",
AccountStatus: "passed",
ProbeSummaryJSON: `{"ok":true}`,
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
if id <= 0 {
t.Fatalf("Create() id = %d, want positive", id)
}
items, _ := store.ImportBatchItems().GetByBatchID(context.Background(), batchID)
if len(items) != 1 || items[0].AccountStatus != "passed" {
t.Fatalf("items = %+v, want 1 with passed status", items)
}
}
func TestImportBatchItemsRepoMultipleItems(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
for _, status := range []string{"passed", "failed"} {
store.ImportBatchItems().Create(context.Background(), ImportBatchItem{
BatchID: batchID, KeyFingerprint: "sha256:" + status, AccountStatus: status,
})
}
items, _ := store.ImportBatchItems().GetByBatchID(context.Background(), batchID)
if len(items) != 2 {
t.Fatalf("count = %d, want 2", len(items))
}
}
func TestImportBatchItemsRepoUpdateResult(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
itemID, _ := store.ImportBatchItems().Create(context.Background(), ImportBatchItem{
BatchID: batchID, KeyFingerprint: "sha256:x", AccountStatus: "pending",
})
store.ImportBatchItems().UpdateResult(context.Background(), itemID, "passed", `{"ok":true}`)
items, _ := store.ImportBatchItems().GetByBatchID(context.Background(), batchID)
if items[0].AccountStatus != "passed" {
t.Fatalf("AccountStatus = %q, want passed", items[0].AccountStatus)
}
}
func TestImportBatchItemsRepoGetByBatchIDEmpty(t *testing.T) {
store := openTestDB(t)
items, err := store.ImportBatchItems().GetByBatchID(context.Background(), 999)
if err != nil {
t.Fatalf("GetByBatchID() error = %v, want empty result", err)
}
if len(items) != 0 {
t.Fatalf("count = %d, want 0", len(items))
}
}
func TestImportBatchItemsRepoValidation(t *testing.T) {
store := openTestDB(t)
_, err := store.ImportBatchItems().Create(context.Background(), ImportBatchItem{
BatchID: 0, KeyFingerprint: "k", AccountStatus: "s",
})
if err == nil {
t.Fatal("Create batch_id=0 error = nil")
}
}
// --- Managed Resources Repo Tests ---
func TestManagedResourcesRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
batch, _ := store.ImportBatches().GetByID(context.Background(), batchID)
id, err := store.ManagedResources().Create(context.Background(), ManagedResource{
BatchID: batchID, HostID: batch.HostID, ResourceType: "group", HostResourceID: "g_01", ResourceName: "test-group",
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
resources, _ := store.ManagedResources().GetByBatchID(context.Background(), batchID)
if len(resources) != 1 || resources[0].HostResourceID != "g_01" {
t.Fatalf("resources = %+v, want 1 with g_01", resources)
}
_ = id
}
func TestManagedResourcesRepoMultipleResources(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
batch, _ := store.ImportBatches().GetByID(context.Background(), batchID)
for _, r := range []ManagedResource{
{BatchID: batchID, HostID: batch.HostID, ResourceType: "group", HostResourceID: "g_01", ResourceName: "group-1"},
{BatchID: batchID, HostID: batch.HostID, ResourceType: "channel", HostResourceID: "c_01", ResourceName: "channel-1"},
{BatchID: batchID, HostID: batch.HostID, ResourceType: "account", HostResourceID: "a_01", ResourceName: "account-1"},
} {
store.ManagedResources().Create(context.Background(), r)
}
resources, _ := store.ManagedResources().GetByBatchID(context.Background(), batchID)
if len(resources) != 3 {
t.Fatalf("count = %d, want 3", len(resources))
}
}
func TestManagedResourcesRepoGetByBatchIDEmpty(t *testing.T) {
store := openTestDB(t)
resources, _ := store.ManagedResources().GetByBatchID(context.Background(), 999)
if len(resources) != 0 {
t.Fatalf("count = %d, want 0", len(resources))
}
}
func TestManagedResourcesRepoGetByResourceIdentity(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
batch, err := store.ImportBatches().GetByID(context.Background(), batchID)
if err != nil {
t.Fatalf("GetByID() error = %v", err)
}
if _, err := store.ManagedResources().Create(context.Background(), ManagedResource{
BatchID: batchID, HostID: batch.HostID, ResourceType: "channel", HostResourceID: "channel-1", ResourceName: "Channel 1",
}); err != nil {
t.Fatalf("Create() error = %v", err)
}
resource, err := store.ManagedResources().GetByResourceIdentity(context.Background(), batch.HostID, "channel", "channel-1")
if err != nil {
t.Fatalf("GetByResourceIdentity() error = %v", err)
}
if resource.ResourceName != "Channel 1" {
t.Fatalf("GetByResourceIdentity() resource_name = %q, want Channel 1", resource.ResourceName)
}
}
func TestManagedResourcesRepoListByProviderScopes(t *testing.T) {
store := openTestDB(t)
hostA := createTestHost(t, store)
hostB := createTestHostWithBaseURL(t, store, "host-b-"+sanitizeTestName(t.Name()), "https://managed-host-b.example.com")
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
otherProviderID := createTestProviderWithPack(t, store, createTestPackWithSuffix(t, store, "managed"))
batchA, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostA, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create(batchA) error = %v", err)
}
batchB, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packID, ProviderID: providerID,
Mode: "partial", BatchStatus: "partially_succeeded", AccessStatus: "degraded",
})
if err != nil {
t.Fatalf("Create(batchB) error = %v", err)
}
otherBatch, err := store.ImportBatches().Create(context.Background(), ImportBatch{
HostID: hostB, PackID: packID, ProviderID: otherProviderID,
Mode: "partial", BatchStatus: "succeeded", AccessStatus: "subscription_ready",
})
if err != nil {
t.Fatalf("Create(otherBatch) error = %v", err)
}
for _, resource := range []ManagedResource{
{BatchID: batchA, HostID: hostA, ResourceType: "group", HostResourceID: "g-a", ResourceName: "Group A"},
{BatchID: batchB, HostID: hostB, ResourceType: "account", HostResourceID: "a-b", ResourceName: "Account B"},
{BatchID: otherBatch, HostID: hostB, ResourceType: "channel", HostResourceID: "c-other", ResourceName: "Other"},
} {
if _, err := store.ManagedResources().Create(context.Background(), resource); err != nil {
t.Fatalf("Create(%s) error = %v", resource.HostResourceID, err)
}
}
byProvider, err := store.ManagedResources().ListByProviderID(context.Background(), providerID)
if err != nil {
t.Fatalf("ListByProviderID() error = %v", err)
}
if len(byProvider) != 2 {
t.Fatalf("ListByProviderID() len = %d, want 2", len(byProvider))
}
byProviderHost, err := store.ManagedResources().ListByProviderIDAndHostID(context.Background(), providerID, hostB)
if err != nil {
t.Fatalf("ListByProviderIDAndHostID() error = %v", err)
}
if len(byProviderHost) != 1 {
t.Fatalf("ListByProviderIDAndHostID() len = %d, want 1", len(byProviderHost))
}
if byProviderHost[0].HostResourceID != "a-b" {
t.Fatalf("ListByProviderIDAndHostID() resource = %q, want a-b", byProviderHost[0].HostResourceID)
}
}
func TestManagedResourcesRepoQueryValidationErrors(t *testing.T) {
store := openTestDB(t)
if _, err := store.ManagedResources().GetByResourceIdentity(context.Background(), 0, "group", "g-1"); err == nil {
t.Fatal("GetByResourceIdentity() host_id=0 error = nil")
}
if _, err := store.ManagedResources().ListByProviderID(context.Background(), 0); err == nil {
t.Fatal("ListByProviderID() provider_id=0 error = nil")
}
if _, err := store.ManagedResources().ListByProviderIDAndHostID(context.Background(), 1, 0); err == nil {
t.Fatal("ListByProviderIDAndHostID() host_id=0 error = nil")
}
}
func TestManagedResourcesRepoValidationErrors(t *testing.T) {
store := openTestDB(t)
for _, tt := range []struct {
name string
r ManagedResource
}{
{"batch_id zero", ManagedResource{HostID: 1, ResourceType: "g", HostResourceID: "h", ResourceName: "n"}},
{"host_id zero", ManagedResource{BatchID: 1, ResourceType: "g", HostResourceID: "h", ResourceName: "n"}},
{"empty resource_type", ManagedResource{BatchID: 1, HostID: 1, HostResourceID: "h", ResourceName: "n"}},
{"empty host_resource_id", ManagedResource{BatchID: 1, HostID: 1, ResourceType: "g", ResourceName: "n"}},
{"empty resource_name", ManagedResource{BatchID: 1, HostID: 1, ResourceType: "g", HostResourceID: "h"}},
} {
t.Run(tt.name, func(t *testing.T) {
_, err := store.ManagedResources().Create(context.Background(), tt.r)
if err == nil {
t.Fatal("Create() error = nil")
}
})
}
}
// --- Probe Results Repo Tests ---
func TestProbeResultsRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
itemID := createTestBatchItem(t, store, batchID)
id, err := store.ProbeResults().Create(context.Background(), ProbeResult{
BatchItemID: itemID, ProbeType: "account_smoke", Status: "passed", SummaryJSON: `{"ok":true}`,
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
results, _ := store.ProbeResults().GetByBatchItemID(context.Background(), itemID)
if len(results) != 1 || results[0].ProbeType != "account_smoke" {
t.Fatalf("results = %+v, want 1 with account_smoke", results)
}
_ = id
}
func TestProbeResultsRepoMultipleResults(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
itemID := createTestBatchItem(t, store, batchID)
for _, p := range []ProbeResult{
{BatchItemID: itemID, ProbeType: "account_smoke", Status: "passed", SummaryJSON: `{"ok":true}`},
{BatchItemID: itemID, ProbeType: "model_list", Status: "passed", SummaryJSON: `{"models":["m1"]}`},
} {
store.ProbeResults().Create(context.Background(), p)
}
results, _ := store.ProbeResults().GetByBatchItemID(context.Background(), itemID)
if len(results) != 2 {
t.Fatalf("count = %d, want 2", len(results))
}
}
func TestProbeResultsRepoGetByBatchItemIDEmpty(t *testing.T) {
store := openTestDB(t)
results, _ := store.ProbeResults().GetByBatchItemID(context.Background(), 999)
if len(results) != 0 {
t.Fatalf("count = %d, want 0", len(results))
}
}
func TestProbeResultsRepoValidationErrors(t *testing.T) {
store := openTestDB(t)
for _, tt := range []struct {
name string
probe ProbeResult
}{
{"batch_item_id zero", ProbeResult{ProbeType: "t", Status: "s"}},
{"empty probe_type", ProbeResult{BatchItemID: 1, Status: "s"}},
{"empty status", ProbeResult{BatchItemID: 1, ProbeType: "t"}},
} {
t.Run(tt.name, func(t *testing.T) {
_, err := store.ProbeResults().Create(context.Background(), tt.probe)
if err == nil {
t.Fatal("Create() error = nil")
}
})
}
}
// --- Access Closures Repo Tests ---
func TestAccessClosureRecordsRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
id, err := store.AccessClosures().Create(context.Background(), AccessClosureRecord{
BatchID: batchID, ClosureType: "subscription", Status: "subscription_ready", DetailsJSON: `{"status_code":200}`,
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
records, _ := store.AccessClosures().GetByBatchID(context.Background(), batchID)
if len(records) != 1 || records[0].ClosureType != "subscription" {
t.Fatalf("records = %+v, want 1 subscription", records)
}
_ = id
}
func TestAccessClosureRecordsRepoMultiple(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
store.AccessClosures().Create(context.Background(), AccessClosureRecord{BatchID: batchID, ClosureType: "subscription", Status: "subscription_ready", DetailsJSON: "{}"})
store.AccessClosures().Create(context.Background(), AccessClosureRecord{BatchID: batchID, ClosureType: "self_service", Status: "self_service_ready", DetailsJSON: "{}"})
records, _ := store.AccessClosures().GetByBatchID(context.Background(), batchID)
if len(records) != 2 {
t.Fatalf("count = %d, want 2", len(records))
}
}
func TestAccessClosureRecordsRepoGetByBatchIDEmpty(t *testing.T) {
store := openTestDB(t)
records, _ := store.AccessClosures().GetByBatchID(context.Background(), 999)
if len(records) != 0 {
t.Fatalf("count = %d, want 0", len(records))
}
}
func TestAccessClosureRecordsRepoValidation(t *testing.T) {
store := openTestDB(t)
_, err := store.AccessClosures().Create(context.Background(), AccessClosureRecord{BatchID: 0, ClosureType: "t", Status: "s"})
if err == nil {
t.Fatal("Create batch_id=0 error = nil")
}
}
// --- Reconcile Runs Repo Tests ---
func createTestProviderWithPack(t *testing.T, store *DB, packID int64) int64 {
t.Helper()
id, err := store.Providers().Create(context.Background(), Provider{
PackID: packID, ProviderID: "test-provider-" + sanitizeTestName(t.Name()), DisplayName: "TP",
BaseURL: "https://tp.com", Platform: "openai",
})
if err != nil {
t.Fatalf("createTestProviderWithPack error = %v", err)
}
return id
}
func createTestProvider(t *testing.T, store *DB) int64 {
t.Helper()
packID := createTestPack(t, store)
return createTestProviderWithPack(t, store, packID)
}
func TestReconcileRunsRepoCreateAndGet(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
batch, err := store.ImportBatches().GetByID(context.Background(), batchID)
if err != nil {
t.Fatalf("ImportBatches().GetByID() error = %v", err)
}
id, err := store.ReconcileRuns().Create(context.Background(), ReconcileRun{
BatchID: batchID, HostID: batch.HostID, ProviderID: batch.ProviderID, Status: "active", SummaryJSON: `{"drifted":false}`,
})
if err != nil {
t.Fatalf("Create() error = %v", err)
}
runs, _ := store.ReconcileRuns().GetByBatchID(context.Background(), batchID)
if len(runs) != 1 || runs[0].Status != "active" {
t.Fatalf("runs = %+v, want 1 active", runs)
}
_ = id
}
func TestReconcileRunsRepoMultipleRunsOrderedDesc(t *testing.T) {
store := openTestDB(t)
batchID := createTestBatch(t, store)
batch, err := store.ImportBatches().GetByID(context.Background(), batchID)
if err != nil {
t.Fatalf("ImportBatches().GetByID() error = %v", err)
}
id1, _ := store.ReconcileRuns().Create(context.Background(), ReconcileRun{BatchID: batchID, HostID: batch.HostID, ProviderID: batch.ProviderID, Status: "first", SummaryJSON: "{}"})
id2, _ := store.ReconcileRuns().Create(context.Background(), ReconcileRun{BatchID: batchID, HostID: batch.HostID, ProviderID: batch.ProviderID, Status: "second", SummaryJSON: "{}"})
runs, _ := store.ReconcileRuns().GetByBatchID(context.Background(), batchID)
if len(runs) != 2 || runs[0].ID != id2 || runs[1].ID != id1 {
t.Fatalf("order: got %d, %d; want %d, %d (DESC)", runs[0].ID, runs[1].ID, id2, id1)
}
}
func TestReconcileRunsRepoSeparatesHosts(t *testing.T) {
store := openTestDB(t)
hostA := createTestHost(t, store)
hostB := createTestHostWithBaseURL(t, store, "host-b", "https://host-b.example.com")
packID := createTestPack(t, store)
providerID := createTestProviderWithPack(t, store, packID)
batchA, err := store.ImportBatches().Create(context.Background(), ImportBatch{HostID: hostA, PackID: packID, ProviderID: providerID, Mode: "partial", BatchStatus: "running", AccessStatus: "pending"})
if err != nil {
t.Fatalf("ImportBatches().Create(hostA) error = %v", err)
}
batchB, err := store.ImportBatches().Create(context.Background(), ImportBatch{HostID: hostB, PackID: packID, ProviderID: providerID, Mode: "partial", BatchStatus: "running", AccessStatus: "pending"})
if err != nil {
t.Fatalf("ImportBatches().Create(hostB) error = %v", err)
}
if _, err := store.ReconcileRuns().Create(context.Background(), ReconcileRun{BatchID: batchA, HostID: hostA, ProviderID: providerID, Status: "drifted", SummaryJSON: `{"host":"a"}`}); err != nil {
t.Fatalf("Create(hostA) error = %v", err)
}
if _, err := store.ReconcileRuns().Create(context.Background(), ReconcileRun{BatchID: batchB, HostID: hostB, ProviderID: providerID, Status: "active", SummaryJSON: `{"host":"b"}`}); err != nil {
t.Fatalf("Create(hostB) error = %v", err)
}
runs, _ := store.ReconcileRuns().GetByProviderIDAndHostID(context.Background(), providerID, hostA)
if len(runs) != 1 {
t.Fatalf("len(runs) = %d, want 1", len(runs))
}
if runs[0].Status != "drifted" {
t.Fatalf("runs[0].Status = %q, want drifted", runs[0].Status)
}
}
func TestReconcileRunsRepoGetByProviderIDAndHostIDEmpty(t *testing.T) {
store := openTestDB(t)
runs, _ := store.ReconcileRuns().GetByProviderIDAndHostID(context.Background(), 999, 1)
if len(runs) != 0 {
t.Fatalf("count = %d, want 0", len(runs))
}
}
func TestReconcileRunsRepoGetByBatchIDEmpty(t *testing.T) {
store := openTestDB(t)
runs, _ := store.ReconcileRuns().GetByBatchID(context.Background(), 999)
if len(runs) != 0 {
t.Fatalf("count = %d, want 0", len(runs))
}
}
func TestReconcileRunsRepoValidation(t *testing.T) {
store := openTestDB(t)
hostID := createTestHost(t, store)
_, err := store.ReconcileRuns().Create(context.Background(), ReconcileRun{BatchID: 1, HostID: hostID, ProviderID: 0, Status: "s"})
if err == nil {
t.Fatal("Create provider_id=0 error = nil")
}
}