github.com/ergo-services/ergo@v1.999.224/etf/encode_test.go (about) 1 package etf 2 3 import ( 4 "fmt" 5 "math/big" 6 "reflect" 7 "testing" 8 9 "github.com/ergo-services/ergo/lib" 10 ) 11 12 func TestEncodeBool(t *testing.T) { 13 b := lib.TakeBuffer() 14 defer lib.ReleaseBuffer(b) 15 16 err := Encode(false, b, EncodeOptions{}) 17 if err != nil { 18 t.Fatal(err) 19 } 20 if !reflect.DeepEqual(b.B, []byte{ettSmallAtom, 5, 'f', 'a', 'l', 's', 'e'}) { 21 t.Fatal("incorrect value") 22 } 23 } 24 25 func TestEncodeBoolWithAtomCache(t *testing.T) { 26 b := lib.TakeBuffer() 27 defer lib.ReleaseBuffer(b) 28 29 senderAtomCache := make(map[Atom]CacheItem) 30 encodingAtomCache := TakeEncodingAtomCache() 31 atomCache := NewAtomCache() 32 ci := CacheItem{ID: 499, Encoded: true, Name: "false"} 33 34 senderAtomCache["false"] = ci 35 36 encodeOptions := EncodeOptions{ 37 AtomCache: atomCache.Out, 38 SenderAtomCache: senderAtomCache, 39 EncodingAtomCache: encodingAtomCache, 40 } 41 42 err := Encode(false, b, encodeOptions) 43 if err != nil { 44 t.Fatal(err) 45 } 46 47 if encodingAtomCache.Len() != 1 || encodingAtomCache.L[0] != ci { 48 t.Fatal("incorrect cache value") 49 } 50 51 if !reflect.DeepEqual(b.B, []byte{ettCacheRef, 0}) { 52 t.Fatal("incorrect value") 53 } 54 55 } 56 57 type integerCase struct { 58 name string 59 integer interface{} 60 expected []byte 61 } 62 63 func integerCases() []integerCase { 64 bigInt := big.Int{} 65 bigInt.SetString("9223372036854775807123456789", 10) 66 bigIntNegative := big.Int{} 67 bigIntNegative.SetString("-9223372036854775807123456789", 10) 68 69 return []integerCase{ 70 // 71 // unsigned integers 72 // 73 {"uint8::255", uint8(255), []byte{ettSmallInteger, 255}}, 74 {"uint16::255", uint16(255), []byte{ettSmallInteger, 255}}, 75 {"uint32::255", uint32(255), []byte{ettSmallInteger, 255}}, 76 {"uint64::255", uint64(255), []byte{ettSmallInteger, 255}}, 77 {"uint::255", uint(255), []byte{ettSmallInteger, 255}}, 78 79 {"uint16::256", uint16(256), []byte{ettInteger, 0, 0, 1, 0}}, 80 81 {"uint16::65535", uint16(65535), []byte{ettInteger, 0, 0, 255, 255}}, 82 {"uint32::65535", uint32(65535), []byte{ettInteger, 0, 0, 255, 255}}, 83 {"uint64::65535", uint64(65535), []byte{ettInteger, 0, 0, 255, 255}}, 84 85 {"uint64::65536", uint64(65536), []byte{ettInteger, 0, 1, 0, 0}}, 86 87 // treat as an int32 88 {"uint32::2147483647", uint32(2147483647), []byte{ettInteger, 127, 255, 255, 255}}, 89 {"uint64::2147483647", uint64(2147483647), []byte{ettInteger, 127, 255, 255, 255}}, 90 {"uint64::2147483648", uint64(2147483648), []byte{ettSmallBig, 4, 0, 0, 0, 0, 128}}, 91 92 {"uint32::4294967295", uint32(4294967295), []byte{ettSmallBig, 4, 0, 255, 255, 255, 255}}, 93 {"uint64::4294967295", uint64(4294967295), []byte{ettSmallBig, 4, 0, 255, 255, 255, 255}}, 94 {"uint64::4294967296", uint64(4294967296), []byte{ettSmallBig, 5, 0, 0, 0, 0, 0, 1}}, 95 96 {"uint64::18446744073709551615", uint64(18446744073709551615), []byte{ettSmallBig, 8, 0, 255, 255, 255, 255, 255, 255, 255, 255}}, 97 98 // 99 // signed integers 100 // 101 102 // negative is always ettInteger for the numbers within the range of int32 103 {"int8::-127", int8(-127), []byte{ettInteger, 255, 255, 255, 129}}, 104 {"int16::-127", int16(-127), []byte{ettInteger, 255, 255, 255, 129}}, 105 {"int32::-127", int32(-127), []byte{ettInteger, 255, 255, 255, 129}}, 106 {"int64::-127", int64(-127), []byte{ettInteger, 255, 255, 255, 129}}, 107 {"int::-127", int(-127), []byte{ettInteger, 255, 255, 255, 129}}, 108 109 // positive within a range of int8 treats as ettSmallInteger 110 {"int8::127", int8(127), []byte{ettSmallInteger, 127}}, 111 {"int16::127", int16(127), []byte{ettSmallInteger, 127}}, 112 {"int32::127", int32(127), []byte{ettSmallInteger, 127}}, 113 {"int64::127", int64(127), []byte{ettSmallInteger, 127}}, 114 115 // a positive int[16,32,64] value within the range of uint8 treats as an uint8 116 {"int16::128", int16(128), []byte{ettSmallInteger, 128}}, 117 {"int32::128", int32(128), []byte{ettSmallInteger, 128}}, 118 {"int64::128", int64(128), []byte{ettSmallInteger, 128}}, 119 {"int::128", int(128), []byte{ettSmallInteger, 128}}, 120 121 // whether its positive or negative value within the range of int16 its treating as an int32 122 {"int16::-32767", int16(-32767), []byte{ettInteger, 255, 255, 128, 1}}, 123 {"int16::32767", int16(32767), []byte{ettInteger, 0, 0, 127, 255}}, 124 125 // treat as an int32 126 {"int32::2147483647", int32(2147483647), []byte{ettInteger, 127, 255, 255, 255}}, 127 {"int32::-2147483648", int32(-2147483648), []byte{ettInteger, 128, 0, 0, 0}}, 128 {"int64::2147483647", int64(2147483647), []byte{ettInteger, 127, 255, 255, 255}}, 129 {"int64::-2147483648", int64(-2147483648), []byte{ettInteger, 128, 0, 0, 0}}, 130 131 {"int64::2147483648", int64(2147483648), []byte{ettSmallBig, 4, 0, 0, 0, 0, 128}}, 132 133 // int64 treats as ettSmallBig whether its positive or negative 134 {"int64::9223372036854775807", int64(9223372036854775807), []byte{ettSmallBig, 8, 0, 255, 255, 255, 255, 255, 255, 255, 127}}, 135 {"int64::-9223372036854775808", int64(-9223372036854775808), []byte{ettSmallBig, 8, 1, 0, 0, 0, 0, 0, 0, 0, 128}}, 136 137 {"big.int::-9223372036854775807123456789", bigIntNegative, []byte{ettSmallBig, 12, 1, 21, 3, 193, 203, 255, 255, 255, 255, 255, 100, 205, 29}}, 138 } 139 } 140 141 func TestEncodeInteger(t *testing.T) { 142 b := lib.TakeBuffer() 143 defer lib.ReleaseBuffer(b) 144 145 for _, c := range integerCases() { 146 t.Run(c.name, func(t *testing.T) { 147 b.Reset() 148 149 err := Encode(c.integer, b, EncodeOptions{}) 150 if err != nil { 151 t.Fatal(err) 152 } 153 if !reflect.DeepEqual(b.B, c.expected) { 154 fmt.Println("exp ", c.expected) 155 fmt.Println("got ", b.B) 156 t.Fatal("incorrect value") 157 } 158 }) 159 } 160 } 161 162 func TestEncodeFloat(t *testing.T) { 163 b := lib.TakeBuffer() 164 defer lib.ReleaseBuffer(b) 165 166 expected := []byte{ettNewFloat, 64, 9, 30, 184, 81, 235, 133, 31} 167 168 err := Encode(float64(3.14), b, EncodeOptions{}) 169 if err != nil { 170 t.Fatal(err) 171 } 172 173 if !reflect.DeepEqual(b.B, expected) { 174 fmt.Println("exp", expected) 175 fmt.Println("got", b.B) 176 t.Fatal("incorrect value") 177 } 178 179 b.Reset() 180 err = Encode(float32(3.14), b, EncodeOptions{}) 181 if err != nil { 182 t.Fatal(err) 183 } 184 185 // float32 to float64 casting makes some changes, thats why 'expected' 186 // has different set of bytes 187 expected = []byte{ettNewFloat, 64, 9, 30, 184, 96, 0, 0, 0} 188 if !reflect.DeepEqual(b.B, expected) { 189 fmt.Println("exp", expected) 190 fmt.Println("got", b.B) 191 t.Fatal("incorrect value") 192 } 193 194 } 195 196 func TestEncodeString(t *testing.T) { 197 b := lib.TakeBuffer() 198 defer lib.ReleaseBuffer(b) 199 200 expected := []byte{ettString, 0, 52, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 46, 32, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 46, 32, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 32, 208, 188, 208, 184, 209, 128, 46, 32, 240, 159, 154, 128} 201 err := Encode("Hello World. 你好世界. Привет мир. 🚀", b, EncodeOptions{}) 202 if err != nil { 203 t.Fatal(err) 204 } 205 206 if !reflect.DeepEqual(b.B, expected) { 207 fmt.Println("exp", expected) 208 fmt.Println("got", b.B) 209 t.Fatal("incorrect value") 210 } 211 } 212 213 func TestEncodeAtom(t *testing.T) { 214 b := lib.TakeBuffer() 215 defer lib.ReleaseBuffer(b) 216 217 expected := []byte{ettSmallAtomUTF8, 14, 69, 114, 103, 111, 32, 70, 114, 97, 109, 101, 119, 218 111, 114, 107} 219 220 err := Encode(Atom("Ergo Framework"), b, EncodeOptions{}) 221 if err != nil { 222 t.Fatal(err) 223 } 224 225 if !reflect.DeepEqual(b.B, expected) { 226 fmt.Println("exp", expected) 227 fmt.Println("got", b.B) 228 t.Fatal("incorrect value") 229 } 230 231 b.Reset() 232 233 // longAtom with 255 utf-8 symbols 446 bytes 234 longAtom := Atom("你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好世界ПриветМирHelloWorld你好") 235 err = Encode(longAtom, b, EncodeOptions{}) 236 237 expected = []byte{ettAtomUTF8, 1, 190, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 208, 156, 208, 184, 209, 128, 72, 101, 108, 108, 111, 87, 111, 114, 108, 100, 228, 189, 160, 229, 165, 189} 238 if !reflect.DeepEqual(b.B, expected) { 239 fmt.Println("exp", expected) 240 fmt.Println("got", b.B) 241 t.Fatal("incorrect value") 242 } 243 244 b.Reset() 245 246 // long Atom. longer 255 symbols. Should return ErrAtomTooLong 247 longAtom = Atom("Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework Ergo Framework") 248 err = Encode(longAtom, b, EncodeOptions{}) 249 if err != ErrAtomTooLong { 250 t.Fatal("incorrect value") 251 } 252 } 253 254 func TestEncodeAtomWithCache(t *testing.T) { 255 b := lib.TakeBuffer() 256 defer lib.ReleaseBuffer(b) 257 258 senderAtomCache := make(map[Atom]CacheItem) 259 encodingAtomCache := TakeEncodingAtomCache() 260 261 atomCache := NewAtomCache() 262 263 ci := CacheItem{ID: 2020, Encoded: true, Name: "cached atom"} 264 senderAtomCache["cached atom"] = ci 265 266 encodeOptions := EncodeOptions{ 267 AtomCache: atomCache.Out, 268 SenderAtomCache: senderAtomCache, 269 EncodingAtomCache: encodingAtomCache, 270 } 271 272 err := Encode(Atom("cached atom"), b, encodeOptions) 273 if err != nil { 274 t.Fatal(err) 275 } 276 277 if encodingAtomCache.Len() != 1 || encodingAtomCache.L[0] != ci { 278 t.Fatal("incorrect cache value") 279 } 280 281 if !reflect.DeepEqual(b.B, []byte{ettCacheRef, 0}) { 282 t.Fatal("incorrect value") 283 } 284 285 b.Reset() 286 287 err = Encode(Atom("not cached atom"), b, encodeOptions) 288 if err != nil { 289 t.Fatal(err) 290 } 291 292 if encodingAtomCache.Len() != 1 || encodingAtomCache.L[0] != ci { 293 t.Fatal("incorrect cache value") 294 } 295 296 expected := []byte{ettSmallAtomUTF8, 15, 110, 111, 116, 32, 99, 97, 99, 104, 101, 100, 32, 97, 116, 111, 109} 297 if !reflect.DeepEqual(b.B, expected) { 298 t.Fatal("incorrect value") 299 } 300 } 301 302 func TestEncodeBinary(t *testing.T) { 303 b := lib.TakeBuffer() 304 defer lib.ReleaseBuffer(b) 305 306 err := Encode([]byte{1, 2, 3, 4, 5}, b, EncodeOptions{}) 307 if err != nil { 308 t.Fatal(err) 309 } 310 311 expected := []byte{ettBinary, 0, 0, 0, 5, 1, 2, 3, 4, 5} 312 if !reflect.DeepEqual(b.B, expected) { 313 t.Fatal("incorrect value") 314 } 315 } 316 317 func TestEncodeList(t *testing.T) { 318 b := lib.TakeBuffer() 319 defer lib.ReleaseBuffer(b) 320 321 expected := []byte{ettList, 0, 0, 0, 3, ettSmallAtomUTF8, 1, 97, ettSmallInteger, 2, ettSmallInteger, 3, ettNil} 322 term := List{Atom("a"), 2, 3} 323 err := Encode(term, b, EncodeOptions{}) 324 if err != nil { 325 t.Fatal(err) 326 } 327 328 if !reflect.DeepEqual(b.B, expected) { 329 fmt.Println("exp", expected) 330 fmt.Println("got", b.B) 331 t.Fatal("incorrect value") 332 } 333 } 334 func TestEncodeListImproper(t *testing.T) { 335 b := lib.TakeBuffer() 336 defer lib.ReleaseBuffer(b) 337 338 expected := []byte{ettList, 0, 0, 0, 2, ettSmallAtomUTF8, 1, 97, ettSmallInteger, 2, ettSmallInteger, 3} 339 term := ListImproper{Atom("a"), 2, 3} 340 err := Encode(term, b, EncodeOptions{}) 341 if err != nil { 342 t.Fatal(err) 343 } 344 345 if !reflect.DeepEqual(b.B, expected) { 346 fmt.Println("exp", expected) 347 fmt.Println("got", b.B) 348 t.Fatal("incorrect value") 349 } 350 } 351 352 func TestEncodeSlice(t *testing.T) { 353 b := lib.TakeBuffer() 354 defer lib.ReleaseBuffer(b) 355 expected := []byte{108, 0, 0, 0, 4, 98, 0, 0, 48, 57, 98, 0, 1, 9, 50, 98, 0, 0, 48, 57, 356 98, 0, 1, 9, 50, 106} 357 //expected := []byte{ettList, 0, 0, 0, 3, ettSmallAtomUTF8, 1, 97, ettSmallInteger, 2, ettSmallInteger, 3, ettNil} 358 term := []int{12345, 67890, 12345, 67890} 359 err := Encode(term, b, EncodeOptions{}) 360 if err != nil { 361 t.Fatal(err) 362 } 363 364 if !reflect.DeepEqual(b.B, expected) { 365 fmt.Println("exp", expected) 366 fmt.Println("got", b.B) 367 t.Fatal("incorrect value") 368 } 369 370 b.Reset() 371 372 expected = []byte{108, 0, 0, 0, 3, 119, 1, 97, 119, 1, 98, 119, 1, 99, 106} 373 termAtoms := []Atom{Atom("a"), Atom("b"), Atom("c")} 374 err = Encode(termAtoms, b, EncodeOptions{}) 375 if err != nil { 376 t.Fatal(err) 377 } 378 379 if !reflect.DeepEqual(b.B, expected) { 380 fmt.Println("exp", expected) 381 fmt.Println("got", b.B) 382 t.Fatal("incorrect value") 383 } 384 } 385 386 func TestEncodeListNested(t *testing.T) { 387 b := lib.TakeBuffer() 388 defer lib.ReleaseBuffer(b) 389 expected := []byte{108, 0, 0, 0, 2, 119, 1, 97, 108, 0, 0, 0, 4, 119, 1, 98, 97, 2, 108, 390 0, 0, 0, 2, 119, 1, 99, 97, 3, 106, 97, 4, 106, 106} 391 392 term := List{Atom("a"), List{Atom("b"), 2, List{Atom("c"), 3}, 4}} 393 err := Encode(term, b, EncodeOptions{}) 394 if err != nil { 395 t.Fatal(err) 396 } 397 398 if !reflect.DeepEqual(b.B, expected) { 399 fmt.Println("exp", expected) 400 fmt.Println("got", b.B) 401 t.Fatal("incorrect value") 402 } 403 } 404 405 func TestEncodeTupleNested(t *testing.T) { 406 b := lib.TakeBuffer() 407 defer lib.ReleaseBuffer(b) 408 expected := []byte{104, 2, 119, 1, 97, 104, 4, 119, 1, 98, 97, 2, 104, 2, 119, 1, 99, 409 97, 3, 97, 4} 410 411 term := Tuple{Atom("a"), Tuple{Atom("b"), 2, Tuple{Atom("c"), 3}, 4}} 412 err := Encode(term, b, EncodeOptions{}) 413 if err != nil { 414 t.Fatal(err) 415 } 416 417 if !reflect.DeepEqual(b.B, expected) { 418 fmt.Println("exp", expected) 419 fmt.Println("got", b.B) 420 t.Fatal("incorrect value") 421 } 422 } 423 424 func TestEncodeTuple(t *testing.T) { 425 b := lib.TakeBuffer() 426 defer lib.ReleaseBuffer(b) 427 428 expected := []byte{ettSmallTuple, 3, ettSmallAtomUTF8, 1, 97, ettSmallInteger, 2, ettSmallInteger, 3} 429 term := Tuple{Atom("a"), 2, 3} 430 err := Encode(term, b, EncodeOptions{}) 431 if err != nil { 432 t.Fatal(err) 433 } 434 435 if !reflect.DeepEqual(b.B, expected) { 436 fmt.Println("exp", expected) 437 fmt.Println("got", b.B) 438 t.Fatal("incorrect value") 439 } 440 } 441 442 func TestEncodeMap(t *testing.T) { 443 b := lib.TakeBuffer() 444 defer lib.ReleaseBuffer(b) 445 446 // map has no guarantee of key order, so the result could be different 447 expected := []byte{116, 0, 0, 0, 2, 119, 4, 107, 101, 121, 49, 98, 0, 0, 48, 57, 119, 4, 448 107, 101, 121, 50, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 449 114, 108, 100} 450 expected1 := []byte{116, 0, 0, 0, 2, 119, 4, 107, 101, 121, 50, 107, 0, 11, 104, 101, 451 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 107, 101, 121, 49, 98, 0, 0, 452 48, 57} 453 term := Map{ 454 Atom("key1"): 12345, 455 Atom("key2"): "hello world", 456 } 457 458 err := Encode(term, b, EncodeOptions{}) 459 if err != nil { 460 t.Fatal(err) 461 } 462 463 if !reflect.DeepEqual(b.B, expected) && !reflect.DeepEqual(b.B, expected1) { 464 fmt.Println("exp", expected) 465 fmt.Println("got", b.B) 466 t.Fatal("incorrect value") 467 } 468 } 469 470 func TestEncodeGoMap(t *testing.T) { 471 b := lib.TakeBuffer() 472 defer lib.ReleaseBuffer(b) 473 474 // map has no guarantee of key order, so the result could be different 475 expected := []byte{116, 0, 0, 0, 2, 119, 4, 107, 101, 121, 49, 98, 0, 0, 48, 57, 119, 4, 476 107, 101, 121, 50, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 477 114, 108, 100} 478 expected1 := []byte{116, 0, 0, 0, 2, 119, 4, 107, 101, 121, 50, 107, 0, 11, 104, 101, 479 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 107, 101, 121, 49, 98, 0, 0, 480 48, 57} 481 term := map[Atom]interface{}{ 482 Atom("key1"): 12345, 483 Atom("key2"): "hello world", 484 } 485 486 err := Encode(term, b, EncodeOptions{}) 487 if err != nil { 488 t.Fatal(err) 489 } 490 491 if !reflect.DeepEqual(b.B, expected) && !reflect.DeepEqual(b.B, expected1) { 492 fmt.Println("exp", expected) 493 fmt.Println("got", b.B) 494 t.Fatal("incorrect value") 495 } 496 } 497 498 func TestEncodeStruct(t *testing.T) { 499 b := lib.TakeBuffer() 500 defer lib.ReleaseBuffer(b) 501 502 expected := []byte{116, 0, 0, 0, 3, 119, 15, 83, 116, 114, 117, 99, 116, 84, 111, 77, 97, 112, 75, 101, 121, 49, 98, 0, 0, 48, 57, 119, 15, 83, 116, 114, 117, 99, 116, 84, 111, 77, 97, 112, 75, 101, 121, 50, 107, 0, 22, 112, 111, 105, 110, 116, 101, 114, 32, 116, 111, 32, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 15, 83, 116, 114, 117, 99, 116, 84, 111, 77, 97, 112, 75, 101, 121, 51, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100} 503 504 s := "pointer to hello world" 505 term := struct { 506 StructToMapKey1 int 507 StructToMapKey2 string 508 StructToMapKey3 string 509 }{ 510 StructToMapKey1: 12345, 511 StructToMapKey2: s, 512 StructToMapKey3: "hello world", 513 } 514 515 err := Encode(term, b, EncodeOptions{}) 516 if err != nil { 517 t.Fatal(err) 518 } 519 520 if !reflect.DeepEqual(b.B, expected) { 521 fmt.Println("exp", expected) 522 fmt.Println("got", b.B) 523 t.Fatal("incorrect value") 524 } 525 b1 := lib.TakeBuffer() 526 defer lib.ReleaseBuffer(b1) 527 528 term1 := struct { 529 StructToMapKey1 int 530 StructToMapKey2 *string 531 StructToMapKey3 string 532 }{ 533 StructToMapKey1: 12345, 534 StructToMapKey2: &s, 535 StructToMapKey3: "hello world", 536 } 537 538 err = Encode(term1, b1, EncodeOptions{}) 539 if err != nil { 540 t.Fatal(err) 541 } 542 543 if !reflect.DeepEqual(b1.B, expected) { 544 fmt.Println("exp", expected) 545 fmt.Println("got", b1.B) 546 t.Fatal("incorrect value") 547 } 548 } 549 550 func TestEncodeStructWithNestedPointers(t *testing.T) { 551 b := lib.TakeBuffer() 552 defer lib.ReleaseBuffer(b) 553 554 type Nested struct { 555 Key1 string 556 Key2 *string 557 Key3 int 558 Key4 *int 559 Key5 float64 560 Key6 *float64 561 Key7 bool 562 Key8 *bool 563 } 564 type Tst struct { 565 Nested 566 Key9 *Nested 567 } 568 ValueString := "hello world" 569 ValueInt := 123 570 ValueFloat := 3.14 571 ValueBool := true 572 573 nested := Nested{ 574 Key1: ValueString, 575 Key2: &ValueString, 576 Key3: ValueInt, 577 Key4: &ValueInt, 578 Key5: ValueFloat, 579 Key6: &ValueFloat, 580 Key7: ValueBool, 581 Key8: &ValueBool, 582 } 583 term := Tst{ 584 Nested: nested, 585 Key9: &nested, 586 } 587 588 expected := []byte{116, 0, 0, 0, 2, 119, 6, 78, 101, 115, 116, 101, 100, 116, 0, 0, 0, 8, 119, 4, 75, 101, 121, 49, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 50, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 51, 97, 123, 119, 4, 75, 101, 121, 52, 97, 123, 119, 4, 75, 101, 121, 53, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 54, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 55, 115, 4, 116, 114, 117, 101, 119, 4, 75, 101, 121, 56, 115, 4, 116, 114, 117, 101, 119, 4, 75, 101, 121, 57, 116, 0, 0, 0, 8, 119, 4, 75, 101, 121, 49, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 50, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 51, 97, 123, 119, 4, 75, 101, 121, 52, 97, 123, 119, 4, 75, 101, 121, 53, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 54, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 55, 115, 4, 116, 114, 117, 101, 119, 4, 75, 101, 121, 56, 115, 4, 116, 114, 117, 101} 589 590 err := Encode(term, b, EncodeOptions{}) 591 if err != nil { 592 t.Fatal(err) 593 } 594 if !reflect.DeepEqual(b.B, expected) { 595 fmt.Println("exp", expected) 596 fmt.Println("got", b.B) 597 t.Fatal("incorrect value") 598 } 599 600 b1 := lib.TakeBuffer() 601 defer lib.ReleaseBuffer(b1) 602 termWithNil := Tst{ 603 Nested: nested, 604 } 605 expectedWithNil := []byte{116, 0, 0, 0, 2, 119, 6, 78, 101, 115, 116, 101, 100, 116, 0, 0, 0, 8, 119, 4, 75, 101, 121, 49, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 50, 107, 0, 11, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 119, 4, 75, 101, 121, 51, 97, 123, 119, 4, 75, 101, 121, 52, 97, 123, 119, 4, 75, 101, 121, 53, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 54, 70, 64, 9, 30, 184, 81, 235, 133, 31, 119, 4, 75, 101, 121, 55, 115, 4, 116, 114, 117, 101, 119, 4, 75, 101, 121, 56, 115, 4, 116, 114, 117, 101, 119, 4, 75, 101, 121, 57, 106} 606 607 err = Encode(termWithNil, b1, EncodeOptions{}) 608 if err != nil { 609 t.Fatal(err) 610 } 611 if !reflect.DeepEqual(b1.B, expectedWithNil) { 612 fmt.Println("exp", expectedWithNil) 613 fmt.Println("got", b1.B) 614 t.Fatal("incorrect value") 615 } 616 } 617 618 func TestEncodeStructWithTags(t *testing.T) { 619 b := lib.TakeBuffer() 620 defer lib.ReleaseBuffer(b) 621 622 expected := []byte{116, 0, 0, 0, 4, 119, 4, 75, 101, 121, 49, 107, 0, 12, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 119, 17, 99, 117, 115, 116, 111, 109, 95, 102, 105, 101, 108, 100, 95, 110, 97, 109, 101, 108, 0, 0, 0, 3, 108, 0, 0, 0, 7, 98, 0, 0, 79, 96, 98, 0, 0, 89, 125, 98, 0, 0, 78, 22, 98, 0, 0, 117, 76, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 13, 98, 0, 0, 4, 31, 98, 0, 0, 4, 64, 98, 0, 0, 4, 56, 98, 0, 0, 4, 50, 98, 0, 0, 4, 53, 98, 0, 0, 4, 66, 97, 32, 98, 0, 0, 4, 28, 98, 0, 0, 4, 56, 98, 0, 0, 4, 64, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 14, 97, 72, 97, 101, 97, 108, 97, 108, 97, 111, 97, 32, 97, 87, 97, 111, 97, 114, 97, 108, 97, 100, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 106, 119, 4, 75, 101, 121, 51, 116, 0, 0, 0, 2, 119, 10, 78, 101, 115, 116, 101, 100, 75, 101, 121, 49, 107, 0, 52, 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33, 32, 228, 189, 160, 229, 165, 189, 228, 184, 150, 231, 149, 140, 33, 32, 208, 159, 209, 128, 208, 184, 208, 178, 208, 181, 209, 130, 32, 208, 156, 208, 184, 209, 128, 33, 32, 240, 159, 154, 128, 119, 5, 102, 105, 101, 108, 100, 116, 0, 0, 0, 1, 107, 0, 7, 109, 97, 112, 95, 107, 101, 121, 108, 0, 0, 0, 32, 97, 72, 97, 101, 97, 108, 97, 108, 97, 111, 97, 32, 97, 87, 97, 111, 97, 114, 97, 108, 97, 100, 97, 33, 97, 32, 98, 0, 0, 79, 96, 98, 0, 0, 89, 125, 98, 0, 0, 78, 22, 98, 0, 0, 117, 76, 97, 33, 97, 32, 98, 0, 0, 4, 31, 98, 0, 0, 4, 64, 98, 0, 0, 4, 56, 98, 0, 0, 4, 50, 98, 0, 0, 4, 53, 98, 0, 0, 4, 66, 97, 32, 98, 0, 0, 4, 28, 98, 0, 0, 4, 56, 98, 0, 0, 4, 64, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 119, 4, 75, 101, 121, 52, 108, 0, 0, 0, 2, 108, 0, 0, 0, 3, 108, 0, 0, 0, 7, 98, 0, 0, 79, 96, 98, 0, 0, 89, 125, 98, 0, 0, 78, 22, 98, 0, 0, 117, 76, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 13, 98, 0, 0, 4, 31, 98, 0, 0, 4, 64, 98, 0, 0, 4, 56, 98, 0, 0, 4, 50, 98, 0, 0, 4, 53, 98, 0, 0, 4, 66, 97, 32, 98, 0, 0, 4, 28, 98, 0, 0, 4, 56, 98, 0, 0, 4, 64, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 14, 97, 72, 97, 101, 97, 108, 97, 108, 97, 111, 97, 32, 97, 87, 97, 111, 97, 114, 97, 108, 97, 100, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 106, 108, 0, 0, 0, 3, 108, 0, 0, 0, 7, 98, 0, 0, 79, 96, 98, 0, 0, 89, 125, 98, 0, 0, 78, 22, 98, 0, 0, 117, 76, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 13, 98, 0, 0, 4, 31, 98, 0, 0, 4, 64, 98, 0, 0, 4, 56, 98, 0, 0, 4, 50, 98, 0, 0, 4, 53, 98, 0, 0, 4, 66, 97, 32, 98, 0, 0, 4, 28, 98, 0, 0, 4, 56, 98, 0, 0, 4, 64, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 108, 0, 0, 0, 14, 97, 72, 97, 101, 97, 108, 97, 108, 97, 111, 97, 32, 97, 87, 97, 111, 97, 114, 97, 108, 97, 100, 97, 33, 97, 32, 98, 0, 1, 246, 128, 106, 106, 106} 623 624 type Nested struct { 625 NestedKey1 string 626 NestedKey2 map[string]*Charlist `etf:"field"` 627 } 628 type StructWithTags struct { 629 Key1 string 630 Key2 []*Charlist `etf:"custom_field_name"` 631 Key3 *Nested 632 Key4 [][]*Charlist 633 } 634 635 nestedMap := make(map[string]*Charlist) 636 value1 := Charlist("Hello World! 你好世界! Привет Мир! 🚀") 637 value11 := "Hello World! 你好世界! Привет Мир! 🚀" 638 nestedMap["map_key"] = &value1 639 640 nested := Nested{ 641 NestedKey1: value11, 642 NestedKey2: nestedMap, 643 } 644 645 value2 := Charlist("你好世界! 🚀") 646 value3 := Charlist("Привет Мир! 🚀") 647 value4 := Charlist("Hello World! 🚀") 648 term := StructWithTags{ 649 Key1: "Hello World!", 650 Key2: []*Charlist{&value2, &value3, &value4}, 651 Key3: &nested, 652 Key4: [][]*Charlist{{&value2, &value3, &value4}, {&value2, &value3, &value4}}, 653 } 654 err := Encode(term, b, EncodeOptions{}) 655 if err != nil { 656 t.Fatal(err) 657 } 658 if !reflect.DeepEqual(b.B, expected) { 659 fmt.Println("exp", expected) 660 fmt.Println("got", b.B) 661 t.Fatal("incorrect value") 662 } 663 } 664 665 func TestEncodePid(t *testing.T) { 666 b := lib.TakeBuffer() 667 defer lib.ReleaseBuffer(b) 668 669 // FlagBigPidRef disabled. max value for ID (15 bits), serial 0 670 expected := []byte{ettPid, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 49, 50, 671 55, 46, 48, 46, 48, 46, 49, 0, 0, 127, 255, 0, 0, 0, 0, 2} 672 term := Pid{Node: "erl-demo@127.0.0.1", ID: 32767, Creation: 2} 673 674 err := Encode(term, b, EncodeOptions{}) 675 if err != nil { 676 t.Fatal(err) 677 } 678 679 if !reflect.DeepEqual(b.B, expected) { 680 fmt.Println("exp", expected) 681 fmt.Println("got", b.B) 682 t.Fatal("incorrect value") 683 } 684 685 // FlagBigPidRef disabled. overflowed 15 bit. ID 0, serial 1 686 b.Reset() 687 expected = []byte{ettPid, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 49, 50, 688 55, 46, 48, 46, 48, 46, 49, 0, 0, 0, 0, 0, 0, 0, 1, 2} 689 term = Pid{Node: "erl-demo@127.0.0.1", ID: 32768, Creation: 2} 690 691 err = Encode(term, b, EncodeOptions{}) 692 if err != nil { 693 t.Fatal(err) 694 } 695 696 if !reflect.DeepEqual(b.B, expected) { 697 fmt.Println("exp", expected) 698 fmt.Println("got", b.B) 699 t.Fatal("incorrect value") 700 } 701 702 // BigCreation, FlagBigPidRef enabled. max value for ID (32 bits), serial 0 703 b.Reset() 704 expected = []byte{ettNewPid, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 49, 50, 705 55, 46, 48, 46, 48, 46, 49, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 2} 706 term = Pid{Node: "erl-demo@127.0.0.1", ID: 4294967295, Creation: 2} 707 708 options := EncodeOptions{ 709 FlagBigCreation: true, 710 FlagBigPidRef: true, 711 } 712 err = Encode(term, b, options) 713 if err != nil { 714 t.Fatal(err) 715 } 716 717 if !reflect.DeepEqual(b.B, expected) { 718 fmt.Println("exp", expected) 719 fmt.Println("got", b.B) 720 t.Fatal("incorrect value") 721 } 722 723 // BigCreation, FlagBigPidRef enabled. max value for ID (32 bits), max value for Serial (32 bits) 724 b.Reset() 725 expected = []byte{ettNewPid, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 49, 50, 726 55, 46, 48, 46, 48, 46, 49, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 2} 727 term = Pid{Node: "erl-demo@127.0.0.1", ID: 18446744073709551615, Creation: 2} 728 729 options = EncodeOptions{ 730 FlagBigCreation: true, 731 FlagBigPidRef: true, 732 } 733 err = Encode(term, b, options) 734 if err != nil { 735 t.Fatal(err) 736 } 737 738 if !reflect.DeepEqual(b.B, expected) { 739 fmt.Println("exp", expected) 740 fmt.Println("got", b.B) 741 t.Fatal("incorrect value") 742 } 743 } 744 745 func TestEncodePidWithAtomCache(t *testing.T) { 746 b := lib.TakeBuffer() 747 defer lib.ReleaseBuffer(b) 748 749 expected := []byte{103, 82, 0, 0, 0, 1, 56, 0, 0, 0, 0, 2} 750 term := Pid{Node: "erl-demo@127.0.0.1", ID: 312, Creation: 2} 751 752 senderAtomCache := make(map[Atom]CacheItem) 753 encodingAtomCache := TakeEncodingAtomCache() 754 atomCache := NewAtomCache() 755 756 ci := CacheItem{ID: 2020, Encoded: true, Name: "erl-demo@127.0.0.1"} 757 senderAtomCache["erl-demo@127.0.0.1"] = ci 758 encodeOptions := EncodeOptions{ 759 AtomCache: atomCache.Out, 760 SenderAtomCache: senderAtomCache, 761 EncodingAtomCache: encodingAtomCache, 762 } 763 err := Encode(term, b, encodeOptions) 764 if err != nil { 765 t.Fatal(err) 766 } 767 768 if encodingAtomCache.Len() != 1 || encodingAtomCache.L[0] != ci { 769 t.Fatal("incorrect cache value") 770 } 771 772 if !reflect.DeepEqual(b.B, expected) { 773 fmt.Println("exp", expected) 774 fmt.Println("got", b.B) 775 t.Fatal("incorrect value") 776 } 777 778 } 779 780 func TestEncodeRef(t *testing.T) { 781 b := lib.TakeBuffer() 782 defer lib.ReleaseBuffer(b) 783 784 // FlagBigCreation = false, FlagBigPidRef = false 785 expected := []byte{ettNewRef, 0, 3, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 786 49, 50, 55, 46, 48, 46, 48, 46, 49, 3, 0, 1, 30, 228, 183, 192, 0, 1, 141, 787 122, 203, 35} 788 789 term := Ref{ 790 Node: Atom("erl-demo@127.0.0.1"), 791 // Creation must be encoded as 3 792 // Only one byte long and only two bits are significant, the rest must be 0. 793 Creation: 7, 794 ID: [5]uint32{73444, 3082813441, 2373634851}, 795 } 796 797 err := Encode(term, b, EncodeOptions{}) 798 if err != nil { 799 t.Fatal(err) 800 } 801 802 if !reflect.DeepEqual(b.B, expected) { 803 fmt.Println("exp", expected) 804 fmt.Println("got", b.B) 805 t.Fatal("incorrect value") 806 } 807 808 // FlagBigCreation = true, FlagBigPidRef = false 809 b.Reset() 810 expected = []byte{ettNewerRef, 0, 3, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 811 49, 50, 55, 46, 48, 46, 48, 46, 49, 0, 0, 0, 8, 0, 1, 30, 228, 183, 192, 0, 1, 141, 812 122, 203, 35} 813 814 term = Ref{ 815 Node: Atom("erl-demo@127.0.0.1"), 816 Creation: 8, 817 ID: [5]uint32{73444, 3082813441, 2373634851, 1, 2}, 818 } 819 820 options := EncodeOptions{ 821 FlagBigCreation: true, 822 } 823 err = Encode(term, b, options) 824 if err != nil { 825 t.Fatal(err) 826 } 827 828 if !reflect.DeepEqual(b.B, expected) { 829 fmt.Println("exp", expected) 830 fmt.Println("got", b.B) 831 t.Fatal("incorrect value") 832 } 833 834 // 835 // FIXME Erlang 24 has a bug https://github.com/erlang/otp/issues/5097 836 // uncomment once they fix it 837 // 838 // FlagBigCreation = true, FlagBigPidRef = true 839 //b.Reset() 840 //expected = []byte{ettNewerRef, 0, 5, 119, 18, 101, 114, 108, 45, 100, 101, 109, 111, 64, 841 // 49, 50, 55, 46, 48, 46, 48, 46, 49, 0, 0, 0, 8, 0, 1, 30, 228, 183, 192, 0, 1, 141, 842 // 122, 203, 35, 0, 0, 0, 1, 0, 0, 0, 2} 843 844 //term = Ref{ 845 // Node: Atom("erl-demo@127.0.0.1"), 846 // Creation: 8, 847 // ID: [5]uint32{73444, 3082813441, 2373634851, 1, 2}, 848 //} 849 850 //options = EncodeOptions{ 851 // FlagBigCreation: true, 852 // FlagBigPidRef: true, 853 //} 854 //err = Encode(term, b, options) 855 //if err != nil { 856 // t.Fatal(err) 857 //} 858 859 //if !reflect.DeepEqual(b.B, expected) { 860 // fmt.Println("exp", expected) 861 // fmt.Println("got", b.B) 862 // t.Fatal("incorrect value") 863 //} 864 } 865 866 func TestEncodeTupleRefPid(t *testing.T) { 867 b := lib.TakeBuffer() 868 defer lib.ReleaseBuffer(b) 869 870 expected := []byte{ettSmallTuple, 2, ettNewRef, 0, 3, ettSmallAtomUTF8, 18, 101, 114, 108, 45, 100, 101, 109, 871 111, 64, 49, 50, 55, 46, 48, 46, 48, 46, 49, 2, 0, 1, 31, 28, 183, 192, 0, 872 1, 141, 122, 203, 35, 103, ettSmallAtomUTF8, 18, 101, 114, 108, 45, 100, 101, 873 109, 111, 64, 49, 50, 55, 46, 48, 46, 48, 46, 49, 0, 0, 1, 56, 0, 0, 0, 0, 874 2} 875 876 term := Tuple{ 877 Ref{ 878 Node: Atom("erl-demo@127.0.0.1"), 879 Creation: 2, 880 ID: [5]uint32{0x11f1c, 0xb7c00001, 0x8d7acb23}}, 881 Pid{ 882 Node: Atom("erl-demo@127.0.0.1"), 883 ID: 312, 884 Creation: 2}} 885 886 err := Encode(term, b, EncodeOptions{}) 887 if err != nil { 888 t.Fatal(err) 889 } 890 891 if !reflect.DeepEqual(b.B, expected) { 892 fmt.Println("exp", expected) 893 fmt.Println("got", b.B) 894 t.Fatal("incorrect value") 895 } 896 } 897 898 func TestEncodeGoPtrNil(t *testing.T) { 899 var x *int 900 b := lib.TakeBuffer() 901 defer lib.ReleaseBuffer(b) 902 903 err := Encode(x, b, EncodeOptions{}) 904 905 if err != nil { 906 t.Fatal(err) 907 } 908 expected := []byte{ettNil} 909 if !reflect.DeepEqual(b.B, expected) { 910 fmt.Println("exp", expected) 911 fmt.Println("got", b.B) 912 t.Fatal("incorrect value") 913 } 914 } 915 916 func TestEncodeRegisteredType(t *testing.T) { 917 var tmp int 918 type regTypeStruct1 struct { 919 a int 920 } 921 type regTypeStruct3 struct { 922 C string 923 } 924 type regTypeStruct2 struct { 925 A int 926 B regTypeStruct3 927 } 928 type regTypeMap map[string]regTypeStruct3 929 type regTypeSlice []regTypeStruct3 930 type regTypeArray [5]regTypeStruct3 931 932 // only struct/map/slice/array types are supported 933 if _, err := RegisterType(tmp, RegisterTypeOptions{}); err == nil { 934 t.Fatal("must be error here") 935 } 936 937 // only struct with no unexported fields 938 if _, err := RegisterType(regTypeStruct1{}, RegisterTypeOptions{}); err == nil { 939 t.Fatal("must be error here") 940 } 941 942 // all nested struct must be registered first 943 if _, err := RegisterType(regTypeStruct2{}, RegisterTypeOptions{}); err == nil { 944 t.Fatal("must be error here") 945 } 946 947 if a, err := RegisterType(regTypeStruct3{}, RegisterTypeOptions{}); err != nil { 948 t.Fatal(err) 949 } else { 950 defer UnregisterType(a) 951 } 952 if a, err := RegisterType(regTypeStruct2{}, RegisterTypeOptions{}); err != nil { 953 t.Fatal(err) 954 } else { 955 defer UnregisterType(a) 956 } 957 958 if a, err := RegisterType(regTypeMap{}, RegisterTypeOptions{}); err != nil { 959 t.Fatal(err) 960 } else { 961 defer UnregisterType(a) 962 } 963 964 if a, err := RegisterType(regTypeSlice{}, RegisterTypeOptions{}); err != nil { 965 t.Fatal(err) 966 } else { 967 defer UnregisterType(a) 968 } 969 970 if a, err := RegisterType(regTypeArray{}, RegisterTypeOptions{}); err != nil { 971 t.Fatal(err) 972 } else { 973 defer UnregisterType(a) 974 } 975 976 b := lib.TakeBuffer() 977 defer lib.ReleaseBuffer(b) 978 979 x := regTypeStruct2{} 980 x.A = 123 981 x.B.C = "hello" 982 983 expected := []byte{ettSmallTuple, 3, ettSmallAtomUTF8, 49, 35, 103, 105, 116, 104, 117, 98, 46, 99, 111, 109, 47, 101, 114, 103, 111, 45, 115, 101, 114, 118, 105, 99, 101, 115, 47, 101, 114, 103, 111, 47, 101, 116, 102, 47, 114, 101, 103, 84, 121, 112, 101, 83, 116, 114, 117, 99, 116, 50, ettSmallInteger, 123, ettSmallTuple, 2, ettSmallAtomUTF8, 49, 35, 103, 105, 116, 104, 117, 98, 46, 99, 111, 109, 47, 101, 114, 103, 111, 45, 115, 101, 114, 118, 105, 99, 101, 115, 47, 101, 114, 103, 111, 47, 101, 116, 102, 47, 114, 101, 103, 84, 121, 112, 101, 83, 116, 114, 117, 99, 116, 51, ettString, 0, 5, 104, 101, 108, 108, 111} 984 err := Encode(x, b, EncodeOptions{}) 985 986 if err != nil { 987 t.Fatal(err) 988 } 989 990 if !reflect.DeepEqual(b.B, expected) { 991 fmt.Println("exp", expected) 992 fmt.Println("got", b.B) 993 t.Fatal("incorrect value") 994 } 995 } 996 997 type testMarshal struct{} 998 999 func (testMarshal) MarshalETF() ([]byte, error) { 1000 return []byte{1, 2, 3}, nil 1001 } 1002 1003 func TestEncodeMarshal(t *testing.T) { 1004 var x testMarshal 1005 1006 b := lib.TakeBuffer() 1007 defer lib.ReleaseBuffer(b) 1008 1009 err := Encode(x, b, EncodeOptions{}) 1010 if err != nil { 1011 t.Fatal(err) 1012 } 1013 expected := []byte{ettBinary, 0, 0, 0, 3, 1, 2, 3} 1014 if !reflect.DeepEqual(b.B, expected) { 1015 fmt.Println("exp", expected) 1016 fmt.Println("got", b.B) 1017 t.Fatal("incorrect value") 1018 } 1019 } 1020 1021 func BenchmarkEncodeBool(b *testing.B) { 1022 1023 buf := lib.TakeBuffer() 1024 defer lib.ReleaseBuffer(buf) 1025 1026 b.ResetTimer() 1027 for i := 0; i < b.N; i++ { 1028 err := Encode(false, buf, EncodeOptions{}) 1029 if err != nil { 1030 b.Fatal(err) 1031 } 1032 } 1033 } 1034 1035 func BenchmarkEncodeBoolWithAtomCache(b *testing.B) { 1036 1037 buf := lib.TakeBuffer() 1038 defer lib.ReleaseBuffer(buf) 1039 1040 senderAtomCache := make(map[Atom]CacheItem) 1041 encodingAtomCache := TakeEncodingAtomCache() 1042 atomCache := NewAtomCache() 1043 1044 senderAtomCache["false"] = CacheItem{ID: 499, Encoded: true, Name: "false"} 1045 1046 encodeOptions := EncodeOptions{ 1047 AtomCache: atomCache.Out, 1048 SenderAtomCache: senderAtomCache, 1049 EncodingAtomCache: encodingAtomCache, 1050 } 1051 b.ResetTimer() 1052 for i := 0; i < b.N; i++ { 1053 err := Encode(false, buf, encodeOptions) 1054 buf.Reset() 1055 if err != nil { 1056 b.Fatal(err) 1057 } 1058 } 1059 } 1060 1061 func BenchmarkEncodeInteger(b *testing.B) { 1062 for _, c := range integerCases() { 1063 b.Run(c.name, func(b *testing.B) { 1064 buf := lib.TakeBuffer() 1065 defer lib.ReleaseBuffer(buf) 1066 1067 for i := 0; i < b.N; i++ { 1068 err := Encode(c.integer, buf, EncodeOptions{}) 1069 if err != nil { 1070 b.Fatal(err) 1071 } 1072 } 1073 }) 1074 } 1075 } 1076 1077 func BenchmarkEncodeFloat32(b *testing.B) { 1078 buf := lib.TakeBuffer() 1079 defer lib.ReleaseBuffer(buf) 1080 1081 b.ResetTimer() 1082 for i := 0; i < b.N; i++ { 1083 err := Encode(float32(3.14), buf, EncodeOptions{}) 1084 if err != nil { 1085 b.Fatal(err) 1086 } 1087 } 1088 } 1089 1090 func BenchmarkEncodeFloat64(b *testing.B) { 1091 buf := lib.TakeBuffer() 1092 defer lib.ReleaseBuffer(buf) 1093 1094 b.ResetTimer() 1095 for i := 0; i < b.N; i++ { 1096 err := Encode(float64(3.14), buf, EncodeOptions{}) 1097 if err != nil { 1098 b.Fatal(err) 1099 } 1100 } 1101 } 1102 1103 func BenchmarkEncodeString(b *testing.B) { 1104 buf := lib.TakeBuffer() 1105 defer lib.ReleaseBuffer(buf) 1106 1107 b.ResetTimer() 1108 for i := 0; i < b.N; i++ { 1109 err := Encode("Ergo Framework", buf, EncodeOptions{}) 1110 if err != nil { 1111 b.Fatal(err) 1112 } 1113 } 1114 } 1115 1116 func BenchmarkEncodeAtom(b *testing.B) { 1117 buf := lib.TakeBuffer() 1118 defer lib.ReleaseBuffer(buf) 1119 1120 b.ResetTimer() 1121 for i := 0; i < b.N; i++ { 1122 err := Encode(Atom("Ergo Framework"), buf, EncodeOptions{}) 1123 if err != nil { 1124 b.Fatal(err) 1125 } 1126 } 1127 } 1128 1129 func BenchmarkEncodeAtomWithCache(b *testing.B) { 1130 buf := lib.TakeBuffer() 1131 defer lib.ReleaseBuffer(buf) 1132 1133 senderAtomCache := make(map[Atom]CacheItem) 1134 encodingAtomCache := TakeEncodingAtomCache() 1135 atomCache := NewAtomCache() 1136 1137 ci := CacheItem{ID: 2020, Encoded: true, Name: "cached atom"} 1138 senderAtomCache["cached atom"] = ci 1139 1140 encodeOptions := EncodeOptions{ 1141 AtomCache: atomCache.Out, 1142 SenderAtomCache: senderAtomCache, 1143 EncodingAtomCache: encodingAtomCache, 1144 } 1145 1146 b.ResetTimer() 1147 for i := 0; i < b.N; i++ { 1148 err := Encode(Atom("cached atom"), buf, encodeOptions) 1149 buf.Reset() 1150 if err != nil { 1151 b.Fatal(err) 1152 } 1153 } 1154 1155 } 1156 1157 func BenchmarkEncodeBinary(b *testing.B) { 1158 buf := lib.TakeBuffer() 1159 defer lib.ReleaseBuffer(buf) 1160 bytes := []byte{1, 2, 3, 4, 5} 1161 b.ResetTimer() 1162 for i := 0; i < b.N; i++ { 1163 err := Encode(bytes, buf, EncodeOptions{}) 1164 buf.Reset() 1165 if err != nil { 1166 b.Fatal(err) 1167 } 1168 } 1169 } 1170 1171 func BenchmarkEncodeList(b *testing.B) { 1172 buf := lib.TakeBuffer() 1173 defer lib.ReleaseBuffer(buf) 1174 1175 term := List{Atom("a"), 2, 3} 1176 b.ResetTimer() 1177 1178 for i := 0; i < b.N; i++ { 1179 err := Encode(term, buf, EncodeOptions{}) 1180 buf.Reset() 1181 if err != nil { 1182 b.Fatal(err) 1183 } 1184 } 1185 1186 } 1187 1188 func BenchmarkEncodeListNested(b *testing.B) { 1189 buf := lib.TakeBuffer() 1190 defer lib.ReleaseBuffer(buf) 1191 1192 term := List{Atom("a"), List{Atom("b"), 2, List{Atom("c"), 3}, 4}} 1193 b.ResetTimer() 1194 1195 for i := 0; i < b.N; i++ { 1196 err := Encode(term, buf, EncodeOptions{}) 1197 buf.Reset() 1198 if err != nil { 1199 b.Fatal(err) 1200 } 1201 } 1202 1203 } 1204 1205 func BenchmarkEncodeTuple(b *testing.B) { 1206 buf := lib.TakeBuffer() 1207 defer lib.ReleaseBuffer(buf) 1208 1209 term := Tuple{Atom("a"), 2, 3} 1210 b.ResetTimer() 1211 1212 for i := 0; i < b.N; i++ { 1213 err := Encode(term, buf, EncodeOptions{}) 1214 buf.Reset() 1215 if err != nil { 1216 b.Fatal(err) 1217 } 1218 } 1219 1220 } 1221 1222 func BenchmarkEncodeTupleNested(b *testing.B) { 1223 buf := lib.TakeBuffer() 1224 defer lib.ReleaseBuffer(buf) 1225 1226 term := Tuple{Atom("a"), Tuple{Atom("b"), 2, Tuple{Atom("c"), 3}, 4}} 1227 b.ResetTimer() 1228 1229 for i := 0; i < b.N; i++ { 1230 err := Encode(term, buf, EncodeOptions{}) 1231 buf.Reset() 1232 if err != nil { 1233 b.Fatal(err) 1234 } 1235 } 1236 1237 } 1238 1239 func BenchmarkEncodeSlice(b *testing.B) { 1240 buf := lib.TakeBuffer() 1241 defer lib.ReleaseBuffer(buf) 1242 1243 term := []int{12345, 67890, 12345, 67890} 1244 b.ResetTimer() 1245 1246 for i := 0; i < b.N; i++ { 1247 err := Encode(term, buf, EncodeOptions{}) 1248 buf.Reset() 1249 if err != nil { 1250 b.Fatal(err) 1251 } 1252 } 1253 } 1254 1255 func BenchmarkEncodeArray(b *testing.B) { 1256 buf := lib.TakeBuffer() 1257 defer lib.ReleaseBuffer(buf) 1258 1259 term := [4]int{12345, 67890, 12345, 67890} 1260 b.ResetTimer() 1261 1262 for i := 0; i < b.N; i++ { 1263 err := Encode(term, buf, EncodeOptions{}) 1264 buf.Reset() 1265 if err != nil { 1266 b.Fatal(err) 1267 } 1268 } 1269 } 1270 1271 func BenchmarkEncodeMap(b *testing.B) { 1272 buf := lib.TakeBuffer() 1273 defer lib.ReleaseBuffer(buf) 1274 1275 term := Map{ 1276 Atom("key1"): 12345, 1277 Atom("key2"): "hello world", 1278 } 1279 b.ResetTimer() 1280 1281 for i := 0; i < b.N; i++ { 1282 err := Encode(term, buf, EncodeOptions{}) 1283 buf.Reset() 1284 if err != nil { 1285 b.Fatal(err) 1286 } 1287 } 1288 } 1289 1290 func BenchmarkEncodeGoMap(b *testing.B) { 1291 buf := lib.TakeBuffer() 1292 defer lib.ReleaseBuffer(buf) 1293 1294 term := map[Atom]interface{}{ 1295 Atom("key1"): 12345, 1296 Atom("key2"): "hello world", 1297 } 1298 b.ResetTimer() 1299 1300 for i := 0; i < b.N; i++ { 1301 err := Encode(term, buf, EncodeOptions{}) 1302 buf.Reset() 1303 if err != nil { 1304 b.Fatal(err) 1305 } 1306 } 1307 } 1308 1309 func BenchmarkEncodeGoStruct(b *testing.B) { 1310 buf := lib.TakeBuffer() 1311 defer lib.ReleaseBuffer(buf) 1312 1313 term := struct { 1314 StructToMapKey1 int 1315 StructToMapKey2 string 1316 }{ 1317 StructToMapKey1: 12345, 1318 StructToMapKey2: "hello world", 1319 } 1320 b.ResetTimer() 1321 1322 for i := 0; i < b.N; i++ { 1323 err := Encode(term, buf, EncodeOptions{}) 1324 buf.Reset() 1325 if err != nil { 1326 b.Fatal(err) 1327 } 1328 } 1329 } 1330 1331 func BenchmarkEncodePid(b *testing.B) { 1332 buf := lib.TakeBuffer() 1333 defer lib.ReleaseBuffer(buf) 1334 1335 term := Pid{Node: "erl-demo@127.0.0.1", ID: 312, Creation: 2} 1336 1337 b.ResetTimer() 1338 for i := 0; i < b.N; i++ { 1339 err := Encode(term, buf, EncodeOptions{}) 1340 buf.Reset() 1341 if err != nil { 1342 b.Fatal(err) 1343 } 1344 } 1345 } 1346 1347 func BenchmarkEncodePidWithAtomCache(b *testing.B) { 1348 buf := lib.TakeBuffer() 1349 defer lib.ReleaseBuffer(buf) 1350 1351 term := Pid{Node: "erl-demo@127.0.0.1", ID: 312, Creation: 2} 1352 1353 senderAtomCache := make(map[Atom]CacheItem) 1354 encodingAtomCache := TakeEncodingAtomCache() 1355 atomCache := NewAtomCache() 1356 1357 ci := CacheItem{ID: 2020, Encoded: true, Name: "erl-demo@127.0.0.1"} 1358 senderAtomCache["erl-demo@127.0.0.1"] = ci 1359 1360 encodeOptions := EncodeOptions{ 1361 AtomCache: atomCache.Out, 1362 SenderAtomCache: senderAtomCache, 1363 EncodingAtomCache: encodingAtomCache, 1364 } 1365 1366 b.ResetTimer() 1367 for i := 0; i < b.N; i++ { 1368 err := Encode(term, buf, encodeOptions) 1369 buf.Reset() 1370 if err != nil { 1371 b.Fatal(err) 1372 } 1373 } 1374 } 1375 1376 func BenchmarkEncodeRef(b *testing.B) { 1377 buf := lib.TakeBuffer() 1378 defer lib.ReleaseBuffer(buf) 1379 1380 term := Ref{ 1381 Node: Atom("erl-demo@127.0.0.1"), 1382 Creation: 2, 1383 ID: [5]uint32{73444, 3082813441, 2373634851}, 1384 } 1385 1386 for i := 0; i < b.N; i++ { 1387 err := Encode(term, buf, EncodeOptions{}) 1388 buf.Reset() 1389 if err != nil { 1390 b.Fatal(err) 1391 } 1392 } 1393 } 1394 1395 func BenchmarkEncodeRefWithAtomCache(b *testing.B) { 1396 buf := lib.TakeBuffer() 1397 defer lib.ReleaseBuffer(buf) 1398 1399 term := Ref{ 1400 Node: Atom("erl-demo@127.0.0.1"), 1401 Creation: 2, 1402 ID: [5]uint32{73444, 3082813441, 2373634851}, 1403 } 1404 1405 senderAtomCache := make(map[Atom]CacheItem) 1406 encodingAtomCache := TakeEncodingAtomCache() 1407 atomCache := NewAtomCache() 1408 1409 ci := CacheItem{ID: 2020, Encoded: true, Name: "erl-demo@127.0.0.1"} 1410 senderAtomCache["erl-demo@127.0.0.1"] = ci 1411 1412 encodeOptions := EncodeOptions{ 1413 AtomCache: atomCache.Out, 1414 SenderAtomCache: senderAtomCache, 1415 EncodingAtomCache: encodingAtomCache, 1416 } 1417 1418 b.ResetTimer() 1419 for i := 0; i < b.N; i++ { 1420 err := Encode(term, buf, encodeOptions) 1421 buf.Reset() 1422 if err != nil { 1423 b.Fatal(err) 1424 } 1425 } 1426 } 1427 1428 func BenchmarkEncodeTupleRefPid(b *testing.B) { 1429 buf := lib.TakeBuffer() 1430 defer lib.ReleaseBuffer(buf) 1431 1432 term := Tuple{ 1433 Ref{ 1434 Node: Atom("erl-demo@127.0.0.1"), 1435 Creation: 2, 1436 ID: [5]uint32{0x11f1c, 0xb7c00001, 0x8d7acb23}}, 1437 Pid{ 1438 Node: Atom("erl-demo@127.0.0.1"), 1439 ID: 312, 1440 Creation: 2}} 1441 1442 b.ResetTimer() 1443 for i := 0; i < b.N; i++ { 1444 err := Encode(term, buf, EncodeOptions{}) 1445 buf.Reset() 1446 if err != nil { 1447 b.Fatal(err) 1448 } 1449 } 1450 } 1451 1452 func BenchmarkEncodeTupleRefPidWithAtomCache(b *testing.B) { 1453 buf := lib.TakeBuffer() 1454 defer lib.ReleaseBuffer(buf) 1455 1456 term := Tuple{ 1457 Ref{ 1458 Node: Atom("erl-demo@127.0.0.1"), 1459 Creation: 2, 1460 ID: [5]uint32{0x11f1c, 0xb7c00001, 0x8d7acb23}}, 1461 Pid{ 1462 Node: Atom("erl-demo@127.0.0.1"), 1463 ID: 312, 1464 Creation: 2}} 1465 1466 senderAtomCache := make(map[Atom]CacheItem) 1467 encodingAtomCache := TakeEncodingAtomCache() 1468 defer ReleaseEncodingAtomCache(encodingAtomCache) 1469 atomCache := NewAtomCache() 1470 1471 ci := CacheItem{ID: 2020, Encoded: true, Name: "erl-demo@127.0.0.1"} 1472 senderAtomCache["erl-demo@127.0.0.1"] = ci 1473 1474 encodeOptions := EncodeOptions{ 1475 AtomCache: atomCache.Out, 1476 SenderAtomCache: senderAtomCache, 1477 EncodingAtomCache: encodingAtomCache, 1478 } 1479 1480 b.ResetTimer() 1481 for i := 0; i < b.N; i++ { 1482 err := Encode(term, buf, encodeOptions) 1483 buf.Reset() 1484 encodingAtomCache.Reset() 1485 if err != nil { 1486 b.Fatal(err) 1487 } 1488 } 1489 }