Skip to content

Commit

Permalink
Merge pull request #480 from benluddy/options-mode-options-roundtrip-fix
Browse files Browse the repository at this point in the history
Fix EncOption/DecOption unset fields on mode regurgitation.
  • Loading branch information
fxamacker authored Feb 4, 2024
2 parents 25223c7 + 7c1f8f3 commit c8f2df8
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 13 deletions.
1 change: 1 addition & 0 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ func (dm *decMode) DecOptions() DecOptions {
IntDec: dm.intDec,
MapKeyByteString: dm.mapKeyByteString,
ExtraReturnErrors: dm.extraReturnErrors,
DefaultMapType: dm.defaultMapType,
UTF8: dm.utf8,
FieldNameMatching: dm.fieldNameMatching,
BigIntDec: dm.bigIntDec,
Expand Down
36 changes: 25 additions & 11 deletions decode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4861,24 +4861,38 @@ func TestUnmarshalToNotNilInterface(t *testing.T) {

func TestDecOptions(t *testing.T) {
opts1 := DecOptions{
DupMapKey: DupMapKeyEnforcedAPF,
TimeTag: DecTagRequired,
MaxNestedLevels: 100,
MaxArrayElements: 102,
MaxMapPairs: 101,
IndefLength: IndefLengthForbidden,
TagsMd: TagsForbidden,
IntDec: IntDecConvertSigned,
ExtraReturnErrors: ExtraDecErrorUnknownField,
UTF8: UTF8DecodeInvalid,
DupMapKey: DupMapKeyEnforcedAPF,
TimeTag: DecTagRequired,
MaxNestedLevels: 100,
MaxArrayElements: 102,
MaxMapPairs: 101,
IndefLength: IndefLengthForbidden,
TagsMd: TagsForbidden,
IntDec: IntDecConvertSigned,
MapKeyByteString: MapKeyByteStringForbidden,
ExtraReturnErrors: ExtraDecErrorUnknownField,
DefaultMapType: reflect.TypeOf(map[string]interface{}(nil)),
UTF8: UTF8DecodeInvalid,
FieldNameMatching: FieldNameMatchingCaseSensitive,
BigIntDec: BigIntDecodePointer,
DefaultByteStringType: reflect.TypeOf(""),
ByteStringToString: ByteStringToStringAllowed,
FieldNameByteString: FieldNameByteStringAllowed,
}
ov := reflect.ValueOf(opts1)
for i := 0; i < ov.NumField(); i++ {
fv := ov.Field(i)
if fv.IsZero() {
t.Errorf("options field %q is unset or set to the zero value for its type", ov.Type().Field(i).Name)
}
}
dm, err := opts1.DecMode()
if err != nil {
t.Errorf("DecMode() returned an error %v", err)
} else {
opts2 := dm.DecOptions()
if !reflect.DeepEqual(opts1, opts2) {
t.Errorf("DecOptions->DecMode->DecOptions returned different values: %v, %v", opts1, opts2)
t.Errorf("DecOptions->DecMode->DecOptions returned different values: %#v, %#v", opts1, opts2)
}
}
}
Expand Down
1 change: 1 addition & 0 deletions encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -643,6 +643,7 @@ func (em *encMode) EncOptions() EncOptions {
Time: em.time,
TimeTag: em.timeTag,
IndefLength: em.indefLength,
NilContainers: em.nilContainers,
TagsMd: em.tagsMd,
OmitEmpty: em.omitEmpty,
String: em.stringType,
Expand Down
38 changes: 36 additions & 2 deletions encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3623,6 +3623,23 @@ func TestEncModeInvalidBigIntConvertMode(t *testing.T) {
}
}

func TestEncOptionsTagsForbidden(t *testing.T) {
// It's not valid to set both TagsMd and TimeTag to a non-zero value in the same EncOptions,
// so this exercises the options-mode-options roundtrip for non-zero TagsMd.
opts1 := EncOptions{
TagsMd: TagsForbidden,
}
em, err := opts1.EncMode()
if err != nil {
t.Errorf("EncMode() returned an error %v", err)
} else {
opts2 := em.EncOptions()
if !reflect.DeepEqual(opts1, opts2) {
t.Errorf("EncOptions->EncMode->EncOptions returned different values: %#v, %#v", opts1, opts2)
}
}
}

func TestEncOptions(t *testing.T) {
opts1 := EncOptions{
Sort: SortBytewiseLexical,
Expand All @@ -3633,16 +3650,33 @@ func TestEncOptions(t *testing.T) {
Time: TimeRFC3339Nano,
TimeTag: EncTagRequired,
IndefLength: IndefLengthForbidden,
NilContainers: NilContainerAsNull,
NilContainers: NilContainerAsEmpty,
TagsMd: TagsAllowed,
OmitEmpty: OmitEmptyGoValue,
String: StringToByteString,
FieldName: FieldNameToByteString,
}
ov := reflect.ValueOf(opts1)
for i := 0; i < ov.NumField(); i++ {
fv := ov.Field(i)
if fv.IsZero() {
fn := ov.Type().Field(i).Name
if fn == "TagsMd" {
// Roundtripping non-zero values for TagsMd is tested separately
// since the non-zero value (TagsForbidden) is incompatible with the
// non-zero value for other options (e.g. TimeTag).
continue
}
t.Errorf("options field %q is unset or set to the zero value for its type", fn)
}
}
em, err := opts1.EncMode()
if err != nil {
t.Errorf("EncMode() returned an error %v", err)
} else {
opts2 := em.EncOptions()
if !reflect.DeepEqual(opts1, opts2) {
t.Errorf("EncOptions->EncMode->EncOptions returned different values: %v, %v", opts1, opts2)
t.Errorf("EncOptions->EncMode->EncOptions returned different values: %#v, %#v", opts1, opts2)
}
}
}
Expand Down

0 comments on commit c8f2df8

Please sign in to comment.