Skip to content

Commit 3f95075

Browse files
committed
GODRIVER-1777 allow inline struct fields to be overwritten by higher … (#535)
1 parent 1f4c834 commit 3f95075

File tree

6 files changed

+330
-25
lines changed

6 files changed

+330
-25
lines changed

bson/bsoncodec/default_value_decoders_test.go

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2677,6 +2677,53 @@ func TestDefaultValueDecoders(t *testing.T) {
26772677
buildDocument([]byte{}),
26782678
nil,
26792679
},
2680+
{
2681+
"inline overwrite",
2682+
struct {
2683+
Foo struct {
2684+
A int32
2685+
B string
2686+
} `bson:",inline"`
2687+
A int64
2688+
}{
2689+
Foo: struct {
2690+
A int32
2691+
B string
2692+
}{
2693+
A: 0,
2694+
B: "foo",
2695+
},
2696+
A: 54321,
2697+
},
2698+
buildDocument(func(doc []byte) []byte {
2699+
doc = bsoncore.AppendStringElement(doc, "b", "foo")
2700+
doc = bsoncore.AppendInt64Element(doc, "a", 54321)
2701+
return doc
2702+
}(nil)),
2703+
nil,
2704+
},
2705+
{
2706+
"inline overwrite with nested structs",
2707+
struct {
2708+
Foo struct {
2709+
A int32
2710+
} `bson:",inline"`
2711+
Bar struct {
2712+
A int32
2713+
} `bson:",inline"`
2714+
A int64
2715+
}{
2716+
Foo: struct {
2717+
A int32
2718+
}{},
2719+
Bar: struct {
2720+
A int32
2721+
}{},
2722+
A: 54321,
2723+
},
2724+
buildDocument(bsoncore.AppendInt64Element(nil, "a", 54321)),
2725+
nil,
2726+
},
26802727
{
26812728
"inline map",
26822729
struct {
@@ -3062,6 +3109,43 @@ func TestDefaultValueDecoders(t *testing.T) {
30623109
}
30633110
})
30643111
})
3112+
t.Run("error path", func(t *testing.T) {
3113+
testCases := []struct {
3114+
name string
3115+
value interface{}
3116+
b []byte
3117+
err error
3118+
}{
3119+
{
3120+
"duplicate name struct",
3121+
struct {
3122+
A int64
3123+
B int64 `bson:"a"`
3124+
}{
3125+
A: 0,
3126+
B: 54321,
3127+
},
3128+
buildDocument(bsoncore.AppendInt32Element(nil, "a", 12345)),
3129+
fmt.Errorf("duplicated key a"),
3130+
},
3131+
}
3132+
3133+
for _, tc := range testCases {
3134+
t.Run(tc.name, func(t *testing.T) {
3135+
vr := bsonrw.NewBSONDocumentReader(tc.b)
3136+
reg := buildDefaultRegistry()
3137+
vtype := reflect.TypeOf(tc.value)
3138+
dec, err := reg.LookupDecoder(vtype)
3139+
noerr(t, err)
3140+
3141+
gotVal := reflect.New(reflect.TypeOf(tc.value)).Elem()
3142+
err = dec.DecodeValue(DecodeContext{Registry: reg}, vr, gotVal)
3143+
if err == nil || !strings.Contains(err.Error(), tc.err.Error()) {
3144+
t.Errorf("Did not receive expected error. got %v; want %v", err, tc.err)
3145+
}
3146+
})
3147+
}
3148+
})
30653149

30663150
t.Run("defaultEmptyInterfaceCodec.DecodeValue", func(t *testing.T) {
30673151
t.Run("DecodeValue", func(t *testing.T) {

bson/bsoncodec/default_value_encoders_test.go

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"math"
1414
"net/url"
1515
"reflect"
16+
"strings"
1617
"testing"
1718
"time"
1819

@@ -1379,6 +1380,78 @@ func TestDefaultValueEncoders(t *testing.T) {
13791380
buildDocument([]byte{}),
13801381
nil,
13811382
},
1383+
{
1384+
"inline overwrite",
1385+
struct {
1386+
Foo struct {
1387+
A int32
1388+
B string
1389+
} `bson:",inline"`
1390+
A int64
1391+
}{
1392+
Foo: struct {
1393+
A int32
1394+
B string
1395+
}{
1396+
A: 0,
1397+
B: "foo",
1398+
},
1399+
A: 54321,
1400+
},
1401+
buildDocument(func(doc []byte) []byte {
1402+
doc = bsoncore.AppendStringElement(doc, "b", "foo")
1403+
doc = bsoncore.AppendInt64Element(doc, "a", 54321)
1404+
return doc
1405+
}(nil)),
1406+
nil,
1407+
},
1408+
{
1409+
"inline overwrite respects ordering",
1410+
struct {
1411+
A int64
1412+
Foo struct {
1413+
A int32
1414+
B string
1415+
} `bson:",inline"`
1416+
}{
1417+
A: 54321,
1418+
Foo: struct {
1419+
A int32
1420+
B string
1421+
}{
1422+
A: 0,
1423+
B: "foo",
1424+
},
1425+
},
1426+
buildDocument(func(doc []byte) []byte {
1427+
doc = bsoncore.AppendInt64Element(doc, "a", 54321)
1428+
doc = bsoncore.AppendStringElement(doc, "b", "foo")
1429+
return doc
1430+
}(nil)),
1431+
nil,
1432+
},
1433+
{
1434+
"inline overwrite with nested structs",
1435+
struct {
1436+
Foo struct {
1437+
A int32
1438+
} `bson:",inline"`
1439+
Bar struct {
1440+
A int32
1441+
} `bson:",inline"`
1442+
A int64
1443+
}{
1444+
Foo: struct {
1445+
A int32
1446+
}{},
1447+
Bar: struct {
1448+
A int32
1449+
}{},
1450+
A: 54321,
1451+
},
1452+
buildDocument(bsoncore.AppendInt64Element(nil, "a", 54321)),
1453+
nil,
1454+
},
13821455
{
13831456
"inline map",
13841457
struct {
@@ -1676,6 +1749,52 @@ func TestDefaultValueEncoders(t *testing.T) {
16761749
}
16771750
})
16781751

1752+
t.Run("error path", func(t *testing.T) {
1753+
testCases := []struct {
1754+
name string
1755+
value interface{}
1756+
err error
1757+
}{
1758+
{
1759+
"duplicate name struct",
1760+
struct {
1761+
A int64
1762+
B int64 `bson:"a"`
1763+
}{
1764+
A: 0,
1765+
B: 54321,
1766+
},
1767+
fmt.Errorf("duplicated key a"),
1768+
},
1769+
{
1770+
"inline map",
1771+
struct {
1772+
Foo map[string]string `bson:",inline"`
1773+
Baz string
1774+
}{
1775+
Foo: map[string]string{"baz": "bar"},
1776+
Baz: "hi",
1777+
},
1778+
fmt.Errorf("Key baz of inlined map conflicts with a struct field name"),
1779+
},
1780+
}
1781+
1782+
for _, tc := range testCases {
1783+
t.Run(tc.name, func(t *testing.T) {
1784+
b := make(bsonrw.SliceWriter, 0, 512)
1785+
vw, err := bsonrw.NewBSONValueWriter(&b)
1786+
noerr(t, err)
1787+
reg := buildDefaultRegistry()
1788+
enc, err := reg.LookupEncoder(reflect.TypeOf(tc.value))
1789+
noerr(t, err)
1790+
err = enc.EncodeValue(EncodeContext{Registry: reg}, vw, reflect.ValueOf(tc.value))
1791+
if err == nil || !strings.Contains(err.Error(), tc.err.Error()) {
1792+
t.Errorf("Did not receive expected error. got %v; want %v", err, tc.err)
1793+
}
1794+
})
1795+
}
1796+
})
1797+
16791798
t.Run("EmptyInterfaceEncodeValue/nil", func(t *testing.T) {
16801799
val := reflect.New(tEmpty).Elem()
16811800
llvrw := new(bsonrwtest.ValueReaderWriter)

0 commit comments

Comments
 (0)