/
cmd.go
135 lines (109 loc) · 2.78 KB
/
cmd.go
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
130
131
132
133
134
135
package common
import (
"bytes"
"os"
"os/exec"
"strings"
"testing"
)
type TestExecCmd struct {
// binary to invoke
// Example: "func", "kn", "kubectl", "/usr/bin/sh"
Binary string
// Binary args to append before actual args. Examples:
// when 'kn' binary binaryArgs should be ["func"]
BinaryArgs []string
// Run commands from Dir
SourceDir string
// Indicates shell should dump command line args during execution
ShouldDumpCmdLine bool
// Indicates shell should dump
ShouldDumpOnSuccess bool
// Fail Test on Error
ShouldFailOnError bool
// Environment variable to be used with the command
Env []string
// Optional function to be used to dump stdout command results
DumpLogger func(out string)
// Access to Running or Latest command
ExecCmd *exec.Cmd
// Function to be executed while the command is running. This function is executed only once
OnWaitCallback func(stdout *bytes.Buffer)
// Function to be executed after the command is completed (before error and cmd stdout logic is executed)
OnFinishCallback func(result *TestExecCmdResult)
T *testing.T
}
// TestExecCmdResult stored command result
type TestExecCmdResult struct {
Out string
Error error
}
func (f *TestExecCmd) WithEnv(envKey string, envValue string) *TestExecCmd {
env := envKey + "=" + envValue
f.Env = append(f.Env, env)
return f
}
func (f *TestExecCmd) FromDir(dir string) *TestExecCmd {
f.SourceDir = dir
return f
}
func (f *TestExecCmd) Run(oneArgs string) TestExecCmdResult {
args := strings.Split(oneArgs, " ")
return f.Exec(args...)
}
// Exec invokes go exec library and runs a shell command combining the binary args with args from method signature
func (f *TestExecCmd) Exec(args ...string) TestExecCmdResult {
finalArgs := f.BinaryArgs
if finalArgs == nil {
finalArgs = args
} else if args != nil {
finalArgs = append(finalArgs, args...)
}
if f.ShouldDumpCmdLine {
f.T.Log(f.Binary, strings.Join(finalArgs, " "))
}
var out bytes.Buffer
cmd := exec.Command(f.Binary, finalArgs...)
cmd.Stderr = &out
cmd.Stdout = &out
f.ExecCmd = cmd
if f.SourceDir != "" {
cmd.Dir = f.SourceDir
}
cmd.Env = append(os.Environ(), f.Env...)
// Start command execution
err := cmd.Start()
if err == nil {
if f.OnWaitCallback != nil {
fn := f.OnWaitCallback
f.OnWaitCallback = nil
go fn(&out)
}
// Wait for command to complete
err = cmd.Wait()
}
result := TestExecCmdResult{
Out: out.String(),
Error: err,
}
if f.OnFinishCallback != nil {
f.OnFinishCallback(&result)
}
if err == nil && f.ShouldDumpOnSuccess {
if result.Out != "" {
if f.DumpLogger != nil {
f.DumpLogger(result.Out)
} else {
f.T.Logf("%v", result.Out)
}
}
}
if err != nil {
f.T.Log(result.Out)
f.T.Log(err.Error())
if f.ShouldFailOnError {
f.T.Fail()
}
}
return result
}