github.com/goshafaq/sonic@v0.0.0-20231026082336-871835fb94c6/ast/encode_test.go (about) 1 /* 2 * Copyright 2021 ByteDance Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package ast 18 19 import ( 20 "encoding/json" 21 "runtime" 22 "sync" 23 "testing" 24 25 "github.com/goshafaq/sonic/internal/native/types" 26 "github.com/stretchr/testify/assert" 27 "github.com/stretchr/testify/require" 28 ) 29 30 func TestGC_Encode(t *testing.T) { 31 if debugSyncGC { 32 return 33 } 34 root, err := NewSearcher(_TwitterJson).GetByPath() 35 if err != nil { 36 t.Fatal(err) 37 } 38 root.LoadAll() 39 _, err = root.MarshalJSON() 40 if err != nil { 41 t.Fatal(err) 42 } 43 wg := &sync.WaitGroup{} 44 N := 10000 45 for i := 0; i < N; i++ { 46 wg.Add(1) 47 go func(wg *sync.WaitGroup) { 48 defer wg.Done() 49 root, err := NewSearcher(_TwitterJson).GetByPath() 50 if err != nil { 51 t.Error(err) 52 return 53 } 54 root.Load() 55 _, err = root.MarshalJSON() 56 if err != nil { 57 t.Error(err) 58 return 59 } 60 runtime.GC() 61 }(wg) 62 } 63 wg.Wait() 64 } 65 66 func TestEncodeValue(t *testing.T) { 67 obj := new(_TwitterStruct) 68 if err := json.Unmarshal([]byte(_TwitterJson), obj); err != nil { 69 t.Fatal(err) 70 } 71 // buf, err := encoder.Encode(obj, encoder.EscapeHTML|encoder.SortMapKeys) 72 buf, err := json.Marshal(obj) 73 if err != nil { 74 t.Fatal(err) 75 } 76 quote, err := json.Marshal(_TwitterJson) 77 if err != nil { 78 t.Fatal(err) 79 } 80 type Case struct { 81 node Node 82 exp string 83 err bool 84 } 85 input := []Case{ 86 {NewNull(), "null", false}, 87 {NewBool(true), "true", false}, 88 {NewBool(false), "false", false}, 89 {NewNumber("0.0"), "0.0", false}, 90 {NewString(""), `""`, false}, 91 {NewString(`\"\"`), `"\\\"\\\""`, false}, 92 {NewString(_TwitterJson), string(quote), false}, 93 {NewArray([]Node{}), "[]", false}, 94 {NewArray([]Node{NewString(""), NewNull()}), `["",null]`, false}, 95 {NewArray([]Node{NewBool(true), NewString("true"), NewString("\t")}), `[true,"true","\t"]`, false}, 96 {NewObject([]Pair{Pair{"a", NewNull()}, Pair{"b", NewNumber("0")}}), `{"a":null,"b":0}`, false}, 97 {NewObject([]Pair{Pair{"\ta", NewString("\t")}, Pair{"\bb", NewString("\b")}, Pair{"\nb", NewString("\n")}, Pair{"\ra", NewString("\r")}}), `{"\ta":"\t","\u0008b":"\u0008","\nb":"\n","\ra":"\r"}`, false}, 98 {NewObject([]Pair{}), `{}`, false}, 99 {NewObject([]Pair{Pair{Key: "", Value: NewNull()}}), `{"":null}`, false}, 100 {NewBytes([]byte("hello, world")), `"aGVsbG8sIHdvcmxk"`, false}, 101 {NewAny(obj), string(buf), false}, 102 {NewRaw(`[{ }]`), "[{}]", false}, 103 {Node{}, "", true}, 104 {Node{t: types.ValueType(1)}, "", true}, 105 } 106 for i, c := range input { 107 t.Log(i) 108 buf, err := json.Marshal(&c.node) 109 if c.err { 110 if err == nil { 111 t.Fatal(i) 112 } 113 continue 114 } 115 if err != nil { 116 t.Fatal(i, err) 117 } 118 assert.Equal(t, c.exp, string(buf)) 119 } 120 } 121 122 func TestEncodeNode(t *testing.T) { 123 data := `{"a":[{},[],-0.1,true,false,null,""],"b":0,"c":true,"d":false,"e":null,"g":""}` 124 root, e := NewSearcher(data).GetByPath() 125 if e != nil { 126 t.Fatal(root) 127 } 128 ret, err := root.MarshalJSON() 129 if err != nil { 130 t.Fatal(err) 131 } 132 if string(ret) != data { 133 t.Fatal(string(ret)) 134 } 135 root.skipAllKey() 136 ret, err = root.MarshalJSON() 137 if err != nil { 138 t.Fatal(err) 139 } 140 if string(ret) != data { 141 t.Fatal(string(ret)) 142 } 143 root.loadAllKey() 144 ret, err = root.MarshalJSON() 145 if err != nil { 146 t.Fatal(err) 147 } 148 if string(ret) != data { 149 t.Fatal(string(ret)) 150 } 151 } 152 153 type SortableNode struct { 154 sorted bool 155 *Node 156 } 157 158 func (j *SortableNode) UnmarshalJSON(data []byte) error { 159 j.Node = new(Node) 160 return j.Node.UnmarshalJSON(data) 161 } 162 163 func (j *SortableNode) MarshalJSON() ([]byte, error) { 164 if !j.sorted { 165 j.Node.SortKeys(true) 166 j.sorted = true 167 } 168 return j.Node.MarshalJSON() 169 } 170 171 func TestMarshalSort(t *testing.T) { 172 var data = `{"d":3,"a":{"c":1,"b":2},"e":null}` 173 var obj map[string]*SortableNode 174 require.NoError(t, json.Unmarshal([]byte(data), &obj)) 175 out, err := json.Marshal(obj) 176 require.NoError(t, err) 177 require.Equal(t, `{"a":{"b":2,"c":1},"d":3,"e":null}`, string(out)) 178 out, err = json.Marshal(obj) 179 require.NoError(t, err) 180 require.Equal(t, `{"a":{"b":2,"c":1},"d":3,"e":null}`, string(out)) 181 } 182 183 func BenchmarkEncodeRaw_Sonic(b *testing.B) { 184 data := _TwitterJson 185 root, e := NewSearcher(data).GetByPath() 186 if e != nil { 187 b.Fatal(root) 188 } 189 _, err := root.MarshalJSON() 190 if err != nil { 191 b.Fatal(err) 192 } 193 b.SetBytes(int64(len(data))) 194 b.ResetTimer() 195 for i := 0; i < b.N; i++ { 196 _, err := root.MarshalJSON() 197 if err != nil { 198 b.Fatal(err) 199 } 200 } 201 } 202 203 func BenchmarkEncodeSkip_Sonic(b *testing.B) { 204 data := _TwitterJson 205 root, e := NewParser(data).Parse() 206 if e != 0 { 207 b.Fatal(root) 208 } 209 root.skipAllKey() 210 _, err := root.MarshalJSON() 211 if err != nil { 212 b.Fatal(err) 213 } 214 b.SetBytes(int64(len(data))) 215 b.ResetTimer() 216 for i := 0; i < b.N; i++ { 217 _, err := root.MarshalJSON() 218 if err != nil { 219 b.Fatal(err) 220 } 221 } 222 } 223 224 func BenchmarkEncodeLoad_Sonic(b *testing.B) { 225 data := _TwitterJson 226 root, e := NewParser(data).Parse() 227 if e != 0 { 228 b.Fatal(root) 229 } 230 root.loadAllKey() 231 _, err := root.MarshalJSON() 232 if err != nil { 233 b.Fatal(err) 234 } 235 b.SetBytes(int64(len(data))) 236 b.ResetTimer() 237 for i := 0; i < b.N; i++ { 238 _, err := root.MarshalJSON() 239 if err != nil { 240 b.Fatal(err) 241 } 242 } 243 } 244 245 func TestEncodeNone(t *testing.T) { 246 n := NewObject([]Pair{{Key: "a", Value: Node{}}}) 247 out, err := n.MarshalJSON() 248 require.NoError(t, err) 249 require.Equal(t, "{}", string(out)) 250 n = NewObject([]Pair{{Key: "a", Value: NewNull()}, {Key: "b", Value: Node{}}}) 251 out, err = n.MarshalJSON() 252 require.NoError(t, err) 253 require.Equal(t, `{"a":null}`, string(out)) 254 255 n = NewArray([]Node{Node{}}) 256 out, err = n.MarshalJSON() 257 require.NoError(t, err) 258 require.Equal(t, "[]", string(out)) 259 n = NewArray([]Node{NewNull(), Node{}}) 260 out, err = n.MarshalJSON() 261 require.NoError(t, err) 262 require.Equal(t, `[null]`, string(out)) 263 }