mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Merge pull request #271 from PR0M3TH3AN/jules-3313039613758629393-8f27954c
Enhance test coverage for relay alert thresholds
This commit is contained in:
1 file changed
+152
-31
@@ -13,38 +13,159 @@ function entry(timestamp, healthyRelays, totalRelays = 3) {
|
||||
};
|
||||
}
|
||||
|
||||
test('raises all-relays-down duration alert after threshold', () => {
|
||||
test('evaluateAlertThresholds', async (t) => {
|
||||
const now = Date.parse('2026-02-15T12:00:00Z');
|
||||
const history = [
|
||||
entry('2026-02-15T11:30:00Z', 1),
|
||||
entry('2026-02-15T11:45:00Z', 0),
|
||||
entry('2026-02-15T11:55:00Z', 0),
|
||||
entry('2026-02-15T12:00:00Z', 0),
|
||||
];
|
||||
const minute = 60_000;
|
||||
|
||||
const current = history[history.length - 1];
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.1,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
await t.test('Happy Path: No alerts when thresholds are not met', () => {
|
||||
const history = [
|
||||
entry(new Date(now - 10 * minute).toISOString(), 3),
|
||||
entry(new Date(now).toISOString(), 3),
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
assert.ok(result.alerts.some((alert) => alert.type === 'all_relays_down_duration'));
|
||||
});
|
||||
|
||||
test('raises success-rate alert when rolling health falls below threshold', () => {
|
||||
const history = [
|
||||
entry('2026-02-15T11:50:00Z', 3),
|
||||
entry('2026-02-15T11:55:00Z', 0),
|
||||
entry('2026-02-15T12:00:00Z', 0),
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 999,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 30,
|
||||
}, { nowMs: Date.parse('2026-02-15T12:00:00Z') });
|
||||
|
||||
assert.ok(result.alerts.some((alert) => alert.type === 'relay_success_rate_below_threshold'));
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
assert.equal(result.alerts.length, 0);
|
||||
});
|
||||
|
||||
await t.test('All Relays Down: Triggers alert when duration equals threshold', () => {
|
||||
// 10 minutes down exactly
|
||||
const history = [
|
||||
entry(new Date(now - 10 * minute).toISOString(), 3), // healthy 10 mins ago
|
||||
entry(new Date(now - 5 * minute).toISOString(), 0),
|
||||
entry(new Date(now).toISOString(), 0),
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.1,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
const alert = result.alerts.find(a => a.type === 'all_relays_down_duration');
|
||||
assert.ok(alert);
|
||||
assert.equal(alert.actualMinutes, 10);
|
||||
});
|
||||
|
||||
await t.test('All Relays Down: Does NOT trigger alert just below threshold', () => {
|
||||
// 9 minutes down
|
||||
const history = [
|
||||
entry(new Date(now - 9 * minute).toISOString(), 3), // healthy 9 mins ago
|
||||
entry(new Date(now).toISOString(), 0),
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.1,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
const alert = result.alerts.find(a => a.type === 'all_relays_down_duration');
|
||||
assert.equal(alert, undefined);
|
||||
});
|
||||
|
||||
await t.test('Success Rate: Triggers alert when rate is strictly below threshold', () => {
|
||||
const history = [
|
||||
entry(new Date(now).toISOString(), 1, 4), // 25% healthy
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
// Threshold 0.3 > 0.25 -> Alert
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 999,
|
||||
minSuccessRate: 0.3,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
const alert = result.alerts.find(a => a.type === 'relay_success_rate_below_threshold');
|
||||
assert.ok(alert);
|
||||
assert.equal(alert.actual, 0.25);
|
||||
});
|
||||
|
||||
await t.test('Success Rate: Does NOT trigger alert when rate equals threshold', () => {
|
||||
const history = [
|
||||
entry(new Date(now).toISOString(), 1, 4), // 25% healthy
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
// Threshold 0.25 == 0.25 -> No Alert
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 999,
|
||||
minSuccessRate: 0.25,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
const alert = result.alerts.find(a => a.type === 'relay_success_rate_below_threshold');
|
||||
assert.equal(alert, undefined);
|
||||
});
|
||||
|
||||
await t.test('Success Rate: Does NOT trigger alert when rate is above threshold', () => {
|
||||
const history = [
|
||||
entry(new Date(now).toISOString(), 3, 4), // 75% healthy
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
// Threshold 0.5 < 0.75 -> No Alert
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 999,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
const alert = result.alerts.find(a => a.type === 'relay_success_rate_below_threshold');
|
||||
assert.equal(alert, undefined);
|
||||
});
|
||||
|
||||
await t.test('Multiple Alerts: Both conditions met', () => {
|
||||
// Down for 20 mins (threshold 10) AND rate 0 (threshold 0.5)
|
||||
const history = [
|
||||
entry(new Date(now - 20 * minute).toISOString(), 3), // Healthy 20m ago
|
||||
entry(new Date(now - 10 * minute).toISOString(), 0),
|
||||
entry(new Date(now).toISOString(), 0),
|
||||
];
|
||||
const current = history[history.length - 1];
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
assert.equal(result.alerts.length, 2);
|
||||
assert.ok(result.alerts.some(a => a.type === 'all_relays_down_duration'));
|
||||
assert.ok(result.alerts.some(a => a.type === 'relay_success_rate_below_threshold'));
|
||||
});
|
||||
|
||||
await t.test('Edge Case: Empty history (should not crash)', () => {
|
||||
const history = [];
|
||||
const current = entry(new Date(now).toISOString(), 3); // current result is healthy
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
assert.equal(result.alerts.length, 0);
|
||||
});
|
||||
|
||||
await t.test('Edge Case: Empty history but current result is unhealthy', () => {
|
||||
const history = [];
|
||||
const current = entry(new Date(now).toISOString(), 0); // current result is unhealthy
|
||||
|
||||
const result = evaluateAlertThresholds(current, history, {
|
||||
allRelaysDownMinutes: 10,
|
||||
minSuccessRate: 0.5,
|
||||
windowMinutes: 60,
|
||||
}, { nowMs: now });
|
||||
|
||||
assert.equal(result.alerts.length, 0);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user