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.
This commit is contained in:
1 parent
391e8f0876
commit
f87ec7522c
3 files changed
+60
-8
No files matched your search
+32
@@ -2,6 +2,8 @@ package gocsv
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
@@ -25,6 +27,36 @@ func TestUnmarshalToCallback_ReaderError(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
Reference in new issue
Block a user