blob: 537d1735f44858f956e6cae30ad9deadf8d5acf3 [file] [log] [blame]
// Copyright (C) 2024 The Android Open Source Project
//
// 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
//
// http://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 {HighPrecisionTime as HPTime} from './high_precision_time';
import {HighPrecisionTimeSpan as HPTimeSpan} from './high_precision_time_span';
import {Time} from './time';
const t = Time.fromRaw;
// Quick 'n' dirty function to convert a string to a HPtime
// Used to make tests more readable
// E.g. '1.3' -> {base: 1, offset: 0.3}
// E.g. '-0.3' -> {base: -1, offset: 0.7}
function hptime(time: string): HPTime {
const array = time.split('.');
if (array.length > 2) throw new Error(`Bad time format ${time}`);
const [base, fractions] = array;
const negative = time.startsWith('-');
const numBase = BigInt(base);
if (fractions) {
const numFractions = Number(`0.${fractions}`);
if (negative) {
return new HPTime(t(numBase - 1n), 1.0 - numFractions);
} else {
return new HPTime(t(numBase), numFractions);
}
} else {
return new HPTime(t(numBase));
}
}
describe('HighPrecisionTimeSpan', () => {
it('can be constructed from integer time', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
expect(span.start.integral).toEqual(10n);
expect(span.start.fractional).toBeCloseTo(0);
expect(span.duration).toBeCloseTo(10);
});
test('end', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
expect(span.end.integral).toEqual(20n);
expect(span.end.fractional).toBeCloseTo(0);
});
test('midpoint', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
expect(span.midpoint.integral).toEqual(15n);
expect(span.midpoint.fractional).toBeCloseTo(0);
});
test('translate', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
expect(span.translate(10).start.integral).toEqual(20n);
expect(span.translate(10).start.fractional).toEqual(0);
expect(span.translate(10).duration).toBeCloseTo(10);
});
test('pad', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
expect(span.pad(10).start.integral).toEqual(0n);
expect(span.pad(10).start.fractional).toEqual(0);
expect(span.pad(10).duration).toBeCloseTo(30);
});
test('scale', () => {
const span = HPTimeSpan.fromTime(t(10n), t(20n));
const zoomed = span.scale(2, 0.5, 0);
expect(zoomed.start.integral).toEqual(5n);
expect(zoomed.start.fractional).toBeCloseTo(0);
expect(zoomed.duration).toBeCloseTo(20);
});
test('intersect', () => {
const span = new HPTimeSpan(hptime('5'), 3);
let result = span.intersect(t(7n), t(10n));
expect(result.start.integral).toBe(7n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(1);
result = span.intersect(t(1n), t(6n));
expect(result.start.integral).toBe(5n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(1);
// Non overlapping time spans should return 0
result = span.intersect(t(100n), t(200n));
expect(result.start.integral).toBe(0n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(0);
});
test('fitWithin', () => {
const span = new HPTimeSpan(hptime('5'), 3);
let result = span.fitWithin(t(10n), t(20n));
expect(result.start.integral).toBe(10n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(3);
result = span.fitWithin(t(-10n), t(-5n));
expect(result.start.integral).toBe(-8n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(3);
result = span.fitWithin(t(1n), t(2n));
expect(result.start.integral).toBe(1n);
expect(result.start.fractional).toBeCloseTo(0);
expect(result.duration).toBeCloseTo(1);
});
test('clampDuration', () => {
const span = new HPTimeSpan(hptime('5'), 1);
const clamped = span.clampDuration(10);
expect(clamped.start.integral).toBe(5n);
expect(clamped.start.fractional).toBeCloseTo(0);
expect(clamped.duration).toBeCloseTo(10);
});
test('equality', () => {
const span = new HPTimeSpan(hptime('10'), 10);
expect(span.equals(span)).toBe(true);
expect(span.equals(new HPTimeSpan(hptime('10'), 10.5))).toBe(false);
expect(span.equals(new HPTimeSpan(hptime('10.1'), 10))).toBe(false);
});
test('contains', () => {
const span = new HPTimeSpan(hptime('10'), 10);
expect(span.contains(t(9n))).toBe(false);
expect(span.contains(t(10n))).toBe(true);
expect(span.contains(t(19n))).toBe(true);
expect(span.contains(t(20n))).toBe(false);
});
test('containsSpan', () => {
const span = new HPTimeSpan(hptime('10'), 10);
expect(span.containsSpan(t(9n), t(15n))).toBe(false);
expect(span.containsSpan(t(10n), t(15n))).toBe(true);
expect(span.containsSpan(t(15n), t(20n))).toBe(true);
expect(span.containsSpan(t(15n), t(21n))).toBe(false);
expect(span.containsSpan(t(30n), t(40n))).toBe(false);
});
test('overlapsSpan', () => {
const span = new HPTimeSpan(hptime('10'), 10);
expect(span.overlaps(t(9n), t(10n))).toBe(false);
expect(span.overlaps(t(9n), t(11n))).toBe(true);
expect(span.overlaps(t(19n), t(21n))).toBe(true);
expect(span.overlaps(t(20n), t(21n))).toBe(false);
});
});