update typescript_kotlin crosstest and add agent-task logs
This commit is contained in:
parent
c3bfb35a72
commit
0d8359959a
5 changed files with 532 additions and 2 deletions
|
|
@ -15,11 +15,13 @@
|
|||
"Bash(bash agent-ops/sync.sh push)",
|
||||
"Bash(git checkout:*)",
|
||||
"Bash(cp /config/workspace/toki_socket/agent-task/tls_crosstest/CODE_REVIEW.md /config/workspace/toki_socket/agent-task/tls_crosstest/code_review_0.log)",
|
||||
"Bash(cp /config/workspace/toki_socket/agent-task/tls_crosstest/PLAN.md /config/workspace/toki_socket/agent-task/tls_crosstest/plan_0.log)"
|
||||
"Bash(cp /config/workspace/toki_socket/agent-task/tls_crosstest/PLAN.md /config/workspace/toki_socket/agent-task/tls_crosstest/plan_0.log)",
|
||||
"Bash(git -C /config/workspace/toki_socket log --oneline)"
|
||||
],
|
||||
"additionalDirectories": [
|
||||
"/config/workspace/toki_socket/tasks",
|
||||
"/config/workspace/agentic-framework/agent-ops/skills/common/sync-agent-ops"
|
||||
"/config/workspace/agentic-framework/agent-ops/skills/common/sync-agent-ops",
|
||||
"/config/workspace/toki_socket/agent-task"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
|
|||
251
agent-task/ts_kotlin_wss_crosstest/code_review_0.log
Normal file
251
agent-task/ts_kotlin_wss_crosstest/code_review_0.log
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
<!-- task=ts_kotlin_wss_crosstest plan=0 tag=TEST -->
|
||||
|
||||
# Code Review Reference - TEST
|
||||
|
||||
## 개요
|
||||
|
||||
date=2026-04-27
|
||||
task=ts_kotlin_wss_crosstest, plan=0, tag=TEST
|
||||
|
||||
## 이 파일을 읽는 리뷰 에이전트에게
|
||||
|
||||
각 항목의 구현을 실제 소스 파일과 대조하고, `검증 결과` 섹션의 출력이 코드와 일치하는지 확인하세요.
|
||||
리뷰 완료 후 반드시 아래 순서로 아카이브하세요.
|
||||
|
||||
1. `CODE_REVIEW.md` → `code_review_N.log` (N = 기존 code_review_*.log 수)
|
||||
2. `PLAN.md` → `plan_M.log` (M = 기존 plan_*.log 수)
|
||||
3. PASS인 경우 `complete.log` 작성 후 종료. WARN/FAIL인 경우 새 `PLAN.md` + `CODE_REVIEW.md` 스텁 작성.
|
||||
|
||||
---
|
||||
|
||||
## 구현 항목별 완료 여부
|
||||
|
||||
| 항목 | 완료 여부 |
|
||||
|------|---------|
|
||||
| [TEST-1] typescript_kotlin.ts에 WSS 페이즈 추가 | [x] |
|
||||
|
||||
## 계획 대비 변경 사항
|
||||
|
||||
없음. 계획서의 지정 범위(`typescript/crosstest/typescript_kotlin.ts`) 안에서만 구현했다.
|
||||
|
||||
## 주요 설계 결정
|
||||
|
||||
- Kotlin 클라이언트가 이미 지원하는 `wss` 모드를 TypeScript 서버 오케스트레이터에 연결했다.
|
||||
- WSS 서버는 기존 WS 서버 생성 패턴에 `serverTlsOptions()`를 5번째 인자로 전달하는 방식으로 구성했다.
|
||||
- WSS 포트는 계획서에 명시된 `29816`을 사용했다.
|
||||
|
||||
## 리뷰어를 위한 체크포인트
|
||||
|
||||
- `typescript/crosstest/typescript_kotlin.ts` 29줄 다음에 `WSS_PORT = 29816` 상수가 추가됐는지 확인
|
||||
- `main()`에서 `runTls()` 다음에 `sleep(150)` + `runWss()` 호출이 순서대로 있는지 확인
|
||||
- `runWss()`, `runWssSendPush()`, `runWssRequests()` 세 함수가 모두 추가됐는지 확인
|
||||
- `runWssSendPush()`에서 `serverTlsOptions()`를 `WsServer` 생성자 5번째 인자로 전달하는지 확인
|
||||
- `runKotlinClient("wss", WSS_PORT, ...)` 호출 시 `CERT_PATH`가 인자로 전달되는지 확인
|
||||
- `kotlin/crosstest/typescript_kotlin_client.kt`는 변경하지 않았는지 확인 (이미 wss 지원)
|
||||
|
||||
## 검증 결과
|
||||
|
||||
_구현 에이전트가 각 중간 검증 및 최종 검증 명령 실행 후 출력을 여기에 붙여 넣는다._
|
||||
|
||||
### TEST-1 중간 검증
|
||||
```
|
||||
$ cd typescript && npx tsc --noEmit
|
||||
```
|
||||
|
||||
출력 없음. 종료 코드 0.
|
||||
|
||||
### 최종 검증
|
||||
```
|
||||
$ cd typescript && npx tsx crosstest/typescript_kotlin.ts
|
||||
INFO typeName ts=TestData
|
||||
Starting a Gradle Daemon, 1 busy and 1 incompatible and 1 stopped Daemons could not be reused, use --status for details
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
SERVER_RECEIVED index=101 message=fire from kotlin client
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=1 detail=fire-and-forget sent
|
||||
PASS scenario=2 detail=received push from typescript server
|
||||
|
||||
BUILD SUCCESSFUL in 7s
|
||||
10 actionable tasks: 2 executed, 8 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=3 detail=single request response matched
|
||||
PASS scenario=4 detail=concurrent request responses matched
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
SERVER_RECEIVED index=101 message=fire from kotlin client
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=1 detail=fire-and-forget sent
|
||||
PASS scenario=2 detail=received push from typescript server
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=3 detail=single request response matched
|
||||
PASS scenario=4 detail=concurrent request responses matched
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
SERVER_RECEIVED index=101 message=fire from kotlin client
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=1 detail=fire-and-forget sent
|
||||
PASS scenario=2 detail=received push from typescript server
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=3 detail=single request response matched
|
||||
PASS scenario=4 detail=concurrent request responses matched
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
SERVER_RECEIVED index=101 message=fire from kotlin client
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=1 detail=fire-and-forget sent
|
||||
PASS scenario=2 detail=received push from typescript server
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
> Task :checkKotlinGradlePluginConfigurationErrors SKIPPED
|
||||
> Task :extractIncludeProto UP-TO-DATE
|
||||
> Task :extractProto UP-TO-DATE
|
||||
> Task :generateProto UP-TO-DATE
|
||||
> Task :compileKotlin UP-TO-DATE
|
||||
> Task :compileJava UP-TO-DATE
|
||||
> Task :processResources UP-TO-DATE
|
||||
> Task :classes UP-TO-DATE
|
||||
> Task :extractCrosstestProto UP-TO-DATE
|
||||
> Task :extractIncludeCrosstestProto UP-TO-DATE
|
||||
> Task :generateCrosstestProto NO-SOURCE
|
||||
> Task :compileCrosstestKotlin UP-TO-DATE
|
||||
> Task :compileCrosstestJava NO-SOURCE
|
||||
> Task :processCrosstestResources NO-SOURCE
|
||||
> Task :crosstestClasses UP-TO-DATE
|
||||
|
||||
> Task :run
|
||||
INFO typeName kotlin=TestData
|
||||
PASS scenario=3 detail=single request response matched
|
||||
PASS scenario=4 detail=concurrent request responses matched
|
||||
|
||||
BUILD SUCCESSFUL in 1s
|
||||
10 actionable tasks: 1 executed, 9 up-to-date
|
||||
PASS all typescript-server/kotlin-client crosstests passed
|
||||
```
|
||||
9
agent-task/ts_kotlin_wss_crosstest/complete.log
Normal file
9
agent-task/ts_kotlin_wss_crosstest/complete.log
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
date=2026-04-27
|
||||
task=ts_kotlin_wss_crosstest
|
||||
plan=0
|
||||
tag=TEST
|
||||
result=PASS
|
||||
|
||||
모든 체크포인트 통과. TypeScript 서버 × Kotlin 클라이언트 WSS 페이즈 추가 완료.
|
||||
변경 파일: typescript/crosstest/typescript_kotlin.ts 1개.
|
||||
최종 검증: PASS all typescript-server/kotlin-client crosstests passed
|
||||
199
agent-task/ts_kotlin_wss_crosstest/plan_0.log
Normal file
199
agent-task/ts_kotlin_wss_crosstest/plan_0.log
Normal file
|
|
@ -0,0 +1,199 @@
|
|||
<!-- 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
|
||||
```
|
||||
|
|
@ -27,6 +27,7 @@ const HOST = "127.0.0.1";
|
|||
const TCP_PORT = 29810;
|
||||
const WS_PORT = 29812;
|
||||
const TLS_TCP_PORT = 29814;
|
||||
const WSS_PORT = 29816;
|
||||
const WS_PATH = "/";
|
||||
const PROCESS_TIMEOUT_MS = 20_000;
|
||||
const SERVER_OBSERVATION_MS = 200;
|
||||
|
|
@ -40,6 +41,8 @@ async function main(): Promise<void> {
|
|||
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)}`);
|
||||
|
|
@ -65,6 +68,12 @@ async function runTls(): Promise<void> {
|
|||
await runTlsTcpRequests();
|
||||
}
|
||||
|
||||
async function runWss(): Promise<void> {
|
||||
await runWssSendPush();
|
||||
await sleep(150);
|
||||
await runWssRequests();
|
||||
}
|
||||
|
||||
async function runTcpSendPush(): Promise<void> {
|
||||
let resolveReceived: ((value: boolean) => void) | null = null;
|
||||
const received = new Promise<boolean>((resolve) => {
|
||||
|
|
@ -213,6 +222,66 @@ async function runTlsTcpRequests(): Promise<void> {
|
|||
await withServer(server, () => runKotlinClient("tls", TLS_TCP_PORT, "requests", new Set(["3", "4"]), CERT_PATH));
|
||||
}
|
||||
|
||||
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),
|
||||
);
|
||||
}
|
||||
|
||||
async function withServer(
|
||||
server: { start: () => Promise<void>; stop: () => Promise<void> },
|
||||
body: () => Promise<void>,
|
||||
|
|
|
|||
Loading…
Reference in a new issue