Functional Weave
Code in Rust

monitor.uptime@1.0.0

vectors.json

5,400 bytes · view raw

[
  {"name": "checks every minute, all up, cover the whole window", "args": [[{"at": 0, "status": "up"}, {"at": 60, "status": "up"}, {"at": 120, "status": "up"}], 0, 180, 120], "expect": {"upSeconds": 180, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 0, "uptimeBasisPoints": 10000, "checks": 3, "downChecks": 0}},
  {"name": "each status holds until the next check; degraded counts towards uptime", "args": [[{"at": 0, "status": "up"}, {"at": 60, "status": "down"}, {"at": 120, "status": "up"}, {"at": 180, "status": "degraded"}], 0, 240, 60], "expect": {"upSeconds": 120, "degradedSeconds": 60, "downSeconds": 60, "unknownSeconds": 0, "uptimeBasisPoints": 7500, "checks": 4, "downChecks": 1}},
  {"name": "one down second in 100000 floors to 99.99%, never rounds up to 100%", "args": [[{"at": 0, "status": "up"}, {"at": 99999, "status": "down"}], 0, 100000, 100000], "expect": {"upSeconds": 99999, "degradedSeconds": 0, "downSeconds": 1, "unknownSeconds": 0, "uptimeBasisPoints": 9999, "checks": 2, "downChecks": 1}},
  {"name": "a gap longer than maxGapSeconds is unknown after the cap, not up", "args": [[{"at": 0, "status": "up"}, {"at": 1000, "status": "up"}], 0, 1060, 300], "expect": {"upSeconds": 360, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 700, "uptimeBasisPoints": 10000, "checks": 2, "downChecks": 0}},
  {"name": "the latest check before the window carries into it but is not counted as a check", "args": [[{"at": 900, "status": "down"}, {"at": 1100, "status": "up"}], 1000, 1200, 300], "expect": {"upSeconds": 100, "degradedSeconds": 0, "downSeconds": 100, "unknownSeconds": 0, "uptimeBasisPoints": 5000, "checks": 1, "downChecks": 0}},
  {"name": "a carried-in check still stops at maxGapSeconds after it ran", "args": [[{"at": 500, "status": "down"}], 1000, 1200, 600], "expect": {"upSeconds": 0, "degradedSeconds": 0, "downSeconds": 100, "unknownSeconds": 100, "uptimeBasisPoints": 0, "checks": 0, "downChecks": 0}},
  {"name": "a check that expired before the window leaves it all unknown and uptime null", "args": [[{"at": 500, "status": "down"}], 1000, 1200, 400], "expect": {"upSeconds": 0, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 200, "uptimeBasisPoints": null, "checks": 0, "downChecks": 0}},
  {"name": "no checks at all is all unknown", "args": [[], 0, 3600, 60], "expect": {"upSeconds": 0, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 3600, "uptimeBasisPoints": null, "checks": 0, "downChecks": 0}},
  {"name": "an empty window when from equals to", "args": [[{"at": 0, "status": "up"}], 100, 100, 60], "expect": {"upSeconds": 0, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 0, "uptimeBasisPoints": null, "checks": 0, "downChecks": 0}},
  {"name": "time before the first check is unknown, not assumed up", "args": [[{"at": 100, "status": "up"}], 0, 200, 1000], "expect": {"upSeconds": 100, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 100, "uptimeBasisPoints": 10000, "checks": 1, "downChecks": 0}},
  {"name": "a check exactly at to belongs to the next window and adds nothing", "args": [[{"at": 0, "status": "up"}, {"at": 100, "status": "down"}], 0, 100, 1000], "expect": {"upSeconds": 100, "degradedSeconds": 0, "downSeconds": 0, "unknownSeconds": 0, "uptimeBasisPoints": 10000, "checks": 1, "downChecks": 0}},
  {"name": "degraded the whole time is still 100% up", "args": [[{"at": 0, "status": "degraded"}], 0, 100, 100], "expect": {"upSeconds": 0, "degradedSeconds": 100, "downSeconds": 0, "unknownSeconds": 0, "uptimeBasisPoints": 10000, "checks": 1, "downChecks": 0}},
  {"name": "down the whole time is 0%", "args": [[{"at": 0, "status": "down"}, {"at": 10, "status": "down"}], 0, 20, 10], "expect": {"upSeconds": 0, "degradedSeconds": 0, "downSeconds": 20, "unknownSeconds": 0, "uptimeBasisPoints": 0, "checks": 2, "downChecks": 2}},
  {"name": "a window so long that seconds times 10000 passes 2^53 still floors exactly", "args": [[{"at": 0, "status": "up"}, {"at": 1000000000000, "status": "down"}], 0, 1000000000001, 1000000000000], "expect": {"upSeconds": 1000000000000, "degradedSeconds": 0, "downSeconds": 1, "unknownSeconds": 0, "uptimeBasisPoints": 9999, "checks": 2, "downChecks": 1}},
  {"name": "from after to is an error", "args": [[], 200, 100, 60], "expectError": "from must not be after to: 200 > 100"},
  {"name": "a maxGapSeconds of zero is an error", "args": [[], 0, 100, 0], "expectError": "maxGapSeconds must be a whole number of at least 1, received 0"},
  {"name": "a fractional maxGapSeconds is an error", "args": [[], 0, 100, 0.5], "expectError": "maxGapSeconds must be a whole number of at least 1, received 0.5"},
  {"name": "a fractional bound is an error", "args": [[], 0.5, 100, 60], "expectError": "from and to must be whole seconds"},
  {"name": "two checks at the same second are an error", "args": [[{"at": 100, "status": "up"}, {"at": 100, "status": "down"}], 0, 1000, 60], "expectError": "checks must be in strictly ascending time order: 100 follows 100"},
  {"name": "misordered checks outside the window are still an error", "args": [[{"at": 300, "status": "up"}, {"at": 100, "status": "up"}], 0, 50, 60], "expectError": "checks must be in strictly ascending time order: 100 follows 300"},
  {"name": "an unknown status is an error", "args": [[{"at": 0, "status": "offline"}], 0, 10, 60], "expectError": "unknown check status: offline"}
]