<!-- task=crosstest_coverage_gaps plan=2 tag=REVIEW_REVIEW_CROSSTEST-COVERAGE -->

# Review Follow-up Plan - REVIEW_REVIEW_CROSSTEST-COVERAGE

## 개요

date=2026-04-25
task=crosstest_coverage_gaps, plan=2, tag=REVIEW_REVIEW_CROSSTEST-COVERAGE

## 배경

plan=1 리뷰 결과 `FAIL` 판정이 나왔다. Kotlin `./gradlew test`는 통과했지만, 테스트에서 추가한 `waitForCondition { server.clients().size == 1 }`는 listener/request handler 등록 완료를 보장하지 않는다.

Kotlin 서버 구현은 다음 순서로 동작한다.

```kotlin
clients.add(client)
onClientConnected(client)
```

따라서 테스트가 `server.clients().size == 1` 조건을 만족하더라도 `onClientConnected` 안의 `addListenerTyped` 또는 `addRequestListenerTyped`가 아직 끝나지 않았을 수 있다.

## 작업 범위

### [REVIEW_REVIEW_CROSSTEST-COVERAGE-1] Kotlin 테스트 listener/request handler readiness 보장

**문제**

`testTcpSendReceive`, `testWsSendReceive`, `testTcpConcurrentRequests`, `testWsConcurrentRequests`가 연결 확인만 하고 listener/request handler 등록 완료를 기다리지 않는다. 원래 suite hang의 원인으로 본 race를 완전히 제거하지 못한다.

**해결 방향**

- 각 테스트에서 `CompletableDeferred<Unit>` 같은 readiness 신호를 둔다.
- `server.onClientConnected` 안에서 listener 또는 request listener를 등록한 직후 readiness를 complete한다.
- 클라이언트 연결 후 send/request 시작 전에 readiness를 await한다.
- `server.clients().size` 대기는 연결 수 확인 용도로만 필요할 때 유지하고, listener 등록 완료 근거로 사용하지 않는다.

Before:

```kotlin
server.onClientConnected = { client ->
    addListenerTyped<TestData>(client.communicator) { received.complete(it) }
}
val client = DialTcp(...)
waitForCondition(message = "client did not connect") { server.clients().size == 1 }
client.send(...)
```

After:

```kotlin
val listenerReady = CompletableDeferred<Unit>()
server.onClientConnected = { client ->
    addListenerTyped<TestData>(client.communicator) { received.complete(it) }
    listenerReady.complete(Unit)
}
val client = DialTcp(...)
listenerReady.await()
client.send(...)
```

**체크리스트**

- [ ] TCP send/receive 테스트가 listener 등록 완료 후 send한다.
- [ ] WS send/receive 테스트가 listener 등록 완료 후 send한다.
- [ ] TCP concurrent request 테스트가 request handler 등록 완료 후 요청을 시작한다.
- [ ] WS concurrent request 테스트가 request handler 등록 완료 후 요청을 시작한다.
- [ ] concurrent 테스트의 `try/finally` cleanup은 유지한다.

**검증**

```bash
cd kotlin && ./gradlew test --tests com.tokilabs.toki_socket.TcpTest
cd kotlin && ./gradlew test --tests com.tokilabs.toki_socket.WsTest
```

## 최종 검증

```bash
cd kotlin && ./gradlew test
git diff --check
```

## 범위 밖

- Kotlin production server/client 동작 변경
- Dart/Go/Python/TypeScript 구현 변경
- secure transport API 신규 구현
9