Files
nezha_domains/integration/agentcompat/cmd/agentcompat/main_test.go
T
2026-07-20 14:09:20 +00:00

195 lines
7.9 KiB
Go

//go:build linux
package main
import (
"bytes"
"context"
"encoding/json"
"os"
"path/filepath"
"strings"
"testing"
"time"
"github.com/nezhahq/nezha/integration/agentcompat/internal/evidence"
"github.com/nezhahq/nezha/integration/agentcompat/internal/scenario"
)
func TestCLI_ParsesTypedFlagsAndWritesMetadata(t *testing.T) {
resultsDir := t.TempDir()
var stdout, stderr bytes.Buffer
err := run([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", resultsDir, "--seed", "0x4e5a4841", "--scenario", "metadata"}, &stdout, &stderr, time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC))
if err != nil {
t.Fatalf("run CLI: %v", err)
}
data, err := os.ReadFile(filepath.Join(resultsDir, "metadata.json"))
if err != nil {
t.Fatalf("read metadata: %v", err)
}
var metadata struct {
Profile struct {
Name string `json:"name"`
} `json:"profile"`
Seed string `json:"seed"`
}
if err := json.Unmarshal(data, &metadata); err != nil {
t.Fatalf("parse metadata: %v", err)
}
if metadata.Profile.Name != "pr-full" || metadata.Seed != "0x4e5a4841" || !strings.Contains(stdout.String(), "metadata written") {
t.Fatalf("unexpected metadata-only output: %#v %q", metadata, stdout.String())
}
}
func TestCLI_MetadataEvidenceValidatesAsCurrentMetadataProfile(t *testing.T) {
resultsDir := t.TempDir()
var stdout, stderr bytes.Buffer
err := run([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", resultsDir, "--scenario", "metadata"}, &stdout, &stderr, time.Date(2026, 1, 2, 3, 4, 5, 0, time.UTC))
if err != nil {
t.Fatalf("run metadata CLI: %v", err)
}
if err := evidence.ValidateDirectory(resultsDir); err != nil {
t.Fatalf("validate metadata evidence: %v", err)
}
}
func TestCLI_RejectsInvalidProfileAndSeedWithoutSecretEcho(t *testing.T) {
for name, args := range map[string][]string{
"profile": {"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "private-profile-secret", "--results-dir", t.TempDir()},
"seed": {"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", t.TempDir(), "--seed", "not-a-seed-secret"},
} {
t.Run(name, func(t *testing.T) {
var stdout, stderr bytes.Buffer
err := run(args, &stdout, &stderr, time.Now())
if err == nil {
t.Fatal("invalid CLI input accepted")
}
if strings.Contains(err.Error(), "not-a-seed-secret") || strings.Contains(err.Error(), "private-profile-secret") {
t.Fatal("invalid input echoed in error")
}
})
}
}
func TestCLI_RejectsMissingPaths(t *testing.T) {
var stdout, stderr bytes.Buffer
err := run([]string{"--profile", "pr-full", "--scenario", "metadata"}, &stdout, &stderr, time.Now())
if err == nil || !strings.Contains(err.Error(), "--nezha-source") {
t.Fatalf("missing source paths were not rejected: %v", err)
}
}
func TestCLI_ParsesRepeatableScenariosAndFault(t *testing.T) {
var stderr bytes.Buffer
config, err := parseFlags([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "soak", "--results-dir", "/tmp/results", "--scenario", "metadata", "--scenario", "transfer-100mib", "--fault", "transfer-hash"}, &stderr)
if err != nil {
t.Fatalf("parse flags: %v", err)
}
if len(config.Scenarios) != 2 || config.Scenarios[0].String() != "metadata" || config.Scenarios[1].String() != "transfer-100mib" || config.Fault.String() != "transfer-hash" {
t.Fatalf("unexpected typed flags: %#v", config)
}
}
func TestCLI_WritesMetadataBeforeRejectingUnsupportedRuntime(t *testing.T) {
resultsDir := t.TempDir()
var stdout, stderr bytes.Buffer
err := run([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", resultsDir, "--scenario", "future-scenario"}, &stdout, &stderr, time.Now())
if err == nil {
t.Fatal("unimplemented runtime reported success")
}
if _, statErr := os.Stat(filepath.Join(resultsDir, "metadata.json")); statErr != nil {
t.Fatalf("metadata was not written before runtime rejection: %v", statErr)
}
}
func TestCLI_RecognizesOnlyMCPFilesystemRuntimeScenario(t *testing.T) {
var stderr bytes.Buffer
config, err := parseFlags([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", t.TempDir(), "--scenario", "mcp-filesystem"}, &stderr)
if err != nil {
t.Fatalf("parse mcp-filesystem flags: %v", err)
}
execution, err := selectScenarioExecution(config)
if err != nil || execution.name != "mcp-filesystem" {
t.Fatalf("mcp-filesystem runtime registration: name=%q err=%v", execution.name, err)
}
config.Scenarios = append(config.Scenarios, config.Scenarios[0])
if _, err := selectScenarioExecution(config); err == nil || !strings.Contains(err.Error(), "exactly one") {
t.Fatalf("multi-scenario runtime was unexpectedly accepted: %v", err)
}
}
func TestCLI_SelectsTerminalRuntimeScenario(t *testing.T) {
var stderr bytes.Buffer
config, err := parseFlags([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", t.TempDir(), "--scenario", "terminal"}, &stderr)
if err != nil {
t.Fatalf("parse terminal flags: %v", err)
}
previous := runTerminalScenario
var received scenario.TerminalInput
runTerminalScenario = func(_ context.Context, input scenario.TerminalInput) (scenario.Result, error) {
received = input
return scenario.Result{Name: "terminal", Passed: true}, nil
}
t.Cleanup(func() { runTerminalScenario = previous })
execution, err := selectScenarioExecution(config)
if err != nil {
t.Fatalf("select terminal scenario: %v", err)
}
if execution.name != "terminal" || execution.run == nil {
t.Fatalf("unexpected terminal execution: %#v", execution)
}
if _, err := execution.run(context.Background()); err != nil {
t.Fatalf("run terminal execution: %v", err)
}
if received.Paths.NezhaSource().String() != "/src/nezha" || received.Paths.AgentSource().String() != "/src/agent" || !received.Fault.IsZero() {
t.Fatalf("terminal input was not forwarded: %#v", received)
}
}
func TestCLI_MetadataWriteReplacesSymlinkWithoutChangingTarget(t *testing.T) {
resultsDir := t.TempDir()
target := filepath.Join(t.TempDir(), "target")
if err := os.WriteFile(target, []byte("sentinel"), 0o644); err != nil {
t.Fatalf("write target: %v", err)
}
if err := os.Symlink(target, filepath.Join(resultsDir, "metadata.json")); err != nil {
t.Fatalf("create metadata symlink: %v", err)
}
var stdout, stderr bytes.Buffer
err := run([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", resultsDir, "--scenario", "metadata"}, &stdout, &stderr, time.Now())
if err != nil {
t.Fatalf("replace metadata symlink: %v", err)
}
data, readErr := os.ReadFile(target)
if readErr != nil || string(data) != "sentinel" {
t.Fatalf("symlink target changed: %q %v", data, readErr)
}
info, statErr := os.Lstat(filepath.Join(resultsDir, "metadata.json"))
if statErr != nil || !info.Mode().IsRegular() || info.Mode().Perm() != 0o600 {
t.Fatalf("metadata replacement mode=%v err=%v", info, statErr)
}
}
func TestCLI_MetadataWriteUsesPrivatePermissions(t *testing.T) {
root := t.TempDir()
resultsDir := filepath.Join(root, "results")
var stdout, stderr bytes.Buffer
if err := run([]string{"--nezha-source", "/src/nezha", "--agent-source", "/src/agent", "--profile", "pr-full", "--results-dir", resultsDir, "--scenario", "metadata"}, &stdout, &stderr, time.Now()); err != nil {
t.Fatalf("write metadata: %v", err)
}
directoryInfo, err := os.Stat(resultsDir)
if err != nil {
t.Fatalf("stat results directory: %v", err)
}
fileInfo, err := os.Stat(filepath.Join(resultsDir, "metadata.json"))
if err != nil {
t.Fatalf("stat metadata: %v", err)
}
if directoryInfo.Mode().Perm() != 0o700 || fileInfo.Mode().Perm() != 0o600 {
t.Fatalf("unexpected permissions: directory=%o file=%o", directoryInfo.Mode().Perm(), fileInfo.Mode().Perm())
}
}