proto-socket/agent-task/ts_kotlin_wss_crosstest/plan_0.log

199 lines
6.3 KiB
Text
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.

<!-- task=ts_kotlin_wss_crosstest plan=0 tag=TEST -->
# TypeScript→Kotlin 크로스테스트 WSS 페이즈 추가
## 이 파일을 읽는 구현 에이전트에게
각 체크리스트 항목을 완료 후 `[x]`로 체크하고, 중간 검증과 최종 검증 명령을 실제로 실행한 뒤 출력을 `CODE_REVIEW.md`의 `검증 결과` 섹션에 붙여넣으세요. 계획과 다르게 구현한 부분이 있으면 `계획 대비 변경 사항`에 이유와 함께 기록하세요.
## 배경
크로스테스트 매트릭스 점검 결과, `typescript/crosstest/typescript_kotlin.ts`(TypeScript 서버 × Kotlin 클라이언트)에 WSS 페이즈가 누락된 것이 확인됐다. 동일 파일의 TLS/TCP 페이즈는 구현돼 있고, Kotlin 클라이언트 측(`kotlin/crosstest/typescript_kotlin_client.kt` 100-103줄)은 `wss` 모드를 이미 완전히 지원한다. 같은 매트릭스의 `typescript_dart.ts`·`typescript_go.ts`·`typescript_python.ts`는 모두 WSS 페이즈를 포함한다. TypeScript 오케스트레이터 파일 한 곳에만 추가하면 갭이 해소된다.
---
## [TEST-1] typescript_kotlin.ts에 WSS 페이즈 추가
### 문제
`typescript/crosstest/typescript_kotlin.ts`
- 29줄: `TLS_TCP_PORT = 29814` 다음에 `WSS_PORT` 상수가 없다.
- 37-48줄: `main()`이 `runTcp()`, `runWs()`, `runTls()`만 호출하고 `runWss()`를 호출하지 않는다.
- `runWss()`, `runWssSendPush()`, `runWssRequests()` 함수가 존재하지 않는다.
### 해결 방법
`typescript_dart.ts`와 `typescript_go.ts`의 WSS 패턴을 그대로 적용한다. 변경은 `typescript_kotlin.ts` 한 파일만이다.
**1) WSS_PORT 상수 추가 — 29~30줄 사이**
Before (29-30줄):
```ts
const TLS_TCP_PORT = 29814;
const WS_PATH = "/";
```
After:
```ts
const TLS_TCP_PORT = 29814;
const WSS_PORT = 29816;
const WS_PATH = "/";
```
포트 29816은 `typescript_python.ts`의 `WS_PORT`와 번호가 같지만, 두 스위트는 동시에 실행되지 않으므로 기존 크로스테스트 관행과 동일하다.
**2) main()에 runWss() 호출 추가 — 42줄 다음**
Before (37-48줄):
```ts
async function main(): Promise<void> {
console.log(`INFO typeName ts=${TestDataSchema.typeName}`);
try {
await runTcp();
await runWs();
await runTls();
console.log("PASS all typescript-server/kotlin-client crosstests passed");
} catch (err) {
console.error(`FAIL crosstest error=${errorMessage(err)}`);
process.exitCode = 1;
}
}
```
After:
```ts
async function main(): Promise<void> {
console.log(`INFO typeName ts=${TestDataSchema.typeName}`);
try {
await runTcp();
await runWs();
await runTls();
await sleep(150);
await runWss();
console.log("PASS all typescript-server/kotlin-client crosstests passed");
} catch (err) {
console.error(`FAIL crosstest error=${errorMessage(err)}`);
process.exitCode = 1;
}
}
```
**3) runWss(), runWssSendPush(), runWssRequests() 추가 — 214줄(runTlsTcpRequests 끝) 바로 뒤에 삽입**
```ts
async function runWss(): Promise<void> {
await runWssSendPush();
await sleep(150);
await runWssRequests();
}
async function runWssSendPush(): Promise<void> {
let resolveReceived: ((value: boolean) => void) | null = null;
const received = new Promise<boolean>((resolve) => {
resolveReceived = resolve;
});
const server = new WsServer(
HOST,
WSS_PORT,
WS_PATH,
(ws) => new WsClient(ws, 0, 0, parserMap()),
serverTlsOptions(),
);
server.onClientConnected = (client) => {
addListenerTyped(client.communicator, TestDataSchema, (data) => {
console.log(`SERVER_RECEIVED index=${data.index} message=${data.message}`);
const valid = data.index === 101 && data.message === "fire from kotlin client";
if (resolveReceived !== null) {
resolveReceived(valid);
resolveReceived = null;
}
if (valid) {
void client.communicator.send(
create(TestDataSchema, {
index: 200,
message: "push from typescript server",
}),
);
}
});
};
await withServer(server, async () => {
await runKotlinClient("wss", WSS_PORT, "send-push", new Set(["1", "2"]), CERT_PATH);
const ok = await withTimeout(received, SERVER_OBSERVATION_MS, "WSS send-push server did not receive expected data");
if (!ok) {
throw new Error("WSS send-push server received unexpected data");
}
});
}
async function runWssRequests(): Promise<void> {
const server = new WsServer(
HOST,
WSS_PORT,
WS_PATH,
(ws) => new WsClient(ws, 0, 0, parserMap()),
serverTlsOptions(),
);
server.onClientConnected = (client) => {
addRequestListenerTyped(client.communicator, TestDataSchema, (req) =>
create(TestDataSchema, {
index: req.index * 2,
message: `echo: ${req.message}`,
}),
);
};
await withServer(server, () =>
runKotlinClient("wss", WSS_PORT, "requests", new Set(["3", "4"]), CERT_PATH),
);
}
```
### 수정 파일 및 체크리스트
- [x] `typescript/crosstest/typescript_kotlin.ts`
- [x] 29줄 다음에 `const WSS_PORT = 29816;` 추가
- [x] `main()` 안 `await runTls();` 다음에 `await sleep(150); await runWss();` 추가
- [x] `runTlsTcpRequests()` 끝(214줄) 다음에 `runWss()`, `runWssSendPush()`, `runWssRequests()` 삽입
### 테스트 작성
별도 테스트 파일을 작성하지 않는다. 이번 변경 자체가 크로스테스트 케이스 추가이며, `runWssSendPush()`와 `runWssRequests()`가 시나리오 1-4를 WSS 전송으로 검증한다.
### 중간 검증
TypeScript 타입 검사만으로 컴파일 오류 없음을 확인한다:
```bash
cd typescript && npx tsc --noEmit
```
기대 결과: 출력 없이 종료 코드 0.
---
## 수정 파일 요약
| 파일 | 항목 |
|------|------|
| `typescript/crosstest/typescript_kotlin.ts` | TEST-1 |
---
## 최종 검증
Kotlin 빌드 환경(JDK + Gradle)이 필요하다. 환경이 없으면 타입 검사(`tsc --noEmit`)만 실행하고 검증 결과에 환경 미비 사유를 명시한다.
```bash
cd typescript && npx tsx crosstest/typescript_kotlin.ts
```
기대 결과:
```
INFO typeName ts=TestData
PASS scenario=1 ...
PASS scenario=2 ...
PASS scenario=3 ...
PASS scenario=4 ...
... (TCP / WS / TLS / WSS 각 페이즈 반복)
PASS all typescript-server/kotlin-client crosstests passed
```