// Copyright (C) 2022-2023 Luke Shumaker // // SPDX-License-Identifier: GPL-2.0-or-later package lowmemjson_test import ( "bytes" "encoding/json" "os" "path/filepath" "testing" "github.com/stretchr/testify/require" "git.lukeshu.com/go/lowmemjson" ) type ScanDevicesResult map[uint64]ScanOneDeviceResult type ScanOneDeviceResult struct { FoundExtentCSums []SysExtentCSum } type SysExtentCSum struct { Generation int64 Sums SumRun } type Optional[T any] struct { OK bool Val T } var ( _ json.Marshaler = Optional[bool]{} _ json.Unmarshaler = (*Optional[bool])(nil) ) func (o Optional[T]) MarshalJSON() ([]byte, error) { if o.OK { return json.Marshal(o.Val) } else { return []byte("null"), nil } } func (o *Optional[T]) UnmarshalJSON(dat []byte) error { if string(dat) == "null" { *o = Optional[T]{} return nil } o.OK = true return json.Unmarshal(dat, &o.Val) } type QualifiedPhysicalAddr struct { Dev uint64 Addr int64 } type Mapping struct { LAddr int64 PAddr QualifiedPhysicalAddr Size int64 SizeLocked bool `json:",omitempty"` Flags Optional[uint64] `json:",omitempty"` } func TestRoundTrip(t *testing.T) { t.Parallel() type testcase struct { ObjPtr any Cfg lowmemjson.ReEncoderConfig } testcases := map[string]testcase{ "scandevices": { ObjPtr: new(ScanDevicesResult), Cfg: lowmemjson.ReEncoderConfig{ Indent: "\t", ForceTrailingNewlines: true, CompactIfUnder: 16, }, }, "mappings": { ObjPtr: new([]Mapping), Cfg: lowmemjson.ReEncoderConfig{ Indent: "\t", ForceTrailingNewlines: true, CompactIfUnder: 120, }, }, } for tcName, tc := range testcases { tcName := tcName tc := tc t.Run(tcName, func(t *testing.T) { t.Parallel() inBytes, err := os.ReadFile(filepath.Join("testdata", "roundtrip", tcName+".json")) // #nosec G304 require.NoError(t, err) require.NoError(t, lowmemjson.NewDecoder(bytes.NewReader(inBytes)).DecodeThenEOF(tc.ObjPtr)) var outBytes bytes.Buffer require.NoError(t, lowmemjson.NewEncoder(lowmemjson.NewReEncoder(&outBytes, tc.Cfg)).Encode(tc.ObjPtr)) require.Equal(t, string(inBytes), outBytes.String()) }) } }