forked from yibn2008/go-bash
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbash_test.go
More file actions
129 lines (121 loc) · 3.68 KB
/
Copy pathbash_test.go
File metadata and controls
129 lines (121 loc) · 3.68 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
package gobash_test
import (
"context"
"errors"
"strings"
"testing"
"time"
gobash "github.com/mark3labs/go-bash"
)
// TestNewZeroOptions covers the Phase 1 acceptance criterion that
// Bash constructs with no options.
func TestNewZeroOptions(t *testing.T) {
b, err := gobash.New(gobash.BashOptions{})
if err != nil {
t.Fatalf("New(BashOptions{}) returned error: %v", err)
}
if b == nil {
t.Fatal("New returned nil *Bash")
}
}
// TestExecEchoHello covers the Phase 1 acceptance criterion that
// `echo hello` returns Stdout: "hello\n", ExitCode: 0.
func TestExecEchoHello(t *testing.T) {
b, err := gobash.New(gobash.BashOptions{})
if err != nil {
t.Fatalf("New: %v", err)
}
res, err := b.Exec(context.Background(), "echo hello", gobash.ExecOptions{})
if err != nil {
t.Fatalf("Exec returned error: %v", err)
}
if res.Stdout != "hello\n" {
t.Errorf("Stdout = %q; want %q", res.Stdout, "hello\n")
}
if res.ExitCode != 0 {
t.Errorf("ExitCode = %d; want 0", res.ExitCode)
}
}
// TestExecExitCode covers the Phase 1 acceptance criterion that
// `exit 7` reports ExitCode: 7 with no error.
func TestExecExitCode(t *testing.T) {
b, err := gobash.New(gobash.BashOptions{})
if err != nil {
t.Fatalf("New: %v", err)
}
res, err := b.Exec(context.Background(), "exit 7", gobash.ExecOptions{})
if err != nil {
t.Fatalf("Exec returned error: %v", err)
}
if res.ExitCode != 7 {
t.Errorf("ExitCode = %d; want 7", res.ExitCode)
}
}
// TestExecMidScriptCancellation covers the Phase 1 acceptance criterion
// that mid-script context cancellation surfaces context.Canceled.
//
// Phase 2 enforces MaxLoopIterations / MaxCommandCount; this test bumps
// them well past anything the busy loop could reach in 50ms so the only
// failure mode is the deliberate ctx cancel.
func TestExecMidScriptCancellation(t *testing.T) {
huge := 1 << 30
b, err := gobash.New(gobash.BashOptions{
ExecutionLimits: &gobash.ExecutionLimits{
MaxLoopIterations: &huge,
MaxCommandCount: &huge,
},
})
if err != nil {
t.Fatalf("New: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(50 * time.Millisecond)
cancel()
}()
// Tight busy loop; mvdan/sh's interp checks ctx between commands.
// MaxLoopIterations / MaxCommandCount are bumped above so the loop
// only terminates on cancellation.
_, err = b.Exec(ctx, "while true; do :; done", gobash.ExecOptions{})
if !errors.Is(err, context.Canceled) {
t.Fatalf("Exec err = %v; want context.Canceled", err)
}
}
// TestExecStdoutWriterPassthrough confirms that a caller-provided Stdout
// writer bypasses string capture, and that result.Stdout is empty in that
// case. This guards the io.Writer-first stream contract.
func TestExecStdoutWriterPassthrough(t *testing.T) {
b, err := gobash.New(gobash.BashOptions{})
if err != nil {
t.Fatalf("New: %v", err)
}
var buf strings.Builder
res, err := b.Exec(context.Background(), "echo world", gobash.ExecOptions{Stdout: &buf})
if err != nil {
t.Fatalf("Exec: %v", err)
}
if got := buf.String(); got != "world\n" {
t.Errorf("writer captured %q; want %q", got, "world\n")
}
if res.Stdout != "" {
t.Errorf("Stdout should be empty when caller supplies Stdout writer; got %q", res.Stdout)
}
}
// TestExecStdinReader confirms stdin is wired from an io.Reader.
func TestExecStdinReader(t *testing.T) {
b, err := gobash.New(gobash.BashOptions{})
if err != nil {
t.Fatalf("New: %v", err)
}
res, err := b.Exec(
context.Background(),
"read line; echo \"got=$line\"",
gobash.ExecOptions{Stdin: strings.NewReader("ping\n")},
)
if err != nil {
t.Fatalf("Exec: %v", err)
}
if res.Stdout != "got=ping\n" {
t.Errorf("Stdout = %q; want %q", res.Stdout, "got=ping\n")
}
}