cowsay/main_test.go
2024-03-30 20:10:41 -04:00

173 lines
4.5 KiB
Go

package main
import (
"os"
"os/exec"
"strings"
"testing"
)
func must[T any](t T, err error) T {
if err != nil {
panic(err)
}
return t
}
var defaultOptions options = options{
tongue: " ",
eyes: "oo",
leftEye: "o",
rightEye: "o",
wrapWidth: 40,
}
func TestGenerateCow(t *testing.T) {
type args struct {
cow string
say string
opt options
}
tests := []struct {
name string
args args
expected string
}{
{
name: "basic cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "test text",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/basic.cow"))),
},
{
name: "single-paragraph test",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "test\ntext",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/one_paragraph.cow"))),
},
{
name: "multiline with wordwrap test",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "this is a long block of text.\nIt goes over many lines! It'll even word-wrap for us.",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/longer_multiline.cow"))),
},
{
name: "two-paragraph multiline with wordwrap test",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "this is a long block of text.\n\nIt goes over many lines! It'll even word-wrap for us.",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/two_paragraph_multiline.cow"))),
},
{
name: "offset bubble",
args: args{
cow: string(must(os.ReadFile("./cows/dragon-and-cow.cow"))),
say: "this is a long block of text.\nIt goes over many lines! It'll even word-wrap for us.",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/dragon.cow"))),
},
{
name: "leading space cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: " text",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/leading_space.cow"))),
},
{
name: "extra spaces cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "some text",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/extra_spaces.cow"))),
},
{
name: "vertical tab cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "some\vtext",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/extra_spaces.cow"))),
},
{
name: "a word that's too long cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: "00000000000000000000000000000000000000000000000000 11",
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/too_long.cow"))),
},
{
name: "fortune cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: `Most people eat as though they were fattening themselves for market.
-- E.W. Howe`,
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/fortune.cow"))),
},
{
name: "trailing space cow",
args: args{
cow: string(must(os.ReadFile("./cows/default.cow"))),
say: `test `,
opt: defaultOptions,
},
expected: string(must(os.ReadFile("./testdata/trailing_space.cow"))),
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
out := generateCow(tt.args.cow, tt.args.say, tt.args.opt)
if out != tt.expected {
t.Logf("expected: \n%v", tt.expected)
t.Logf("got: \n%v", out)
t.Fatal()
}
})
}
}
// fuzz testing requires perl to be installed and in the PATH
func FuzzCow(f *testing.F) {
cowString := string(must(os.ReadFile("./cows/default.cow")))
f.Add("phrase")
f.Add("phrase with many many words in it so that we get a word-wrap situation")
f.Fuzz(func(t *testing.T, phrase string) {
if strings.TrimSpace(phrase) != phrase || phrase == "" {
// uninteresting degenerate cases where there's a bug in the perl
t.Skip()
}
res := generateCow(cowString, phrase, options{tongue: " ", eyes: "oo", wrapWidth: 40})
cmd := exec.Command("perl", "./perl/cowsay", "-f", "./perl/cows/default.cow")
cmd.Stdin = strings.NewReader(phrase)
var out strings.Builder
cmd.Stdout = &out
err := cmd.Run()
if err != nil {
t.Error(err)
}
if res != out.String() {
t.Errorf("mismatch between perl and go.\nPerl:\n%s\ngo:\n%s", out.String(), res)
}
})
}