• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright (C) 2024 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//      http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15import {HighPrecisionTime as HPTime} from './high_precision_time';
16import {HighPrecisionTimeSpan as HPTimeSpan} from './high_precision_time_span';
17import {Time} from './time';
18
19const t = Time.fromRaw;
20
21// Quick 'n' dirty function to convert a string to a HPtime
22// Used to make tests more readable
23// E.g. '1.3' -> {base: 1, offset: 0.3}
24// E.g. '-0.3' -> {base: -1, offset: 0.7}
25function hptime(time: string): HPTime {
26  const array = time.split('.');
27  if (array.length > 2) throw new Error(`Bad time format ${time}`);
28  const [base, fractions] = array;
29  const negative = time.startsWith('-');
30  const numBase = BigInt(base);
31
32  if (fractions) {
33    const numFractions = Number(`0.${fractions}`);
34    if (negative) {
35      return new HPTime(t(numBase - 1n), 1.0 - numFractions);
36    } else {
37      return new HPTime(t(numBase), numFractions);
38    }
39  } else {
40    return new HPTime(t(numBase));
41  }
42}
43
44describe('HighPrecisionTimeSpan', () => {
45  it('can be constructed from integer time', () => {
46    const span = HPTimeSpan.fromTime(t(10n), t(20n));
47    expect(span.start.integral).toEqual(10n);
48    expect(span.start.fractional).toBeCloseTo(0);
49    expect(span.duration).toBeCloseTo(10);
50  });
51
52  it('can be constructed from hp times', () => {
53    const span = HPTimeSpan.fromHpTimes(hptime('123'), hptime('456'));
54    expect(span.start.integral).toEqual(123n);
55    expect(span.start.fractional).toBeCloseTo(0);
56    expect(span.duration).toBeCloseTo(333);
57  });
58
59  it('can be constructed from hp times reversed', () => {
60    const span = HPTimeSpan.fromHpTimes(hptime('456'), hptime('123'));
61    expect(span.start.integral).toEqual(123n);
62    expect(span.start.fractional).toBeCloseTo(0);
63    expect(span.duration).toBeCloseTo(333);
64  });
65
66  test('end', () => {
67    const span = HPTimeSpan.fromTime(t(10n), t(20n));
68    expect(span.end.integral).toEqual(20n);
69    expect(span.end.fractional).toBeCloseTo(0);
70  });
71
72  test('midpoint', () => {
73    const span = HPTimeSpan.fromTime(t(10n), t(20n));
74    expect(span.midpoint.integral).toEqual(15n);
75    expect(span.midpoint.fractional).toBeCloseTo(0);
76  });
77
78  test('translate', () => {
79    const span = HPTimeSpan.fromTime(t(10n), t(20n));
80    expect(span.translate(10).start.integral).toEqual(20n);
81    expect(span.translate(10).start.fractional).toEqual(0);
82    expect(span.translate(10).duration).toBeCloseTo(10);
83  });
84
85  test('pad', () => {
86    const span = HPTimeSpan.fromTime(t(10n), t(20n));
87    expect(span.pad(10).start.integral).toEqual(0n);
88    expect(span.pad(10).start.fractional).toEqual(0);
89    expect(span.pad(10).duration).toBeCloseTo(30);
90  });
91
92  test('scale', () => {
93    const span = HPTimeSpan.fromTime(t(10n), t(20n));
94    const zoomed = span.scale(2, 0.5, 0);
95    expect(zoomed.start.integral).toEqual(5n);
96    expect(zoomed.start.fractional).toBeCloseTo(0);
97    expect(zoomed.duration).toBeCloseTo(20);
98  });
99
100  test('intersect', () => {
101    const span = new HPTimeSpan(hptime('5'), 3);
102
103    let result = span.intersect(t(7n), t(10n));
104    expect(result.start.integral).toBe(7n);
105    expect(result.start.fractional).toBeCloseTo(0);
106    expect(result.duration).toBeCloseTo(1);
107
108    result = span.intersect(t(1n), t(6n));
109    expect(result.start.integral).toBe(5n);
110    expect(result.start.fractional).toBeCloseTo(0);
111    expect(result.duration).toBeCloseTo(1);
112
113    // Non overlapping time spans should return 0
114    result = span.intersect(t(100n), t(200n));
115    expect(result.start.integral).toBe(0n);
116    expect(result.start.fractional).toBeCloseTo(0);
117    expect(result.duration).toBeCloseTo(0);
118  });
119
120  test('fitWithin', () => {
121    const span = new HPTimeSpan(hptime('5'), 3);
122
123    let result = span.fitWithin(t(10n), t(20n));
124    expect(result.start.integral).toBe(10n);
125    expect(result.start.fractional).toBeCloseTo(0);
126    expect(result.duration).toBeCloseTo(3);
127
128    result = span.fitWithin(t(-10n), t(-5n));
129    expect(result.start.integral).toBe(-8n);
130    expect(result.start.fractional).toBeCloseTo(0);
131    expect(result.duration).toBeCloseTo(3);
132
133    result = span.fitWithin(t(1n), t(2n));
134    expect(result.start.integral).toBe(1n);
135    expect(result.start.fractional).toBeCloseTo(0);
136    expect(result.duration).toBeCloseTo(1);
137  });
138
139  test('clampDuration', () => {
140    const span = new HPTimeSpan(hptime('5'), 1);
141    const clamped = span.clampDuration(10);
142
143    expect(clamped.start.integral).toBe(5n);
144    expect(clamped.start.fractional).toBeCloseTo(0);
145    expect(clamped.duration).toBeCloseTo(10);
146  });
147
148  test('equality', () => {
149    const span = new HPTimeSpan(hptime('10'), 10);
150    expect(span.equals(span)).toBe(true);
151    expect(span.equals(new HPTimeSpan(hptime('10'), 10.5))).toBe(false);
152    expect(span.equals(new HPTimeSpan(hptime('10.1'), 10))).toBe(false);
153  });
154
155  test('contains', () => {
156    const span = new HPTimeSpan(hptime('10'), 10);
157    expect(span.contains(t(9n))).toBe(false);
158    expect(span.contains(t(10n))).toBe(true);
159    expect(span.contains(t(19n))).toBe(true);
160    expect(span.contains(t(20n))).toBe(false);
161  });
162
163  test('containsSpan', () => {
164    const span = new HPTimeSpan(hptime('10'), 10);
165    expect(span.containsSpan(t(9n), t(15n))).toBe(false);
166    expect(span.containsSpan(t(10n), t(15n))).toBe(true);
167    expect(span.containsSpan(t(15n), t(20n))).toBe(true);
168    expect(span.containsSpan(t(15n), t(21n))).toBe(false);
169    expect(span.containsSpan(t(30n), t(40n))).toBe(false);
170  });
171
172  test('overlapsSpan', () => {
173    const span = new HPTimeSpan(hptime('10'), 10);
174    expect(span.overlaps(t(9n), t(10n))).toBe(false);
175    expect(span.overlaps(t(9n), t(11n))).toBe(true);
176    expect(span.overlaps(t(19n), t(21n))).toBe(true);
177    expect(span.overlaps(t(20n), t(21n))).toBe(false);
178  });
179});
180