Skip to content

Commit dae7fb9

Browse files
committed
test(checkup): add tests for all reports and metrics.yml validation
Extend PostgreSQL version compatibility tests (PG13-18): - Add tests for D004 (pg_stat_statements), F001 (autovacuum settings), and G001 (memory settings) reports across all versions - Update generateAllReports test to verify all 11 check IDs - Add comprehensive metrics.yml validation: ensure all embedded metrics return valid SQL for each PostgreSQL version (13-18) - Add edge case tests for boundary versions (PG13 min, PG18 max) - Add METRIC_NAMES mapping tests for all core metrics Total: 187 tests covering all checkup reports across 6 PG versions.
1 parent 9931218 commit dae7fb9

1 file changed

Lines changed: 113 additions & 37 deletions

File tree

cli/test/checkup.test.ts

Lines changed: 113 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,14 +1090,60 @@ describe("PostgreSQL version compatibility (PG13-PG18)", () => {
10901090
}
10911091
});
10921092

1093+
describe("generateD004 (pg_stat_statements) works for each PG version", () => {
1094+
for (const { major, minor } of pgVersions) {
1095+
test(`PG ${major}.${minor}`, async () => {
1096+
const mockClient = createMockClient(createVersionMockData(major, minor));
1097+
const report = await checkup.REPORT_GENERATORS.D004(mockClient as any, "test-node");
1098+
1099+
expect(report.checkId).toBe("D004");
1100+
expect(report.checkTitle).toBe("pg_stat_statements and pg_stat_kcache settings");
1101+
expect("test-node" in report.results).toBe(true);
1102+
// D004 should include settings and extension info
1103+
expect("settings" in report.results["test-node"].data).toBe(true);
1104+
});
1105+
}
1106+
});
1107+
1108+
describe("generateF001 (autovacuum settings) works for each PG version", () => {
1109+
for (const { major, minor } of pgVersions) {
1110+
test(`PG ${major}.${minor}`, async () => {
1111+
const mockClient = createMockClient(createVersionMockData(major, minor));
1112+
const report = await checkup.REPORT_GENERATORS.F001(mockClient as any, "test-node");
1113+
1114+
expect(report.checkId).toBe("F001");
1115+
expect(report.checkTitle).toBe("Autovacuum: current settings");
1116+
expect("test-node" in report.results).toBe(true);
1117+
expect(report.results["test-node"].postgres_version?.version).toBe(`${major}.${minor}`);
1118+
});
1119+
}
1120+
});
1121+
1122+
describe("generateG001 (memory settings) works for each PG version", () => {
1123+
for (const { major, minor } of pgVersions) {
1124+
test(`PG ${major}.${minor}`, async () => {
1125+
const mockClient = createMockClient(createVersionMockData(major, minor));
1126+
const report = await checkup.REPORT_GENERATORS.G001(mockClient as any, "test-node");
1127+
1128+
expect(report.checkId).toBe("G001");
1129+
expect(report.checkTitle).toBe("Memory-related settings");
1130+
expect("test-node" in report.results).toBe(true);
1131+
// G001 should include settings and analysis sections
1132+
expect("settings" in report.results["test-node"].data).toBe(true);
1133+
expect("analysis" in report.results["test-node"].data).toBe(true);
1134+
expect(report.results["test-node"].postgres_version?.version).toBe(`${major}.${minor}`);
1135+
});
1136+
}
1137+
});
1138+
10931139
describe("generateAllReports works for each PG version", () => {
10941140
for (const { major, minor } of pgVersions) {
10951141
test(`PG ${major}.${minor}`, async () => {
10961142
const mockClient = createMockClient(createVersionMockData(major, minor));
10971143
const reports = await checkup.generateAllReports(mockClient as any, "test-node");
10981144

1099-
// Verify all expected checks are generated
1100-
const expectedChecks = ["A002", "A003", "A004", "A007", "A013", "H001", "H002", "H004"];
1145+
// Verify all expected checks are generated (includes D004, F001, G001)
1146+
const expectedChecks = ["A002", "A003", "A004", "A007", "A013", "D004", "F001", "G001", "H001", "H002", "H004"];
11011147
for (const checkId of expectedChecks) {
11021148
expect(checkId in reports).toBe(true);
11031149
expect(reports[checkId].checkId).toBe(checkId);
@@ -1119,58 +1165,54 @@ describe("PostgreSQL version compatibility (PG13-PG18)", () => {
11191165
describe("Version-aware SQL query selection (PG13-PG18)", () => {
11201166
const pgVersions = [13, 14, 15, 16, 17, 18];
11211167

1122-
// Core metrics that should be available for all versions
1123-
const coreMetrics = [
1124-
"settings",
1125-
"db_stats",
1126-
"db_size",
1127-
"stats_reset",
1128-
"pg_invalid_indexes",
1129-
"unused_indexes",
1130-
"redundant_indexes",
1131-
];
1168+
// All metrics from metrics.yml that are used by checkup
1169+
const allMetrics = metricsLoader.listMetricNames();
11321170

1133-
describe("getMetricSql returns SQL for all PG versions", () => {
1171+
describe("All metrics from metrics.yml return valid SQL for each PG version", () => {
11341172
for (const pgVersion of pgVersions) {
1135-
for (const metric of coreMetrics) {
1136-
test(`${metric} for PG${pgVersion}`, () => {
1137-
const sql = metricsLoader.getMetricSql(metric, pgVersion);
1138-
expect(typeof sql).toBe("string");
1139-
expect(sql.length).toBeGreaterThan(0);
1140-
// Verify it's actually SQL
1141-
expect(sql.toLowerCase()).toMatch(/select/);
1142-
});
1143-
}
1144-
}
1145-
});
1146-
1147-
describe("getMetricSql selects appropriate version for each PG major version", () => {
1148-
for (const pgVersion of pgVersions) {
1149-
test(`PG${pgVersion} gets compatible SQL version`, () => {
1150-
// Settings metric should return SQL for all supported versions
1151-
const sql = metricsLoader.getMetricSql("settings", pgVersion);
1152-
expect(sql).toBeTruthy();
1153-
// SQL should be valid (not throw an error)
1154-
expect(() => metricsLoader.getMetricSql("settings", pgVersion)).not.toThrow();
1173+
describe(`PG${pgVersion}`, () => {
1174+
for (const metric of allMetrics) {
1175+
test(`${metric}`, () => {
1176+
// Should not throw an error
1177+
expect(() => metricsLoader.getMetricSql(metric, pgVersion)).not.toThrow();
1178+
1179+
const sql = metricsLoader.getMetricSql(metric, pgVersion);
1180+
expect(typeof sql).toBe("string");
1181+
expect(sql.length).toBeGreaterThan(0);
1182+
// Verify it's actually SQL (contains SELECT)
1183+
expect(sql.toLowerCase()).toMatch(/select/);
1184+
});
1185+
}
11551186
});
11561187
}
11571188
});
11581189

11591190
describe("getMetricDefinition returns metadata for all metrics", () => {
1160-
for (const metric of coreMetrics) {
1161-
test(`${metric} has definition`, () => {
1191+
for (const metric of allMetrics) {
1192+
test(`${metric} has definition with versioned SQL`, () => {
11621193
const definition = metricsLoader.getMetricDefinition(metric);
11631194
expect(definition).toBeTruthy();
11641195
expect(definition?.sqls).toBeTruthy();
11651196
expect(typeof definition?.sqls).toBe("object");
1197+
// Should have at least one version defined
1198+
expect(Object.keys(definition!.sqls).length).toBeGreaterThan(0);
11661199
});
11671200
}
11681201
});
11691202

1170-
test("listMetricNames returns all expected metrics", () => {
1203+
test("listMetricNames returns all expected core metrics", () => {
11711204
const names = metricsLoader.listMetricNames();
11721205
expect(Array.isArray(names)).toBe(true);
1173-
// Should include core metrics
1206+
// Core metrics used by checkup reports
1207+
const coreMetrics = [
1208+
"settings",
1209+
"db_stats",
1210+
"db_size",
1211+
"stats_reset",
1212+
"pg_invalid_indexes",
1213+
"unused_indexes",
1214+
"redundant_indexes",
1215+
];
11741216
for (const metric of coreMetrics) {
11751217
expect(names).toContain(metric);
11761218
}
@@ -1192,6 +1234,40 @@ describe("Version-aware SQL query selection (PG13-PG18)", () => {
11921234
test("settings metric exists", () => {
11931235
expect(metricsLoader.METRIC_NAMES.settings).toBe("settings");
11941236
});
1237+
1238+
test("dbStats metric exists", () => {
1239+
expect(metricsLoader.METRIC_NAMES.dbStats).toBe("db_stats");
1240+
});
1241+
1242+
test("dbSize metric exists", () => {
1243+
expect(metricsLoader.METRIC_NAMES.dbSize).toBe("db_size");
1244+
});
1245+
1246+
test("statsReset metric exists", () => {
1247+
expect(metricsLoader.METRIC_NAMES.statsReset).toBe("stats_reset");
1248+
});
1249+
});
1250+
1251+
describe("SQL queries are syntactically valid for version edge cases", () => {
1252+
// Test boundary versions
1253+
const boundaryVersions = [
1254+
{ version: 13, description: "minimum supported" },
1255+
{ version: 18, description: "maximum supported" },
1256+
];
1257+
1258+
for (const { version, description } of boundaryVersions) {
1259+
test(`PG${version} (${description}) returns valid SQL for all metrics`, () => {
1260+
for (const metric of allMetrics) {
1261+
const sql = metricsLoader.getMetricSql(metric, version);
1262+
// Basic SQL validation
1263+
expect(sql.toLowerCase()).toMatch(/select/);
1264+
expect(sql.toLowerCase()).toMatch(/from/);
1265+
// Should not contain unresolved template variables
1266+
expect(sql).not.toMatch(/\{\{.*\}\}/);
1267+
expect(sql).not.toMatch(/\$\{.*\}/);
1268+
}
1269+
});
1270+
}
11951271
});
11961272
});
11971273

0 commit comments

Comments
 (0)