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  }