136 lines
4.6 KiB
TypeScript
136 lines
4.6 KiB
TypeScript
// Copyright 2025 Signal Messenger, LLC
|
|
// SPDX-License-Identifier: AGPL-3.0-only
|
|
import assert from 'node:assert/strict';
|
|
import {
|
|
_getSegmentRanges,
|
|
_getSegmentSize,
|
|
_SEGMENT_SIZE_BUCKETS,
|
|
type _SegmentRange,
|
|
} from '../../../components/fun/data/segments';
|
|
|
|
const SMALLEST_BUCKET = Math.min(..._SEGMENT_SIZE_BUCKETS);
|
|
|
|
describe('segments', () => {
|
|
describe('_getSegmentSize', () => {
|
|
function check(contentLength: number, expectedSize: number, label: string) {
|
|
assert.equal(_getSegmentSize(contentLength), expectedSize, label);
|
|
}
|
|
|
|
it('should use the content-length if its shorter than the smallest segment size', () => {
|
|
check(0, 0, 'zero');
|
|
check(1, 1, 'one');
|
|
check(10, 10, 'ten');
|
|
check(SMALLEST_BUCKET - 1, SMALLEST_BUCKET - 1, 'smallest - 1');
|
|
check(SMALLEST_BUCKET - 10, SMALLEST_BUCKET - 10, 'smallest - 10');
|
|
});
|
|
|
|
it('should pick the closest smaller bucket to the content-length', () => {
|
|
_SEGMENT_SIZE_BUCKETS.forEach((size, index) => {
|
|
check(size, size, `exact size ${size}`);
|
|
check(size + 1, size, `size ${size} + 1`);
|
|
check(size + 10, size, `size ${size} + 10`);
|
|
const largerSize = _SEGMENT_SIZE_BUCKETS[index - 1] ?? null; // Note: at() wraps
|
|
if (largerSize != null) {
|
|
check(largerSize - 1, size, `larger size ${largerSize} - 1`);
|
|
check(largerSize - 10, size, `larger size ${largerSize} - 10`);
|
|
}
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('_getSegmentRanges', () => {
|
|
function check(
|
|
contentLength: number,
|
|
segmentSize: number,
|
|
expected: ReadonlyArray<_SegmentRange>
|
|
) {
|
|
assert.deepEqual(_getSegmentRanges(contentLength, segmentSize), expected);
|
|
}
|
|
|
|
function segmentAtIndex(segmentSize: number, index: number): _SegmentRange {
|
|
return {
|
|
startIndex: segmentSize * index,
|
|
endIndexInclusive: segmentSize * (index + 1) - 1,
|
|
sliceStart: 0,
|
|
sliceSize: segmentSize,
|
|
segmentSize,
|
|
};
|
|
}
|
|
|
|
function finalSegment(contentLength: number, segmentSize: number) {
|
|
const offset = contentLength % segmentSize;
|
|
return {
|
|
startIndex: contentLength - segmentSize,
|
|
endIndexInclusive: contentLength - 1,
|
|
sliceStart: segmentSize - offset,
|
|
sliceSize: offset,
|
|
segmentSize,
|
|
};
|
|
}
|
|
|
|
it('should return 0 segments for contentLength 0', () => {
|
|
const contentLength = 0;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, []);
|
|
});
|
|
|
|
it('should return 1 segments for contentLength equal to bucket segmentSize', () => {
|
|
const contentLength = SMALLEST_BUCKET;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [segmentAtIndex(segmentSize, 0)]);
|
|
});
|
|
|
|
it('should return 2 segments for contentLength slightly bigger than segmentSize', () => {
|
|
const offset = 10;
|
|
const contentLength = SMALLEST_BUCKET + offset;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [
|
|
segmentAtIndex(segmentSize, 0),
|
|
finalSegment(contentLength, segmentSize),
|
|
]);
|
|
});
|
|
|
|
it('should return 2 segments for contentLength equal to 2x segmentSize', () => {
|
|
const contentLength = SMALLEST_BUCKET * 2;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [
|
|
segmentAtIndex(segmentSize, 0),
|
|
segmentAtIndex(segmentSize, 1),
|
|
]);
|
|
});
|
|
|
|
it('should return 3 segments for contentLength slightly bigger than 2x segmentSize', () => {
|
|
const offset = 10;
|
|
const contentLength = SMALLEST_BUCKET * 2 + offset;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [
|
|
segmentAtIndex(segmentSize, 0),
|
|
segmentAtIndex(segmentSize, 1),
|
|
finalSegment(contentLength, segmentSize),
|
|
]);
|
|
});
|
|
|
|
it('should return 3 segments for contentLength equal to 3x segmentSize', () => {
|
|
const contentLength = SMALLEST_BUCKET * 3;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [
|
|
segmentAtIndex(segmentSize, 0),
|
|
segmentAtIndex(segmentSize, 1),
|
|
segmentAtIndex(segmentSize, 2),
|
|
]);
|
|
});
|
|
|
|
it('should return 4 segments for contentLength slightly bigger than 3x segmentSize', () => {
|
|
const offset = 10;
|
|
const contentLength = SMALLEST_BUCKET * 3 + offset;
|
|
const segmentSize = SMALLEST_BUCKET;
|
|
check(contentLength, segmentSize, [
|
|
segmentAtIndex(segmentSize, 0),
|
|
segmentAtIndex(segmentSize, 1),
|
|
segmentAtIndex(segmentSize, 2),
|
|
finalSegment(contentLength, segmentSize),
|
|
]);
|
|
});
|
|
});
|
|
});
|