mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Add message clear option
This commit is contained in:
116
test/utils/image_message_parser_test.dart
Normal file
116
test/utils/image_message_parser_test.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:meshcore_sar_app/utils/image_message_parser.dart';
|
||||
|
||||
void main() {
|
||||
group('ImageEnvelope', () {
|
||||
test('encodes and parses IE2 with compressed session id', () {
|
||||
final env = ImageEnvelope(
|
||||
sessionId: '0000000a',
|
||||
format: ImageFormat.avif,
|
||||
total: 14,
|
||||
width: 256,
|
||||
height: 171,
|
||||
sizeBytes: 2100,
|
||||
senderKey6: 'aabbccddeeff',
|
||||
timestampSec: 1700000000,
|
||||
);
|
||||
|
||||
final text = env.encode();
|
||||
expect(text.startsWith('IE2:'), isTrue);
|
||||
expect(text.split(':')[1], equals('a'));
|
||||
|
||||
final parsed = ImageEnvelope.tryParse(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('0000000a'));
|
||||
expect(parsed.format, equals(ImageFormat.avif));
|
||||
expect(parsed.total, equals(14));
|
||||
expect(parsed.width, equals(256));
|
||||
expect(parsed.height, equals(171));
|
||||
expect(parsed.sizeBytes, equals(2100));
|
||||
expect(parsed.senderKey6, equals('aabbccddeeff'));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
|
||||
test('rejects IE1 legacy prefix', () {
|
||||
const legacy = 'IE1:deadbeef:0:7:128:128:1050:aabbccddeeff:1700000000:1';
|
||||
expect(ImageEnvelope.tryParse(legacy), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('ImageFetchRequest', () {
|
||||
test('encodes and parses IR2 with compressed sid', () {
|
||||
final req = ImageFetchRequest(
|
||||
sessionId: '0000000a',
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
|
||||
final text = req.encode();
|
||||
expect(text.startsWith('IR2:'), isTrue);
|
||||
expect(text.split(':')[1], equals('a'));
|
||||
|
||||
final parsed = ImageFetchRequest.tryParse(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('0000000a'));
|
||||
expect(parsed.want, equals('all'));
|
||||
expect(parsed.requesterKey6, equals('ffeeddccbbaa'));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
|
||||
test('encodes and parses compact missing index ranges', () {
|
||||
final req = ImageFetchRequest(
|
||||
sessionId: '0000000a',
|
||||
want: 'missing',
|
||||
missingIndices: const [0, 1, 2, 5, 6, 8],
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
|
||||
final text = req.encode();
|
||||
expect(text, contains(':m0-2.5-6.8:'));
|
||||
|
||||
final parsed = ImageFetchRequest.tryParse(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.want, equals('missing'));
|
||||
expect(parsed.missingIndices, equals([0, 1, 2, 5, 6, 8]));
|
||||
});
|
||||
|
||||
test('rejects IR1 legacy prefix', () {
|
||||
const legacy = 'IR1:00112233:a:ffeeddccbbaa:1700000001:1';
|
||||
expect(ImageFetchRequest.tryParse(legacy), isNull);
|
||||
});
|
||||
|
||||
test('encodes and parses binary fetch request', () {
|
||||
final req = ImageFetchRequest(
|
||||
sessionId: '01020304',
|
||||
want: 'missing',
|
||||
missingIndices: const [0, 2, 5],
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
|
||||
final payload = req.encodeBinary();
|
||||
expect(ImageFetchRequest.isRequestBinary(payload), isTrue);
|
||||
|
||||
final parsed = ImageFetchRequest.tryParseBinary(payload);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('01020304'));
|
||||
expect(parsed.want, equals('missing'));
|
||||
expect(parsed.missingIndices, equals([0, 2, 5]));
|
||||
expect(parsed.requesterKey6, equals('ffeeddccbbaa'));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
});
|
||||
|
||||
group('ImageFragmentAck', () {
|
||||
test('encodes and parses binary ack', () {
|
||||
final ack = ImageFragmentAck(sessionId: '01020304', index: 9);
|
||||
final payload = ack.encodeBinary();
|
||||
expect(ImageFragmentAck.isImageFragmentAckBinary(payload), isTrue);
|
||||
final parsed = ImageFragmentAck.tryParseBinary(payload);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('01020304'));
|
||||
expect(parsed.index, equals(9));
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -6,74 +6,122 @@ void main() {
|
||||
group('VoiceEnvelope', () {
|
||||
test('encodes and parses valid envelope', () {
|
||||
final env = VoiceEnvelope(
|
||||
sessionId: 'deadbeef',
|
||||
sessionId: '0000000a',
|
||||
mode: VoicePacketMode.mode1200,
|
||||
total: 4,
|
||||
durationMs: 3200,
|
||||
durationMs: 3000,
|
||||
senderKey6: 'aabbccddeeff',
|
||||
timestampSec: 1700000000,
|
||||
);
|
||||
|
||||
final text = env.encodeText();
|
||||
expect(VoiceEnvelope.isVoiceEnvelopeText(text), isTrue);
|
||||
expect(text.startsWith('VE2:'), isTrue);
|
||||
expect(text.split(':')[1], equals('a'));
|
||||
|
||||
final parsed = VoiceEnvelope.tryParseText(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('deadbeef'));
|
||||
expect(parsed!.sessionId, equals('0000000a'));
|
||||
expect(parsed.mode, equals(VoicePacketMode.mode1200));
|
||||
expect(parsed.total, equals(4));
|
||||
expect(parsed.durationMs, equals(3200));
|
||||
expect(parsed.durationMs, equals(3000));
|
||||
expect(parsed.senderKey6, equals('aabbccddeeff'));
|
||||
expect(parsed.version, equals(1));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
|
||||
test('rejects invalid envelope payload', () {
|
||||
final text = 'VE1:nothex:1:2:1000:aabbccddeeff:1700000000:1';
|
||||
final text = 'VE2:bad_sid:1:2:1000:aabbccddeeff:s44we8';
|
||||
expect(VoiceEnvelope.tryParseText(text), isNull);
|
||||
});
|
||||
|
||||
test('rejects legacy v1 envelope prefix', () {
|
||||
const legacy = 'VE1:deadbeef:1:4:3200:aabbccddeeff:1700000000:1';
|
||||
expect(VoiceEnvelope.tryParseText(legacy), isNull);
|
||||
});
|
||||
});
|
||||
|
||||
group('VoiceFetchRequest', () {
|
||||
test('encodes and parses valid request', () {
|
||||
final req = VoiceFetchRequest(
|
||||
sessionId: '00112233',
|
||||
sessionId: '0000000a',
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
final text = req.encodeText();
|
||||
expect(VoiceFetchRequest.isVoiceFetchRequestText(text), isTrue);
|
||||
expect(text.startsWith('VR2:'), isTrue);
|
||||
expect(text.split(':')[1], equals('a'));
|
||||
|
||||
final parsed = VoiceFetchRequest.tryParseText(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('00112233'));
|
||||
expect(parsed!.sessionId, equals('0000000a'));
|
||||
expect(parsed.want, equals('all'));
|
||||
expect(parsed.requesterKey6, equals('ffeeddccbbaa'));
|
||||
expect(parsed.version, equals(1));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
|
||||
test('rejects invalid request payload', () {
|
||||
expect(
|
||||
VoiceFetchRequest.tryParseText(
|
||||
'VR1:00112233:chunk:ffeeddccbbaa:1700000001:1',
|
||||
'VR2:a:chunk:ffeeddccbbaa:s44we9',
|
||||
),
|
||||
isNull,
|
||||
);
|
||||
});
|
||||
|
||||
test('rejects legacy v1 request prefix', () {
|
||||
const legacy = 'VR1:00112233:a:ffeeddccbbaa:1700000001:1';
|
||||
expect(VoiceFetchRequest.tryParseText(legacy), isNull);
|
||||
});
|
||||
|
||||
test('encodes and parses missing-packet request', () {
|
||||
final req = VoiceFetchRequest(
|
||||
sessionId: '00112233',
|
||||
sessionId: '0000000a',
|
||||
want: 'missing',
|
||||
missingIndices: const [0, 3, 7],
|
||||
missingIndices: const [0, 1, 2, 3, 7],
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
final text = req.encodeText();
|
||||
expect(text, contains(':m0-3.7:'));
|
||||
|
||||
final parsed = VoiceFetchRequest.tryParseText(text);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.want, equals('missing'));
|
||||
expect(parsed.missingIndices, equals([0, 3, 7]));
|
||||
expect(parsed.missingIndices, equals([0, 1, 2, 3, 7]));
|
||||
});
|
||||
|
||||
test('encodes and parses binary fetch request', () {
|
||||
final req = VoiceFetchRequest(
|
||||
sessionId: '01020304',
|
||||
want: 'missing',
|
||||
missingIndices: const [1, 4],
|
||||
requesterKey6: 'ffeeddccbbaa',
|
||||
timestampSec: 1700000001,
|
||||
);
|
||||
|
||||
final payload = req.encodeBinary();
|
||||
expect(VoiceFetchRequest.isVoiceFetchRequestBinary(payload), isTrue);
|
||||
|
||||
final parsed = VoiceFetchRequest.tryParseBinary(payload);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('01020304'));
|
||||
expect(parsed.want, equals('missing'));
|
||||
expect(parsed.missingIndices, equals([1, 4]));
|
||||
expect(parsed.requesterKey6, equals('ffeeddccbbaa'));
|
||||
expect(parsed.version, equals(2));
|
||||
});
|
||||
});
|
||||
|
||||
group('VoiceFragmentAck', () {
|
||||
test('encodes and parses binary ack', () {
|
||||
final ack = VoiceFragmentAck(sessionId: '01020304', index: 7);
|
||||
final payload = ack.encodeBinary();
|
||||
expect(VoiceFragmentAck.isVoiceFragmentAckBinary(payload), isTrue);
|
||||
final parsed = VoiceFragmentAck.tryParseBinary(payload);
|
||||
expect(parsed, isNotNull);
|
||||
expect(parsed!.sessionId, equals('01020304'));
|
||||
expect(parsed.index, equals(7));
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user