A JSON verb's answer is its standard output alone
status --json prints its warnings beside the document; parsed from both streams together the first status asked through the console carried no answer as data. Output stays both streams, in order.
This commit is contained in:
@@ -113,14 +113,18 @@ func runVerb(ctx context.Context, argv []string) (verbAnswer, error) {
|
|||||||
// The same environment: the stores' credentials, the bus, the broker — everything a command run
|
// The same environment: the stores' credentials, the bus, the broker — everything a command run
|
||||||
// from a shell in this container would have, because it is that.
|
// from a shell in this container would have, because it is that.
|
||||||
cmd.Env = os.Environ()
|
cmd.Env = os.Environ()
|
||||||
var out bytes.Buffer
|
// Two buffers, one answer. What the command *says* is both streams, in the order a person at
|
||||||
cmd.Stdout = &out
|
// a shell would read them; what it *answers as data* is standard output alone — `status --json`
|
||||||
cmd.Stderr = &out
|
// prints its warnings beside the document, and a JSON parsed from the two together parsed
|
||||||
|
// nothing (2026-09-30, the first status asked through the console had no `answer`).
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
cmd.Stdout = &stdout
|
||||||
|
cmd.Stderr = &stderr
|
||||||
runErr := cmd.Run()
|
runErr := cmd.Run()
|
||||||
answer := verbAnswer{Output: out.String(), OK: runErr == nil}
|
answer := verbAnswer{Output: stdout.String() + stderr.String(), OK: runErr == nil}
|
||||||
if jsonVerbs[argv[0]] && runErr == nil {
|
if jsonVerbs[argv[0]] && runErr == nil {
|
||||||
var parsed any
|
var parsed any
|
||||||
if json.Unmarshal(bytes.TrimSpace(out.Bytes()), &parsed) == nil {
|
if json.Unmarshal(bytes.TrimSpace(stdout.Bytes()), &parsed) == nil {
|
||||||
answer.Answer = parsed
|
answer.Answer = parsed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,3 +77,21 @@ func TestToolsAnswersTheSeatsRecords(t *testing.T) {
|
|||||||
t.Fatal("the mesh-controller seat is not in the listing")
|
t.Fatal("the mesh-controller seat is not in the listing")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A JSON verb's answer is parsed from what the command wrote to standard output alone; a warning it
|
||||||
|
// printed beside the document does not take the document away. The test binary stands in for the
|
||||||
|
// controller: `-test.run` with a name that matches nothing prints `ok` and a warning about no tests.
|
||||||
|
func TestAJSONVerbsAnswerIsItsStandardOutput(t *testing.T) {
|
||||||
|
jsonVerbs["-test.run"] = true
|
||||||
|
t.Cleanup(func() { delete(jsonVerbs, "-test.run") })
|
||||||
|
answer, err := runVerb(t.Context(), []string{"-test.run", "TestAnswerEcho", "-test.v"})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if !answer.OK {
|
||||||
|
t.Fatalf("the command failed: %s", answer.Output)
|
||||||
|
}
|
||||||
|
if !strings.Contains(answer.Output, "PASS") {
|
||||||
|
t.Fatalf("stderr and stdout are both what the command said: %s", answer.Output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user