1
0
Fork 0
mirror of https://github.com/imjasonh/csvstruct synced 2026-07-07 02:32:20 +00:00

Clean up tests, account for pre-1.4 csv encoding with a const bool

This commit is contained in:
Jason Hall 2014-12-22 17:57:10 -05:00
parent 731c8af66a
commit ccd21804a5
3 changed files with 98 additions and 110 deletions

View file

@ -20,7 +20,7 @@ func BenchmarkDecode(b *testing.B) {
if err := d.DecodeNext(&r); err == io.EOF {
break
} else if err != nil {
b.Errorf("unexpected error: %v", err)
b.Errorf("DecodeNext(%q): %v", in, err)
return
}
}
@ -33,7 +33,7 @@ func BenchmarkCSVRead(b *testing.B) {
r := csv.NewReader(in)
for i := 0; i < b.N; i++ {
if _, err := r.ReadAll(); err != nil {
b.Errorf("unexpected error: %v", err)
b.Errorf("ReadAll(%q): %v", in, err)
return
}
}
@ -51,7 +51,7 @@ func BenchmarkEncode(b *testing.B) {
for i := 0; i < b.N; i++ {
for _, r := range rows {
if err := e.EncodeNext(r); err != nil {
b.Errorf("unexpected error: %v", err)
b.Errorf("EncodeNext(%v): %v", r, err)
return
}
}
@ -68,7 +68,10 @@ func BenchmarkCSVWrite(b *testing.B) {
w := csv.NewWriter(ioutil.Discard)
for i := 0; i < b.N; i++ {
for _, r := range d {
w.Write(r)
if err := w.Write(r); err != nil {
b.Errorf("Write(%v): %v", r, err)
return
}
}
}
}

View file

@ -17,36 +17,25 @@ func TestDecode(t *testing.T) {
}
for _, c := range []struct {
data string
s string
want []row
}{{
data: `Foo,Bar,Baz
a,b,c
d,e,f
`,
want: []row{{"a", "b", "c"}, {"d", "e", "f"}},
"Foo,Bar,Baz\na,b,c\nd,e,f",
[]row{{"a", "b", "c"}, {"d", "e", "f"}},
}, {
// Rows that only have partial data are only partially filled.
data: `Foo,Bar,Baz
a,"",""
"",b,""
`,
want: []row{{"a", "", ""}, {"", "b", ""}},
"Foo,Bar,Baz\na,,\n,b,",
[]row{{"a", "", ""}, {"", "b", ""}},
}, {
// Rows that don't define all the columns are partially filled.
data: `Foo,Bar
a,""
"",b
`,
want: []row{{"a", "", ""}, {"", "b", ""}},
"Foo,Bar\na,\n,b",
[]row{{"a", "", ""}, {"", "b", ""}},
}, {
// Entirely disjoint columns produce empty structs.
data: `Qux
d
`,
want: []row{{}},
"Qux\nd",
[]row{{}},
}} {
d := NewDecoder(strings.NewReader(c.data))
d := NewDecoder(strings.NewReader(c.s))
rows := []row{}
var r row
for {
@ -59,7 +48,7 @@ d
rows = append(rows, r)
}
if !reflect.DeepEqual(rows, c.want) {
t.Errorf("unexpected result, got %v, want %v", rows, c.want)
t.Errorf("DecodeNext(%q): got %v, want %v", c.s, rows, c.want)
}
if !isDone(d) {
t.Errorf("decoder unexpectedly not done")
@ -68,38 +57,39 @@ d
}
func TestDecode_Unexported(t *testing.T) {
s := "Exported,unexported\na,b"
type row struct {
Exported, unexported string
}
var r row
if err := NewDecoder(strings.NewReader(`Exported,unexported
a,b`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
if err := NewDecoder(strings.NewReader(s)).DecodeNext(&r); err != nil {
t.Errorf("DecodeNext(%q): %v", s, err)
}
want := row{Exported: "a"}
if r != want {
t.Errorf("unexpected result, got %v, want %v", r, want)
t.Errorf("DecodeNext(%q): got %v, want %v", s, r, want)
}
}
func TestDecode_Tags(t *testing.T) {
s := "renamed_foo,Bar,Ignored\na,b,c"
type row struct {
Foo string `csv:"renamed_foo"`
Bar string
Ignored string `csv:"-"`
}
var r row
if err := NewDecoder(strings.NewReader(`renamed_foo,Bar,Ignored
a,b,c`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
if err := NewDecoder(strings.NewReader(s)).DecodeNext(&r); err != nil {
t.Errorf("DecodeNext(%q): %v", s, err)
}
want := row{"a", "b", ""}
if r != want {
t.Errorf("unexpected results, got %v, want %v", r, want)
t.Errorf("DecodeNext(%q): got %v, want %v", s, r, want)
}
}
func TestDecode_NonStrings(t *testing.T) {
s := "Int,Int64,Uint64,Float64,Bool\n123,-123456789,123456789,123.456,true"
type row struct {
Int int
Int64 int64
@ -108,40 +98,40 @@ func TestDecode_NonStrings(t *testing.T) {
Bool bool
}
var r row
if err := NewDecoder(strings.NewReader(`Int,Int64,Uint64,Float64,Bool
123,-123456789,123456789,123.456,true`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
if err := NewDecoder(strings.NewReader(s)).DecodeNext(&r); err != nil {
t.Errorf("DecodeNext(%q): %v", s, err)
}
want := row{123, -123456789, 123456789, 123.456, true}
if r != want {
t.Errorf("unexpected results, got %v, want %v", r, want)
t.Errorf("DecodeNext(%q): got %v, want %v", s, r, want)
}
}
func TestDecode_IncompatibleTypes(t *testing.T) {
// Attempting to parse a string as an int will fail in strconv
s := "Int\nfoo"
type row struct {
Int int
}
var r row
if err := NewDecoder(strings.NewReader(`Int
foo`)).DecodeNext(&r); err.Error() != "error decoding: strconv.ParseInt: parsing \"foo\": invalid syntax" {
t.Errorf("unexpected error: %v", err)
if err := NewDecoder(strings.NewReader(s)).DecodeNext(&r); err.Error() != "error decoding: strconv.ParseInt: parsing \"foo\": invalid syntax" {
t.Errorf("DecodeNext(%q): %v", s, err)
}
}
func TestDecode_CompatibleTypes(t *testing.T) {
// Attempting to parse an int as a string will succeed
s := "String\n123"
type row struct {
String string
}
var r row
if err := NewDecoder(strings.NewReader(`String
123`)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
if err := NewDecoder(strings.NewReader(s)).DecodeNext(&r); err != nil {
t.Errorf("DecodeNext(%q): %v", s, err)
}
if r.String != "123" {
t.Errorf("unexpected results, got %v, want %v", r, row{"123"})
want := row{"123"}
if r != want {
t.Errorf("DecodeNext(%q): got %v, want %v", s, r, want)
}
}
@ -154,30 +144,26 @@ func TestDecode_Pointers(t *testing.T) {
for _, c := range []struct {
s string
want row
}{{
`S,SP
a,b`, row{"a", &b},
}, {
`S,SP
a,`, row{"a", nil},
}} {
}{
{"S,SP\na,b", row{"a", &b}},
{"S,SP\na,", row{"a", nil}},
} {
var r row
if err := NewDecoder(strings.NewReader(c.s)).DecodeNext(&r); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("DecodeNext(%q): %v", c.s, err)
}
if !reflect.DeepEqual(r, c.want) {
t.Errorf("DecodeNext(%q): unexpected results, got %v, want %v", c.s, r, c.want)
t.Errorf("DecodeNext(%q): got %v, want %v", c.s, r, c.want)
}
}
}
func TestDecode_DecodeNil(t *testing.T) {
s := "Foo,Bar\nignore,this\na,b"
type row struct {
Foo, Bar string
}
d := NewDecoder(strings.NewReader(`Foo,Bar
ignore,this
a,b`))
d := NewDecoder(strings.NewReader(s))
if err := d.DecodeNext(nil); err != nil {
t.Errorf("unexpected error while skipping line: %v", err)
}
@ -187,7 +173,7 @@ a,b`))
}
want := row{"a", "b"}
if r != want {
t.Errorf("unexpected result, got %v, want %v", r, want)
t.Errorf("DecodeNext(%q): got %v, want %v", s, r, want)
}
if !isDone(d) {
t.Errorf("decoder unexpectedly not done")
@ -195,18 +181,18 @@ a,b`))
}
func TestDecode_Opts(t *testing.T) {
// TODO: test LazyQuotes
type row struct{ A, B, C string }
want := []row{{"a", "b", "c"}, {"d", "", "f"}}
for _, c := range []struct {
opts DecodeOpts
data string
s string
}{{
DecodeOpts{Comma: '%'},
`A%B%C
a%b%c
d%""%f
`,
d%""%f`,
}, {
DecodeOpts{Comment: '$'},
`A,B,C
@ -214,22 +200,12 @@ $comment
a,b,c
$comment
d,"",f
$comment
`,
}, {
DecodeOpts{LazyQuotes: true},
`A,B,C
a,b,c
d,,f
`,
$comment`,
}, {
DecodeOpts{TrimLeadingSpace: true},
`A,B,C
a,b,c
d,"",f
`,
"A,B,C\n a,b,c\n\td,,f",
}} {
d := NewDecoder(strings.NewReader(c.data)).Opts(c.opts)
d := NewDecoder(strings.NewReader(c.s)).Opts(c.opts)
rows := []row{}
var r row
for {
@ -242,7 +218,7 @@ d,,f
rows = append(rows, r)
}
if !reflect.DeepEqual(rows, want) {
t.Errorf("unexpected result, got %v, want %v", rows, want)
t.Errorf("DecodeNext(%q): got %v, want %v", c.s, rows, want)
}
if !isDone(d) {
t.Errorf("decoder unexpectedly not done")
@ -251,21 +227,19 @@ d,,f
}
func TestDecode_Map(t *testing.T) {
data := `foo,bar,baz
a,b,c
`
s := "foo,bar,baz\na,b,c"
want := map[string]string{
"foo": "a",
"bar": "b",
"baz": "c",
}
got := map[string]string{}
d := NewDecoder(strings.NewReader(data))
d := NewDecoder(strings.NewReader(s))
if err := d.DecodeNext(&got); err != nil {
t.Errorf("%v", err)
}
if !reflect.DeepEqual(got, want) {
t.Errorf("unexpected result, got %v, want %v", got, want)
t.Errorf("DecodeNext(%q): got %v, want %v", s, got, want)
}
if !isDone(d) {
t.Errorf("decoder unexpectedly not done")
@ -273,9 +247,7 @@ a,b,c
}
func TestDecode_MapErrors(t *testing.T) {
d := NewDecoder(strings.NewReader(`foo,bar
a,b
`))
d := NewDecoder(strings.NewReader("foo,bar\na,b"))
m := map[string]string{}
if err := d.DecodeNext(m); err == nil {
@ -295,15 +267,14 @@ a,b
// Tests that values that implement encoding.TextUnarshaler are correctly unmarshaled.
func TestDecode_TextUnmarshaler(t *testing.T) {
d := NewDecoder(strings.NewReader(`N
128.0.0.1
`))
var s struct{ N *net.IP }
if err := d.DecodeNext(&s); err != nil {
t.Errorf("unexpected error: %v", err)
s := "N\n128.0.0.1"
d := NewDecoder(strings.NewReader(s))
var r struct{ N *net.IP }
if err := d.DecodeNext(&r); err != nil {
t.Errorf("DecodeNext(%q): %v", s, err)
}
if !ip.Equal(*s.N) {
t.Errorf("unexpected result, got %v want %v", s.N, ip)
if !ip.Equal(*r.N) {
t.Errorf("DecodeNext(%q): got %v want %v", s, r.N, ip)
}
}

View file

@ -3,9 +3,15 @@ package csvstruct
import (
"bytes"
"net"
"strings"
"testing"
)
// Accounts for changes between Go 1.3 and 1.4 that changed how encoding/csv encodes empty strings
// See https://github.com/golang/go/commit/6ad2749dcd614270ac58c5254b6ada3bce0af090
// Set this to true if tests are failing against Go 1.3 or before
const backcompat = false
func TestEncodeNext(t *testing.T) {
type row struct {
Foo, Bar, Baz string
@ -28,7 +34,7 @@ a,,
`,
}, {
// Encoding incomplete structs still fills in missing columns.
[]interface{}{row{"a", "", ""}, struct{ Foo, Bar string }{"", "b"}},
[]interface{}{row{Foo: "a"}, struct{ Foo, Bar string }{Bar: "b"}},
`Foo,Bar,Baz
a,,
,b,
@ -101,11 +107,15 @@ true
e := NewEncoder(&buf)
for _, r := range c.rows {
if err := e.EncodeNext(r); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
}
if got := buf.String(); got != c.want {
t.Errorf("unexpected result encoding %+v, got %s, want %s", c.rows, got, c.want)
got := buf.String()
if backcompat {
got = strings.Replace(got, `""`, "", -1)
}
if got != c.want {
t.Errorf("EncodeNext(%v): got %s, want %s", c.rows, got, c.want)
}
}
}
@ -137,11 +147,11 @@ d,e,f
e := NewEncoder(&buf).Opts(c.opts)
for _, r := range rows {
if err := e.EncodeNext(r); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
}
if got := buf.String(); got != c.want {
t.Errorf("unexpected results encoding %+v, got %s, want %s", rows, got, c.want)
t.Errorf("EncodeNext(%v): got %s, want %s", rows, got, c.want)
}
}
}
@ -191,11 +201,15 @@ true
e := NewEncoder(&buf)
for _, r := range c.rows {
if err := e.EncodeNext(r); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
}
if got := buf.String(); got != c.want {
t.Errorf("unexpected results encoding %+v, got %s, want %s", c.rows, got, c.want)
got := buf.String()
if backcompat {
got = strings.Replace(got, `""`, "", -1)
}
if got != c.want {
t.Errorf("EncodeNext(%v): got %s, want %s", c.rows, got, c.want)
}
}
}
@ -209,21 +223,21 @@ func TestEncode_Hybrid(t *testing.T) {
Bar string
}{"a", "b"}
if err := e.EncodeNext(s); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
m := map[string]interface{}{
"foo": "c",
"Bar": "d",
}
if err := e.EncodeNext(m); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
want := `foo,Bar
a,b
c,d
`
if got := buf.String(); got != want {
t.Errorf("unexpected results, got %s, want %s", got, want)
t.Errorf("EncodeNext(%v): got %s, want %s", m, got, want)
}
}
@ -231,15 +245,15 @@ c,d
func TestEncode_TextMarshaler(t *testing.T) {
var buf bytes.Buffer
e := NewEncoder(&buf)
s := struct{ N net.IP }{ip}
if err := e.EncodeNext(s); err != nil {
t.Errorf("unexpected error: %v", err)
r := struct{ N net.IP }{ip}
if err := e.EncodeNext(r); err != nil {
t.Errorf("EncodeNext(%v): %v", r, err)
}
want := `N
128.0.0.1
`
if got := buf.String(); got != want {
t.Errorf("unexpected results, got %s, want %s", got, want)
t.Errorf("EncodeNext(%v): got %s, want %s", r, got, want)
}
}
@ -253,12 +267,12 @@ func TestEncode_Ptrs(t *testing.T) {
SP *string
}{bar, &bar}
if err := e.EncodeNext(s); err != nil {
t.Errorf("unexpected error: %v", err)
t.Errorf("EncodeNext(%v): %v", r, err)
}
want := `S,SP
bar,bar
`
if got := buf.String(); got != want {
t.Errorf("unexpected results, got %s, want %s", got, want)
t.Errorf("EncodeNext(%v): got %s, want %s", s, got, want)
}
}