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 }