feat(go): add ping CLI subcommand (§4.3)
Add PingRaw to Session (session.go), runPing to the CLI dispatch (main.go), and three tests covering plain-text echo, JSON output, and missing-session-id validation (main_test.go). Default message is "ping"; gateway echo is read from DiagnosticMessage, falling back to the kind string if absent.
This commit is contained in:
@@ -190,6 +190,102 @@ func TestRunBenchReadBulkRespectsContextCancellation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunPingPlainText verifies the ping subcommand round-trips through the
|
||||
// fake gateway and prints the echo (diagnostic_message) in plain-text mode.
|
||||
func TestRunPingPlainText(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
server := grpc.NewServer()
|
||||
fake := &pingFakeGateway{}
|
||||
pb.RegisterMxAccessGatewayServer(server, fake)
|
||||
go func() { _ = server.Serve(listener) }()
|
||||
defer server.Stop()
|
||||
defer listener.Close()
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
args := []string{
|
||||
"ping",
|
||||
"-endpoint", listener.Addr().String(),
|
||||
"-plaintext",
|
||||
"-api-key", "test",
|
||||
"-session-id", "test-session",
|
||||
"-message", "hello",
|
||||
}
|
||||
if err := runWithIO(t.Context(), args, &stdout, &stderr); err != nil {
|
||||
t.Fatalf("runWithIO() error = %v; stderr = %s", err, stderr.String())
|
||||
}
|
||||
got := strings.TrimSpace(stdout.String())
|
||||
if got != "pong:hello" {
|
||||
t.Fatalf("ping plain-text output = %q, want %q", got, "pong:hello")
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunPingJSON verifies the ping subcommand emits valid JSON in --json mode.
|
||||
func TestRunPingJSON(t *testing.T) {
|
||||
listener, err := net.Listen("tcp", "127.0.0.1:0")
|
||||
if err != nil {
|
||||
t.Fatalf("listen: %v", err)
|
||||
}
|
||||
server := grpc.NewServer()
|
||||
fake := &pingFakeGateway{}
|
||||
pb.RegisterMxAccessGatewayServer(server, fake)
|
||||
go func() { _ = server.Serve(listener) }()
|
||||
defer server.Stop()
|
||||
defer listener.Close()
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
args := []string{
|
||||
"ping",
|
||||
"-endpoint", listener.Addr().String(),
|
||||
"-plaintext",
|
||||
"-api-key", "test",
|
||||
"-session-id", "test-session",
|
||||
"-message", "hello",
|
||||
"-json",
|
||||
}
|
||||
if err := runWithIO(t.Context(), args, &stdout, &stderr); err != nil {
|
||||
t.Fatalf("runWithIO() error = %v; stderr = %s", err, stderr.String())
|
||||
}
|
||||
var out commandReplyOutput
|
||||
if err := json.Unmarshal(stdout.Bytes(), &out); err != nil {
|
||||
t.Fatalf("parse JSON: %v\noutput: %s", err, stdout.String())
|
||||
}
|
||||
if out.Command != "ping" {
|
||||
t.Fatalf("command = %q, want %q", out.Command, "ping")
|
||||
}
|
||||
}
|
||||
|
||||
// TestRunPingRequiresSessionID verifies the ping subcommand rejects missing session-id.
|
||||
func TestRunPingRequiresSessionID(t *testing.T) {
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := runWithIO(t.Context(), []string{"ping", "-plaintext", "-api-key", "test"}, &stdout, &stderr)
|
||||
if err == nil {
|
||||
t.Fatalf("runWithIO(ping without --session-id) returned no error")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "session-id is required") {
|
||||
t.Fatalf("error = %v; want 'session-id is required'", err)
|
||||
}
|
||||
}
|
||||
|
||||
// pingFakeGateway handles Invoke for MX_COMMAND_KIND_PING by echoing the
|
||||
// message back in the diagnostic_message field so the CLI plain-text path
|
||||
// has a deterministic, non-empty string to assert on.
|
||||
type pingFakeGateway struct {
|
||||
pb.UnimplementedMxAccessGatewayServer
|
||||
}
|
||||
|
||||
func (g *pingFakeGateway) Invoke(_ context.Context, req *pb.MxCommandRequest) (*pb.MxCommandReply, error) {
|
||||
echo := "pong:" + req.GetCommand().GetPing().GetMessage()
|
||||
return &pb.MxCommandReply{
|
||||
SessionId: req.GetSessionId(),
|
||||
Kind: pb.MxCommandKind_MX_COMMAND_KIND_PING,
|
||||
DiagnosticMessage: echo,
|
||||
ProtocolStatus: &pb.ProtocolStatus{Code: pb.ProtocolStatusCode_PROTOCOL_STATUS_CODE_OK},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// benchFakeGateway is a minimal MxAccessGatewayServer that satisfies the
|
||||
// bench-read-bulk session-setup sequence (OpenSession + Invoke for Register
|
||||
// / SubscribeBulk / ReadBulk / UnsubscribeBulk / CloseSession).
|
||||
|
||||
Reference in New Issue
Block a user