11cb0ef41Sopenharmony_ci'use strict';
21cb0ef41Sopenharmony_ci
31cb0ef41Sopenharmony_ciconst common = require('../common');
41cb0ef41Sopenharmony_ciconst { performance } = require('perf_hooks');
51cb0ef41Sopenharmony_ci// Get the start time as soon as possible.
61cb0ef41Sopenharmony_ciconst testStartTime = performance.now();
71cb0ef41Sopenharmony_ciconst assert = require('assert');
81cb0ef41Sopenharmony_ciconst { writeSync } = require('fs');
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci// Use writeSync to stdout to avoid disturbing the loop.
111cb0ef41Sopenharmony_cifunction log(str) {
121cb0ef41Sopenharmony_ci  writeSync(1, str + '\n');
131cb0ef41Sopenharmony_ci}
141cb0ef41Sopenharmony_ci
151cb0ef41Sopenharmony_ciassert(performance);
161cb0ef41Sopenharmony_ciassert(performance.nodeTiming);
171cb0ef41Sopenharmony_ciassert.strictEqual(typeof performance.timeOrigin, 'number');
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciassert(testStartTime > 0, `${testStartTime} <= 0`);
201cb0ef41Sopenharmony_ci// Use a fairly large epsilon value, since we can only guarantee that the node
211cb0ef41Sopenharmony_ci// process started up in 15 seconds.
221cb0ef41Sopenharmony_ciassert(testStartTime < 15000, `${testStartTime} >= 15000`);
231cb0ef41Sopenharmony_ci
241cb0ef41Sopenharmony_ci// Use different ways to calculate process uptime to check that
251cb0ef41Sopenharmony_ci// performance.timeOrigin and performance.now() are in reasonable range.
261cb0ef41Sopenharmony_ciconst epsilon = 50;
271cb0ef41Sopenharmony_ci{
281cb0ef41Sopenharmony_ci  const uptime1 = Date.now() - performance.timeOrigin;
291cb0ef41Sopenharmony_ci  const uptime2 = performance.now();
301cb0ef41Sopenharmony_ci  const uptime3 = process.uptime() * 1000;
311cb0ef41Sopenharmony_ci  assert(Math.abs(uptime1 - uptime2) < epsilon,
321cb0ef41Sopenharmony_ci         `Date.now() - performance.timeOrigin (${uptime1}) - ` +
331cb0ef41Sopenharmony_ci         `performance.now() (${uptime2}) = ` +
341cb0ef41Sopenharmony_ci         `${uptime1 - uptime2} >= +- ${epsilon}`);
351cb0ef41Sopenharmony_ci  assert(Math.abs(uptime1 - uptime3) < epsilon,
361cb0ef41Sopenharmony_ci         `Date.now() - performance.timeOrigin (${uptime1}) - ` +
371cb0ef41Sopenharmony_ci         `process.uptime() * 1000 (${uptime3}) = ` +
381cb0ef41Sopenharmony_ci         `${uptime1 - uptime3} >= +- ${epsilon}`);
391cb0ef41Sopenharmony_ci}
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ciassert.strictEqual(performance.nodeTiming.name, 'node');
421cb0ef41Sopenharmony_ciassert.strictEqual(performance.nodeTiming.entryType, 'node');
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci// Copy all the values from the getters.
451cb0ef41Sopenharmony_ciconst initialTiming = { ...performance.nodeTiming };
461cb0ef41Sopenharmony_ci
471cb0ef41Sopenharmony_ci{
481cb0ef41Sopenharmony_ci  const {
491cb0ef41Sopenharmony_ci    startTime,
501cb0ef41Sopenharmony_ci    nodeStart,
511cb0ef41Sopenharmony_ci    v8Start,
521cb0ef41Sopenharmony_ci    environment,
531cb0ef41Sopenharmony_ci    bootstrapComplete,
541cb0ef41Sopenharmony_ci  } = initialTiming;
551cb0ef41Sopenharmony_ci
561cb0ef41Sopenharmony_ci  assert.strictEqual(startTime, 0);
571cb0ef41Sopenharmony_ci  assert.strictEqual(typeof nodeStart, 'number');
581cb0ef41Sopenharmony_ci  assert(nodeStart > 0, `nodeStart ${nodeStart} <= 0`);
591cb0ef41Sopenharmony_ci  // The whole process starts before this test starts.
601cb0ef41Sopenharmony_ci  assert(nodeStart < testStartTime,
611cb0ef41Sopenharmony_ci         `nodeStart ${nodeStart} >= ${testStartTime}`);
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  assert.strictEqual(typeof v8Start, 'number');
641cb0ef41Sopenharmony_ci  assert(v8Start > 0, `v8Start ${v8Start} <= 0`);
651cb0ef41Sopenharmony_ci  // V8 starts after the process starts.
661cb0ef41Sopenharmony_ci  assert(v8Start > nodeStart, `v8Start ${v8Start} <= ${nodeStart}`);
671cb0ef41Sopenharmony_ci  // V8 starts before this test starts.
681cb0ef41Sopenharmony_ci  assert(v8Start < testStartTime,
691cb0ef41Sopenharmony_ci         `v8Start ${v8Start} >= ${testStartTime}`);
701cb0ef41Sopenharmony_ci
711cb0ef41Sopenharmony_ci  assert.strictEqual(typeof environment, 'number');
721cb0ef41Sopenharmony_ci  assert(environment > 0, `environment ${environment} <= 0`);
731cb0ef41Sopenharmony_ci  // Environment starts after V8 starts.
741cb0ef41Sopenharmony_ci  assert(environment > v8Start,
751cb0ef41Sopenharmony_ci         `environment ${environment} <= ${v8Start}`);
761cb0ef41Sopenharmony_ci  // Environment starts before this test starts.
771cb0ef41Sopenharmony_ci  assert(environment < testStartTime,
781cb0ef41Sopenharmony_ci         `environment ${environment} >= ${testStartTime}`);
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ci  assert.strictEqual(typeof bootstrapComplete, 'number');
811cb0ef41Sopenharmony_ci  assert(bootstrapComplete > 0, `bootstrapComplete ${bootstrapComplete} <= 0`);
821cb0ef41Sopenharmony_ci  // Bootstrap completes after environment starts.
831cb0ef41Sopenharmony_ci  assert(bootstrapComplete > environment,
841cb0ef41Sopenharmony_ci         `bootstrapComplete ${bootstrapComplete} <= ${environment}`);
851cb0ef41Sopenharmony_ci  // Bootstrap completes before this test starts.
861cb0ef41Sopenharmony_ci  assert(bootstrapComplete < testStartTime,
871cb0ef41Sopenharmony_ci         `bootstrapComplete ${bootstrapComplete} >= ${testStartTime}`);
881cb0ef41Sopenharmony_ci}
891cb0ef41Sopenharmony_ci
901cb0ef41Sopenharmony_cifunction checkNodeTiming(timing) {
911cb0ef41Sopenharmony_ci  // Calculate the difference between now() and duration as soon as possible.
921cb0ef41Sopenharmony_ci  const now = performance.now();
931cb0ef41Sopenharmony_ci  const delta = Math.abs(now - timing.duration);
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  log(JSON.stringify(timing, null, 2));
961cb0ef41Sopenharmony_ci  // Check that the properties are still reasonable.
971cb0ef41Sopenharmony_ci  assert.strictEqual(timing.name, 'node');
981cb0ef41Sopenharmony_ci  assert.strictEqual(timing.entryType, 'node');
991cb0ef41Sopenharmony_ci
1001cb0ef41Sopenharmony_ci  // Check that duration is positive and practically the same as
1011cb0ef41Sopenharmony_ci  // performance.now() i.e. measures Node.js instance up time.
1021cb0ef41Sopenharmony_ci  assert.strictEqual(typeof timing.duration, 'number');
1031cb0ef41Sopenharmony_ci  assert(timing.duration > 0, `timing.duration ${timing.duration} <= 0`);
1041cb0ef41Sopenharmony_ci  assert(delta < 10,
1051cb0ef41Sopenharmony_ci         `now (${now}) - timing.duration (${timing.duration}) = ${delta} >= 10`);
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  // Check that the following fields do not change.
1081cb0ef41Sopenharmony_ci  assert.strictEqual(timing.startTime, initialTiming.startTime);
1091cb0ef41Sopenharmony_ci  assert.strictEqual(timing.nodeStart, initialTiming.nodeStart);
1101cb0ef41Sopenharmony_ci  assert.strictEqual(timing.v8Start, initialTiming.v8Start);
1111cb0ef41Sopenharmony_ci  assert.strictEqual(timing.environment, initialTiming.environment);
1121cb0ef41Sopenharmony_ci  assert.strictEqual(timing.bootstrapComplete, initialTiming.bootstrapComplete);
1131cb0ef41Sopenharmony_ci
1141cb0ef41Sopenharmony_ci  assert.strictEqual(typeof timing.loopStart, 'number');
1151cb0ef41Sopenharmony_ci  assert.strictEqual(typeof timing.loopExit, 'number');
1161cb0ef41Sopenharmony_ci}
1171cb0ef41Sopenharmony_ci
1181cb0ef41Sopenharmony_cilog('check initial nodeTiming');
1191cb0ef41Sopenharmony_cicheckNodeTiming(initialTiming);
1201cb0ef41Sopenharmony_ciassert.strictEqual(initialTiming.loopExit, -1);
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_cifunction checkValue(timing, name, min, max) {
1231cb0ef41Sopenharmony_ci  const value = timing[name];
1241cb0ef41Sopenharmony_ci  assert(value > 0, `${name} ${value} <= 0`);
1251cb0ef41Sopenharmony_ci  // Loop starts after bootstrap completes.
1261cb0ef41Sopenharmony_ci  assert(value > min,
1271cb0ef41Sopenharmony_ci         `${name} ${value} <= ${min}`);
1281cb0ef41Sopenharmony_ci  assert(value < max, `${name} ${value} >= ${max}`);
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_cilet loopStart = initialTiming.loopStart;
1321cb0ef41Sopenharmony_ciif (common.isMainThread) {
1331cb0ef41Sopenharmony_ci  // In the main thread, the loop does not start until we start an operation
1341cb0ef41Sopenharmony_ci  // that requires it, e.g. setTimeout().
1351cb0ef41Sopenharmony_ci  assert.strictEqual(initialTiming.loopStart, -1);
1361cb0ef41Sopenharmony_ci  log('Start timer');
1371cb0ef41Sopenharmony_ci  setTimeout(() => {
1381cb0ef41Sopenharmony_ci    log('Check nodeTiming in timer');
1391cb0ef41Sopenharmony_ci    const timing = { ...performance.nodeTiming };
1401cb0ef41Sopenharmony_ci    checkNodeTiming(timing);
1411cb0ef41Sopenharmony_ci    // Loop should start after we fire the timeout, and before we call
1421cb0ef41Sopenharmony_ci    // performance.now() here.
1431cb0ef41Sopenharmony_ci    loopStart = timing.loopStart;
1441cb0ef41Sopenharmony_ci    checkValue(timing, 'loopStart', initialTiming.duration, performance.now());
1451cb0ef41Sopenharmony_ci  }, 1000);
1461cb0ef41Sopenharmony_ci} else {
1471cb0ef41Sopenharmony_ci  // In the worker, the loop always starts before the user code is evaluated,
1481cb0ef41Sopenharmony_ci  // and after bootstrap completes.
1491cb0ef41Sopenharmony_ci  checkValue(initialTiming,
1501cb0ef41Sopenharmony_ci             'loopStart',
1511cb0ef41Sopenharmony_ci             initialTiming.bootstrapComplete,
1521cb0ef41Sopenharmony_ci             testStartTime);
1531cb0ef41Sopenharmony_ci}
1541cb0ef41Sopenharmony_ci
1551cb0ef41Sopenharmony_ciprocess.on('exit', () => {
1561cb0ef41Sopenharmony_ci  log('Check nodeTiming in process exit event');
1571cb0ef41Sopenharmony_ci  const timing = { ...performance.nodeTiming };
1581cb0ef41Sopenharmony_ci  checkNodeTiming(timing);
1591cb0ef41Sopenharmony_ci  // Check that loopStart does not change.
1601cb0ef41Sopenharmony_ci  assert.strictEqual(timing.loopStart, loopStart);
1611cb0ef41Sopenharmony_ci  checkValue(timing,
1621cb0ef41Sopenharmony_ci             'loopExit',
1631cb0ef41Sopenharmony_ci             loopStart,
1641cb0ef41Sopenharmony_ci             performance.now());
1651cb0ef41Sopenharmony_ci});
166