Files
buzz/mobile/test/shared/relay/mp4_fast_start_test.dart
T
cls 9dfa06ffee
Docker image / Build (linux/amd64) (push) Has been cancelled
Docker image / Build (linux/arm64) (push) Has been cancelled
Docker image / Merge release multi-arch manifest (push) Has been cancelled
Docker image / Merge debug multi-arch manifest (push) Has been cancelled
Docker image / Build public push gateway (linux/amd64) (push) Has been cancelled
Docker image / Build public push gateway (linux/arm64) (push) Has been cancelled
Docker image / Publish public push gateway image (push) Has been cancelled
Sprig image / Build (linux/amd64) (push) Has been cancelled
Sprig image / Build (linux/arm64) (push) Has been cancelled
Sprig image / Merge multi-arch manifest (push) Has been cancelled
Harbor Buzz Orchestra / Python tests and lint (push) Has been cancelled
CI / Detect Changed Paths (push) Has been cancelled
CI / Rust Lint (push) Has been cancelled
CI / Unit Tests (push) Has been cancelled
CI / Desktop Core (push) Has been cancelled
CI / Desktop Smoke E2E (1) (push) Has been cancelled
CI / Desktop Smoke E2E (2) (push) Has been cancelled
CI / Desktop Smoke E2E (3) (push) Has been cancelled
CI / Desktop Smoke E2E (4) (push) Has been cancelled
CI / Desktop (push) Has been cancelled
CI / Desktop E2E Relay (push) Has been cancelled
CI / Desktop E2E Integration (1/2) (push) Has been cancelled
CI / Desktop E2E Integration (2/2) (push) Has been cancelled
CI / Desktop E2E Integration (push) Has been cancelled
CI / Backend Integration (relay e2e) (push) Has been cancelled
CI / Relay E2E (push) Has been cancelled
CI / Web (push) Has been cancelled
CI / Mobile (push) Has been cancelled
CI / Security (push) Has been cancelled
CI / Dead Token Reference Guard (push) Has been cancelled
CI / Server Cross-Compile (aarch64-unknown-linux-musl) (push) Has been cancelled
CI / Server Cross-Compile (x86_64-unknown-linux-musl) (push) Has been cancelled
CI / Windows Rust (x86_64-pc-windows-msvc) (push) Has been cancelled
CI / Desktop Build (macOS) (push) Has been cancelled
helm chart / lint + unittest + render matrix (push) Has been cancelled
helm chart / install on kind (gated) (push) Has been cancelled
helm chart / publish chart to GHCR (push) Has been cancelled
Mesh Lifecycle / Relay-Driven Mesh Lifecycle Smoke (push) Has been cancelled
Sprig / Build (aarch64-unknown-linux-musl) (push) Has been cancelled
Sprig / Build (x86_64-unknown-linux-musl) (push) Has been cancelled
Sprig / Publish rolling release (push) Has been cancelled
Sprig / Publish tagged release (push) Has been cancelled
feat: import Chinese-localized Buzz source snapshot
Signed-off-by: cls_宁波本机 <908705107@qq.com>
2026-08-13 18:34:25 +08:00

146 lines
4.2 KiB
Dart

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:buzz/shared/relay/mp4_fast_start.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
late Directory tempDirectory;
setUp(() async {
tempDirectory = await Directory.systemTemp.createTemp(
'buzz-faststart-test-',
);
});
tearDown(() async {
await tempDirectory.delete(recursive: true);
});
for (final offsetBox in ['stco', 'co64']) {
test('moves moov before mdat and patches $offsetBox offsets', () async {
final ftyp = _box('ftyp', [
...ascii.encode('isom'),
0,
0,
0,
0,
...ascii.encode('isom'),
]);
final mdat = _box('mdat', [1, 2, 3, 4]);
final originalMediaOffset = ftyp.length + 8;
final offsetPayload = BytesBuilder()
..add([0, 0, 0, 0])
..add(_uint32(1))
..add(
offsetBox == 'stco'
? _uint32(originalMediaOffset)
: _uint64(originalMediaOffset),
);
final sampleTable = _box(offsetBox, offsetPayload.takeBytes());
final moov = _nestedMoov(sampleTable);
final sourceBytes = Uint8List.fromList([...ftyp, ...mdat, ...moov]);
final source = File('${tempDirectory.path}/source.mp4');
final destination = File('${tempDirectory.path}/output.mp4');
await source.writeAsBytes(sourceBytes);
await rewriteMp4ForFastStart(source, destination);
final output = await destination.readAsBytes();
expect(_topLevelTypes(output), ['ftyp', 'moov', 'mdat']);
expect(
output.sublist(ftyp.length + moov.length + 8),
equals([1, 2, 3, 4]),
);
final typeOffset = _findAscii(output, offsetBox);
expect(typeOffset, greaterThanOrEqualTo(4));
final entryOffset = typeOffset + 12;
final adjusted = offsetBox == 'stco'
? _readUint32(output, entryOffset)
: _readUint64(output, entryOffset);
expect(adjusted, originalMediaOffset + moov.length);
});
}
test(
'rejects excessive nested box depth and deletes partial output',
() async {
final ftyp = _box('ftyp', [
...ascii.encode('isom'),
0,
0,
0,
0,
...ascii.encode('isom'),
]);
final mdat = _box('mdat', [1]);
var nested = _box('stco', [0, 0, 0, 0, ..._uint32(0)]);
for (var index = 0; index < 34; index++) {
nested = _box('stbl', nested);
}
final source = File('${tempDirectory.path}/deep.mp4');
final destination = File('${tempDirectory.path}/output.mp4');
await source.writeAsBytes([...ftyp, ...mdat, ..._box('moov', nested)]);
await expectLater(
rewriteMp4ForFastStart(source, destination),
throwsA(isA<FormatException>()),
);
expect(await destination.exists(), isFalse);
},
);
}
Uint8List _nestedMoov(List<int> leaf) =>
_box('moov', _box('trak', _box('mdia', _box('minf', _box('stbl', leaf)))));
Uint8List _box(String type, List<int> payload) => Uint8List.fromList([
..._uint32(payload.length + 8),
...ascii.encode(type),
...payload,
]);
Uint8List _uint32(int value) {
final bytes = ByteData(4)..setUint32(0, value, Endian.big);
return bytes.buffer.asUint8List();
}
Uint8List _uint64(int value) {
final bytes = ByteData(8)..setUint64(0, value, Endian.big);
return bytes.buffer.asUint8List();
}
int _readUint32(Uint8List bytes, int offset) =>
ByteData.sublistView(bytes).getUint32(offset, Endian.big);
int _readUint64(Uint8List bytes, int offset) =>
ByteData.sublistView(bytes).getUint64(offset, Endian.big);
List<String> _topLevelTypes(Uint8List bytes) {
final types = <String>[];
var offset = 0;
while (offset < bytes.length) {
final size = _readUint32(bytes, offset);
types.add(ascii.decode(bytes.sublist(offset + 4, offset + 8)));
offset += size;
}
return types;
}
int _findAscii(Uint8List bytes, String value) {
final needle = ascii.encode(value);
for (var offset = 0; offset + needle.length <= bytes.length; offset++) {
var matches = true;
for (var index = 0; index < needle.length; index++) {
if (bytes[offset + index] != needle[index]) {
matches = false;
break;
}
}
if (matches) return offset;
}
return -1;
}