From 9a85031375355a437bb80f9a7d5608a8232a1919 Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Date: Sun, 20 Jul 2025 22:17:48 -0400 Subject: [PATCH 1/3] Remove extra comment from decoder tests --- decoder_test.go | 215 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) diff --git a/decoder_test.go b/decoder_test.go index a6987fd..78d53fb 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -3318,3 +3318,218 @@ func BenchmarkTimeDurationDecoding(b *testing.B) { _ = decoder.Decode(&ds, input) } } + +func TestConversionErrorError(t *testing.T) { + e := ConversionError{Key: "f", Index: -1} + if got := e.Error(); got != "schema: error converting value for \"f\"" { + t.Errorf("unexpected message %q", got) + } + e = ConversionError{Key: "f", Index: 2, Err: errors.New("boom")} + msg := e.Error() + if !strings.Contains(msg, "index 2 of \"f\"") || !strings.Contains(msg, "boom") { + t.Errorf("unexpected message %q", msg) + } +} + +type sliceValue []byte + +func (sliceValue) UnmarshalText([]byte) error { return nil } + +type valueUM string + +func (valueUM) UnmarshalText([]byte) error { return nil } + +type ptrUM string + +func (*ptrUM) UnmarshalText([]byte) error { return nil } + +type elemUM struct{} + +func (*elemUM) UnmarshalText([]byte) error { return nil } + +type failUM string + +func (*failUM) UnmarshalText([]byte) error { return errors.New("fail") } + +func TestIsTextUnmarshaler(t *testing.T) { + cases := []struct { + name string + val interface{} + check func(t *testing.T, u unmarshaler) + }{ + {"value", valueUM(""), func(t *testing.T, u unmarshaler) { + if !u.IsValid || u.IsPtr { + t.Fatalf("wrong flags: %+v", u) + } + }}, + {"ptr", ptrUM(""), func(t *testing.T, u unmarshaler) { + if !u.IsValid || !u.IsPtr { + t.Fatalf("wrong flags: %+v", u) + } + }}, + {"sliceValue", sliceValue{}, func(t *testing.T, u unmarshaler) { + if !u.IsValid { + t.Fatalf("not valid") + } + }}, + {"sliceElemPtr", []*elemUM{}, func(t *testing.T, u unmarshaler) { + if !u.IsValid || !u.IsSliceElement || !u.IsSliceElementPtr { + t.Fatalf("wrong flags: %+v", u) + } + }}, + {"invalid", 42, func(t *testing.T, u unmarshaler) { + if u.IsValid { + t.Fatalf("expected invalid") + } + }}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + c.check(t, isTextUnmarshaler(reflect.ValueOf(c.val))) + }) + } +} + +func TestHandleMultipartFieldAdditional(t *testing.T) { + fh1 := &multipart.FileHeader{Filename: "f1"} + fh2 := &multipart.FileHeader{Filename: "f2"} + + var a *multipart.FileHeader + if !handleMultipartField(reflect.ValueOf(&a).Elem(), []*multipart.FileHeader{fh1}) || a != fh1 { + t.Errorf("single header not set") + } + + var b []*multipart.FileHeader + if !handleMultipartField(reflect.ValueOf(&b).Elem(), []*multipart.FileHeader{fh1, fh2}) || len(b) != 2 || b[1] != fh2 { + t.Errorf("slice headers not set") + } + + var c *[]*multipart.FileHeader + if !handleMultipartField(reflect.ValueOf(&c).Elem(), []*multipart.FileHeader{fh1}) || c == nil || len(*c) != 1 || (*c)[0] != fh1 { + t.Errorf("pointer slice not set") + } + + var d *multipart.FileHeader + if !handleMultipartField(reflect.ValueOf(&d).Elem(), nil) || d != nil { + t.Errorf("empty files not handled") + } + + x := 0 + if handleMultipartField(reflect.ValueOf(&x).Elem(), []*multipart.FileHeader{fh1}) { + t.Errorf("non multipart field handled") + } +} + +type unsupported struct { + C complex64 `schema:"c"` +} + +type textErr struct{} + +func (*textErr) UnmarshalText([]byte) error { return errors.New("bad") } + +type withSlice struct { + A []struct { + B int `schema:"b"` + } `schema:"a"` +} + +type withText struct { + T textErr `schema:"t"` +} + +type valueErrUM string + +func (valueErrUM) UnmarshalText([]byte) error { return errors.New("bad") } + +type sliceUM struct{} + +func (*sliceUM) UnmarshalText([]byte) error { return errors.New("bad") } + +type panicType int + +func TestDecodeErrors(t *testing.T) { + t.Run("invalid pointer", func(t *testing.T) { + var s unsupported + if err := NewDecoder().Decode(s, nil); err == nil { + t.Fatalf("expected error") + } + }) + + t.Run("panic converter", func(t *testing.T) { + dec := NewDecoder() + dec.RegisterConverter(panicType(0), func(string) reflect.Value { panic("boom") }) + var target struct { + P panicType `schema:"p"` + } + if err := dec.Decode(&target, map[string][]string{"p": {"x"}}); err == nil { + t.Fatalf("expected panic error") + } + }) + + t.Run("panic error converter", func(t *testing.T) { + dec := NewDecoder() + dec.RegisterConverter(panicType(0), func(string) reflect.Value { panic(errors.New("x")) }) + var target struct { + P panicType `schema:"p"` + } + if err := dec.Decode(&target, map[string][]string{"p": {"x"}}); err == nil { + t.Fatalf("expected panic error") + } + }) + + t.Run("unsupported type", func(t *testing.T) { + var u unsupported + if err := NewDecoder().Decode(&u, map[string][]string{"c": {"1"}}); err == nil { + t.Fatalf("expected error") + } + }) + + t.Run("text unmarshaler error", func(t *testing.T) { + var w withText + err := NewDecoder().Decode(&w, map[string][]string{"t": {"x"}}) + if err == nil { + t.Fatalf("expected error") + } + if _, ok := err.(MultiError)["t"].(ConversionError); !ok { + t.Fatalf("wrong error type: %v", err) + } + }) + + t.Run("index larger", func(t *testing.T) { + dec := NewDecoder() + dec.MaxSize(0) + var s withSlice + err := dec.Decode(&s, map[string][]string{"a.1.b": {"5"}}) + if err == nil || !strings.Contains(err.(MultiError)["a.1.b"].Error(), "maxSize") { + t.Fatalf("unexpected error: %v", err) + } + }) + + t.Run("slice converter missing", func(t *testing.T) { + var s struct { + C []complex64 `schema:"c"` + } + if err := NewDecoder().Decode(&s, map[string][]string{"c": {"1"}}); err == nil { + t.Fatalf("expected error") + } + }) + + t.Run("slice textunmarshal error", func(t *testing.T) { + var s struct { + S []sliceUM `schema:"s"` + } + if err := NewDecoder().Decode(&s, map[string][]string{"s": {"a"}}); err == nil { + t.Fatalf("expected error") + } + }) + + t.Run("value unmarshal error", func(t *testing.T) { + var s struct { + V valueErrUM `schema:"v"` + } + if err := NewDecoder().Decode(&s, map[string][]string{"v": {"a"}}); err == nil { + t.Fatalf("expected error") + } + }) +} From 544dd4f70d2206c4b14a1c47d96b5b6d1b5d160c Mon Sep 17 00:00:00 2001 From: Juan Calderon-Perez <835733+gaby@users.noreply.github.com> Date: Sun, 20 Jul 2025 22:23:49 -0400 Subject: [PATCH 2/3] fix lint --- decoder_test.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/decoder_test.go b/decoder_test.go index 78d53fb..fed208a 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -3347,10 +3347,6 @@ type elemUM struct{} func (*elemUM) UnmarshalText([]byte) error { return nil } -type failUM string - -func (*failUM) UnmarshalText([]byte) error { return errors.New("fail") } - func TestIsTextUnmarshaler(t *testing.T) { cases := []struct { name string From a73860dd0e6c280858254c2cdbd3ccc2f665f273 Mon Sep 17 00:00:00 2001 From: RW Date: Mon, 21 Jul 2025 15:28:57 +0200 Subject: [PATCH 3/3] Update decoder_test.go add t.Parallel() everywhere Signed-off-by: RW --- decoder_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/decoder_test.go b/decoder_test.go index fed208a..d157d23 100644 --- a/decoder_test.go +++ b/decoder_test.go @@ -3320,6 +3320,7 @@ func BenchmarkTimeDurationDecoding(b *testing.B) { } func TestConversionErrorError(t *testing.T) { + t.Parallel() e := ConversionError{Key: "f", Index: -1} if got := e.Error(); got != "schema: error converting value for \"f\"" { t.Errorf("unexpected message %q", got) @@ -3348,6 +3349,7 @@ type elemUM struct{} func (*elemUM) UnmarshalText([]byte) error { return nil } func TestIsTextUnmarshaler(t *testing.T) { + t.Parallel() cases := []struct { name string val interface{} @@ -3381,12 +3383,14 @@ func TestIsTextUnmarshaler(t *testing.T) { } for _, c := range cases { t.Run(c.name, func(t *testing.T) { + t.Parallel() c.check(t, isTextUnmarshaler(reflect.ValueOf(c.val))) }) } } func TestHandleMultipartFieldAdditional(t *testing.T) { + t.Parallel() fh1 := &multipart.FileHeader{Filename: "f1"} fh2 := &multipart.FileHeader{Filename: "f2"} @@ -3445,7 +3449,9 @@ func (*sliceUM) UnmarshalText([]byte) error { return errors.New("bad") } type panicType int func TestDecodeErrors(t *testing.T) { + t.Parallel() t.Run("invalid pointer", func(t *testing.T) { + t.Parallel() var s unsupported if err := NewDecoder().Decode(s, nil); err == nil { t.Fatalf("expected error") @@ -3453,6 +3459,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("panic converter", func(t *testing.T) { + t.Parallel() dec := NewDecoder() dec.RegisterConverter(panicType(0), func(string) reflect.Value { panic("boom") }) var target struct { @@ -3464,6 +3471,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("panic error converter", func(t *testing.T) { + t.Parallel() dec := NewDecoder() dec.RegisterConverter(panicType(0), func(string) reflect.Value { panic(errors.New("x")) }) var target struct { @@ -3475,6 +3483,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("unsupported type", func(t *testing.T) { + t.Parallel() var u unsupported if err := NewDecoder().Decode(&u, map[string][]string{"c": {"1"}}); err == nil { t.Fatalf("expected error") @@ -3482,6 +3491,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("text unmarshaler error", func(t *testing.T) { + t.Parallel() var w withText err := NewDecoder().Decode(&w, map[string][]string{"t": {"x"}}) if err == nil { @@ -3493,6 +3503,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("index larger", func(t *testing.T) { + t.Parallel() dec := NewDecoder() dec.MaxSize(0) var s withSlice @@ -3503,6 +3514,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("slice converter missing", func(t *testing.T) { + t.Parallel() var s struct { C []complex64 `schema:"c"` } @@ -3512,6 +3524,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("slice textunmarshal error", func(t *testing.T) { + t.Parallel() var s struct { S []sliceUM `schema:"s"` } @@ -3521,6 +3534,7 @@ func TestDecodeErrors(t *testing.T) { }) t.Run("value unmarshal error", func(t *testing.T) { + t.Parallel() var s struct { V valueErrUM `schema:"v"` }