From 90262b3dcdc518ca3eaec7171aa14d74d95f34b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisendo=CC=88rfer?= Date: Sun, 11 Jan 2015 16:15:50 +0100 Subject: [PATCH] Make code testable, add test against native xxd --- xxd.go | 42 +++++++++++++++++++++++------------------ xxd_test.go | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 18 deletions(-) create mode 100644 xxd_test.go diff --git a/xxd.go b/xxd.go index 6000603..31fc3d9 100644 --- a/xxd.go +++ b/xxd.go @@ -8,15 +8,7 @@ import ( "unicode/utf8" ) -const ( - byteOffsetInit = 8 - charOffsetInt = 39 - line_length = 50 -) - func main() { - line_offset := 0 - if len(os.Args) != 2 { fmt.Fprintf(os.Stderr, "Usage: %s [file]\n", os.Args[0]) os.Exit(1) @@ -27,8 +19,21 @@ func main() { panic(err) } defer f.Close() + if err := XXD(f, os.Stdout); err != nil { + panic(err) + } +} + +const ( + byteOffsetInit = 8 + charOffsetInt = 39 + line_length = 50 +) + +func XXD(r io.Reader, w io.Writer) error { + line_offset := 0 - r := bufio.NewReader(f) + r = bufio.NewReader(r) buf := make([]byte, 16) for { n, err := r.Read(buf) @@ -37,27 +42,27 @@ func main() { } // Line offset - fmt.Printf("%06x0: ", line_offset) + fmt.Fprintf(w, "%06x0: ", line_offset) line_offset++ // Hex values for i := 0; i < n; i++ { - fmt.Printf("%02x", buf[i]) + fmt.Fprintf(w, "%02x", buf[i]) if i%2 == 1 { - fmt.Print(" ") + fmt.Fprint(w, " ") } } if n < len(buf) { for i := n; i < len(buf); i++ { - fmt.Printf(" ") + fmt.Fprintf(w, " ") if i%2 == 1 { - fmt.Print(" ") + fmt.Fprint(w, " ") } } } - fmt.Printf(" ") + fmt.Fprintf(w, " ") // Character values b := buf[:n] @@ -65,13 +70,14 @@ func main() { r, size := utf8.DecodeRune(b) if int(r) > 0x1f && int(r) < 0x7f { - fmt.Printf("%v", string(r)) + fmt.Fprintf(w, "%v", string(r)) } else { - fmt.Printf(".") + fmt.Fprintf(w, ".") } b = b[size:] } - fmt.Printf("\n") + fmt.Fprintf(w, "\n") } + return nil } diff --git a/xxd_test.go b/xxd_test.go new file mode 100644 index 0000000..4625276 --- /dev/null +++ b/xxd_test.go @@ -0,0 +1,54 @@ +package main + +import ( + "bytes" + "flag" + "io" + "io/ioutil" + "os/exec" + "strings" + "testing" + "testing/quick" +) + +var xxdFile = flag.String("xxdFile", "", "File to test against.") + +func TestXXD(t *testing.T) { + if *xxdFile == "" { + t.Skip("-xxdFile argument not given") + } + data, err := ioutil.ReadFile(*xxdFile) + if err != nil { + t.Fatal(err) + } + test := func(fn func(r io.Reader, w io.Writer) error) func(n uint64) []string { + return func(n uint64) []string { + size := n % uint64(len(data)) + var out bytes.Buffer + if err := fn(bytes.NewBuffer(data[0:size]), &out); err != nil { + return []string{err.Error()} + } + return strings.Split(out.String(), "\n") + } + } + if err := quick.CheckEqual(test(XXD), test(xxdNative), nil); err != nil { + cErr := err.(*quick.CheckEqualError) + size := cErr.In[0].(uint64) % uint64(len(data)) + for i := range cErr.Out1[0].([]string) { + got := cErr.Out1[0].([]string)[i] + want := cErr.Out2[0].([]string)[i] + if got != want { + t.Errorf("size: %d\n\ngot : %s\nwant: %s\n", size, got, want) + break + } + } + } +} + +func xxdNative(r io.Reader, w io.Writer) error { + xxd := exec.Command("xxd", "-") + xxd.Stdin = r + xxd.Stdout = w + xxd.Stderr = w + return xxd.Run() +}