• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (C) 2022 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16import {ElapsedTimestamp, RealTimestamp, Timestamp, TimestampType} from 'trace/timestamp';
17import {TimeUtils} from './time_utils';
18
19describe('TimeUtils', () => {
20  const MILLISECOND = BigInt(1000000);
21  const SECOND = BigInt(1000) * MILLISECOND;
22  const MINUTE = BigInt(60) * SECOND;
23  const HOUR = BigInt(60) * MINUTE;
24  const DAY = BigInt(24) * HOUR;
25
26  describe('compareFn', () => {
27    it('throws if timestamps have different type', () => {
28      const real = new RealTimestamp(10n);
29      const elapsed = new ElapsedTimestamp(10n);
30
31      expect(() => {
32        TimeUtils.compareFn(real, elapsed);
33      }).toThrow();
34    });
35
36    it('allows to sort arrays', () => {
37      const array = [
38        new RealTimestamp(100n),
39        new RealTimestamp(10n),
40        new RealTimestamp(12n),
41        new RealTimestamp(110n),
42        new RealTimestamp(11n),
43      ];
44      array.sort(TimeUtils.compareFn);
45
46      const expected = [
47        new RealTimestamp(10n),
48        new RealTimestamp(11n),
49        new RealTimestamp(12n),
50        new RealTimestamp(100n),
51        new RealTimestamp(110n),
52      ];
53      expect(array).toEqual(expected);
54    });
55  });
56
57  it('nanosecondsToHuman', () => {
58    expect(TimeUtils.format(new ElapsedTimestamp(0n), true)).toEqual('0ms');
59    expect(TimeUtils.format(new ElapsedTimestamp(0n), false)).toEqual('0ns');
60    expect(TimeUtils.format(new ElapsedTimestamp(1000n), true)).toEqual('0ms');
61    expect(TimeUtils.format(new ElapsedTimestamp(1000n), false)).toEqual('1000ns');
62    expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND - 1n), true)).toEqual('0ms');
63    expect(TimeUtils.format(new ElapsedTimestamp(MILLISECOND), true)).toEqual('1ms');
64    expect(TimeUtils.format(new ElapsedTimestamp(10n * MILLISECOND), true)).toEqual('10ms');
65
66    expect(TimeUtils.format(new ElapsedTimestamp(SECOND - 1n), true)).toEqual('999ms');
67    expect(TimeUtils.format(new ElapsedTimestamp(SECOND), true)).toEqual('1s0ms');
68    expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), true)).toEqual('1s1ms');
69    expect(TimeUtils.format(new ElapsedTimestamp(SECOND + MILLISECOND), false)).toEqual('1s1ms0ns');
70
71    expect(TimeUtils.format(new ElapsedTimestamp(MINUTE - 1n), true)).toEqual('59s999ms');
72    expect(TimeUtils.format(new ElapsedTimestamp(MINUTE), true)).toEqual('1m0s0ms');
73    expect(TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND), true)).toEqual(
74      '1m1s1ms'
75    );
76    expect(
77      TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), true)
78    ).toEqual('1m1s1ms');
79    expect(
80      TimeUtils.format(new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND + 1n), false)
81    ).toEqual('1m1s1ms1ns');
82
83    expect(TimeUtils.format(new ElapsedTimestamp(HOUR - 1n), true)).toEqual('59m59s999ms');
84    expect(TimeUtils.format(new ElapsedTimestamp(HOUR - 1n), false)).toEqual('59m59s999ms999999ns');
85    expect(TimeUtils.format(new ElapsedTimestamp(HOUR), true)).toEqual('1h0m0s0ms');
86    expect(
87      TimeUtils.format(new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND), true)
88    ).toEqual('1h1m1s1ms');
89
90    expect(TimeUtils.format(new ElapsedTimestamp(DAY - 1n), true)).toEqual('23h59m59s999ms');
91    expect(TimeUtils.format(new ElapsedTimestamp(DAY), true)).toEqual('1d0h0m0s0ms');
92    expect(
93      TimeUtils.format(new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND), true)
94    ).toEqual('1d1h1m1s1ms');
95  });
96
97  it('humanElapsedToNanoseconds', () => {
98    expect(TimeUtils.parseHumanElapsed('0ns')).toEqual(new ElapsedTimestamp(0n));
99    expect(TimeUtils.parseHumanElapsed('1000ns')).toEqual(new ElapsedTimestamp(1000n));
100    expect(TimeUtils.parseHumanElapsed('0ms')).toEqual(new ElapsedTimestamp(0n));
101    expect(TimeUtils.parseHumanElapsed('1ms')).toEqual(new ElapsedTimestamp(MILLISECOND));
102    expect(TimeUtils.parseHumanElapsed('10ms')).toEqual(new ElapsedTimestamp(10n * MILLISECOND));
103
104    expect(TimeUtils.parseHumanElapsed('999ms')).toEqual(new ElapsedTimestamp(999n * MILLISECOND));
105    expect(TimeUtils.parseHumanElapsed('1s')).toEqual(new ElapsedTimestamp(SECOND));
106    expect(TimeUtils.parseHumanElapsed('1s0ms')).toEqual(new ElapsedTimestamp(SECOND));
107    expect(TimeUtils.parseHumanElapsed('1s0ms0ns')).toEqual(new ElapsedTimestamp(SECOND));
108    expect(TimeUtils.parseHumanElapsed('1s0ms1ns')).toEqual(new ElapsedTimestamp(SECOND + 1n));
109    expect(TimeUtils.parseHumanElapsed('0d1s1ms')).toEqual(
110      new ElapsedTimestamp(SECOND + MILLISECOND)
111    );
112
113    expect(TimeUtils.parseHumanElapsed('1m0s0ms')).toEqual(new ElapsedTimestamp(MINUTE));
114    expect(TimeUtils.parseHumanElapsed('1m1s1ms')).toEqual(
115      new ElapsedTimestamp(MINUTE + SECOND + MILLISECOND)
116    );
117
118    expect(TimeUtils.parseHumanElapsed('1h0m')).toEqual(new ElapsedTimestamp(HOUR));
119    expect(TimeUtils.parseHumanElapsed('1h1m1s1ms')).toEqual(
120      new ElapsedTimestamp(HOUR + MINUTE + SECOND + MILLISECOND)
121    );
122
123    expect(TimeUtils.parseHumanElapsed('1d0s1ms')).toEqual(new ElapsedTimestamp(DAY + MILLISECOND));
124    expect(TimeUtils.parseHumanElapsed('1d1h1m1s1ms')).toEqual(
125      new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND)
126    );
127
128    expect(TimeUtils.parseHumanElapsed('1d')).toEqual(new ElapsedTimestamp(DAY));
129    expect(TimeUtils.parseHumanElapsed('1d1ms')).toEqual(new ElapsedTimestamp(DAY + MILLISECOND));
130  });
131
132  it('humanToNanoseconds throws on invalid input format', () => {
133    const invalidFormatError = new Error('Invalid elapsed timestamp format');
134    expect(() => TimeUtils.parseHumanElapsed('1d1h1m1s0ns1ms')).toThrow(invalidFormatError);
135    expect(() => TimeUtils.parseHumanElapsed('1dns')).toThrow(invalidFormatError);
136    expect(() => TimeUtils.parseHumanElapsed('100')).toThrow(invalidFormatError);
137    expect(() => TimeUtils.parseHumanElapsed('')).toThrow(invalidFormatError);
138  });
139
140  it('nanosecondsToHumanReal', () => {
141    const NOV_10_2022 = 1668038400000n * MILLISECOND;
142    expect(TimeUtils.format(new RealTimestamp(0n), true)).toEqual('1970-01-01T00:00:00.000');
143    expect(
144      TimeUtils.format(
145        new RealTimestamp(
146          NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n
147        ),
148        true
149      )
150    ).toEqual('2022-11-10T22:04:54.186');
151    expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), true)).toEqual(
152      '2022-11-10T00:00:00.000'
153    );
154    expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), true)).toEqual(
155      '2022-11-10T00:00:00.000'
156    );
157
158    expect(TimeUtils.format(new RealTimestamp(0n), false)).toEqual('1970-01-01T00:00:00.000000000');
159    expect(
160      TimeUtils.format(
161        new RealTimestamp(
162          NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n
163        ),
164        false
165      )
166    ).toEqual('2022-11-10T22:04:54.186123212');
167    expect(TimeUtils.format(new RealTimestamp(NOV_10_2022), false)).toEqual(
168      '2022-11-10T00:00:00.000000000'
169    );
170    expect(TimeUtils.format(new RealTimestamp(NOV_10_2022 + 1n), false)).toEqual(
171      '2022-11-10T00:00:00.000000001'
172    );
173  });
174
175  it('humanRealToNanoseconds', () => {
176    const NOV_10_2022 = 1668038400000n * MILLISECOND;
177    expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186123212')).toEqual(
178      new RealTimestamp(
179        NOV_10_2022 + 22n * HOUR + 4n * MINUTE + 54n * SECOND + 186n * MILLISECOND + 123212n
180      )
181    );
182    expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186123212Z')).toEqual(
183      new RealTimestamp(1668117894186123212n)
184    );
185    expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.186000212')).toEqual(
186      new RealTimestamp(1668117894186000212n)
187    );
188    expect(TimeUtils.parseHumanReal('2022-11-10T22:04:54.006000002')).toEqual(
189      new RealTimestamp(1668117894006000002n)
190    );
191    expect(TimeUtils.parseHumanReal('2022-11-10T06:04:54.006000002')).toEqual(
192      new RealTimestamp(1668060294006000002n)
193    );
194  });
195
196  it('canReverseDateFormatting', () => {
197    let timestamp = new RealTimestamp(1668117894186123212n);
198    expect(TimeUtils.parseHumanReal(TimeUtils.format(timestamp))).toEqual(timestamp);
199
200    timestamp = new ElapsedTimestamp(DAY + HOUR + MINUTE + SECOND + MILLISECOND + 1n);
201    expect(TimeUtils.parseHumanElapsed(TimeUtils.format(timestamp))).toEqual(timestamp);
202  });
203
204  it('humanToNanoseconds throws on invalid input format', () => {
205    const invalidFormatError = new Error('Invalid real timestamp format');
206    expect(() => TimeUtils.parseHumanReal('23h59m59s999ms5ns')).toThrow(invalidFormatError);
207    expect(() => TimeUtils.parseHumanReal('1d')).toThrow(invalidFormatError);
208    expect(() => TimeUtils.parseHumanReal('100')).toThrow(invalidFormatError);
209    expect(() => TimeUtils.parseHumanReal('06h4m54s, 10 Nov 2022')).toThrow(invalidFormatError);
210    expect(() => TimeUtils.parseHumanReal('')).toThrow(invalidFormatError);
211  });
212
213  it('nano second regex accept all expected inputs', () => {
214    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123')).toBeTrue();
215    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123ns')).toBeTrue();
216    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('123 ns')).toBeTrue();
217    expect(TimeUtils.NS_TIMESTAMP_REGEX.test(' 123 ns ')).toBeTrue();
218    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('   123  ')).toBeTrue();
219
220    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('1a23')).toBeFalse();
221    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('a123 ns')).toBeFalse();
222    expect(TimeUtils.NS_TIMESTAMP_REGEX.test('')).toBeFalse();
223  });
224
225  it('format real', () => {
226    expect(TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n, 500n))).toEqual(
227      '1970-01-01T00:00:00.000000600'
228    );
229    expect(
230      TimeUtils.format(Timestamp.from(TimestampType.REAL, 100n * MILLISECOND, 500n), true)
231    ).toEqual('1970-01-01T00:00:00.100');
232  });
233
234  it('format elapsed', () => {
235    expect(
236      TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n), true)
237    ).toEqual('100ms');
238    expect(
239      TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND), true)
240    ).toEqual('100ms');
241    expect(
242      TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND, 500n))
243    ).toEqual('100ms0ns');
244    expect(TimeUtils.format(Timestamp.from(TimestampType.ELAPSED, 100n * MILLISECOND))).toEqual(
245      '100ms0ns'
246    );
247  });
248});
249