toInt and toUint passed base 0 to strconv, which infers the base from the literal the way the Go compiler does. A zero-padded CSV field was then read as octal: 08 and 09 failed with invalid syntax and 010 silently parsed as 8. Pass base 10 at both call sites. Go-style prefixed literals such as 0x1f are no longer accepted; they were undocumented and untested, and cannot be kept without keeping the octal reading of 010 as well. Closes #182
197 lines
3.8 KiB
Go
197 lines
3.8 KiB
Go
package gocsv
|
|
|
|
import (
|
|
"reflect"
|
|
"testing"
|
|
)
|
|
|
|
type sampleTypeUnmarshaller struct {
|
|
val string
|
|
}
|
|
|
|
func (s *sampleTypeUnmarshaller) UnmarshalCSV(val string) error {
|
|
s.val = val
|
|
return nil
|
|
}
|
|
|
|
func (s sampleTypeUnmarshaller) MarshalCSV() (string, error) {
|
|
return s.val, nil
|
|
}
|
|
|
|
type sampleTextUnmarshaller struct {
|
|
val []byte
|
|
}
|
|
|
|
func (s *sampleTextUnmarshaller) UnmarshalText(text []byte) error {
|
|
s.val = text
|
|
return nil
|
|
}
|
|
|
|
func (s sampleTextUnmarshaller) MarshalText() ([]byte, error) {
|
|
return s.val, nil
|
|
}
|
|
|
|
type sampleStringer string
|
|
|
|
func (s sampleStringer) String() string {
|
|
return string(s)
|
|
}
|
|
|
|
type stringAlias string
|
|
type customStringAlias string
|
|
|
|
func (s customStringAlias) MarshalCSV() (string, error) {
|
|
return `"` + string(s) + `"`, nil
|
|
}
|
|
|
|
func Test_getFieldAsString_CustomStringAlias(t *testing.T) {
|
|
s, err := getFieldAsString(reflect.ValueOf(customStringAlias("foo")))
|
|
if err != nil {
|
|
t.Fatalf("getFieldAsString failure: %s", err)
|
|
}
|
|
|
|
if string(s) != `"foo"` {
|
|
t.Fatalf(`expected "foo" got %s`, s)
|
|
}
|
|
|
|
s, err = getFieldAsString(reflect.ValueOf(stringAlias("foo")))
|
|
if err != nil {
|
|
t.Fatalf("getFieldAsString failure: %s", err)
|
|
}
|
|
|
|
if string(s) != `foo` {
|
|
t.Fatalf(`expected foo got %s`, s)
|
|
}
|
|
}
|
|
|
|
func Benchmark_unmarshall_TypeUnmarshaller(b *testing.B) {
|
|
sample := sampleTypeUnmarshaller{}
|
|
val := reflect.ValueOf(&sample)
|
|
for n := 0; n < b.N; n++ {
|
|
if err := unmarshall(val, "foo"); err != nil {
|
|
b.Fatalf("unmarshall error: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark_unmarshall_TextUnmarshaller(b *testing.B) {
|
|
sample := sampleTextUnmarshaller{}
|
|
val := reflect.ValueOf(&sample)
|
|
for n := 0; n < b.N; n++ {
|
|
if err := unmarshall(val, "foo"); err != nil {
|
|
b.Fatalf("unmarshall error: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark_marshall_TypeMarshaller(b *testing.B) {
|
|
sample := sampleTypeUnmarshaller{"foo"}
|
|
val := reflect.ValueOf(&sample)
|
|
for n := 0; n < b.N; n++ {
|
|
_, err := marshall(val)
|
|
if err != nil {
|
|
b.Fatalf("marshall error: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark_marshall_TextMarshaller(b *testing.B) {
|
|
sample := sampleTextUnmarshaller{[]byte("foo")}
|
|
val := reflect.ValueOf(&sample)
|
|
for n := 0; n < b.N; n++ {
|
|
_, err := marshall(val)
|
|
if err != nil {
|
|
b.Fatalf("marshall error: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func Benchmark_marshall_Stringer(b *testing.B) {
|
|
sample := sampleStringer("foo")
|
|
val := reflect.ValueOf(&sample)
|
|
for n := 0; n < b.N; n++ {
|
|
_, err := marshall(val)
|
|
if err != nil {
|
|
b.Fatalf("marshall error: %s", err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestToInt(t *testing.T) {
|
|
TestCase := []struct {
|
|
field string
|
|
result int
|
|
err error
|
|
}{
|
|
{"123.2", 123, nil},
|
|
{"123", 123, nil},
|
|
{"1.2.3", 1, nil},
|
|
{"0.123", 0, nil},
|
|
}
|
|
|
|
for idx, item := range TestCase {
|
|
out, err := toInt(item.field)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if int(out) != item.result {
|
|
t.Fatal(idx, "result not equal")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestToIntLeadingZeros(t *testing.T) {
|
|
testCases := []struct {
|
|
field string
|
|
result int64
|
|
}{
|
|
{"08", 8},
|
|
{"09", 9},
|
|
{"010", 10},
|
|
{"007", 7},
|
|
{"0009", 9},
|
|
{"-08", -8},
|
|
{"-010", -10},
|
|
{"0", 0},
|
|
{"00", 0},
|
|
{"010.9", 10},
|
|
}
|
|
|
|
for _, item := range testCases {
|
|
out, err := toInt(item.field)
|
|
if err != nil {
|
|
t.Errorf("toInt(%q) returned an error: %s", item.field, err)
|
|
continue
|
|
}
|
|
if out != item.result {
|
|
t.Errorf("toInt(%q) = %d, want %d", item.field, out, item.result)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestToUintLeadingZeros(t *testing.T) {
|
|
testCases := []struct {
|
|
field string
|
|
result uint64
|
|
}{
|
|
{"08", 8},
|
|
{"09", 9},
|
|
{"010", 10},
|
|
{"007", 7},
|
|
{"0009", 9},
|
|
{"0", 0},
|
|
{"00", 0},
|
|
}
|
|
|
|
for _, item := range testCases {
|
|
out, err := toUint(item.field)
|
|
if err != nil {
|
|
t.Errorf("toUint(%q) returned an error: %s", item.field, err)
|
|
continue
|
|
}
|
|
if out != item.result {
|
|
t.Errorf("toUint(%q) = %d, want %d", item.field, out, item.result)
|
|
}
|
|
}
|
|
}
|