summaryrefslogtreecommitdiff
path: root/internal/hexaiaction/cmdentry_test.go
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2025-09-08 12:02:40 +0300
committerPaul Buetow <paul@buetow.org>2025-09-08 12:02:40 +0300
commit75cf6abd55bfb60324fc47cf91eac08dbb8b87b4 (patch)
tree6ef90d8014fe4d9a757d3f7e95bf736b70e4c685 /internal/hexaiaction/cmdentry_test.go
parent0dcf347c3fbc6e4ffb7e46294f5dd92dbbcd98ef (diff)
docs: move tmux documentation to its own file
Diffstat (limited to 'internal/hexaiaction/cmdentry_test.go')
-rw-r--r--internal/hexaiaction/cmdentry_test.go250
1 files changed, 149 insertions, 101 deletions
diff --git a/internal/hexaiaction/cmdentry_test.go b/internal/hexaiaction/cmdentry_test.go
index de8b5dd..9c896f6 100644
--- a/internal/hexaiaction/cmdentry_test.go
+++ b/internal/hexaiaction/cmdentry_test.go
@@ -1,135 +1,183 @@
package hexaiaction
import (
- "context"
- "fmt"
- "io"
- "os"
- "path/filepath"
- "strings"
- "testing"
- "time"
+ "context"
+ "fmt"
+ "io"
+ "os"
+ "path/filepath"
+ "strings"
+ "testing"
+ "time"
- "codeberg.org/snonux/hexai/internal/tmux"
+ "codeberg.org/snonux/hexai/internal/tmux"
)
// tmux-only flow: decision helpers removed.
func TestPersistStdin_WritesFile(t *testing.T) {
- dir := t.TempDir()
- path := filepath.Join(dir, "in.txt")
- // Point stdin to content
- src := filepath.Join(dir, "src.txt")
- if err := os.WriteFile(src, []byte("hello world"), 0o600); err != nil { t.Fatalf("write src: %v", err) }
- f, _ := os.Open(src)
- defer f.Close()
- if err := persistStdin(path, f); err != nil { t.Fatalf("persistStdin: %v", err) }
- b, _ := os.ReadFile(path)
- if string(b) != "hello world" { t.Fatalf("unexpected content %q", string(b)) }
+ dir := t.TempDir()
+ path := filepath.Join(dir, "in.txt")
+ // Point stdin to content
+ src := filepath.Join(dir, "src.txt")
+ if err := os.WriteFile(src, []byte("hello world"), 0o600); err != nil {
+ t.Fatalf("write src: %v", err)
+ }
+ f, _ := os.Open(src)
+ defer f.Close()
+ if err := persistStdin(path, f); err != nil {
+ t.Fatalf("persistStdin: %v", err)
+ }
+ b, _ := os.ReadFile(path)
+ if string(b) != "hello world" {
+ t.Fatalf("unexpected content %q", string(b))
+ }
}
func TestEchoThrough(t *testing.T) {
- dir := t.TempDir()
- in := filepath.Join(dir, "in.txt")
- out := filepath.Join(dir, "out.txt")
- _ = os.WriteFile(in, []byte("hello"), 0o600)
- if err := echoThrough(in, out, os.Stdin, os.Stdout); err != nil { t.Fatalf("echoThrough: %v", err) }
- b, _ := os.ReadFile(out)
- if string(b) != "hello" { t.Fatalf("unexpected: %q", string(b)) }
+ dir := t.TempDir()
+ in := filepath.Join(dir, "in.txt")
+ out := filepath.Join(dir, "out.txt")
+ _ = os.WriteFile(in, []byte("hello"), 0o600)
+ if err := echoThrough(in, out, os.Stdin, os.Stdout); err != nil {
+ t.Fatalf("echoThrough: %v", err)
+ }
+ b, _ := os.ReadFile(out)
+ if string(b) != "hello" {
+ t.Fatalf("unexpected: %q", string(b))
+ }
}
func TestEchoThrough_StdinStdout(t *testing.T) {
- // set stdin
- rIn, wIn, _ := os.Pipe()
- _, _ = wIn.Write([]byte("PIPE"))
- _ = wIn.Close()
- // capture stdout
- r, w, _ := os.Pipe()
- if err := echoThrough("", "", rIn, w); err != nil { t.Fatalf("echoThrough: %v", err) }
- _ = w.Close()
- data, _ := io.ReadAll(r)
- if string(data) != "PIPE" { t.Fatalf("stdout: %q", string(data)) }
+ // set stdin
+ rIn, wIn, _ := os.Pipe()
+ _, _ = wIn.Write([]byte("PIPE"))
+ _ = wIn.Close()
+ // capture stdout
+ r, w, _ := os.Pipe()
+ if err := echoThrough("", "", rIn, w); err != nil {
+ t.Fatalf("echoThrough: %v", err)
+ }
+ _ = w.Close()
+ data, _ := io.ReadAll(r)
+ if string(data) != "PIPE" {
+ t.Fatalf("stdout: %q", string(data))
+ }
}
func TestRunInTmuxParent_Stubbed(t *testing.T) {
- dir := t.TempDir()
- // set stdin content
- r, w, _ := os.Pipe()
- _, _ = w.Write([]byte("input"))
- _ = w.Close()
- // capture stdout
- rout, wout, _ := os.Pipe()
- oldExec := osExecutableFn
- oldSplit := splitRunFn
- osExecutableFn = func() (string, error) { return "/bin/hexai-tmux-action", nil }
- splitRunFn = func(opts tmux.SplitOpts, argv []string) error {
- for i := 0; i < len(argv)-1; i++ {
- if argv[i] == "-outfile" && i+1 < len(argv) {
- _ = os.WriteFile(argv[i+1], []byte("OUT:"+strings.Join(argv, ",")), 0o600)
- break
- }
- }
- return nil
- }
- t.Cleanup(func() { osExecutableFn = oldExec; splitRunFn = oldSplit })
- if err := runInTmuxParent(r, wout, "", "v", 33); err != nil { t.Fatalf("runInTmuxParent: %v", err) }
- _ = wout.Close()
- got, _ := io.ReadAll(rout)
- if !strings.HasPrefix(string(got), "OUT:") { t.Fatalf("unexpected stdout: %q", string(got)) }
- _ = dir
+ dir := t.TempDir()
+ // set stdin content
+ r, w, _ := os.Pipe()
+ _, _ = w.Write([]byte("input"))
+ _ = w.Close()
+ // capture stdout
+ rout, wout, _ := os.Pipe()
+ oldExec := osExecutableFn
+ oldSplit := splitRunFn
+ osExecutableFn = func() (string, error) { return "/bin/hexai-tmux-action", nil }
+ splitRunFn = func(opts tmux.SplitOpts, argv []string) error {
+ for i := 0; i < len(argv)-1; i++ {
+ if argv[i] == "-outfile" && i+1 < len(argv) {
+ _ = os.WriteFile(argv[i+1], []byte("OUT:"+strings.Join(argv, ",")), 0o600)
+ break
+ }
+ }
+ return nil
+ }
+ t.Cleanup(func() { osExecutableFn = oldExec; splitRunFn = oldSplit })
+ if err := runInTmuxParent(r, wout, "", "v", 33); err != nil {
+ t.Fatalf("runInTmuxParent: %v", err)
+ }
+ _ = wout.Close()
+ got, _ := io.ReadAll(rout)
+ if !strings.HasPrefix(string(got), "OUT:") {
+ t.Fatalf("unexpected stdout: %q", string(got))
+ }
+ _ = dir
}
func TestRunInTmuxParent_ExecutableError(t *testing.T) {
- old := osExecutableFn
- osExecutableFn = func() (string, error) { return "", fmt.Errorf("no exe") }
- t.Cleanup(func() { osExecutableFn = old })
- r, w, _ := os.Pipe(); _, _ = w.Write([]byte("x")); _ = w.Close()
- if err := runInTmuxParent(r, io.Discard, "", "v", 33); err == nil { t.Fatal("expected error from missing executable") }
+ old := osExecutableFn
+ osExecutableFn = func() (string, error) { return "", fmt.Errorf("no exe") }
+ t.Cleanup(func() { osExecutableFn = old })
+ r, w, _ := os.Pipe()
+ _, _ = w.Write([]byte("x"))
+ _ = w.Close()
+ if err := runInTmuxParent(r, io.Discard, "", "v", 33); err == nil {
+ t.Fatal("expected error from missing executable")
+ }
}
func TestRunInTmuxParent_SplitError(t *testing.T) {
- oldExec := osExecutableFn
- osExecutableFn = func() (string, error) { return "/bin/hexai-tmux-action", nil }
- oldSplit := splitRunFn
- splitRunFn = func(_ tmux.SplitOpts, _ []string) error { return fmt.Errorf("split failed") }
- t.Cleanup(func() { osExecutableFn = oldExec; splitRunFn = oldSplit })
- r, w, _ := os.Pipe(); _, _ = w.Write([]byte("x")); _ = w.Close()
- if err := runInTmuxParent(r, io.Discard, "", "v", 33); err == nil { t.Fatal("expected split error") }
+ oldExec := osExecutableFn
+ osExecutableFn = func() (string, error) { return "/bin/hexai-tmux-action", nil }
+ oldSplit := splitRunFn
+ splitRunFn = func(_ tmux.SplitOpts, _ []string) error { return fmt.Errorf("split failed") }
+ t.Cleanup(func() { osExecutableFn = oldExec; splitRunFn = oldSplit })
+ r, w, _ := os.Pipe()
+ _, _ = w.Write([]byte("x"))
+ _ = w.Close()
+ if err := runInTmuxParent(r, io.Discard, "", "v", 33); err == nil {
+ t.Fatal("expected split error")
+ }
}
func TestRunChild_StdoutAndOutfile(t *testing.T) {
- // Outfile mode
- dir := t.TempDir()
- in := filepath.Join(dir, "in.txt")
- out := filepath.Join(dir, "out.txt")
- _ = os.WriteFile(in, []byte("sel"), 0o600)
- oldRun := runFn
- runFn = func(_ context.Context, _ io.Reader, w io.Writer, _ io.Writer) error { _, _ = io.WriteString(w, "RESULT"); return nil }
- t.Cleanup(func(){ runFn = oldRun })
- if err := runChild(context.Background(), in, out, io.Discard, io.Discard); err != nil { t.Fatalf("runChild: %v", err) }
- b, _ := os.ReadFile(out)
- if len(b) == 0 { t.Fatalf("expected some output") }
- // Stdout mode
- r, w, _ := os.Pipe()
- if err := runChild(context.Background(), in, "", w, io.Discard); err != nil { t.Fatalf("runChild: %v", err) }
- _ = w.Close(); buf, _ := io.ReadAll(r)
- if len(buf) == 0 { t.Fatalf("expected stdout output") }
+ // Outfile mode
+ dir := t.TempDir()
+ in := filepath.Join(dir, "in.txt")
+ out := filepath.Join(dir, "out.txt")
+ _ = os.WriteFile(in, []byte("sel"), 0o600)
+ oldRun := runFn
+ runFn = func(_ context.Context, _ io.Reader, w io.Writer, _ io.Writer) error {
+ _, _ = io.WriteString(w, "RESULT")
+ return nil
+ }
+ t.Cleanup(func() { runFn = oldRun })
+ if err := runChild(context.Background(), in, out, io.Discard, io.Discard); err != nil {
+ t.Fatalf("runChild: %v", err)
+ }
+ b, _ := os.ReadFile(out)
+ if len(b) == 0 {
+ t.Fatalf("expected some output")
+ }
+ // Stdout mode
+ r, w, _ := os.Pipe()
+ if err := runChild(context.Background(), in, "", w, io.Discard); err != nil {
+ t.Fatalf("runChild: %v", err)
+ }
+ _ = w.Close()
+ buf, _ := io.ReadAll(r)
+ if len(buf) == 0 {
+ t.Fatalf("expected stdout output")
+ }
}
func TestWaitForFile_Timeout(t *testing.T) {
- dir := t.TempDir()
- p := filepath.Join(dir, "nope")
- if err := waitForFile(p, 10*time.Millisecond); err == nil { t.Fatal("expected timeout error") }
+ dir := t.TempDir()
+ p := filepath.Join(dir, "nope")
+ if err := waitForFile(p, 10*time.Millisecond); err == nil {
+ t.Fatal("expected timeout error")
+ }
}
func TestOpenIO_InfileOutfile(t *testing.T) {
- dir := t.TempDir()
- in := filepath.Join(dir, "i"); out := filepath.Join(dir, "o")
- _ = os.WriteFile(in, []byte("X"), 0o600)
- r, w, ci, co, err := openIO(in, out)
- if err != nil { t.Fatalf("openIO: %v", err) }
- defer ci(); defer co()
- if _, err := io.Copy(w, r); err != nil { t.Fatalf("copy: %v", err) }
- b, _ := os.ReadFile(out)
- if string(b) != "X" { t.Fatalf("got %q", string(b)) }
+ dir := t.TempDir()
+ in := filepath.Join(dir, "i")
+ out := filepath.Join(dir, "o")
+ _ = os.WriteFile(in, []byte("X"), 0o600)
+ r, w, ci, co, err := openIO(in, out)
+ if err != nil {
+ t.Fatalf("openIO: %v", err)
+ }
+ defer ci()
+ defer co()
+ if _, err := io.Copy(w, r); err != nil {
+ t.Fatalf("copy: %v", err)
+ }
+ b, _ := os.ReadFile(out)
+ if string(b) != "X" {
+ t.Fatalf("got %q", string(b))
+ }
}