test: cover monitor status derivation
This commit is contained in:
@@ -2,13 +2,15 @@ import { assert, assertEquals, assertRejects } from "jsr:@std/assert@^1.0.0";
|
|||||||
|
|
||||||
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
|
import { RunnerCoordinator } from "../../../uptime.link/ts_api/classes/runner-coordinator.ts";
|
||||||
import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts";
|
import { RunnerFileStore } from "../../../uptime.link/ts_api/classes/runner-file-store.ts";
|
||||||
|
import {
|
||||||
|
createRunnerSchedulesFromMonitors,
|
||||||
|
type IRunnerMonitorDefinition,
|
||||||
|
} from "../../../uptime.link/ts_api/classes/runner-monitor-mapper.ts";
|
||||||
import { createRunnerRequestHandler } from "../../../uptime.link/ts_api/classes/runner-request-handler.ts";
|
import { createRunnerRequestHandler } from "../../../uptime.link/ts_api/classes/runner-request-handler.ts";
|
||||||
|
import { RunnerResultIngestor } from "../../../uptime.link/ts_api/classes/runner-result-ingestor.ts";
|
||||||
import { RunnerScheduler } from "../../../uptime.link/ts_api/classes/runner-scheduler.ts";
|
import { RunnerScheduler } from "../../../uptime.link/ts_api/classes/runner-scheduler.ts";
|
||||||
import { UptimeRunner } from "../../../uptimerunner/ts/runner.ts";
|
import { UptimeRunner } from "../../../uptimerunner/ts/runner.ts";
|
||||||
import type {
|
import type { IResultSubmitRequest } from "../../../uptimerunner/ts/interfaces.ts";
|
||||||
IResultSubmitRequest,
|
|
||||||
TCheckJob,
|
|
||||||
} from "../../../uptimerunner/ts/interfaces.ts";
|
|
||||||
|
|
||||||
const scenarioName = "uptimerunner-basic";
|
const scenarioName = "uptimerunner-basic";
|
||||||
const runnerId = `scenario-runner-${Date.now().toString(36)}`;
|
const runnerId = `scenario-runner-${Date.now().toString(36)}`;
|
||||||
@@ -18,28 +20,47 @@ const main = async () => {
|
|||||||
const targetServer = await startServer(() => new Response("healthy"));
|
const targetServer = await startServer(() => new Response("healthy"));
|
||||||
const tcpServer = startTcpServer();
|
const tcpServer = startTcpServer();
|
||||||
const resultSubmissions: IResultSubmitRequest[] = [];
|
const resultSubmissions: IResultSubmitRequest[] = [];
|
||||||
const checkQueue: TCheckJob[] = [
|
const monitors: IRunnerMonitorDefinition[] = [
|
||||||
{
|
{
|
||||||
id: "local-http-health",
|
id: "local-http-health",
|
||||||
type: "http",
|
name: "Local HTTP Health",
|
||||||
url: targetServer.url,
|
intervalMs: 60000,
|
||||||
expectedStatusCodes: [200],
|
check: {
|
||||||
expectedBodyIncludes: "healthy",
|
type: "http",
|
||||||
metadata: {
|
url: targetServer.url,
|
||||||
scenario: scenarioName,
|
expectedStatusCodes: [200],
|
||||||
|
expectedBodyIncludes: "healthy",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "local-tcp-health",
|
id: "local-tcp-health",
|
||||||
type: "tcp",
|
name: "Local TCP Health",
|
||||||
host: "127.0.0.1",
|
intervalMs: 60000,
|
||||||
port: tcpServer.port,
|
check: {
|
||||||
|
type: "tcp",
|
||||||
|
host: "127.0.0.1",
|
||||||
|
port: tcpServer.port,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "manual-assumption",
|
id: "manual-assumption",
|
||||||
type: "assumption",
|
name: "Manual Assumption",
|
||||||
assumedStatus: "ok",
|
intervalMs: 60000,
|
||||||
message: "manual assumption is healthy",
|
check: {
|
||||||
|
type: "assumption",
|
||||||
|
assumedStatus: "ok",
|
||||||
|
message: "manual assumption is healthy",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "manual-degraded",
|
||||||
|
name: "Manual Degraded",
|
||||||
|
intervalMs: 60000,
|
||||||
|
check: {
|
||||||
|
type: "assumption",
|
||||||
|
assumedStatus: "not ok",
|
||||||
|
message: "manual assumption is degraded",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -48,14 +69,10 @@ const main = async () => {
|
|||||||
});
|
});
|
||||||
const scheduler = new RunnerScheduler(coordinator, { now: () => 1000 });
|
const scheduler = new RunnerScheduler(coordinator, { now: () => 1000 });
|
||||||
const scheduleResult = scheduler.scheduleDueChecks(
|
const scheduleResult = scheduler.scheduleDueChecks(
|
||||||
checkQueue.map((check) => ({
|
createRunnerSchedulesFromMonitors(monitors),
|
||||||
monitorId: `monitor-${check.id}`,
|
|
||||||
check,
|
|
||||||
intervalMs: 60000,
|
|
||||||
})),
|
|
||||||
);
|
);
|
||||||
assertEquals(scheduleResult.scheduledChecks.length, 3);
|
assertEquals(scheduleResult.scheduledChecks.length, 4);
|
||||||
assertEquals(coordinator.getQueueLength(), 3);
|
assertEquals(coordinator.getQueueLength(), 4);
|
||||||
assertEquals(
|
assertEquals(
|
||||||
scheduler.scheduleDueChecks(scheduleResult.schedules).scheduledChecks
|
scheduler.scheduleDueChecks(scheduleResult.schedules).scheduledChecks
|
||||||
.length,
|
.length,
|
||||||
@@ -84,20 +101,23 @@ const main = async () => {
|
|||||||
console.log(`[${scenarioName}] Running single runner iteration`);
|
console.log(`[${scenarioName}] Running single runner iteration`);
|
||||||
const result = await runner.runOnce();
|
const result = await runner.runOnce();
|
||||||
|
|
||||||
assertEquals(result.checks.length, 3);
|
assertEquals(result.checks.length, 4);
|
||||||
assertEquals(result.results.length, 3);
|
assertEquals(result.results.length, 4);
|
||||||
assertEquals(result.results[0].checkId, "local-http-health");
|
assertEquals(result.results[0].checkId, "monitor-local-http-health");
|
||||||
assertEquals(result.results[0].status, "ok");
|
assertEquals(result.results[0].status, "ok");
|
||||||
assertEquals(result.results[1].checkId, "local-tcp-health");
|
assertEquals(result.results[1].checkId, "monitor-local-tcp-health");
|
||||||
assertEquals(result.results[1].status, "ok");
|
assertEquals(result.results[1].status, "ok");
|
||||||
assertEquals(result.results[2].checkId, "manual-assumption");
|
assertEquals(result.results[2].checkId, "monitor-manual-assumption");
|
||||||
assertEquals(result.results[2].status, "ok");
|
assertEquals(result.results[2].status, "ok");
|
||||||
|
assertEquals(result.results[3].checkId, "monitor-manual-degraded");
|
||||||
|
assertEquals(result.results[3].status, "not ok");
|
||||||
assertEquals(resultSubmissions.length, 1);
|
assertEquals(resultSubmissions.length, 1);
|
||||||
assertEquals(resultSubmissions[0].runnerId, runnerId);
|
assertEquals(resultSubmissions[0].runnerId, runnerId);
|
||||||
assertEquals(resultSubmissions[0].results[0].status, "ok");
|
assertEquals(resultSubmissions[0].results[0].status, "ok");
|
||||||
assert(resultSubmissions[0].results[0].responseTime !== undefined);
|
assert(resultSubmissions[0].results[0].responseTime !== undefined);
|
||||||
assertEquals(coordinator.listResults().length, 3);
|
assertEquals(coordinator.listResults().length, 4);
|
||||||
assertEquals(coordinator.getQueueLength(), 0);
|
assertEquals(coordinator.getQueueLength(), 0);
|
||||||
|
assertMonitorStatusDerivation(coordinator.listResults());
|
||||||
await assertSnapshotPersistence(coordinator, targetServer.url);
|
await assertSnapshotPersistence(coordinator, targetServer.url);
|
||||||
|
|
||||||
const emptyResult = await runner.runOnce();
|
const emptyResult = await runner.runOnce();
|
||||||
@@ -170,6 +190,28 @@ function startTcpServer(): { port: number; close: () => void } {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function assertMonitorStatusDerivation(
|
||||||
|
results: IResultSubmitRequest["results"],
|
||||||
|
): void {
|
||||||
|
const ingestor = new RunnerResultIngestor();
|
||||||
|
const ingestion = ingestor.ingest(results);
|
||||||
|
assertEquals(ingestion.monitorStates.length, 4);
|
||||||
|
assertEquals(ingestion.ignoredResults.length, 0);
|
||||||
|
assertEquals(
|
||||||
|
ingestor.getMonitorState("local-http-health")?.status,
|
||||||
|
"operational",
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
ingestor.getMonitorState("local-tcp-health")?.status,
|
||||||
|
"operational",
|
||||||
|
);
|
||||||
|
assertEquals(
|
||||||
|
ingestor.getMonitorState("manual-assumption")?.status,
|
||||||
|
"operational",
|
||||||
|
);
|
||||||
|
assertEquals(ingestor.getMonitorState("manual-degraded")?.status, "degraded");
|
||||||
|
}
|
||||||
|
|
||||||
async function assertSnapshotPersistence(
|
async function assertSnapshotPersistence(
|
||||||
coordinatorArg: RunnerCoordinator,
|
coordinatorArg: RunnerCoordinator,
|
||||||
targetUrlArg: string,
|
targetUrlArg: string,
|
||||||
@@ -196,7 +238,7 @@ async function assertSnapshotPersistence(
|
|||||||
const snapshot = await store.load();
|
const snapshot = await store.load();
|
||||||
assert(snapshot);
|
assert(snapshot);
|
||||||
const restoredCoordinator = new RunnerCoordinator({ snapshot });
|
const restoredCoordinator = new RunnerCoordinator({ snapshot });
|
||||||
assertEquals(restoredCoordinator.listResults().length, 3);
|
assertEquals(restoredCoordinator.listResults().length, 4);
|
||||||
assertEquals(restoredCoordinator.listRunners().length, 1);
|
assertEquals(restoredCoordinator.listRunners().length, 1);
|
||||||
restoredCoordinator.enqueueCheck({
|
restoredCoordinator.enqueueCheck({
|
||||||
id: "post-restart-http-health",
|
id: "post-restart-http-health",
|
||||||
@@ -218,7 +260,7 @@ async function assertSnapshotPersistence(
|
|||||||
const restoredResult = await restoredRunner.runOnce();
|
const restoredResult = await restoredRunner.runOnce();
|
||||||
assertEquals(restoredResult.results.length, 1);
|
assertEquals(restoredResult.results.length, 1);
|
||||||
assertEquals(restoredResult.results[0].status, "ok");
|
assertEquals(restoredResult.results[0].status, "ok");
|
||||||
assertEquals(restoredCoordinator.listResults().length, 4);
|
assertEquals(restoredCoordinator.listResults().length, 5);
|
||||||
} finally {
|
} finally {
|
||||||
await restoredServer.server.shutdown();
|
await restoredServer.server.shutdown();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user