- Implement backtest workflow validation for headless operator mode - Add handoff evidence tracking for backtest runs - Update operator client, runner, scenario, and output modules - Add test files for handoff, backtest runner, and error handling - Add test data for backtest scenarios and validation
81 lines
3 KiB
Go
81 lines
3 KiB
Go
package cli
|
|
|
|
import (
|
|
"bytes"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
func TestRunVersion(t *testing.T) {
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"version"}, &stdout, &stderr)
|
|
if code != 0 {
|
|
t.Fatalf("exit code = %d, want 0 (stderr=%q)", code, stderr.String())
|
|
}
|
|
if got := strings.TrimSpace(stdout.String()); got != "alt dev" {
|
|
t.Errorf("stdout = %q, want \"alt dev\"", got)
|
|
}
|
|
}
|
|
|
|
func TestRunScenarioValidate(t *testing.T) {
|
|
path := filepath.Join("..", "..", "testdata", "operator", "api_connection_smoke.yaml")
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"operator", "scenario", "validate", "--file", path}, &stdout, &stderr)
|
|
if code != 0 {
|
|
t.Fatalf("exit code = %d, want 0 (stderr=%q)", code, stderr.String())
|
|
}
|
|
out := stdout.String()
|
|
for _, want := range []string{"scenario=api_connection_smoke", "status=valid", "steps=1"} {
|
|
if !strings.Contains(out, want) {
|
|
t.Errorf("stdout %q missing %q", out, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestRunScenarioValidateParseError(t *testing.T) {
|
|
path := filepath.Join("..", "..", "testdata", "operator", "malformed_scenario.yaml")
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"operator", "scenario", "validate", "--file", path}, &stdout, &stderr)
|
|
if code != 2 {
|
|
t.Fatalf("exit code = %d, want 2 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "status=parse_error") {
|
|
t.Errorf("stdout %q missing status=parse_error", stdout.String())
|
|
}
|
|
}
|
|
|
|
func TestRunScenarioRunRequiresFlags(t *testing.T) {
|
|
// Missing --file (and --api-url) is a flag/usage error: exit code 2.
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"operator", "scenario", "run"}, &stdout, &stderr)
|
|
if code != 2 {
|
|
t.Fatalf("exit code = %d, want 2 (stderr=%q)", code, stderr.String())
|
|
}
|
|
}
|
|
|
|
func TestRunScenarioRunParseError(t *testing.T) {
|
|
path := filepath.Join("..", "..", "testdata", "operator", "malformed_scenario.yaml")
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"operator", "scenario", "run", "--file", path, "--api-url", "ws://127.0.0.1:8080/socket"}, &stdout, &stderr)
|
|
if code != 2 {
|
|
t.Fatalf("exit code = %d, want 2 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "status=parse_error") {
|
|
t.Errorf("stdout %q missing status=parse_error", stdout.String())
|
|
}
|
|
}
|
|
|
|
func TestRunScenarioRunTransportFailure(t *testing.T) {
|
|
// Port 1 is closed for inbound app traffic on localhost, so the dial fails
|
|
// before any typed response and the run reports a transport error.
|
|
path := filepath.Join("..", "..", "testdata", "operator", "api_connection_smoke.yaml")
|
|
var stdout, stderr bytes.Buffer
|
|
code := Run([]string{"operator", "scenario", "run", "--file", path, "--api-url", "ws://127.0.0.1:1/socket", "--timeout", "2s"}, &stdout, &stderr)
|
|
if code != 3 {
|
|
t.Fatalf("exit code = %d, want 3 (stdout=%q stderr=%q)", code, stdout.String(), stderr.String())
|
|
}
|
|
if !strings.Contains(stdout.String(), "status=transport_error") {
|
|
t.Errorf("stdout %q missing status=transport_error", stdout.String())
|
|
}
|
|
}
|