docs: update cross-language crosstest commands in README and add dart_typescript/go_typescript/kotlin_* python_typescript crosstest files
This commit is contained in:
parent
f0da42c63a
commit
a3f3ccf4b5
7 changed files with 92 additions and 20 deletions
24
README.md
24
README.md
|
|
@ -196,16 +196,40 @@ Cross-language checks:
|
|||
cd go
|
||||
go run ./crosstest/go_dart.go
|
||||
go run ./crosstest/go_kotlin.go
|
||||
go run ./crosstest/go_python.go
|
||||
go run ./crosstest/go_typescript.go
|
||||
```
|
||||
|
||||
```bash
|
||||
cd dart
|
||||
dart run crosstest/dart_go.dart
|
||||
dart run crosstest/dart_kotlin.dart
|
||||
dart run crosstest/dart_python.dart
|
||||
dart run crosstest/dart_typescript.dart
|
||||
```
|
||||
|
||||
```bash
|
||||
cd kotlin
|
||||
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinDartKt
|
||||
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinGoKt
|
||||
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinPythonKt
|
||||
./gradlew run -PmainClass=com.tokilabs.proto_socket.crosstest.KotlinTypescriptKt
|
||||
```
|
||||
|
||||
```bash
|
||||
cd python
|
||||
python3 crosstest/python_dart.py
|
||||
python3 crosstest/python_go.py
|
||||
python3 crosstest/python_kotlin.py
|
||||
python3 crosstest/python_typescript.py
|
||||
```
|
||||
|
||||
```bash
|
||||
cd typescript
|
||||
./node_modules/.bin/tsx crosstest/typescript_dart.ts
|
||||
./node_modules/.bin/tsx crosstest/typescript_go.ts
|
||||
./node_modules/.bin/tsx crosstest/typescript_kotlin.ts
|
||||
./node_modules/.bin/tsx crosstest/typescript_python.ts
|
||||
```
|
||||
|
||||
When proto files change, also run:
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ const _heartbeatIntervalSeconds = 30;
|
|||
const _heartbeatWaitSeconds = 10;
|
||||
const _serverObservationWindow = Duration(milliseconds: 200);
|
||||
const _processTimeout = Duration(seconds: 20);
|
||||
const _streamTimeout = Duration(seconds: 5);
|
||||
final _repoRoot = File.fromUri(Platform.script).parent.parent.parent.path;
|
||||
final _typescriptDir = Directory('$_repoRoot/typescript').path;
|
||||
final _certFile = '$_repoRoot/dart/test/certs/server.crt';
|
||||
|
|
@ -295,10 +296,10 @@ Future<void> _runWssRequests(SecurityContext ctx) async {
|
|||
Future<void> _runTypescriptClient(
|
||||
String mode, int port, String phase, Set<String> expectedScenarios,
|
||||
{String? certFile}) async {
|
||||
final tsxBin = '$_typescriptDir/node_modules/.bin/tsx';
|
||||
final process = await Process.start(
|
||||
'npx',
|
||||
tsxBin,
|
||||
[
|
||||
'tsx',
|
||||
'crosstest/dart_typescript_client.ts',
|
||||
'--mode=$mode',
|
||||
'--port=$port',
|
||||
|
|
@ -329,7 +330,10 @@ Future<void> _runTypescriptClient(
|
|||
process.kill(ProcessSignal.sigkill);
|
||||
return -1;
|
||||
});
|
||||
await Future.wait([stdoutDone, stderrDone]);
|
||||
await Future.wait([stdoutDone, stderrDone])
|
||||
.timeout(_streamTimeout, onTimeout: () {
|
||||
throw StateError('typescript-client $mode/$phase streams did not finish');
|
||||
});
|
||||
|
||||
_validateResultLines(
|
||||
'typescript-client $mode/$phase',
|
||||
|
|
|
|||
|
|
@ -367,8 +367,8 @@ func runTypescriptClient(mode string, port int, phase string, expected map[strin
|
|||
return err
|
||||
}
|
||||
|
||||
tsxBin := filepath.Join(typescriptDir, "node_modules", ".bin", "tsx")
|
||||
args := []string{
|
||||
"tsx",
|
||||
"crosstest/go_typescript_client.ts",
|
||||
"--mode=" + mode,
|
||||
fmt.Sprintf("--port=%d", port),
|
||||
|
|
@ -377,8 +377,9 @@ func runTypescriptClient(mode string, port int, phase string, expected map[strin
|
|||
if len(certFile) > 0 && certFile[0] != "" {
|
||||
args = append(args, "--cert="+certFile[0])
|
||||
}
|
||||
cmd := exec.CommandContext(ctx, "npx", args...)
|
||||
cmd := exec.CommandContext(ctx, tsxBin, args...)
|
||||
cmd.Dir = typescriptDir
|
||||
cmd.WaitDelay = 5 * time.Second
|
||||
|
||||
stdoutPipe, err := cmd.StdoutPipe()
|
||||
if err != nil {
|
||||
|
|
@ -400,7 +401,13 @@ func runTypescriptClient(mode string, port int, phase string, expected map[strin
|
|||
go scanLines(&wg, stderrPipe, os.Stderr, nil, nil)
|
||||
|
||||
waitErr := cmd.Wait()
|
||||
wg.Wait()
|
||||
done := make(chan struct{})
|
||||
go func() { wg.Wait(); close(done) }()
|
||||
select {
|
||||
case <-done:
|
||||
case <-time.After(5 * time.Second):
|
||||
return fmt.Errorf("typescript client %s/%s pipe scan timed out", mode, phase)
|
||||
}
|
||||
if ctx.Err() == context.DeadlineExceeded {
|
||||
return fmt.Errorf("typescript client %s/%s timed out", mode, phase)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ private const val WSS_PORT = 29496
|
|||
private const val WS_PATH = "/"
|
||||
private const val PROCESS_TIMEOUT_MS = 20_000L
|
||||
private const val SERVER_OBSERVATION_MS = 200L
|
||||
private const val STREAM_JOIN_TIMEOUT_MS = 5_000L
|
||||
|
||||
fun main() = runBlocking {
|
||||
println("INFO typeName kotlin=${typeNameOf<TestData>()}")
|
||||
|
|
@ -279,6 +280,11 @@ private suspend fun withServer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun destroyProcessTree(process: Process) {
|
||||
process.toHandle().descendants().forEach { it.destroyForcibly() }
|
||||
process.destroyForcibly()
|
||||
}
|
||||
|
||||
private suspend fun runDartClient(
|
||||
mode: String,
|
||||
port: Int,
|
||||
|
|
@ -321,13 +327,17 @@ private suspend fun runDartClient(
|
|||
|
||||
val finished = process.waitFor(PROCESS_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||
if (!finished) {
|
||||
process.destroyForcibly()
|
||||
destroyProcessTree(process)
|
||||
}
|
||||
stdoutThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
stderrThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
val label = "dart-client $mode/$phase"
|
||||
check(!stdoutThread.isAlive && !stderrThread.isAlive) {
|
||||
"$label stream readers did not finish"
|
||||
}
|
||||
stdoutThread.join()
|
||||
stderrThread.join()
|
||||
|
||||
validateResultLines(
|
||||
"dart-client $mode/$phase",
|
||||
label,
|
||||
if (finished) process.exitValue() else -1,
|
||||
stdoutLines,
|
||||
expectedScenarios,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ private const val WSS_PORT = 29396
|
|||
private const val WS_PATH = "/"
|
||||
private const val PROCESS_TIMEOUT_MS = 20_000L
|
||||
private const val SERVER_OBSERVATION_MS = 200L
|
||||
private const val STREAM_JOIN_TIMEOUT_MS = 5_000L
|
||||
|
||||
fun main() = runBlocking {
|
||||
println("INFO typeName kotlin=${typeNameOf<TestData>()}")
|
||||
|
|
@ -279,6 +280,11 @@ private suspend fun withServer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun destroyProcessTree(process: Process) {
|
||||
process.toHandle().descendants().forEach { it.destroyForcibly() }
|
||||
process.destroyForcibly()
|
||||
}
|
||||
|
||||
private suspend fun runGoClient(
|
||||
mode: String,
|
||||
port: Int,
|
||||
|
|
@ -321,13 +327,17 @@ private suspend fun runGoClient(
|
|||
|
||||
val finished = process.waitFor(PROCESS_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||
if (!finished) {
|
||||
process.destroyForcibly()
|
||||
destroyProcessTree(process)
|
||||
}
|
||||
stdoutThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
stderrThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
val label = "go-client $mode/$phase"
|
||||
check(!stdoutThread.isAlive && !stderrThread.isAlive) {
|
||||
"$label stream readers did not finish"
|
||||
}
|
||||
stdoutThread.join()
|
||||
stderrThread.join()
|
||||
|
||||
validateResultLines(
|
||||
"go-client $mode/$phase",
|
||||
label,
|
||||
if (finished) process.exitValue() else -1,
|
||||
stdoutLines,
|
||||
expectedScenarios,
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ private const val WSS_PORT = 29400
|
|||
private const val WS_PATH = "/"
|
||||
private const val PROCESS_TIMEOUT_MS = 20_000L
|
||||
private const val SERVER_OBSERVATION_MS = 200L
|
||||
private const val STREAM_JOIN_TIMEOUT_MS = 5_000L
|
||||
|
||||
fun main() = runBlocking {
|
||||
println("INFO typeName kotlin=${typeNameOf<TestData>()}")
|
||||
|
|
@ -279,6 +280,11 @@ private suspend fun withServer(
|
|||
}
|
||||
}
|
||||
|
||||
private fun destroyProcessTree(process: Process) {
|
||||
process.toHandle().descendants().forEach { it.destroyForcibly() }
|
||||
process.destroyForcibly()
|
||||
}
|
||||
|
||||
private suspend fun runPythonClient(
|
||||
mode: String,
|
||||
port: Int,
|
||||
|
|
@ -320,13 +326,17 @@ private suspend fun runPythonClient(
|
|||
|
||||
val finished = process.waitFor(PROCESS_TIMEOUT_MS, TimeUnit.MILLISECONDS)
|
||||
if (!finished) {
|
||||
process.destroyForcibly()
|
||||
destroyProcessTree(process)
|
||||
}
|
||||
stdoutThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
stderrThread.join(STREAM_JOIN_TIMEOUT_MS)
|
||||
val label = "python-client $mode/$phase"
|
||||
check(!stdoutThread.isAlive && !stderrThread.isAlive) {
|
||||
"$label stream readers did not finish"
|
||||
}
|
||||
stdoutThread.join()
|
||||
stderrThread.join()
|
||||
|
||||
validateResultLines(
|
||||
"python-client $mode/$phase",
|
||||
label,
|
||||
if (finished) process.exitValue() else -1,
|
||||
stdoutLines,
|
||||
expectedScenarios,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import ssl
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
|
@ -266,8 +268,9 @@ async def run_typescript_client(
|
|||
cert: Path | None = None,
|
||||
) -> None:
|
||||
ts_dir = typescript_package_dir()
|
||||
tsx_bin = ts_dir / "node_modules" / ".bin" / "tsx"
|
||||
args = [
|
||||
"tsx",
|
||||
str(tsx_bin),
|
||||
"crosstest/python_typescript_client.ts",
|
||||
f"--mode={mode}",
|
||||
f"--port={port}",
|
||||
|
|
@ -276,15 +279,19 @@ async def run_typescript_client(
|
|||
if cert is not None:
|
||||
args.append(f"--cert={cert}")
|
||||
process = await asyncio.create_subprocess_exec(
|
||||
"npx",
|
||||
*args,
|
||||
cwd=ts_dir,
|
||||
start_new_session=True,
|
||||
stdout=asyncio.subprocess.PIPE,
|
||||
stderr=asyncio.subprocess.PIPE,
|
||||
)
|
||||
try:
|
||||
stdout, stderr = await asyncio.wait_for(process.communicate(), PROCESS_TIMEOUT)
|
||||
except TimeoutError as exc:
|
||||
try:
|
||||
os.killpg(process.pid, signal.SIGKILL)
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
process.kill()
|
||||
await process.wait()
|
||||
raise TimeoutError(f"typescript client {mode}/{phase} timed out") from exc
|
||||
|
|
|
|||
Loading…
Reference in a new issue