6ab1e7c56c
gates / gates (push) Successful in 20s
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
63 lines
2.1 KiB
Go
63 lines
2.1 KiB
Go
package guesthook
|
|
|
|
import (
|
|
"context"
|
|
"io"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
)
|
|
|
|
// recordingRunner is a fake proxmox.Runner that records every call and snapshots the content of the
|
|
// install SOURCE file at call time (the deferred os.Remove would erase it before the test can look).
|
|
type recordingRunner struct {
|
|
calls [][]string
|
|
srcContent []string
|
|
}
|
|
|
|
func (r *recordingRunner) Run(_ context.Context, name string, args ...string) ([]byte, []byte, error) {
|
|
r.calls = append(r.calls, append([]string{name}, args...))
|
|
if name == "install" && len(args) > 0 {
|
|
src := args[len(args)-2]
|
|
b, _ := os.ReadFile(src)
|
|
r.srcContent = append(r.srcContent, string(b))
|
|
}
|
|
return nil, nil, nil
|
|
}
|
|
|
|
func (r *recordingRunner) RunStdin(ctx context.Context, _ io.Reader, name string, args ...string) ([]byte, []byte, error) {
|
|
return r.Run(ctx, name, args...)
|
|
}
|
|
|
|
// R-861 (agent v0.146.0): the hook file comes with the signed config bundle; the agent never installs it, only checks.
|
|
// RED-PROOF (audits/hub-safety-2026-10-05/partF/red-proof.txt): make SnippetReady accept any content → the
|
|
// "differs" case fails.
|
|
func TestSnippetReady(t *testing.T) {
|
|
d := t.TempDir()
|
|
p := filepath.Join(d, "felhom-guest-hook.sh")
|
|
if err := SnippetReady(p); err == nil {
|
|
t.Fatal("a missing hook read as ready — the guest would get a hookscript that does not exist")
|
|
}
|
|
_ = os.WriteFile(p, []byte("#!/bin/sh\nid > /tmp/x\n"), 0o755)
|
|
if err := SnippetReady(p); err == nil {
|
|
t.Fatal("a hook with other content read as ready")
|
|
}
|
|
_ = os.WriteFile(p, []byte(snippetBody), 0o755)
|
|
if err := SnippetReady(p); err != nil {
|
|
t.Fatalf("the bundle's hook was not accepted: %v", err)
|
|
}
|
|
l := filepath.Join(d, "link.sh")
|
|
_ = os.Symlink(p, l)
|
|
if err := SnippetReady(l); err == nil {
|
|
t.Fatal("a symlink read as the hook")
|
|
}
|
|
}
|
|
|
|
// The bundle's copy is byte-identical to the body the agent checks against.
|
|
func TestSnippetEqualsTheBundle(t *testing.T) {
|
|
got, err := os.ReadFile(filepath.Join("..", "..", "configs", "felhom-guest-hook.sh"))
|
|
if err != nil || string(got) != snippetBody {
|
|
t.Fatalf("configs/felhom-guest-hook.sh differs from snippetBody (err %v)", err)
|
|
}
|
|
}
|