proto-socket/dart/test/communicator_test.dart
toki c384516b47 feat: implement new communication patterns and add cross-test support
- Add Transport class for unified communication layer
- Implement new communicator patterns
- Add VERSIONING.md for version management
- Add crosstest files for Dart/Go integration testing
- Update protocol documentation
- Add new skills and templates for AI-assisted development
- Various bug fixes and improvements to Dart implementation
2026-04-12 07:53:31 +09:00

149 lines
4 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import 'package:protobuf/protobuf.dart';
import 'package:test/test.dart';
import 'package:toki_socket/toki_socket.dart';
class _FakeCommunicator extends Communicator {
final _FakeTransport transport = _FakeTransport();
_FakeCommunicator() {
isAlive = true;
initialize({
TestData.getDefault().info_.qualifiedMessageName: TestData.fromBuffer,
HeartBeat.getDefault().info_.qualifiedMessageName: HeartBeat.fromBuffer,
}, transport: transport);
}
void closeForTest() {
isAlive = false;
cancelPendingRequests();
}
@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();
}
}
class _FakeTransport implements Transport {
final sentPackets = <PacketBase>[];
Object? error;
@override
Future<void> writePacket(PacketBase base) async {
final error = this.error;
if (error != null) {
throw error;
}
sentPackets.add(base);
}
@override
Future<void> close() async {}
}
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.transport.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('close 후 sendRequest는 StateError로 완료ë<C592>œë¤', () async {
final communicator = _FakeCommunicator();
final future = communicator.sendRequest<TestData, TestData>(
TestData()..index = 1,
);
await Future<void>.delayed(Duration.zero);
communicator.closeForTest();
await expectLater(
future,
throwsA(
isA<StateError>().having(
(error) => error.message,
'message',
contains('connection closed'),
),
),
);
});
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>()),
);
});
test('queuePacket uses injected transport', () async {
final communicator = _FakeCommunicator();
final packet = PacketBase()
..typeName = TestData.getDefault().info_.qualifiedMessageName
..nonce = 1
..data = (TestData()..index = 7).writeToBuffer();
await communicator.queuePacket(packet);
expect(communicator.transport.sentPackets, hasLength(1));
expect(communicator.transport.sentPackets.single, same(packet));
final error = StateError('write failed');
communicator.transport.error = error;
await expectLater(
communicator.queuePacket(PacketBase()..typeName = 'TestData'),
throwsA(same(error)),
);
});
});
}