From 5ac05bd298ecebb3d6636b3c248c3051e93d183d Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Mon, 17 Dec 2018 18:12:51 -0800 Subject: [PATCH] Add debug printer. --- dbg/dbg.go | 76 ++++++++++++++++++++++++++++++ dbg/dbg_test.go | 120 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 196 insertions(+) create mode 100644 dbg/dbg.go create mode 100644 dbg/dbg_test.go diff --git a/dbg/dbg.go b/dbg/dbg.go new file mode 100644 index 0000000..97e64ba --- /dev/null +++ b/dbg/dbg.go @@ -0,0 +1,76 @@ +// Package dbg implements a debug printer. +package dbg + +import ( + "fmt" + "io" + "os" +) + +// A DebugPrinter is a drop-in replacement for fmt.Print*, and also acts as +// an io.WriteCloser when enabled. +type DebugPrinter struct { + // If Enabled is false, the print statements won't do anything. + Enabled bool + out io.WriteCloser +} + +// Close satisfies the Closer interface. +func (dbg *DebugPrinter) Close() error { + return dbg.out.Close() +} + +// Write satisfies the Writer interface. +func (dbg *DebugPrinter) Write(p []byte) (int, error) { + if dbg.Enabled { + return dbg.out.Write(p) + } + return 0, nil +} + +// New returns a new DebugPrinter on os.Stdout. +func New() *DebugPrinter { + return &DebugPrinter{ + out: os.Stdout, + } +} + +// ToFile sets up a new DebugPrinter to a file, truncating it if it exists. +func ToFile(path string) (*DebugPrinter, error) { + file, err := os.Create(path) + if err != nil { + return nil, err + } + + return &DebugPrinter{ + out: file, + }, nil +} + +// To sets up a new DebugPrint to an io.WriteCloser. +func To(w io.WriteCloser) *DebugPrinter { + return &DebugPrinter{ + out: w, + } +} + +// Print calls fmt.Print if Enabled is true. +func (dbg DebugPrinter) Print(v ...interface{}) { + if dbg.Enabled { + fmt.Fprint(dbg.out, v...) + } +} + +// Println calls fmt.Println if Enabled is true. +func (dbg DebugPrinter) Println(v ...interface{}) { + if dbg.Enabled { + fmt.Fprintln(dbg.out, v...) + } +} + +// Printf calls fmt.Printf if Enabled is true. +func (dbg DebugPrinter) Printf(format string, v ...interface{}) { + if dbg.Enabled { + fmt.Fprintf(dbg.out, format, v...) + } +} diff --git a/dbg/dbg_test.go b/dbg/dbg_test.go new file mode 100644 index 0000000..dc07833 --- /dev/null +++ b/dbg/dbg_test.go @@ -0,0 +1,120 @@ +package dbg + +import ( + "io/ioutil" + "os" + "testing" + + "github.com/kisom/goutils/testio" + "github.com/stretchr/testify/require" +) + +func TestNew(t *testing.T) { + buf := testio.NewBufCloser(nil) + dbg := New() + dbg.out = buf + + dbg.Print("hello") + dbg.Println("hello") + dbg.Printf("hello %s", "world") + require.Equal(t, 0, buf.Len()) + + dbg.Enabled = true + dbg.Print("hello") // +5 + dbg.Println("hello") // +6 + dbg.Printf("hello %s", "world") // +11 + require.Equal(t, 22, buf.Len()) + + err := dbg.Close() + require.NoError(t, err) +} + +func TestTo(t *testing.T) { + buf := testio.NewBufCloser(nil) + dbg := To(buf) + + dbg.Print("hello") + dbg.Println("hello") + dbg.Printf("hello %s", "world") + require.Equal(t, 0, buf.Len()) + + dbg.Enabled = true + dbg.Print("hello") // +5 + dbg.Println("hello") // +6 + dbg.Printf("hello %s", "world") // +11 + + require.Equal(t, 22, buf.Len()) + + err := dbg.Close() + require.NoError(t, err) +} + +func TestToFile(t *testing.T) { + testFile, err := ioutil.TempFile("", "dbg") + require.NoError(t, err) + err = testFile.Close() + require.NoError(t, err) + + testFileName := testFile.Name() + defer os.Remove(testFileName) + + dbg, err := ToFile(testFileName) + require.NoError(t, err) + + dbg.Print("hello") + dbg.Println("hello") + dbg.Printf("hello %s", "world") + + stat, err := os.Stat(testFileName) + require.NoError(t, err) + + require.EqualValues(t, 0, stat.Size()) + + dbg.Enabled = true + dbg.Print("hello") // +5 + dbg.Println("hello") // +6 + dbg.Printf("hello %s", "world") // +11 + + stat, err = os.Stat(testFileName) + require.NoError(t, err) + + require.EqualValues(t, 22, stat.Size()) + + err = dbg.Close() + require.NoError(t, err) +} + +func TestWriting(t *testing.T) { + data := []byte("hello, world") + buf := testio.NewBufCloser(nil) + dbg := To(buf) + + n, err := dbg.Write(data) + require.NoError(t, err) + require.EqualValues(t, 0, n) + + dbg.Enabled = true + n, err = dbg.Write(data) + require.NoError(t, err) + require.EqualValues(t, 12, n) + + err = dbg.Close() + require.NoError(t, err) +} + +func TestToFileError(t *testing.T) { + testFile, err := ioutil.TempFile("", "dbg") + require.NoError(t, err) + err = testFile.Chmod(0400) + require.NoError(t, err) + err = testFile.Close() + require.NoError(t, err) + + testFileName := testFile.Name() + + _, err = ToFile(testFileName) + require.Error(t, err) + + err = os.Remove(testFileName) + require.NoError(t, err) +}