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
|
package cli
import (
"os"
"strings"
"testing"
"time"
"github.com/google/go-cmp/cmp"
"gopkg.in/yaml.v3"
)
func init() {
addDefaultModulePaths = false
os.Setenv("NO_COLOR", "")
os.Setenv("GOJQ_COLORS", "")
}
func setLocation(loc *time.Location) func() {
orig := time.Local
time.Local = loc
return func() { time.Local = orig }
}
func TestCliRun(t *testing.T) {
f, err := os.Open("test.yaml")
if err != nil {
t.Fatal(err)
}
defer f.Close()
defer setLocation(time.FixedZone("UTC-7", -7*60*60))()
errorReplacer := strings.NewReplacer(
name+": ", "",
"testdata\\", "testdata/",
"flag `/", "flag `--",
)
var testCases []struct {
Name string
Args []string
Input string
Env []string
Expected string
Error string
ExitCode int `yaml:"exit_code"`
}
if err = yaml.NewDecoder(f).Decode(&testCases); err != nil {
t.Fatal(err)
}
for _, tc := range testCases {
t.Run(tc.Name, func(t *testing.T) {
defer func() {
if err := recover(); err != nil {
t.Fatal(err)
}
}()
var outStream, errStream strings.Builder
cli := cli{
inStream: strings.NewReader(tc.Input),
outStream: &outStream,
errStream: &errStream,
}
for _, env := range tc.Env {
xs := strings.SplitN(env, "=", 2)
k, v := xs[0], xs[1]
defer func(v string) { os.Setenv(k, v) }(os.Getenv(k))
if k == "GOJQ_COLORS" {
defer func(colors [][]byte) {
nullColor, falseColor, trueColor, numberColor,
stringColor, objectKeyColor, arrayColor, objectColor =
colors[0], colors[1], colors[2], colors[3],
colors[4], colors[5], colors[6], colors[7]
}([][]byte{
nullColor, falseColor, trueColor, numberColor,
stringColor, objectKeyColor, arrayColor, objectColor,
})
}
os.Setenv(k, v)
}
code := cli.run(tc.Args)
if tc.Error == "" {
if code != tc.ExitCode {
t.Errorf("exit code: got: %v, expected: %v", code, tc.ExitCode)
}
if diff := cmp.Diff(tc.Expected, outStream.String()); diff != "" {
t.Error("standard output:\n" + diff)
}
if diff := cmp.Diff("", errStream.String()); diff != "" {
t.Error("standard error output:\n" + diff)
}
} else {
errStr := errStream.String()
if strings.Contains(errStr, "DEBUG:") {
if code != exitCodeOK {
t.Errorf("exit code: got: %v, expected: %v", code, exitCodeOK)
}
} else if tc.ExitCode != 0 {
if code != tc.ExitCode {
t.Errorf("exit code: got: %v, expected: %v", code, tc.ExitCode)
}
} else {
if code != exitCodeDefaultErr {
t.Errorf("exit code: got: %v, expected: %v", code, exitCodeDefaultErr)
}
}
if diff := cmp.Diff(tc.Expected, outStream.String()); diff != "" {
t.Error("standard output:\n" + diff)
}
if got, expected := errorReplacer.Replace(errStr), strings.TrimSpace(tc.Error); !strings.Contains(got, expected) {
t.Error("standard error output:\n" + cmp.Diff(expected, got))
}
if !strings.HasSuffix(errStr, "\n") && !strings.Contains(tc.Name, "stderr") && !strings.Contains(tc.Name, "halt_error") {
t.Error(`standard error output should end with "\n"`)
}
if strings.HasSuffix(errStr, "\n\n") {
t.Error(`standard error output should not end with "\n\n"`)
}
}
})
}
}
|