import 'dart:async'; import 'dart:io'; import 'package:test/test.dart'; import 'package:toki_socket/toki_socket.dart'; const _testPort = 19090; const _host = 'localhost'; // ── 테스트 전용 픽스처 ────────────────────────────────────────── class _TestClient extends ProtobufClient { _TestClient(Socket socket) : super(socket, 5, 3, { TestData.getDefault().info_.qualifiedMessageName: TestData.fromBuffer, }); } class _TestServer extends ProtobufServer { final receivedMessages = []; final connectedClients = []; _TestServer() : super(_host, _testPort, (socket) => _TestClient(socket)); @override void onClientConnected(ProtobufClient client) { connectedClients.add(client); client.addListener((data) => receivedMessages.add(data)); } } // ── 테스트 ────────────────────────────────────────────────────── void main() { group('ProtobufServer', () { late _TestServer server; setUp(() async { server = _TestServer(); await server.start(); }); tearDown(() async { await server.stop(); }); test('서버가 정상 시작된다', () { expect(server.started, isTrue); }); }); group('ProtobufClient', () { late _TestServer server; late Socket clientSocket; late _TestClient client; setUp(() async { server = _TestServer(); await server.start(); clientSocket = await Socket.connect(_host, _testPort); client = _TestClient(clientSocket); await Future.delayed(const Duration(milliseconds: 100)); }); tearDown(() async { client.dispose(); await Future.delayed(const Duration(milliseconds: 100)); await server.stop(); }); test('클라이언트가 서버에 연결된다', () { expect(server.connectedClients, isNotEmpty); }); test('TestData 메시지를 서버가 수신한다', () async { final msg = TestData() ..index = 42 ..message = 'hello toki-socket'; await client.send(msg); await Future.delayed(const Duration(milliseconds: 200)); expect(server.receivedMessages, hasLength(1)); expect(server.receivedMessages.first.index, equals(42)); expect(server.receivedMessages.first.message, equals('hello toki-socket')); }); test('여러 메시지를 순서대로 수신한다', () async { for (var i = 0; i < 5; i++) { await client.send(TestData() ..index = i ..message = 'msg$i'); } await Future.delayed(const Duration(milliseconds: 300)); expect(server.receivedMessages, hasLength(5)); for (var i = 0; i < 5; i++) { expect(server.receivedMessages[i].index, equals(i)); } }); test('서버에서 클라이언트로 메시지를 전송한다', () async { final completer = Completer(); client.addListener((data) => completer.complete(data)); await Future.delayed(const Duration(milliseconds: 100)); final serverClient = server.connectedClients.first; await serverClient.send(TestData() ..index = 99 ..message = 'from server'); final received = await completer.future.timeout(const Duration(seconds: 2)); expect(received.index, equals(99)); expect(received.message, equals('from server')); }); test('nonce가 송신마다 증가한다', () async { final receivedNonces = []; server.connectedClients.first.addListener((data) {}); // 서버에서 수신한 PacketBase의 nonce를 검증하기 위해 // 클라이언트에서 3개의 메시지를 순서대로 전송 for (var i = 1; i <= 3; i++) { await client.send(TestData()..index = i); } await Future.delayed(const Duration(milliseconds: 200)); // 3개 수신 확인 (nonce 단조 증가는 wire level 검증 — 여기선 수신 순서로 간접 확인) expect(server.receivedMessages, hasLength(3)); }); test('클라이언트 disconnect 시 서버 콜백이 호출된다', () async { final completer = Completer(); server.connectedClients.first.addDisconnectListener((_) { if (!completer.isCompleted) completer.complete(); }); client.dispose(); await completer.future.timeout(const Duration(seconds: 2)); // completer가 완료되면 disconnect 콜백이 정상 호출된 것 expect(completer.isCompleted, isTrue); }); test('HeartBeat interval 동안 연결이 유지된다', () async { // heartbeat interval(5초)보다 짧은 시간 대기 후 메시지 송수신 확인 await Future.delayed(const Duration(seconds: 2)); await client.send(TestData()..index = 1..message = 'alive check'); await Future.delayed(const Duration(milliseconds: 200)); expect(server.receivedMessages, hasLength(1)); }); }); }