// Copyright (C) 2022-2023 Luke Shumaker // // SPDX-License-Identifier: GPL-2.0-or-later package lowmemjson import ( "strings" "testing" "github.com/stretchr/testify/assert" "git.lukeshu.com/go/lowmemjson/internal/fastio" ) func TestReEncode(t *testing.T) { t.Parallel() type testcase struct { enc ReEncoderConfig in any exp string } testcases := map[string]testcase{ "basic": { enc: ReEncoderConfig{ Indent: "\t", CompactIfUnder: 10, }, in: map[string][]string{ "a": {"b", "c"}, "d": {"eeeeeeeeeeeeeee"}, }, exp: `{ "a": ["b","c"], "d": [ "eeeeeeeeeeeeeee" ] }`, }, "arrays1": { enc: ReEncoderConfig{ Indent: "\t", CompactIfUnder: 10, ForceTrailingNewlines: true, }, in: []any{ map[string]any{ "generation": 123456, }, map[string]any{ "a": 1, }, map[string]any{ "generation": 7891011213, }, }, exp: `[ { "generation": 123456 }, {"a":1}, { "generation": 7891011213 } ] `, }, "arrays2": { enc: ReEncoderConfig{ Indent: "\t", CompactIfUnder: 15, ForceTrailingNewlines: true, }, in: []any{ map[string]any{ "a": 1, "b": 2, }, map[string]any{ "generation": 123456, }, map[string]any{ "generation": 7891011213, }, }, exp: `[ {"a":1,"b":2}, { "generation": 123456 }, { "generation": 7891011213 } ] `, }, "arrays3": { enc: ReEncoderConfig{ Indent: "\t", ForceTrailingNewlines: true, }, in: []any{ map[string]any{ "a": 1, }, map[string]any{ "generation": 123456, }, map[string]any{ "generation": 7891011213, }, }, exp: `[ { "a": 1 }, { "generation": 123456 }, { "generation": 7891011213 } ] `, }, "indent-unicode": { enc: ReEncoderConfig{ Prefix: "—", Indent: "»", }, in: []int{9}, exp: `[ —»9 —]`, }, "numbers": { enc: ReEncoderConfig{ Compact: true, CompactFloats: true, }, in: []any{ Number("1.200e003"), }, exp: `[1.2e3]`, }, "numbers-zero": { enc: ReEncoderConfig{ Compact: true, CompactFloats: true, }, in: []any{ Number("1.000e000"), }, exp: `[1.0e0]`, }, } for tcName, tc := range testcases { tc := tc t.Run(tcName, func(t *testing.T) { t.Parallel() var out strings.Builder enc := NewEncoder(NewReEncoder(&out, tc.enc)) assert.NoError(t, enc.Encode(tc.in)) assert.Equal(t, tc.exp, out.String()) }) } } func TestReEncodeWriteSize(t *testing.T) { t.Parallel() multibyteRune := `😂` assert.Len(t, multibyteRune, 4) input := `"` + multibyteRune + `"` t.Run("bytes-bigwrite", func(t *testing.T) { t.Parallel() var out strings.Builder enc := NewReEncoder(&out, ReEncoderConfig{}) n, err := enc.Write([]byte(input)) assert.NoError(t, err) assert.Equal(t, len(input), n) assert.Equal(t, input, out.String()) }) t.Run("string-bigwrite", func(t *testing.T) { t.Parallel() var out strings.Builder enc := NewReEncoder(&out, ReEncoderConfig{}) n, err := enc.WriteString(input) assert.NoError(t, err) assert.Equal(t, len(input), n) assert.Equal(t, input, out.String()) }) t.Run("bytes-smallwrites", func(t *testing.T) { t.Parallel() var out strings.Builder enc := NewReEncoder(&out, ReEncoderConfig{}) var buf [1]byte for i := 0; i < len(input); i++ { buf[0] = input[i] n, err := enc.Write(buf[:]) assert.NoError(t, err) assert.Equal(t, 1, n) } assert.Equal(t, input, out.String()) }) t.Run("string-smallwrites", func(t *testing.T) { t.Parallel() var out strings.Builder enc := NewReEncoder(&out, ReEncoderConfig{}) for i := 0; i < len(input); i++ { n, err := enc.WriteString(input[i : i+1]) assert.NoError(t, err) assert.Equal(t, 1, n) } assert.Equal(t, input, out.String()) }) } func TestReEncoderStackSize(t *testing.T) { t.Parallel() enc := NewReEncoder(fastio.Discard, ReEncoderConfig{}) assert.Equal(t, 0, enc.stackSize()) for i := 0; i < 5; i++ { assert.NoError(t, enc.WriteByte('[')) assert.Equal(t, i+1, enc.stackSize()) enc.pushWriteBarrier() assert.Equal(t, i+2, enc.stackSize()) } }