github.com/ipld/go-ipld-prime@v0.21.0/node/tests/schemaLists.go (about)

     1  package tests
     2  
     3  import (
     4  	"testing"
     5  
     6  	qt "github.com/frankban/quicktest"
     7  
     8  	"github.com/ipld/go-ipld-prime/datamodel"
     9  	"github.com/ipld/go-ipld-prime/fluent"
    10  	"github.com/ipld/go-ipld-prime/must"
    11  	"github.com/ipld/go-ipld-prime/node/basicnode"
    12  	"github.com/ipld/go-ipld-prime/schema"
    13  )
    14  
    15  func SchemaTestListsContainingMaybe(t *testing.T, engine Engine) {
    16  	ts := schema.TypeSystem{}
    17  	ts.Init()
    18  	ts.Accumulate(schema.SpawnString("String"))
    19  	ts.Accumulate(schema.SpawnList("List__String",
    20  		"String", false))
    21  	ts.Accumulate(schema.SpawnList("List__nullableString",
    22  		"String", true))
    23  	engine.Init(t, ts)
    24  
    25  	t.Run("non-nullable", func(t *testing.T) {
    26  		np := engine.PrototypeByName("List__String")
    27  		nrp := engine.PrototypeByName("List__String.Repr")
    28  		var n schema.TypedNode
    29  		t.Run("typed-create", func(t *testing.T) {
    30  			n = fluent.MustBuildList(np, 2, func(la fluent.ListAssembler) {
    31  				la.AssembleValue().AssignString("1")
    32  				la.AssembleValue().AssignString("2")
    33  			}).(schema.TypedNode)
    34  			t.Run("typed-read", func(t *testing.T) {
    35  				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
    36  				qt.Check(t, n.Length(), qt.Equals, int64(2))
    37  
    38  				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
    39  				qt.Check(t, must.String(must.Node(n.LookupByIndex(1))), qt.Equals, "2")
    40  
    41  				qt.Check(t, must.String(must.Node(n.LookupBySegment(datamodel.PathSegmentOfInt(0)))), qt.Equals, "1")
    42  				qt.Check(t, must.String(must.Node(n.LookupByNode(basicnode.NewInt(0)))), qt.Equals, "1")
    43  
    44  				_, err := n.LookupByIndex(3)
    45  				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
    46  			})
    47  			t.Run("repr-read", func(t *testing.T) {
    48  				nr := n.Representation()
    49  				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
    50  				qt.Check(t, nr.Length(), qt.Equals, int64(2))
    51  
    52  				qt.Check(t, must.String(must.Node(nr.LookupByIndex(0))), qt.Equals, "1")
    53  				qt.Check(t, must.String(must.Node(nr.LookupByIndex(1))), qt.Equals, "2")
    54  
    55  				qt.Check(t, must.String(must.Node(n.LookupBySegment(datamodel.PathSegmentOfInt(0)))), qt.Equals, "1")
    56  				qt.Check(t, must.String(must.Node(n.LookupByNode(basicnode.NewInt(0)))), qt.Equals, "1")
    57  
    58  				_, err := n.LookupByIndex(3)
    59  				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
    60  			})
    61  		})
    62  		t.Run("repr-create", func(t *testing.T) {
    63  			nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
    64  				la.AssembleValue().AssignString("1")
    65  				la.AssembleValue().AssignString("2")
    66  			})
    67  			qt.Check(t, n, NodeContentEquals, nr)
    68  		})
    69  	})
    70  	t.Run("nullable", func(t *testing.T) {
    71  		np := engine.PrototypeByName("List__nullableString")
    72  		nrp := engine.PrototypeByName("List__nullableString.Repr")
    73  		var n schema.TypedNode
    74  		t.Run("typed-create", func(t *testing.T) {
    75  			n = fluent.MustBuildList(np, 2, func(la fluent.ListAssembler) {
    76  				la.AssembleValue().AssignString("1")
    77  				la.AssembleValue().AssignNull()
    78  			}).(schema.TypedNode)
    79  			t.Run("typed-read", func(t *testing.T) {
    80  				qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
    81  				qt.Check(t, n.Length(), qt.Equals, int64(2))
    82  				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
    83  				qt.Check(t, must.Node(n.LookupByIndex(1)), qt.Equals, datamodel.Null)
    84  				_, err := n.LookupByIndex(3)
    85  				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
    86  			})
    87  			t.Run("repr-read", func(t *testing.T) {
    88  				nr := n.Representation()
    89  				qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
    90  				qt.Check(t, nr.Length(), qt.Equals, int64(2))
    91  				qt.Check(t, must.String(must.Node(n.LookupByIndex(0))), qt.Equals, "1")
    92  				qt.Check(t, must.Node(n.LookupByIndex(1)), qt.Equals, datamodel.Null)
    93  				_, err := n.LookupByIndex(3)
    94  				qt.Check(t, err, qt.ErrorAs, &datamodel.ErrNotExists{})
    95  			})
    96  		})
    97  		t.Run("repr-create", func(t *testing.T) {
    98  			nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
    99  				la.AssembleValue().AssignString("1")
   100  				la.AssembleValue().AssignNull()
   101  			})
   102  			qt.Check(t, n, NodeContentEquals, nr)
   103  		})
   104  	})
   105  }
   106  
   107  // TestListsContainingLists is probing *two* things:
   108  //   - that lists can nest, obviously
   109  //   - that representation semantics are held correctly when we recurse, both in builders and in reading
   110  //
   111  // To cover that latter situation, this depends on structs (so we can use rename directives on the representation to make it distinctive).
   112  func SchemaTestListsContainingLists(t *testing.T, engine Engine) {
   113  	ts := schema.TypeSystem{}
   114  	ts.Init()
   115  	ts.Accumulate(schema.SpawnString("String"))
   116  	ts.Accumulate(schema.SpawnStruct("Frub",
   117  		[]schema.StructField{
   118  			schema.SpawnStructField("field", "String", false, false), // plain field.
   119  		},
   120  		schema.SpawnStructRepresentationMap(map[string]string{
   121  			"field": "encoded",
   122  		}),
   123  	))
   124  	ts.Accumulate(schema.SpawnList("List__Frub",
   125  		"Frub", false))
   126  	ts.Accumulate(schema.SpawnList("List__List__Frub",
   127  		"List__Frub", true))
   128  	engine.Init(t, ts)
   129  
   130  	np := engine.PrototypeByName("List__List__Frub")
   131  	nrp := engine.PrototypeByName("List__List__Frub.Repr")
   132  	var n schema.TypedNode
   133  	t.Run("typed-create", func(t *testing.T) {
   134  		n = fluent.MustBuildList(np, 3, func(la fluent.ListAssembler) {
   135  			la.AssembleValue().CreateList(3, func(la fluent.ListAssembler) {
   136  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("11") })
   137  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("12") })
   138  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("13") })
   139  			})
   140  			la.AssembleValue().CreateList(1, func(la fluent.ListAssembler) {
   141  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("21") })
   142  			})
   143  			la.AssembleValue().CreateList(2, func(la fluent.ListAssembler) {
   144  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("31") })
   145  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("32") })
   146  			})
   147  		}).(schema.TypedNode)
   148  		t.Run("typed-read", func(t *testing.T) {
   149  			qt.Assert(t, n.Kind(), qt.Equals, datamodel.Kind_List)
   150  			qt.Assert(t, n.Length(), qt.Equals, int64(3))
   151  			qt.Assert(t, must.Node(n.LookupByIndex(0)).Length(), qt.Equals, int64(3))
   152  			qt.Assert(t, must.Node(n.LookupByIndex(1)).Length(), qt.Equals, int64(1))
   153  			qt.Assert(t, must.Node(n.LookupByIndex(2)).Length(), qt.Equals, int64(2))
   154  
   155  			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(0)).LookupByString("field"))), qt.Equals, "11")
   156  			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(2)).LookupByString("field"))), qt.Equals, "13")
   157  			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(1)).LookupByIndex(0)).LookupByString("field"))), qt.Equals, "21")
   158  			qt.Check(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(2)).LookupByIndex(1)).LookupByString("field"))), qt.Equals, "32")
   159  		})
   160  		t.Run("repr-read", func(t *testing.T) {
   161  			nr := n.Representation()
   162  			qt.Assert(t, nr.Kind(), qt.Equals, datamodel.Kind_List)
   163  			qt.Assert(t, nr.Length(), qt.Equals, int64(3))
   164  			qt.Assert(t, must.Node(nr.LookupByIndex(0)).Length(), qt.Equals, int64(3))
   165  			qt.Assert(t, must.Node(nr.LookupByIndex(1)).Length(), qt.Equals, int64(1))
   166  			qt.Assert(t, must.Node(nr.LookupByIndex(2)).Length(), qt.Equals, int64(2))
   167  
   168  			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(0)).LookupByString("encoded"))), qt.Equals, "11")
   169  			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(2)).LookupByString("encoded"))), qt.Equals, "13")
   170  			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(1)).LookupByIndex(0)).LookupByString("encoded"))), qt.Equals, "21")
   171  			qt.Check(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(2)).LookupByIndex(1)).LookupByString("encoded"))), qt.Equals, "32")
   172  		})
   173  	})
   174  	t.Run("repr-create", func(t *testing.T) {
   175  		nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
   176  			// This is the same as the type-level create earlier, except note the field names are now all different.
   177  			la.AssembleValue().CreateList(3, func(la fluent.ListAssembler) {
   178  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("11") })
   179  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("12") })
   180  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("13") })
   181  			})
   182  			la.AssembleValue().CreateList(1, func(la fluent.ListAssembler) {
   183  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("21") })
   184  			})
   185  			la.AssembleValue().CreateList(2, func(la fluent.ListAssembler) {
   186  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("31") })
   187  				la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("32") })
   188  			})
   189  		})
   190  		qt.Check(t, n, NodeContentEquals, nr)
   191  	})
   192  }