259 lines
8.6 KiB
TypeScript
259 lines
8.6 KiB
TypeScript
/*
|
|
* Copyright The OpenTelemetry Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* https://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
import * as assert from 'assert';
|
|
import { otperformance as performance } from '../../src/platform';
|
|
import * as sinon from 'sinon';
|
|
import * as api from '@opentelemetry/api';
|
|
import {
|
|
hrTime,
|
|
timeInputToHrTime,
|
|
hrTimeDuration,
|
|
hrTimeToNanoseconds,
|
|
hrTimeToMilliseconds,
|
|
hrTimeToMicroseconds,
|
|
hrTimeToTimeStamp,
|
|
isTimeInput,
|
|
addHrTimes,
|
|
} from '../../src/common/time';
|
|
|
|
describe('time', () => {
|
|
afterEach(() => {
|
|
sinon.restore();
|
|
});
|
|
|
|
describe('#hrTime', () => {
|
|
it('should return hrtime now', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
sinon.stub(performance, 'now').callsFake(() => 11.3);
|
|
|
|
const output = hrTime();
|
|
assert.deepStrictEqual(output, [0, 22800000]);
|
|
});
|
|
|
|
it('should convert performance now', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
const performanceNow = 11.3;
|
|
|
|
const output = hrTime(performanceNow);
|
|
assert.deepStrictEqual(output, [0, 22800000]);
|
|
});
|
|
|
|
it('should handle nanosecond overflow', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
const performanceNow = 11.6;
|
|
|
|
const output = hrTime(performanceNow);
|
|
assert.deepStrictEqual(output, [0, 23100000]);
|
|
});
|
|
|
|
it('should allow passed "performanceNow" equal to 0', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
sinon.stub(performance, 'now').callsFake(() => 11.3);
|
|
|
|
const output = hrTime(0);
|
|
assert.deepStrictEqual(output, [0, 11500000]);
|
|
});
|
|
|
|
it('should use performance.now() when "performanceNow" is equal to undefined', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
sinon.stub(performance, 'now').callsFake(() => 11.3);
|
|
|
|
const output = hrTime(undefined);
|
|
assert.deepStrictEqual(output, [0, 22800000]);
|
|
});
|
|
|
|
it('should use performance.now() when "performanceNow" is equal to null', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(11.5);
|
|
sinon.stub(performance, 'now').callsFake(() => 11.3);
|
|
|
|
const output = hrTime(null as any);
|
|
assert.deepStrictEqual(output, [0, 22800000]);
|
|
});
|
|
|
|
describe('when timeOrigin is not available', () => {
|
|
it('should use the performance.timing.fetchStart as a fallback', () => {
|
|
Object.defineProperty(performance, 'timing', {
|
|
writable: true,
|
|
value: {
|
|
fetchStart: 11.5,
|
|
},
|
|
});
|
|
|
|
sinon.stub(performance, 'timeOrigin').value(undefined);
|
|
sinon.stub(performance, 'now').callsFake(() => 11.3);
|
|
|
|
const output = hrTime();
|
|
assert.deepStrictEqual(output, [0, 22800000]);
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('#timeInputToHrTime', () => {
|
|
it('should convert Date hrTime', () => {
|
|
const timeInput = new Date(1609297640313);
|
|
const output = timeInputToHrTime(timeInput);
|
|
assert.deepStrictEqual(output, [1609297640, 313000000]);
|
|
});
|
|
|
|
it('should convert epoch milliseconds hrTime', () => {
|
|
const timeInput = Date.now();
|
|
const output = timeInputToHrTime(timeInput);
|
|
assert.deepStrictEqual(output[0], Math.trunc(timeInput / 1000));
|
|
});
|
|
|
|
it('should convert arbitrary epoch milliseconds (with sub-millis precision) hrTime', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(111.5);
|
|
const inputs = [
|
|
// [ input, expected ]
|
|
[1609297640313, [1609297640, 313000000]],
|
|
// inevitable precision loss without decimal arithmetics.
|
|
[1609297640313.333, [1609297640, 313333008]],
|
|
// eslint-disable-next-line @typescript-eslint/no-loss-of-precision
|
|
[1609297640313.333333333, [1609297640, 313333252]],
|
|
] as const;
|
|
for (const [idx, input] of inputs.entries()) {
|
|
const output = timeInputToHrTime(input[0]);
|
|
assert.deepStrictEqual(output, input[1], `input[${idx}]: ${input}`);
|
|
}
|
|
});
|
|
|
|
it('should convert performance.now() hrTime', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(111.5);
|
|
|
|
const timeInput = 11.9;
|
|
const output = timeInputToHrTime(timeInput);
|
|
|
|
assert.deepStrictEqual(output, [0, 123400000]);
|
|
});
|
|
|
|
it('should not convert hrtime hrTime', () => {
|
|
sinon.stub(performance, 'timeOrigin').value(111.5);
|
|
|
|
const timeInput: [number, number] = [3138971, 245466222];
|
|
const output = timeInputToHrTime(timeInput);
|
|
|
|
assert.deepStrictEqual(timeInput, output);
|
|
});
|
|
});
|
|
|
|
describe('#hrTimeDuration', () => {
|
|
it('should return duration', () => {
|
|
const startTime: api.HrTime = [22, 400000000];
|
|
const endTime: api.HrTime = [32, 800000000];
|
|
|
|
const output = hrTimeDuration(startTime, endTime);
|
|
assert.deepStrictEqual(output, [10, 400000000]);
|
|
});
|
|
|
|
it('should handle nanosecond overflow', () => {
|
|
const startTime: api.HrTime = [22, 400000000];
|
|
const endTime: api.HrTime = [32, 200000000];
|
|
|
|
const output = hrTimeDuration(startTime, endTime);
|
|
assert.deepStrictEqual(output, [9, 800000000]);
|
|
});
|
|
});
|
|
|
|
describe('#hrTimeToTimeStamp', () => {
|
|
it('should return timestamp', () => {
|
|
const time: api.HrTime = [1573513121, 123456];
|
|
|
|
const output = hrTimeToTimeStamp(time);
|
|
assert.deepStrictEqual(output, '2019-11-11T22:58:41.000123456Z');
|
|
});
|
|
});
|
|
|
|
describe('#hrTimeToNanoseconds', () => {
|
|
it('should return nanoseconds', () => {
|
|
const output = hrTimeToNanoseconds([1, 200000000]);
|
|
assert.deepStrictEqual(output, 1200000000);
|
|
});
|
|
});
|
|
|
|
describe('#hrTimeToMilliseconds', () => {
|
|
it('should return milliseconds', () => {
|
|
const output = hrTimeToMilliseconds([1, 200000000]);
|
|
assert.deepStrictEqual(output, 1200);
|
|
});
|
|
});
|
|
|
|
describe('#hrTimeToMicroseconds', () => {
|
|
it('should return microseconds', () => {
|
|
const output = hrTimeToMicroseconds([1, 200000000]);
|
|
assert.deepStrictEqual(output, 1200000);
|
|
});
|
|
});
|
|
describe('#isTimeInput', () => {
|
|
it('should return true for a number', () => {
|
|
assert.strictEqual(isTimeInput(12), true);
|
|
});
|
|
it('should return true for a date', () => {
|
|
assert.strictEqual(isTimeInput(new Date()), true);
|
|
});
|
|
it('should return true for an array with 2 elements type number', () => {
|
|
assert.strictEqual(isTimeInput([1, 1]), true);
|
|
});
|
|
it('should return FALSE for different cases for an array ', () => {
|
|
assert.strictEqual(isTimeInput([1, 1, 1]), false);
|
|
assert.strictEqual(isTimeInput([1]), false);
|
|
assert.strictEqual(isTimeInput([1, 'a']), false);
|
|
});
|
|
it('should return FALSE for a string', () => {
|
|
assert.strictEqual(isTimeInput('a'), false);
|
|
});
|
|
it('should return FALSE for an object', () => {
|
|
assert.strictEqual(isTimeInput({}), false);
|
|
});
|
|
it('should return FALSE for a null', () => {
|
|
assert.strictEqual(isTimeInput(null), false);
|
|
});
|
|
it('should return FALSE for undefined', () => {
|
|
assert.strictEqual(isTimeInput(undefined), false);
|
|
});
|
|
});
|
|
|
|
describe('#addHrTimes', () => {
|
|
const NANOSECOND_DIGITS = 9;
|
|
const SECOND_TO_NANOSECONDS = Math.pow(10, NANOSECOND_DIGITS);
|
|
|
|
it('should add two positive times', () => {
|
|
const output = addHrTimes([10, 20], [30, 40]);
|
|
assert.deepStrictEqual(output, [40, 60]);
|
|
});
|
|
it('should add two negative times', () => {
|
|
const output = addHrTimes([-10, 20], [-30, 40]);
|
|
assert.deepStrictEqual(output, [-40, 60]);
|
|
});
|
|
it('should add a positive and negative time (result positive)', () => {
|
|
const output = addHrTimes([-10, 20], [30, 40]);
|
|
assert.deepStrictEqual(output, [20, 60]);
|
|
});
|
|
it('should add a positive and negative time (result negative)', () => {
|
|
const output = addHrTimes([10, 20], [-30, 40]);
|
|
assert.deepStrictEqual(output, [-20, 60]);
|
|
});
|
|
it('should overflow nanoseconds to seconds', () => {
|
|
const output = addHrTimes([10, SECOND_TO_NANOSECONDS - 10], [10, 20]);
|
|
assert.deepStrictEqual(output, [21, 10]);
|
|
});
|
|
it('should overflow nanoseconds to seconds (negative)', () => {
|
|
const output = addHrTimes([-10, SECOND_TO_NANOSECONDS - 10], [-10, 20]);
|
|
assert.deepStrictEqual(output, [-19, 10]);
|
|
});
|
|
});
|
|
});
|