github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/cache/binary_read_test.go (about) 1 package cache 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "io" 7 "math/big" 8 "reflect" 9 "strconv" 10 "testing" 11 ) 12 13 type testUnmarshaler struct { 14 value int32 15 } 16 17 func (t *testUnmarshaler) UnmarshalCache(version uint64, reader io.Reader) error { 18 return binary.Read(reader, binary.LittleEndian, &t.value) 19 } 20 21 type likeString string 22 23 func (l *likeString) UnmarshalCache(version uint64, reader io.Reader) error { 24 var v int32 25 if err := binary.Read(reader, binary.LittleEndian, &v); err != nil { 26 return err 27 } 28 s := strconv.Itoa(int(v)) 29 *l = likeString(s) 30 return nil 31 } 32 33 func TestReadValue(t *testing.T) { 34 var data []byte 35 buf := bytes.NewBuffer(data) 36 37 expectedUint64 := uint64(123) 38 if err := binary.Write(buf, binary.LittleEndian, expectedUint64); err != nil { 39 t.Fatal(err) 40 } 41 var uint64Value uint64 42 if err := ReadValue(buf, &uint64Value, 0); err != nil { 43 t.Fatal(err) 44 } 45 if uint64Value != expectedUint64 { 46 t.Fatal("uint64 wrong value:", uint64Value) 47 } 48 49 buf.Reset() 50 expectedStr := "hello" 51 binaryStrLen := uint64(len(expectedStr)) 52 binaryStr := []byte(expectedStr) 53 if err := binary.Write(buf, binary.LittleEndian, binaryStrLen); err != nil { 54 t.Fatal(err) 55 } 56 if err := binary.Write(buf, binary.LittleEndian, binaryStr); err != nil { 57 t.Fatal(err) 58 } 59 var stringValue string 60 if err := ReadValue(buf, &stringValue, 0); err != nil { 61 t.Fatal(err) 62 } 63 if stringValue != expectedStr { 64 t.Fatal("string wrong value:", stringValue) 65 } 66 67 buf.Reset() 68 expectedStrSlice := []string{"hello", "world"} 69 if err := binary.Write(buf, binary.LittleEndian, uint64(2)); err != nil { 70 t.Fatal(err) 71 } 72 for _, str := range expectedStrSlice { 73 if err := binary.Write(buf, binary.LittleEndian, uint64(len(str))); err != nil { 74 t.Fatal(err) 75 } 76 if err := binary.Write(buf, binary.LittleEndian, []byte(str)); err != nil { 77 t.Fatal(err) 78 } 79 } 80 var stringSliceValue []string 81 if err := ReadValue(buf, &stringSliceValue, 0); err != nil { 82 t.Fatal(err) 83 } 84 if !reflect.DeepEqual(stringSliceValue, expectedStrSlice) { 85 t.Fatal("string slice wrong value", stringSliceValue) 86 } 87 88 buf.Reset() 89 expectedUnmarshalValue := int32(42) 90 if err := binary.Write(buf, binary.LittleEndian, expectedUnmarshalValue); err != nil { 91 t.Fatal(err) 92 } 93 unmarshalValue := new(testUnmarshaler) 94 if err := ReadValue(buf, unmarshalValue, 0); err != nil { 95 t.Fatal(err) 96 } 97 if unmarshalValue.value != expectedUnmarshalValue { 98 t.Fatal("unmarshal wrong value", unmarshalValue.value) 99 } 100 101 expectedIntSliceValue := []int32{42, 10} 102 if err := binary.Write(buf, binary.LittleEndian, uint64(len(expectedIntSliceValue))); err != nil { 103 t.Fatal(err) 104 } 105 for _, item := range expectedIntSliceValue { 106 if err := binary.Write(buf, binary.LittleEndian, item); err != nil { 107 t.Fatal(err) 108 } 109 } 110 intSliceValue := make([]int32, 0) 111 if err := ReadValue(buf, &intSliceValue, 0); err != nil { 112 t.Fatal(err) 113 } 114 if !reflect.DeepEqual(intSliceValue, expectedIntSliceValue) { 115 t.Fatal("unmarshal wrong int slice value", intSliceValue) 116 } 117 118 // This test checks the use of CacheUnmarshaler being implement by a custom string type. 119 // We will write int32 to the buffer. If the support for CacheUnmarshaler doesn't work, we would get an 120 // error (we cannot read int32 into a string). But if it does work, UnmarshalCache will be called, intercept 121 // the value and parse it into a string and set the string as the value for `likeStringValue`. 122 buf.Reset() 123 expectedLikeStringValue := "42" 124 if err := binary.Write(buf, binary.LittleEndian, int32(42)); err != nil { 125 t.Fatal(err) 126 } 127 var likeStringValue likeString 128 if err := ReadValue(buf, &likeStringValue, 0); err != nil { 129 t.Fatal(err) 130 } 131 if likeStringValue != likeString(expectedLikeStringValue) { 132 t.Fatal("unmarshal wrong value", unmarshalValue.value) 133 } 134 135 buf.Reset() 136 expectedUnmarshalSlice := []testUnmarshaler{ 137 {value: 42}, 138 {value: 10}, 139 } 140 if err := binary.Write(buf, binary.LittleEndian, uint64(len(expectedUnmarshalSlice))); err != nil { 141 t.Fatal(err) 142 } 143 for _, item := range expectedUnmarshalSlice { 144 if err := binary.Write(buf, binary.LittleEndian, item.value); err != nil { 145 t.Fatal(err) 146 } 147 } 148 unmarshalSliceValue := make([]testUnmarshaler, 0) 149 if err := ReadValue(buf, &unmarshalSliceValue, 0); err != nil { 150 t.Fatal(err) 151 } 152 // e := []testUnmarshaler{ 153 // {value: 42}, 154 // {value: 10}, 155 // } 156 if !reflect.DeepEqual(expectedUnmarshalSlice, unmarshalSliceValue) { 157 t.Fatal("unmarshal wrong value", unmarshalSliceValue) 158 } 159 } 160 161 func TestReadBigInt(t *testing.T) { 162 buf := new(bytes.Buffer) 163 bigint := big.NewInt(0) 164 _, ok := bigint.SetString("57006123709077586392", 10) 165 if !ok { 166 t.Fatal("cannot set test value") 167 } 168 169 data, err := bigint.GobEncode() 170 if err != nil { 171 t.Fatal(err) 172 } 173 size := uint64(len(data)) 174 if err := write(buf, size); err != nil { 175 t.Fatal(err) 176 } 177 if err := write(buf, data); err != nil { 178 t.Fatal(err) 179 } 180 181 result := big.NewInt(0) 182 if err := readBigInt(buf, result); err != nil { 183 t.Fatal(err) 184 } 185 186 // we expect size to be len(bigint.Bytes()) + 1, because GobEncode adds 1 byte 187 // for storing the sign 188 if byteLen := len(result.Bytes()) + 1; int(size) != byteLen { 189 t.Fatal("size is", size, "expected", byteLen) 190 } 191 192 if result.Cmp(bigint) != 0 { 193 t.Fatal("values are not same") 194 } 195 }