package tasks import ( "context" "database/sql" "testing" "vctp/db" "github.com/jmoiron/sqlx" _ "modernc.org/sqlite" ) func newTasksTestDB(t *testing.T) *sqlx.DB { t.Helper() dbConn, err := sqlx.Open("sqlite", ":memory:") if err != nil { t.Fatalf("failed to open sqlite test db: %v", err) } t.Cleanup(func() { _ = dbConn.Close() }) return dbConn } func TestBackfillSnapshotRowFromHourlyCache(t *testing.T) { ctx := context.Background() dbConn := newTasksTestDB(t) if err := db.EnsureVmHourlyStats(ctx, dbConn); err != nil { t.Fatalf("failed to ensure vm_hourly_stats: %v", err) } insertSQL := ` INSERT INTO vm_hourly_stats ( "SnapshotTime","Vcenter","VmId","VmUuid","Name","CreationTime","DeletionTime","ResourcePool", "Datacenter","Cluster","Folder","ProvisionedDisk","VcpuCount","RamGB","IsTemplate","PoweredOn","SrmPlaceholder" ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) ` if _, err := dbConn.ExecContext(ctx, insertSQL, int64(1000), "vc-a", "vm-1", "uuid-1", "demo-vm", int64(900), int64(0), "Tin", "dc-1", "cluster-1", "/Prod", 123.4, int64(4), int64(16), "FALSE", "TRUE", "FALSE", ); err != nil { t.Fatalf("failed to insert cache row: %v", err) } row := InventorySnapshotRow{ Vcenter: "vc-a", VmId: sql.NullString{String: "vm-1", Valid: true}, Name: "demo-vm", SnapshotTime: 2000, ResourcePool: sql.NullString{String: "Tin", Valid: true}, SrmPlaceholder: "", } if !needsSnapshotBackfill(row) { t.Fatal("expected sparse row to require backfill") } changed := backfillSnapshotRowFromHourlyCache(ctx, dbConn, &row) if !changed { t.Fatal("expected cache backfill to update the row") } if !row.CreationTime.Valid || row.CreationTime.Int64 != 900 { t.Fatalf("unexpected CreationTime after backfill: %#v", row.CreationTime) } if !row.Cluster.Valid || row.Cluster.String != "cluster-1" { t.Fatalf("unexpected Cluster after backfill: %#v", row.Cluster) } if !row.Datacenter.Valid || row.Datacenter.String != "dc-1" { t.Fatalf("unexpected Datacenter after backfill: %#v", row.Datacenter) } if !row.ProvisionedDisk.Valid || row.ProvisionedDisk.Float64 != 123.4 { t.Fatalf("unexpected ProvisionedDisk after backfill: %#v", row.ProvisionedDisk) } if !row.VcpuCount.Valid || row.VcpuCount.Int64 != 4 { t.Fatalf("unexpected VcpuCount after backfill: %#v", row.VcpuCount) } if !row.RamGB.Valid || row.RamGB.Int64 != 16 { t.Fatalf("unexpected RamGB after backfill: %#v", row.RamGB) } if row.SrmPlaceholder != "FALSE" { t.Fatalf("unexpected SrmPlaceholder after backfill: %q", row.SrmPlaceholder) } if !row.VmUuid.Valid || row.VmUuid.String != "uuid-1" { t.Fatalf("unexpected VmUuid after backfill: %#v", row.VmUuid) } } func TestBackfillSnapshotRowFromHourlyCacheNoMatch(t *testing.T) { ctx := context.Background() dbConn := newTasksTestDB(t) if err := db.EnsureVmHourlyStats(ctx, dbConn); err != nil { t.Fatalf("failed to ensure vm_hourly_stats: %v", err) } row := InventorySnapshotRow{ Vcenter: "vc-a", VmId: sql.NullString{String: "vm-missing", Valid: true}, } changed := backfillSnapshotRowFromHourlyCache(ctx, dbConn, &row) if changed { t.Fatal("expected no backfill change for missing VM") } }