|
1 | 1 | 'use strict'
|
2 | 2 |
|
| 3 | +const { tspl } = require('@matteo.collina/tspl') |
3 | 4 | const { strictEqual, throws, doesNotThrow } = require('node:assert')
|
4 | 5 | const { test, describe } = require('node:test')
|
5 | 6 | const { isBlobLike, parseURL, isHttpOrHttpsPrefixed, isValidPort } = require('../lib/core/util')
|
6 | 7 | const { Blob, File } = require('node:buffer')
|
7 | 8 | const { InvalidArgumentError } = require('../lib/core/errors')
|
| 9 | +const timers = require('../lib/util/timers') |
8 | 10 |
|
9 | 11 | describe('isBlobLike', () => {
|
10 | 12 | test('buffer', () => {
|
@@ -253,3 +255,79 @@ describe('parseURL', () => {
|
253 | 255 | })
|
254 | 256 | })
|
255 | 257 | })
|
| 258 | + |
| 259 | +describe('timers', () => { |
| 260 | + const getDelta = (start, target) => { |
| 261 | + const end = process.hrtime.bigint() |
| 262 | + const actual = (end - start) / 1_000_000n |
| 263 | + return actual - BigInt(target) |
| 264 | + } |
| 265 | + |
| 266 | + // timers.setTimeout impelements a low resolution timer with a 500 ms granularity |
| 267 | + // It is expected that in the worst case, a timer will fire about 500 ms after the |
| 268 | + // intended amount of time, an extra 200 ms is added to account event loop overhead |
| 269 | + // Timers should never fire excessively early, 1ms early is tolerated |
| 270 | + const ACCEPTABLE_DELTA = 700n |
| 271 | + |
| 272 | + test('meet acceptable resolution time', async (t) => { |
| 273 | + const testTimeouts = [0, 1, 499, 500, 501, 990, 999, 1000, 1001, 1100, 1400, 1499, 1500, 4000, 5000] |
| 274 | + |
| 275 | + t = tspl(t, { plan: 1 + testTimeouts.length * 2 }) |
| 276 | + |
| 277 | + const start = process.hrtime.bigint() |
| 278 | + |
| 279 | + for (const target of testTimeouts) { |
| 280 | + timers.setTimeout(() => { |
| 281 | + const delta = getDelta(start, target) |
| 282 | + |
| 283 | + t.ok(delta >= -1n, `${target}ms fired early`) |
| 284 | + t.ok(delta < ACCEPTABLE_DELTA, `${target}ms fired late`) |
| 285 | + }, target) |
| 286 | + } |
| 287 | + |
| 288 | + setTimeout(() => t.ok(true), 6000) |
| 289 | + await t.completed |
| 290 | + }) |
| 291 | + |
| 292 | + test('refresh correctly with timeout < TICK_MS', async (t) => { |
| 293 | + t = tspl(t, { plan: 3 }) |
| 294 | + |
| 295 | + const start = process.hrtime.bigint() |
| 296 | + |
| 297 | + const timeout = timers.setTimeout(() => { |
| 298 | + // 400 ms timer was refreshed after 600ms; total target is 1000 |
| 299 | + const delta = getDelta(start, 1000) |
| 300 | + |
| 301 | + t.ok(delta >= -1n, 'refreshed timer fired early') |
| 302 | + t.ok(delta < ACCEPTABLE_DELTA, 'refreshed timer fired late') |
| 303 | + }, 400) |
| 304 | + |
| 305 | + setTimeout(() => timeout.refresh(), 200) |
| 306 | + setTimeout(() => timeout.refresh(), 400) |
| 307 | + setTimeout(() => timeout.refresh(), 600) |
| 308 | + |
| 309 | + setTimeout(() => t.ok(true), 1500) |
| 310 | + await t.completed |
| 311 | + }) |
| 312 | + |
| 313 | + test('refresh correctly with timeout > TICK_MS', async (t) => { |
| 314 | + t = tspl(t, { plan: 3 }) |
| 315 | + |
| 316 | + const start = process.hrtime.bigint() |
| 317 | + |
| 318 | + const timeout = timers.setTimeout(() => { |
| 319 | + // 501ms timer was refreshed after 1250ms; total target is 1751 |
| 320 | + const delta = getDelta(start, 1751) |
| 321 | + |
| 322 | + t.ok(delta >= -1n, 'refreshed timer fired early') |
| 323 | + t.ok(delta < ACCEPTABLE_DELTA, 'refreshed timer fired late') |
| 324 | + }, 501) |
| 325 | + |
| 326 | + setTimeout(() => timeout.refresh(), 250) |
| 327 | + setTimeout(() => timeout.refresh(), 750) |
| 328 | + setTimeout(() => timeout.refresh(), 1250) |
| 329 | + |
| 330 | + setTimeout(() => t.ok(true), 3000) |
| 331 | + await t.completed |
| 332 | + }) |
| 333 | +}) |
0 commit comments