proto-socket/dart/test/communicator_test.dart
toki cab031ea28 Refactor client implementations with baseClient pattern
- Dart: Add explicit Future<void> return type to send() method
- Dart: Improve onDisconnected() logic with proper isAlive handling and heartbeat response
- Go: Introduce baseClient generic base class for shared client logic
- Go: Refactor TcpClient and WsClient to embed baseClient instead of embedding Communicator
- Remove duplicate heartbeat and disconnect handling code across client implementations
- Clean up unused imports (time package)
2026-04-11 13:52:50 +09:00

91 lines
2.4 KiB
Dart

import 'package:protobuf/protobuf.dart';
import 'package:test/test.dart';
import 'package:toki_socket/toki_socket.dart';
class _FakeCommunicator extends Communicator {
final sentPackets = <PacketBase>[];
_FakeCommunicator() {
isAlive = true;
initialize({
TestData.getDefault().info_.qualifiedMessageName: TestData.fromBuffer,
HeartBeat.getDefault().info_.qualifiedMessageName: HeartBeat.fromBuffer,
});
}
@override
Future<void> transmitPacket(PacketBase base) async {
sentPackets.add(base);
}
@override
Future<void> send<T extends GeneratedMessage>(T data) async {
if (isAlive) {
await queuePacket(PacketBase()
..typeName = data.info_.qualifiedMessageName
..nonce = ++nonce
..data = data.writeToBuffer());
}
return Future.value();
}
}
void main() {
group('Communicator protocol guards', () {
test('response typeName mismatch completes sendRequest with error',
() async {
final communicator = _FakeCommunicator();
final future = communicator.sendRequest<TestData, TestData>(
TestData()
..index = 1
..message = 'hello',
);
await Future<void>.delayed(Duration.zero);
final requestNonce = communicator.sentPackets.single.nonce;
communicator.onReceivedData(
HeartBeat.getDefault().info_.qualifiedMessageName,
HeartBeat().writeToBuffer(),
responseNonce: requestNonce,
);
await expectLater(
future,
throwsA(
isA<StateError>().having((error) => error.toString(), 'message',
contains('Response type mismatch')),
),
);
});
test(
'cannot register addRequestListener for a type already using addListener',
() {
final communicator = _FakeCommunicator();
communicator.addListener<TestData>((_) {});
expect(
() => communicator.addRequestListener<TestData, TestData>(
(req) async => TestData()..index = req.index,
),
throwsA(isA<StateError>()),
);
});
test(
'cannot register addListener for a type already using addRequestListener',
() {
final communicator = _FakeCommunicator();
communicator.addRequestListener<TestData, TestData>(
(req) async => TestData()..index = req.index,
);
expect(
() => communicator.addListener<TestData>((_) {}),
throwsA(isA<StateError>()),
);
});
});
}