github.com/ipld/go-ipld-prime@v0.21.0/node/bindnode/api_test.go (about) 1 package bindnode_test 2 3 import ( 4 "encoding/hex" 5 "math" 6 "testing" 7 8 qt "github.com/frankban/quicktest" 9 "github.com/ipld/go-ipld-prime" 10 "github.com/ipld/go-ipld-prime/codec/dagcbor" 11 "github.com/ipld/go-ipld-prime/datamodel" 12 "github.com/ipld/go-ipld-prime/node/basicnode" 13 "github.com/ipld/go-ipld-prime/node/bindnode" 14 ) 15 16 func TestEnumError(t *testing.T) { 17 type Action string 18 const ( 19 ActionPresent = Action("p") 20 ActionMissing = Action("m") 21 ) 22 type S struct{ Action Action } 23 24 schema := ` 25 type S struct { 26 Action Action 27 } representation tuple 28 type Action enum { 29 | Present ("p") 30 | Missing ("m") 31 } representation string 32 ` 33 34 typeSystem, err := ipld.LoadSchemaBytes([]byte(schema)) 35 qt.Assert(t, err, qt.IsNil) 36 schemaType := typeSystem.TypeByName("S") 37 38 node := bindnode.Wrap(&S{Action: ActionPresent}, schemaType).Representation() 39 _, err = ipld.Encode(node, dagcbor.Encode) 40 qt.Assert(t, err, qt.IsNotNil) 41 qt.Assert(t, err.Error(), qt.Equals, `AsString: "p" is not a valid member of enum Action (bindnode works at the type level; did you mean "Present"?)`) 42 } 43 44 func TestSubNodeWalkAndUnwrap(t *testing.T) { 45 type F struct { 46 F bool 47 } 48 type B struct { 49 B int 50 } 51 type A struct { 52 A string 53 } 54 type S struct { 55 F F 56 B B 57 A *A 58 Any datamodel.Node 59 Bytes []byte 60 String string 61 } 62 63 schema := ` 64 type F struct { 65 F Bool 66 } representation tuple 67 type B struct { 68 B Int 69 } representation tuple 70 type A struct { 71 A String 72 } representation tuple 73 type S struct { 74 F F 75 B B 76 A optional A 77 Any Any 78 Bytes Bytes 79 String String 80 } representation tuple 81 ` 82 83 encodedHex := "8681f581186581624141fb4069466666666666430102036f636f6e7374616e7420737472696e67" // [[true],[101],["AA"],202.2,[]byte{1,2,3},"constant string"] 84 byts := []byte{0, 1, 2, 3} 85 const constStr = "constant string" 86 87 expected := S{ 88 F: F{true}, 89 B: B{101}, 90 A: &A{"AAA"[1:]}, 91 Any: basicnode.NewFloat(202.2), 92 Bytes: byts[1:], 93 String: constStr, 94 } 95 96 typeSystem, err := ipld.LoadSchemaBytes([]byte(schema)) 97 qt.Assert(t, err, qt.IsNil) 98 schemaType := typeSystem.TypeByName("S") 99 100 verifyMap := func(node datamodel.Node) { 101 mi := node.MapIterator() 102 103 key, value, err := mi.Next() 104 qt.Assert(t, err, qt.IsNil) 105 106 str, err := key.AsString() 107 qt.Assert(t, err, qt.IsNil) 108 qt.Assert(t, str, qt.Equals, "F") 109 110 typ := bindnode.Unwrap(value) 111 instF, ok := typ.(*F) 112 qt.Assert(t, ok, qt.IsTrue) 113 qt.Assert(t, *instF, qt.Equals, F{true}) 114 115 key, value, err = mi.Next() 116 qt.Assert(t, err, qt.IsNil) 117 118 str, err = key.AsString() 119 qt.Assert(t, err, qt.IsNil) 120 qt.Assert(t, str, qt.Equals, "B") 121 122 typ = bindnode.Unwrap(value) 123 instB, ok := typ.(*B) 124 qt.Assert(t, ok, qt.IsTrue) 125 qt.Assert(t, *instB, qt.Equals, B{101}) 126 127 key, value, err = mi.Next() 128 qt.Assert(t, err, qt.IsNil) 129 130 str, err = key.AsString() 131 qt.Assert(t, err, qt.IsNil) 132 qt.Assert(t, str, qt.Equals, "A") 133 134 typ = bindnode.Unwrap(value) 135 instA, ok := typ.(*A) 136 qt.Assert(t, ok, qt.IsTrue) 137 qt.Assert(t, *instA, qt.Equals, A{"AA"}) 138 139 key, value, err = mi.Next() 140 qt.Assert(t, err, qt.IsNil) 141 142 str, err = key.AsString() 143 qt.Assert(t, err, qt.IsNil) 144 qt.Assert(t, str, qt.Equals, "Any") 145 146 qt.Assert(t, ipld.DeepEqual(basicnode.NewFloat(202.2), value), qt.IsTrue) 147 148 key, value, err = mi.Next() 149 qt.Assert(t, err, qt.IsNil) 150 151 str, err = key.AsString() 152 qt.Assert(t, err, qt.IsNil) 153 qt.Assert(t, str, qt.Equals, "Bytes") 154 155 typ = bindnode.Unwrap(value) 156 instByts, ok := typ.(*[]byte) 157 qt.Assert(t, ok, qt.IsTrue) 158 qt.Assert(t, *instByts, qt.DeepEquals, []byte{1, 2, 3}) 159 160 key, value, err = mi.Next() 161 qt.Assert(t, err, qt.IsNil) 162 163 str, err = key.AsString() 164 qt.Assert(t, err, qt.IsNil) 165 qt.Assert(t, str, qt.Equals, "String") 166 167 typ = bindnode.Unwrap(value) 168 instStr, ok := typ.(*string) 169 qt.Assert(t, ok, qt.IsTrue) 170 qt.Assert(t, *instStr, qt.DeepEquals, "constant string") 171 } 172 173 t.Run("decode", func(t *testing.T) { 174 encoded, _ := hex.DecodeString(encodedHex) 175 176 proto := bindnode.Prototype(&S{}, schemaType) 177 178 node, err := ipld.DecodeUsingPrototype([]byte(encoded), dagcbor.Decode, proto) 179 qt.Assert(t, err, qt.IsNil) 180 181 typ := bindnode.Unwrap(node) 182 instS, ok := typ.(*S) 183 qt.Assert(t, ok, qt.IsTrue) 184 185 qt.Assert(t, *instS, qt.DeepEquals, expected) 186 187 verifyMap(node) 188 }) 189 190 t.Run("encode", func(t *testing.T) { 191 node := bindnode.Wrap(&expected, schemaType) 192 193 byts, err := ipld.Encode(node, dagcbor.Encode) 194 qt.Assert(t, err, qt.IsNil) 195 196 qt.Assert(t, hex.EncodeToString(byts), qt.Equals, encodedHex) 197 198 verifyMap(node) 199 }) 200 } 201 202 func TestUint64Struct(t *testing.T) { 203 t.Run("in struct", func(t *testing.T) { 204 type IntHolder struct { 205 Int32 int32 206 Int64 int64 207 Uint64 uint64 208 } 209 schema := ` 210 type IntHolder struct { 211 Int32 Int 212 Int64 Int 213 Uint64 Int 214 } 215 ` 216 217 maxExpectedHex := "a365496e7433321a7fffffff65496e7436341b7fffffffffffffff6655696e7436341bffffffffffffffff" 218 maxExpected, err := hex.DecodeString(maxExpectedHex) 219 qt.Assert(t, err, qt.IsNil) 220 221 typeSystem, err := ipld.LoadSchemaBytes([]byte(schema)) 222 qt.Assert(t, err, qt.IsNil) 223 schemaType := typeSystem.TypeByName("IntHolder") 224 proto := bindnode.Prototype(&IntHolder{}, schemaType) 225 226 node, err := ipld.DecodeUsingPrototype([]byte(maxExpected), dagcbor.Decode, proto) 227 qt.Assert(t, err, qt.IsNil) 228 229 typ := bindnode.Unwrap(node) 230 inst, ok := typ.(*IntHolder) 231 qt.Assert(t, ok, qt.IsTrue) 232 233 qt.Assert(t, *inst, qt.DeepEquals, IntHolder{ 234 Int32: math.MaxInt32, 235 Int64: math.MaxInt64, 236 Uint64: math.MaxUint64, 237 }) 238 239 node = bindnode.Wrap(inst, schemaType).Representation() 240 byt, err := ipld.Encode(node, dagcbor.Encode) 241 qt.Assert(t, err, qt.IsNil) 242 243 qt.Assert(t, hex.EncodeToString(byt), qt.Equals, maxExpectedHex) 244 }) 245 246 t.Run("plain", func(t *testing.T) { 247 type IntHolder uint64 248 schema := `type IntHolder int` 249 250 maxExpectedHex := "1bffffffffffffffff" 251 maxExpected, err := hex.DecodeString(maxExpectedHex) 252 qt.Assert(t, err, qt.IsNil) 253 254 typeSystem, err := ipld.LoadSchemaBytes([]byte(schema)) 255 qt.Assert(t, err, qt.IsNil) 256 schemaType := typeSystem.TypeByName("IntHolder") 257 proto := bindnode.Prototype((*IntHolder)(nil), schemaType) 258 259 node, err := ipld.DecodeUsingPrototype([]byte(maxExpected), dagcbor.Decode, proto) 260 qt.Assert(t, err, qt.IsNil) 261 262 typ := bindnode.Unwrap(node) 263 inst, ok := typ.(*IntHolder) 264 qt.Assert(t, ok, qt.IsTrue) 265 266 qt.Assert(t, *inst, qt.Equals, IntHolder(math.MaxUint64)) 267 268 node = bindnode.Wrap(inst, schemaType).Representation() 269 byt, err := ipld.Encode(node, dagcbor.Encode) 270 qt.Assert(t, err, qt.IsNil) 271 272 qt.Assert(t, hex.EncodeToString(byt), qt.Equals, maxExpectedHex) 273 }) 274 }