71d2c39f01
scripts/run-client-e2e-tests.ps1 expects each language CLI to expose a `batch` subcommand that reads command lines from stdin, runs each through the normal subcommand dispatch, writes the JSON result, then a sentinel line `__MXGW_BATCH_EOR__`. The implementation lived on a divergent branch (commit6126099) that was never merged into main — this commit ports the same protocol to HEAD's renamed CLIs so the existing matrix script runs end-to-end. The protocol: - one line of stdin = one full CLI invocation - successful output → stdout, then __MXGW_BATCH_EOR__ - failure → {"error":"...","type":"error"} JSON on stdout, then __MXGW_BATCH_EOR__ (errors do NOT exit the loop) - empty line or EOF terminates the loop Per-CLI additions: .NET: RunBatchAsync + per-line StringWriter capture, JSON error envelope when forceJsonErrors is true. Two new tests in MxGatewayClientCliTests covering the success and error paths. Go: runBatch with bufio.Scanner, runs each line through the existing runWithIO switch with a buffered stdout writer. One new test pinning the EOR sentinel. Rust: new `Batch` variant on the clap Command enum, run_batch re-parses each line via Cli::try_parse_from. Two new tests in the inline mod tests block. Python: new `batch` click command in commands.py that uses CliRunner to dispatch each line; synthesises {"error",..."type"} JSON from click error messages when the captured output isn't already JSON-shaped. Three new tests in test_cli.py. Java: BatchCommand inner @Command with BufferedReader stdin loop, fresh commandLine() per dispatch with captured stdout/stderr PrintWriters; non-zero exit codes and uncaught exceptions both surface as JSON-error blocks. Two new tests. Also fixes scripts/run-client-e2e-tests.ps1 line 705: the Python invocation was still passing the old module name `mxgateway_cli` to `python -m`; the client SDK rename in397d3c5moved it to `zb_mom_ww_mxgateway_cli`. Without the fix the Python leg fails with "No module named mxgateway_cli" before reaching open-session. Verification: full matrix at the redeployed gateway (localhost:5120, running ZB.MOM.WW.MxGateway.Server.exe / ZB.MOM.WW.MxGateway.Worker.exe) with -SkipBulk -SkipReadWriteBulk -SkipParity -SkipAuth (those phases exercise bulk read/write CLI subcommands that also live on the divergent branch — porting those is a follow-up). All five clients report `closed=true, addedItems=120, eventCount=5` and overall `success=true`. Per-language unit tests pass: - dotnet: 59/59 - go: all packages clean - rust: cargo test --workspace clean - python: 42/42 - java: gradle build SUCCESSFUL Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
87 lines
2.4 KiB
Go
87 lines
2.4 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRunVersionJSON(t *testing.T) {
|
|
var stdout bytes.Buffer
|
|
var stderr bytes.Buffer
|
|
|
|
if err := runWithIO(t.Context(), []string{"version", "-json"}, &stdout, &stderr); err != nil {
|
|
t.Fatalf("runWithIO() error = %v; stderr = %s", err, stderr.String())
|
|
}
|
|
|
|
var output versionOutput
|
|
if err := json.Unmarshal(stdout.Bytes(), &output); err != nil {
|
|
t.Fatalf("parse JSON: %v", err)
|
|
}
|
|
if output.GatewayProtocolVersion == 0 || output.WorkerProtocolVersion == 0 {
|
|
t.Fatalf("protocol versions were not populated: %+v", output)
|
|
}
|
|
}
|
|
|
|
func TestCommonOptionsRedactsAPIKey(t *testing.T) {
|
|
options, err := (&commonOptions{
|
|
Endpoint: "localhost:5000",
|
|
APIKey: "mxgw_super_secret",
|
|
Plaintext: true,
|
|
CallTimeout: "2s",
|
|
}).resolved()
|
|
if err != nil {
|
|
t.Fatalf("resolved() error = %v", err)
|
|
}
|
|
|
|
data, err := json.Marshal(options)
|
|
if err != nil {
|
|
t.Fatalf("marshal options: %v", err)
|
|
}
|
|
if strings.Contains(string(data), "super_secret") {
|
|
t.Fatalf("redacted JSON leaked API key: %s", data)
|
|
}
|
|
if !strings.Contains(string(data), "mxgw") {
|
|
t.Fatalf("redacted JSON did not preserve key shape: %s", data)
|
|
}
|
|
}
|
|
|
|
func TestRunBatchEmitsEORAfterVersion(t *testing.T) {
|
|
var stdout bytes.Buffer
|
|
var stderr bytes.Buffer
|
|
|
|
in := strings.NewReader("version --json\n")
|
|
if err := runBatch(t.Context(), in, &stdout, &stderr); err != nil {
|
|
t.Fatalf("runBatch() error = %v; stderr = %s", err, stderr.String())
|
|
}
|
|
|
|
out := stdout.String()
|
|
if !strings.Contains(out, "\n"+batchEOR+"\n") && !strings.HasSuffix(out, batchEOR+"\n") {
|
|
t.Fatalf("expected EOR marker %q in stdout; got: %q", batchEOR, out)
|
|
}
|
|
|
|
idx := strings.Index(out, batchEOR)
|
|
if idx <= 0 {
|
|
t.Fatalf("EOR marker not found or appeared before any output: %q", out)
|
|
}
|
|
payload := out[:idx]
|
|
var output versionOutput
|
|
if err := json.Unmarshal([]byte(payload), &output); err != nil {
|
|
t.Fatalf("parse JSON block before EOR: %v (payload=%q)", err, payload)
|
|
}
|
|
if output.GatewayProtocolVersion == 0 || output.WorkerProtocolVersion == 0 {
|
|
t.Fatalf("protocol versions were not populated: %+v", output)
|
|
}
|
|
}
|
|
|
|
func TestParseValueBuildsTypedValue(t *testing.T) {
|
|
value, err := parseValue("int32", "123")
|
|
if err != nil {
|
|
t.Fatalf("parseValue() error = %v", err)
|
|
}
|
|
if got := value.GetInt32Value(); got != 123 {
|
|
t.Fatalf("int32 value = %d, want 123", got)
|
|
}
|
|
}
|