119 lines
3.4 KiB
Dart
119 lines
3.4 KiB
Dart
import 'dart:typed_data';
|
|
|
|
import 'package:flutter_test/flutter_test.dart';
|
|
|
|
import 'package:dmc_app/transport/loopback/loopback_transport.dart';
|
|
import 'package:dmc_app/transport/msp/msp_client.dart';
|
|
import 'package:dmc_app/transport/msp/msp_commands.dart';
|
|
import 'package:dmc_app/transport/msp/msp_frame.dart';
|
|
import 'package:dmc_app/transport/msp/msp_frame_decoder.dart';
|
|
|
|
MspFrame _decodeSingle(Uint8List bytes) =>
|
|
MspFrameDecoder().addBytes(bytes).single;
|
|
|
|
void main() {
|
|
late LoopbackTransport transport;
|
|
|
|
setUp(() async {
|
|
transport = LoopbackTransport();
|
|
await transport.connect();
|
|
});
|
|
|
|
tearDown(() {
|
|
transport.dispose();
|
|
});
|
|
|
|
test('request() sendet einen MSPv2-Rahmen und liefert den Antwort-Payload',
|
|
() async {
|
|
final client = MspClient(transport);
|
|
final future = client.request(MspCommands.altitude);
|
|
|
|
await Future<void>.delayed(Duration.zero);
|
|
expect(transport.sentData, hasLength(1));
|
|
final sentFrame = _decodeSingle(transport.sentData.single);
|
|
expect(sentFrame.direction, MspDirection.request);
|
|
expect(sentFrame.function, MspCommands.altitude);
|
|
|
|
final payload = Uint8List.fromList([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
|
transport.feed(
|
|
encodeMspV2Frame(MspDirection.response, MspCommands.altitude, payload),
|
|
);
|
|
|
|
expect(await future, payload);
|
|
client.dispose();
|
|
});
|
|
|
|
test('wirft nach Timeout + Wiederholungen MspRequestException und sendet '
|
|
'jedes Mal erneut', () async {
|
|
final client = MspClient(
|
|
transport,
|
|
requestTimeout: const Duration(milliseconds: 30),
|
|
maxRetries: 2,
|
|
);
|
|
|
|
await expectLater(
|
|
client.request(MspCommands.altitude),
|
|
throwsA(isA<MspRequestException>()),
|
|
);
|
|
|
|
// Erstversuch + 2 Wiederholungen = 3 gesendete Anfragen.
|
|
expect(transport.sentData, hasLength(3));
|
|
for (final sent in transport.sentData) {
|
|
expect(_decodeSingle(sent).function, MspCommands.altitude);
|
|
}
|
|
client.dispose();
|
|
});
|
|
|
|
test('Fehlerantwort (dir = \'!\') wirft sofort ohne weiteren Versuch',
|
|
() async {
|
|
final client = MspClient(
|
|
transport,
|
|
requestTimeout: const Duration(seconds: 5),
|
|
maxRetries: 2,
|
|
);
|
|
|
|
final future = client.request(MspCommands.altitude);
|
|
await Future<void>.delayed(Duration.zero);
|
|
transport.feed(
|
|
encodeMspV2Frame(MspDirection.error, MspCommands.altitude, Uint8List(0)),
|
|
);
|
|
|
|
await expectLater(future, throwsA(isA<MspRequestException>()));
|
|
expect(transport.sentData, hasLength(1));
|
|
client.dispose();
|
|
});
|
|
|
|
test('serialisiert ueberlappende Anfragen - immer nur eine offen', () async {
|
|
final client = MspClient(transport);
|
|
|
|
final future1 = client.request(MspCommands.rawGps);
|
|
final future2 = client.request(MspCommands.altitude);
|
|
|
|
await Future<void>.delayed(Duration.zero);
|
|
expect(transport.sentData, hasLength(1));
|
|
expect(_decodeSingle(transport.sentData.single).function,
|
|
MspCommands.rawGps);
|
|
|
|
transport.feed(encodeMspV2Frame(
|
|
MspDirection.response,
|
|
MspCommands.rawGps,
|
|
Uint8List(18),
|
|
));
|
|
await future1;
|
|
await Future<void>.delayed(Duration.zero);
|
|
|
|
expect(transport.sentData, hasLength(2));
|
|
expect(_decodeSingle(transport.sentData[1]).function,
|
|
MspCommands.altitude);
|
|
|
|
transport.feed(encodeMspV2Frame(
|
|
MspDirection.response,
|
|
MspCommands.altitude,
|
|
Uint8List(10),
|
|
));
|
|
await future2;
|
|
|
|
client.dispose();
|
|
});
|
|
}
|