github.com/cloudwego/frugal@v0.1.15/internal/binary/decoder/decoder_test.go (about) 1 /* 2 * Copyright 2022 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 decoder 18 19 import ( 20 `testing` 21 `unsafe` 22 23 `github.com/cloudwego/frugal/internal/rt` 24 `github.com/davecgh/go-spew/spew` 25 `github.com/stretchr/testify/require` 26 ) 27 28 func TestDecoder_Decode(t *testing.T) { 29 var v TranslatorTestStruct 30 rs := new(RuntimeState) 31 buf := []byte { 32 0x02, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x12, 0x04, 0x00, 0x02, 0x40, 0x28, 0xae, 0x14, 0x7a, 33 0xe1, 0x47, 0xae, 0x06, 0x00, 0x03, 0x34, 0x56, 0x08, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, 0x0a, 34 0x00, 0x05, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0x0b, 0x00, 0x06, 0x00, 0x00, 0x00, 35 0x0c, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0b, 0x00, 0x07, 36 0x00, 0x00, 0x00, 0x0e, 0x74, 0x65, 0x73, 0x74, 0x62, 0x79, 0x74, 0x65, 0x62, 0x75, 0x66, 0x66, 37 0x65, 0x72, 0x0f, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x05, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 38 0x77, 0x88, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x00, 39 0x09, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x61, 0x73, 0x64, 0x66, 0x00, 40 0x00, 0x00, 0x04, 0x71, 0x77, 0x65, 0x72, 0x00, 0x00, 0x00, 0x04, 0x7a, 0x78, 0x63, 0x76, 0x00, 41 0x00, 0x00, 0x04, 0x68, 0x6a, 0x6b, 0x6c, 0x0d, 0x00, 0x41, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x01, 42 0x00, 0x00, 0x00, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0xff, 0x04, 43 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x08, 44 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 45 0x00, 0x0b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 46 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x09, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 47 0x0d, 0x00, 0x41, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 48 } 49 sl := (*rt.GoSlice)(unsafe.Pointer(&buf)) 50 pos, err := decode(rt.UnpackEface(v).Type, sl.Ptr, sl.Len, 0, unsafe.Pointer(&v), rs, 0) 51 require.NoError(t, err) 52 require.Equal(t, len(buf), pos) 53 require.Equal(t, TranslatorTestStruct { 54 A: true, 55 B: 0x12, 56 C: 12.34, 57 D: 0x3456, 58 E: 0x12345678, 59 F: 0x66778899aabbccdd, 60 G: "hello, world", 61 H: []byte("testbytebuffer"), 62 I: []int32{0x11223344, 0x55667788, 3, 4, 5}, 63 J: map[string]string{"asdf": "qwer", "zxcv": "hjkl"}, 64 K: map[string]*TranslatorTestStruct{ 65 "foo": { 66 B: -1, 67 H: []uint8{}, 68 I: []int32{}, 69 J: map[string]string{}, 70 K: map[string]*TranslatorTestStruct{}, 71 }, 72 }, 73 }, v) 74 spew.Dump(v) 75 } 76 77 type TestSimple struct { 78 A bool `frugal:"0,default,bool"` 79 } 80 81 func TestDecoder_Simple(t *testing.T) { 82 var v TestSimple 83 rs := new(RuntimeState) 84 buf := []byte { 85 0x02, 0x00, 0x00, 0x01, 0x03, 0x00, 0x01, 0x12, 0x04, 0x00, 0x02, 0x40, 0x28, 0xae, 0x14, 0x7a, 86 0xe1, 0x47, 0xae, 0x06, 0x00, 0x03, 0x34, 0x56, 0x08, 0x00, 0x04, 0x12, 0x34, 0x56, 0x78, 0x0a, 87 0x00, 0x05, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0x0b, 0x00, 0x06, 0x00, 0x00, 0x00, 88 0x0c, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x2c, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x0b, 0x00, 0x07, 89 0x00, 0x00, 0x00, 0x0e, 0x74, 0x65, 0x73, 0x74, 0x62, 0x79, 0x74, 0x65, 0x62, 0x75, 0x66, 0x66, 90 0x65, 0x72, 0x0f, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x05, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 91 0x77, 0x88, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x0d, 0x00, 92 0x09, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x61, 0x73, 0x64, 0x66, 0x00, 93 0x00, 0x00, 0x04, 0x71, 0x77, 0x65, 0x72, 0x00, 0x00, 0x00, 0x04, 0x7a, 0x78, 0x63, 0x76, 0x00, 94 0x00, 0x00, 0x04, 0x68, 0x6a, 0x6b, 0x6c, 0x0d, 0x00, 0x41, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x01, 95 0x00, 0x00, 0x00, 0x03, 0x66, 0x6f, 0x6f, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x01, 0xff, 0x04, 96 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x03, 0x00, 0x00, 0x08, 97 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 98 0x00, 0x0b, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x0f, 99 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x09, 0x0b, 0x0b, 0x00, 0x00, 0x00, 0x00, 100 0x0d, 0x00, 0x41, 0x0b, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 101 } 102 sl := (*rt.GoSlice)(unsafe.Pointer(&buf)) 103 pos, err := decode(rt.UnpackEface(v).Type, sl.Ptr, sl.Len, 0, unsafe.Pointer(&v), rs, 0) 104 require.NoError(t, err) 105 require.Equal(t, len(buf), pos) 106 } 107 108 type TestWithDefaultValue struct { 109 A int64 `frugal:"0,default,i64"` 110 B int64 `frugal:"1,default,i64"` 111 C int64 `frugal:"2,default,i64"` 112 } 113 114 func (self *TestWithDefaultValue) InitDefault() { 115 *self = TestWithDefaultValue { B: 100 } 116 } 117 118 func TestDecoder_WithDefaultValue(t *testing.T) { 119 var v TestWithDefaultValue 120 rs := new(RuntimeState) 121 buf := []byte { 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00 } 122 sl := (*rt.GoSlice)(unsafe.Pointer(&buf)) 123 pos, err := decode(rt.UnpackEface(v).Type, sl.Ptr, sl.Len, 0, unsafe.Pointer(&v), rs, 0) 124 require.NoError(t, err) 125 require.Equal(t, len(buf), pos) 126 spew.Dump(v) 127 } 128 129 type TestNoCopyString struct { 130 A string `frugal:"1,default,string"` 131 B string `frugal:"2,default,string,nocopy"` 132 C *string `frugal:"3,optional,string,nocopy"` 133 D []byte `frugal:"4,default,binary"` 134 E []byte `frugal:"5,default,binary,nocopy"` 135 F *[]byte `frugal:"6,optional,binary,nocopy"` 136 } 137 138 func TestDecoder_NoCopyString(t *testing.T) { 139 var v TestNoCopyString 140 rs := new(RuntimeState) 141 buf := []byte { 142 0x0b, 0, 1, 0, 0, 0, 5, 't', 'e', 's', 't', '1', 143 0x0b, 0, 2, 0, 0, 0, 5, 't', 'e', 's', 't', '2', 144 0x0b, 0, 3, 0, 0, 0, 5, 't', 'e', 's', 't', '3', 145 0x0b, 0, 4, 0, 0, 0, 5, 't', 'e', 's', 't', '4', 146 0x0b, 0, 5, 0, 0, 0, 5, 't', 'e', 's', 't', '5', 147 0x0b, 0, 6, 0, 0, 0, 5, 't', 'e', 's', 't', '6', 148 0x00, 149 } 150 sl := (*rt.GoSlice)(unsafe.Pointer(&buf)) 151 pos, err := decode(rt.UnpackEface(v).Type, sl.Ptr, sl.Len, 0, unsafe.Pointer(&v), rs, 0) 152 require.NoError(t, err) 153 require.Equal(t, len(buf), pos) 154 require.Equal(t, TestNoCopyString { 155 A: "test1", 156 B: "test2", 157 C: &(&struct{v string}{"test3"}).v, 158 D: []byte("test4"), 159 E: []byte("test5"), 160 F: &(&struct{v []byte}{[]byte("test6")}).v, 161 }, v) 162 println("buf: source =", &buf[0]) 163 println("v.A: normal =", *(*unsafe.Pointer)(unsafe.Pointer(&v.A))) 164 println("v.B: nocopy =", *(*unsafe.Pointer)(unsafe.Pointer(&v.B))) 165 println("v.C: nocopy =", *(*unsafe.Pointer)(unsafe.Pointer(v.C))) 166 println("v.D: normal =", &v.D[0]) 167 println("v.E: nocopy =", &v.E[0]) 168 println("v.F: nocopy =", &(*v.F)[0]) 169 spew.Dump(v) 170 }