Files
vctp2/internal/tasks/compatibility_integration_test.go
T
nathan 916b0b5054
continuous-integration/drone/push Build is passing
more tests
2026-04-20 18:38:12 +10:00

213 lines
7.7 KiB
Go

package tasks
import (
"context"
"os"
"path/filepath"
"testing"
"time"
"vctp/db"
"vctp/internal/settings"
)
func TestSnapshotTableCompatModeSettingControlsTaskBehaviorFlag(t *testing.T) {
task := &CronTask{}
if !task.snapshotTableCompatModeEnabled() {
t.Fatal("expected default snapshot_table_compat_mode=true when settings are absent")
}
task.Settings = &settings.Settings{Values: &settings.SettingsYML{}}
if !task.snapshotTableCompatModeEnabled() {
t.Fatal("expected default snapshot_table_compat_mode=true when value is unset")
}
disabled := false
task.Settings.Values.Settings.SnapshotTableCompatMode = &disabled
if task.snapshotTableCompatModeEnabled() {
t.Fatal("expected snapshot_table_compat_mode=false to disable legacy snapshot-table writes")
}
enabled := true
task.Settings.Values.Settings.SnapshotTableCompatMode = &enabled
if !task.snapshotTableCompatModeEnabled() {
t.Fatal("expected snapshot_table_compat_mode=true to enable legacy snapshot-table writes")
}
}
func TestManualDailyAggregate_SQLFallback_LegacyTablesAndReport(t *testing.T) {
ctx := context.Background()
dbConn := newTasksTestDB(t)
task := newTasksTestCronTaskForAggregateFlow(t, dbConn)
t.Setenv("DAILY_AGG_SQL", "1")
t.Setenv("DAILY_AGG_GO", "")
dayStart := time.Date(2026, time.March, 15, 0, 0, 0, 0, time.UTC)
t1 := dayStart.Add(1 * time.Hour).Unix()
t2 := dayStart.Add(2 * time.Hour).Unix()
table1, err := hourlyInventoryTableName(time.Unix(t1, 0).UTC())
if err != nil {
t.Fatalf("failed to build first hourly table name: %v", err)
}
table2, err := hourlyInventoryTableName(time.Unix(t2, 0).UTC())
if err != nil {
t.Fatalf("failed to build second hourly table name: %v", err)
}
for _, table := range []string{table1, table2} {
if err := db.EnsureSnapshotTable(ctx, dbConn, table); err != nil {
t.Fatalf("failed to ensure hourly snapshot table %s: %v", table, err)
}
}
seeds := []hourlySeedRow{
{SnapshotTime: t1, Name: "vm-a", Vcenter: "vc-a", VmID: "vm-a", VmUUID: "uuid-a", ResourcePool: "Tin", Datacenter: "dc-a", Cluster: "cluster-a", Folder: "/prod", ProvisionedDisk: 100, VcpuCount: 2, RamGB: 8, CreationTime: dayStart.Add(-24 * time.Hour).Unix(), IsTemplate: "FALSE", PoweredOn: "TRUE", SrmPlaceholder: "FALSE"},
{SnapshotTime: t2, Name: "vm-a", Vcenter: "vc-a", VmID: "vm-a", VmUUID: "uuid-a", ResourcePool: "Gold", Datacenter: "dc-a", Cluster: "cluster-a", Folder: "/prod", ProvisionedDisk: 120, VcpuCount: 4, RamGB: 8, CreationTime: dayStart.Add(-24 * time.Hour).Unix(), IsTemplate: "FALSE", PoweredOn: "TRUE", SrmPlaceholder: "FALSE"},
{SnapshotTime: t2, Name: "vm-b", Vcenter: "vc-a", VmID: "vm-b", VmUUID: "uuid-b", ResourcePool: "Bronze", Datacenter: "dc-a", Cluster: "cluster-a", Folder: "/prod", ProvisionedDisk: 40, VcpuCount: 1, RamGB: 4, CreationTime: dayStart.Add(-48 * time.Hour).Unix(), IsTemplate: "FALSE", PoweredOn: "TRUE", SrmPlaceholder: "FALSE"},
}
for _, row := range seeds {
table, tableErr := hourlyInventoryTableName(time.Unix(row.SnapshotTime, 0).UTC())
if tableErr != nil {
t.Fatalf("failed to build hourly table for seed row: %v", tableErr)
}
if err := insertHourlySnapshotSeedRow(ctx, dbConn, table, row); err != nil {
t.Fatalf("failed to insert hourly snapshot seed row: %v", err)
}
}
if err := task.aggregateDailySummaryWithMode(ctx, dayStart, true, false); err != nil {
t.Fatalf("aggregateDailySummaryWithMode (legacy SQL fallback) failed: %v", err)
}
summaryTable, err := dailySummaryTableName(dayStart)
if err != nil {
t.Fatalf("failed to build daily summary table name: %v", err)
}
rows, err := loadDailySummaryRows(ctx, dbConn, summaryTable)
if err != nil {
t.Fatalf("failed to load daily summary rows: %v", err)
}
if len(rows) != 2 {
t.Fatalf("unexpected daily summary row count: got %d want %d", len(rows), 2)
}
assertSnapshotRegistryRow(t, ctx, dbConn, "daily", summaryTable, dayStart.Unix(), int64(len(rows)))
assertSummaryCacheMatchesByVcenter(t, ctx, dbConn, summaryTable, "daily", dayStart.Unix())
reportPath := filepath.Join(task.Settings.Values.Settings.ReportsDir, summaryTable+".xlsx")
if _, err := os.Stat(reportPath); err != nil {
t.Fatalf("expected daily report file at %s: %v", reportPath, err)
}
}
func TestManualMonthlyAggregate_SQLFallback_LegacyTablesAndReport(t *testing.T) {
ctx := context.Background()
dbConn := newTasksTestDB(t)
task := newTasksTestCronTaskForAggregateFlow(t, dbConn)
t.Setenv("MONTHLY_AGG_SQL", "1")
t.Setenv("MONTHLY_AGG_GO", "")
monthStart := time.Date(2026, time.April, 1, 0, 0, 0, 0, time.UTC)
day1 := monthStart.AddDate(0, 0, 2)
day2 := monthStart.AddDate(0, 0, 3)
day1Table, err := dailySummaryTableName(day1)
if err != nil {
t.Fatalf("failed to build day1 summary table name: %v", err)
}
day2Table, err := dailySummaryTableName(day2)
if err != nil {
t.Fatalf("failed to build day2 summary table name: %v", err)
}
for _, table := range []string{day1Table, day2Table} {
if err := db.EnsureSummaryTable(ctx, dbConn, table); err != nil {
t.Fatalf("failed to ensure daily summary table %s: %v", table, err)
}
}
seeds := []dailySeedRow{
{
SnapshotTime: day1.Unix(),
Name: "vm-a",
Vcenter: "vc-a",
VmID: "vm-a",
VmUUID: "uuid-a",
ResourcePool: "Bronze",
Datacenter: "dc-a",
Cluster: "cluster-a",
Folder: "/prod",
ProvisionedDisk: 100,
VcpuCount: 2,
RamGB: 8,
CreationTime: monthStart.Add(-72 * time.Hour).Unix(),
IsTemplate: "FALSE",
PoweredOn: "TRUE",
SrmPlaceholder: "FALSE",
SamplesPresent: 2,
AvgVcpuCount: 2,
AvgRamGB: 8,
AvgProvisionedDisk: 100,
AvgIsPresent: 1.0,
PoolBronzePct: 100,
Bronze: 100,
},
{
SnapshotTime: day2.Unix(),
Name: "vm-a",
Vcenter: "vc-a",
VmID: "vm-a",
VmUUID: "uuid-a",
ResourcePool: "Tin",
Datacenter: "dc-a",
Cluster: "cluster-a",
Folder: "/prod",
ProvisionedDisk: 120,
VcpuCount: 4,
RamGB: 12,
CreationTime: monthStart.Add(-72 * time.Hour).Unix(),
IsTemplate: "FALSE",
PoweredOn: "TRUE",
SrmPlaceholder: "FALSE",
SamplesPresent: 2,
AvgVcpuCount: 4,
AvgRamGB: 12,
AvgProvisionedDisk: 120,
AvgIsPresent: 1.0,
PoolTinPct: 100,
Tin: 100,
},
}
for _, seed := range seeds {
targetTable := day1Table
if seed.SnapshotTime == day2.Unix() {
targetTable = day2Table
}
if err := insertDailySummarySeedRow(ctx, dbConn, targetTable, seed); err != nil {
t.Fatalf("failed to insert daily summary seed row: %v", err)
}
}
if err := task.aggregateMonthlySummaryWithMode(ctx, monthStart, true, false); err != nil {
t.Fatalf("aggregateMonthlySummaryWithMode (legacy SQL fallback) failed: %v", err)
}
summaryTable, err := monthlySummaryTableName(monthStart)
if err != nil {
t.Fatalf("failed to build monthly summary table name: %v", err)
}
rows, err := loadMonthlySummaryRows(ctx, dbConn, summaryTable)
if err != nil {
t.Fatalf("failed to load monthly summary rows: %v", err)
}
if len(rows) != 1 {
t.Fatalf("unexpected monthly summary row count: got %d want %d", len(rows), 1)
}
assertSnapshotRegistryRow(t, ctx, dbConn, "monthly", summaryTable, monthStart.Unix(), int64(len(rows)))
assertSummaryCacheMatchesByVcenter(t, ctx, dbConn, summaryTable, "monthly", monthStart.Unix())
reportPath := filepath.Join(task.Settings.Values.Settings.ReportsDir, summaryTable+".xlsx")
if _, err := os.Stat(reportPath); err != nil {
t.Fatalf("expected monthly report file at %s: %v", reportPath, err)
}
}