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  }