Files
dualfroz f87ec7522c Make SetHeaderNormalizer safe to call while decoding
SetHeaderNormalizer reassigned the normalizer and copied a fresh sync.Map
over the struct info cache while other goroutines were using it. Keep both
in one value swapped atomically instead. Fixes #237.
2026-10-02 16:20:31 +02:00

67 lines
1.5 KiB
Go

package gocsv
import (
"errors"
"strings"
"sync"
"testing"
)
func TestUnmarshalToCallback_ReaderError(t *testing.T) {
type Dummy struct{}
var reader = &errorReader{}
err := UnmarshalToCallback(reader, func(Dummy) {})
if !errors.Is(err, readerErr) {
t.Error("UnmarshalToCallback should return first reader error")
}
err = UnmarshalDecoderToCallback(newSimpleDecoderFromReader(reader), func(Dummy) {})
if !errors.Is(err, readerErr) {
t.Error("UnmarshalDecoderToCallback should return first reader error")
}
err = UnmarshalToCallbackWithError(reader, func(Dummy) error { return nil })
if !errors.Is(err, readerErr) {
t.Error("UnmarshalToCallbackWithError should return first reader error")
}
}
func TestSetHeaderNormalizerWhileUnmarshaling(t *testing.T) {
defer SetHeaderNormalizer(DefaultNameNormalizer())
type row struct {
ID string `csv:"id"`
Name string `csv:"name"`
}
var wg sync.WaitGroup
for i := 0; i < 50; i++ {
wg.Add(2)
go func() {
defer wg.Done()
SetHeaderNormalizer(strings.ToLower)
}()
go func() {
defer wg.Done()
var rows []row
if err := UnmarshalString("id,name\n1,foo\n", &rows); err != nil {
t.Error(err)
return
}
if len(rows) != 1 || rows[0].ID != "1" || rows[0].Name != "foo" {
t.Errorf("unexpected rows: %+v", rows)
}
}()
}
wg.Wait()
}
type errorReader struct{}
func (e *errorReader) Read([]byte) (n int, err error) {
return 0, readerErr
}
var readerErr = errors.New("reader error")