Skip to content

Commit

Permalink
add support to pretty print into a file
Browse files Browse the repository at this point in the history
Sometimes like during Fuzz testing, stdout is supressed, make it difficult to debug.
  • Loading branch information
adamluzsi committed Oct 14, 2024
1 parent 031cb25 commit 752ef40
Show file tree
Hide file tree
Showing 6 changed files with 147 additions and 18 deletions.
30 changes: 25 additions & 5 deletions pp/Diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,15 @@ func TestDiff_smoke(t *testing.T) {

exp := strings.TrimSpace(DiffOutput)
got := strings.TrimSpace(buf.String())
mustEqual(t, exp, got)
assertEqual(t, exp, got)
}

func TestDiffFormat_smoke(t *testing.T) {
type X struct{ A, B int }
v1 := X{A: 1, B: 2}
v2 := X{A: 2, B: 2}
tr := strings.TrimSpace
mustEqual(t, tr(DiffOutput), tr(DiffFormat(v1, v2)))
assertEqual(t, tr(DiffOutput), tr(DiffFormat(v1, v2)))
}

const DiffStringA = `
Expand Down Expand Up @@ -76,7 +76,7 @@ func TestPrettyPrinter_DiffString_smoke(t *testing.T) {
exp := tr(DiffStringOut)
act := tr(got)
t.Logf("\n\nexpected:\n%s\n\nactual:\n%s", exp, act)
mustEqual(t, exp, act)
assertEqual(t, exp, act)
})
tr := func(str string) string {
var strs []string
Expand Down Expand Up @@ -140,14 +140,34 @@ func TestPrettyPrinter_DiffString_smoke(t *testing.T) {
tc := tc
t.Run(tc.Desc, func(t *testing.T) {
diff := DiffString(tr(tc.A), tr(tc.B))
mustEqual(t, tr(tc.Diff), tr(diff))
assertEqual(t, tr(tc.Diff), tr(diff))
})
}
}

func mustEqual(tb testing.TB, exp string, act string) {
func assertEqual(tb testing.TB, exp string, act string) {
tb.Helper()
if act != exp {
tb.Fatalf("exp and got not equal: \n\nexpected:\n%s\n\nactual:\n%s\n", exp, act)
}
}

func assertNoError(tb testing.TB, err error) {
if err != nil {
tb.Fatalf("expected no error but got: %s", err.Error())
}
}

func assertNotEmpty[T any](tb testing.TB, vs []T) {
tb.Helper()
if len(vs) == 0 {
tb.Fatal("expected that slice is not empty")
}
}

func assertEmpty[T any](tb testing.TB, vs []T) {
tb.Helper()
if len(vs) != 0 {
tb.Fatalf("expected that slice is empty, but got %d elements in it", len(vs))
}
}
2 changes: 0 additions & 2 deletions pp/PP.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package pp
import (
"fmt"
"io"
"os"
"runtime"
"strings"
"sync"

"go.llib.dev/testcase/internal/caller"
)

var defaultWriter io.Writer = os.Stderr
var l sync.Mutex

func PP(vs ...any) {
Expand Down
18 changes: 11 additions & 7 deletions pp/PP_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,11 @@ func TestFPP(t *testing.T) {

act := buf.String()

mustEqual(t, exp, act)
assertEqual(t, exp, act)
}

func TestPP(t *testing.T) {
ogw := defaultWriter
defer func() { defaultWriter = ogw }()

buf := &bytes.Buffer{}
defaultWriter = buf
buf := stubDefaultWriter(t)

v1 := time.Date(2022, time.July, 26, 17, 36, 19, 882377000, time.UTC)
v2 := "bar"
Expand All @@ -45,5 +41,13 @@ func TestPP(t *testing.T) {
filepath.Base(file), line+1)
act := buf.String()

mustEqual(t, exp, act)
assertEqual(t, exp, act)
}

func stubDefaultWriter(tb testing.TB) *bytes.Buffer {
ogw := defaultWriter
tb.Cleanup(func() { defaultWriter = ogw })
buf := &bytes.Buffer{}
defaultWriter = buf
return buf
}
17 changes: 13 additions & 4 deletions pp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->

- [Pretty Print (PP)](#pretty-print-pp)
- [usage](#usage)
- [PP / Format](#pp--format)
- [Diff](#diff)
- [usage](#usage)
- [PP / Format](#pp--format)
- [Diff](#diff)
- [printing into a file](#printing-into-a-file)

<!-- END doctoc generated TOC please keep comment here to allow auto update -->

Expand Down Expand Up @@ -80,9 +81,17 @@ func main(t *testing.T) {

> output in GNU diff side-by-side style
```
```go
pp_test.ExampleStruct{ pp_test.ExampleStruct{
A: "The Answer", | A: "The Question",
B: 42, B: 42,
}
```
## printing into a file
If STDOUT is supressed, you can also instruct PP to print into a file by setting the output file path in the `PP` environment variable.
```shell
export PP="out.txt"
```
34 changes: 34 additions & 0 deletions pp/default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package pp

import (
"io"
"os"
)

func init() {
initDefaultWriter()
}

var defaultWriter io.Writer = os.Stderr

func initDefaultWriter() {
fpath, ok := os.LookupEnv("PP")
if !ok {
return
}
if fpath == "" {
return
}
stat, err := os.Stat(fpath)
if err != nil && !os.IsNotExist(err) {
return
}
if stat != nil && stat.IsDir() {
return
}
out, err := os.OpenFile(fpath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
panic(err)
}
defaultWriter = out
}
64 changes: 64 additions & 0 deletions pp/default_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package pp

import (
"io"
"os"
"path/filepath"
"testing"

"go.llib.dev/testcase/internal/env"
)

func Test_envPP(t *testing.T) {
defer initDefaultWriter()

t.Run("when not supplied", func(t *testing.T) {
env.UnsetEnv(t, "PP")
buf := stubDefaultWriter(t)
initDefaultWriter()
PP("OK")
assertNotEmpty(t, buf.Bytes())
})

t.Run("when provided but empty", func(t *testing.T) {
env.SetEnv(t, "PP", "")
buf := stubDefaultWriter(t)
initDefaultWriter()
PP("OK")
assertNotEmpty(t, buf.Bytes())
})

t.Run("when provided but not a valid file path", func(t *testing.T) {
env.SetEnv(t, "PP", ".")
buf := stubDefaultWriter(t)
initDefaultWriter()
PP("OK")
assertNotEmpty(t, buf.Bytes())
})

t.Run("when existing file provided", func(t *testing.T) {
f, err := os.CreateTemp(t.TempDir(), "")
assertNoError(t, err)
env.SetEnv(t, "PP", f.Name())
buf := stubDefaultWriter(t)
initDefaultWriter()
PP("OK")
assertEmpty(t, buf.Bytes())
bs, err := io.ReadAll(f)
assertNoError(t, err)
assertNotEmpty(t, bs)
})

t.Run("when non existing file provided", func(t *testing.T) {
fpath := filepath.Join(t.TempDir(), "test.txt")
env.SetEnv(t, "PP", fpath)
buf := stubDefaultWriter(t)
initDefaultWriter()
PP("OK")
assertEmpty(t, buf.Bytes())
bs, err := os.ReadFile(fpath)
assertNoError(t, err)
assertNotEmpty(t, bs)
})

}

0 comments on commit 752ef40

Please sign in to comment.