testLists_test.go 9.48 KB
Newer Older
Eric Myhre's avatar
Eric Myhre committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
package gengo

import (
	"testing"

	. "github.com/warpfork/go-wish"

	"github.com/ipld/go-ipld-prime"
	"github.com/ipld/go-ipld-prime/fluent"
	"github.com/ipld/go-ipld-prime/must"
	"github.com/ipld/go-ipld-prime/schema"
)

func TestListsContainingMaybe(t *testing.T) {
15 16
	t.Parallel()

Eric Myhre's avatar
Eric Myhre committed
17 18 19 20 21 22 23
	ts := schema.TypeSystem{}
	ts.Init()
	adjCfg := &AdjunctCfg{
		maybeUsesPtr: map[schema.TypeName]bool{},
	}
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnList("List__String",
24
		"String", false))
Eric Myhre's avatar
Eric Myhre committed
25
	ts.Accumulate(schema.SpawnList("List__nullableString",
26
		"String", true))
Eric Myhre's avatar
Eric Myhre committed
27

28
	test := func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
Eric Myhre's avatar
Eric Myhre committed
29
		t.Run("non-nullable", func(t *testing.T) {
30 31
			np := getPrototypeByName("List__String")
			nrp := getPrototypeByName("List__String.Repr")
Eric Myhre's avatar
Eric Myhre committed
32 33
			var n schema.TypedNode
			t.Run("typed-create", func(t *testing.T) {
34
				n = fluent.MustBuildList(np, 2, func(la fluent.ListAssembler) {
Eric Myhre's avatar
Eric Myhre committed
35 36 37 38
					la.AssembleValue().AssignString("1")
					la.AssembleValue().AssignString("2")
				}).(schema.TypedNode)
				t.Run("typed-read", func(t *testing.T) {
39
					Require(t, n.Kind(), ShouldEqual, ipld.Kind_List)
40
					Wish(t, n.Length(), ShouldEqual, int64(2))
41 42 43
					Wish(t, must.String(must.Node(n.LookupByIndex(0))), ShouldEqual, "1")
					Wish(t, must.String(must.Node(n.LookupByIndex(1))), ShouldEqual, "2")
					_, err := n.LookupByIndex(3)
Eric Myhre's avatar
Eric Myhre committed
44 45 46 47
					Wish(t, err, ShouldBeSameTypeAs, ipld.ErrNotExists{})
				})
				t.Run("repr-read", func(t *testing.T) {
					nr := n.Representation()
48
					Require(t, nr.Kind(), ShouldEqual, ipld.Kind_List)
49
					Wish(t, nr.Length(), ShouldEqual, int64(2))
50 51 52
					Wish(t, must.String(must.Node(nr.LookupByIndex(0))), ShouldEqual, "1")
					Wish(t, must.String(must.Node(nr.LookupByIndex(1))), ShouldEqual, "2")
					_, err := n.LookupByIndex(3)
Eric Myhre's avatar
Eric Myhre committed
53 54 55 56
					Wish(t, err, ShouldBeSameTypeAs, ipld.ErrNotExists{})
				})
			})
			t.Run("repr-create", func(t *testing.T) {
57
				nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
Eric Myhre's avatar
Eric Myhre committed
58 59 60
					la.AssembleValue().AssignString("1")
					la.AssembleValue().AssignString("2")
				})
61
				Wish(t, ipld.DeepEqual(n, nr), ShouldEqual, true)
Eric Myhre's avatar
Eric Myhre committed
62 63 64
			})
		})
		t.Run("nullable", func(t *testing.T) {
65 66
			np := getPrototypeByName("List__nullableString")
			nrp := getPrototypeByName("List__nullableString.Repr")
Eric Myhre's avatar
Eric Myhre committed
67 68
			var n schema.TypedNode
			t.Run("typed-create", func(t *testing.T) {
69
				n = fluent.MustBuildList(np, 2, func(la fluent.ListAssembler) {
Eric Myhre's avatar
Eric Myhre committed
70 71 72 73
					la.AssembleValue().AssignString("1")
					la.AssembleValue().AssignNull()
				}).(schema.TypedNode)
				t.Run("typed-read", func(t *testing.T) {
74
					Require(t, n.Kind(), ShouldEqual, ipld.Kind_List)
75
					Wish(t, n.Length(), ShouldEqual, int64(2))
76 77 78
					Wish(t, must.String(must.Node(n.LookupByIndex(0))), ShouldEqual, "1")
					Wish(t, must.Node(n.LookupByIndex(1)), ShouldEqual, ipld.Null)
					_, err := n.LookupByIndex(3)
Eric Myhre's avatar
Eric Myhre committed
79 80 81 82
					Wish(t, err, ShouldBeSameTypeAs, ipld.ErrNotExists{})
				})
				t.Run("repr-read", func(t *testing.T) {
					nr := n.Representation()
83
					Require(t, nr.Kind(), ShouldEqual, ipld.Kind_List)
84
					Wish(t, nr.Length(), ShouldEqual, int64(2))
85 86 87
					Wish(t, must.String(must.Node(n.LookupByIndex(0))), ShouldEqual, "1")
					Wish(t, must.Node(n.LookupByIndex(1)), ShouldEqual, ipld.Null)
					_, err := n.LookupByIndex(3)
Eric Myhre's avatar
Eric Myhre committed
88 89 90 91
					Wish(t, err, ShouldBeSameTypeAs, ipld.ErrNotExists{})
				})
			})
			t.Run("repr-create", func(t *testing.T) {
92
				nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
Eric Myhre's avatar
Eric Myhre committed
93 94 95
					la.AssembleValue().AssignString("1")
					la.AssembleValue().AssignNull()
				})
96
				Wish(t, ipld.DeepEqual(n, nr), ShouldEqual, true)
Eric Myhre's avatar
Eric Myhre committed
97 98 99 100 101 102 103 104 105
			})
		})
	}

	t.Run("maybe-using-embed", func(t *testing.T) {
		adjCfg.maybeUsesPtr["String"] = false

		prefix := "lists-embed"
		pkgName := "main"
106 107
		genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
			test(t, getPrototypeByName)
Eric Myhre's avatar
Eric Myhre committed
108 109 110 111 112 113 114
		})
	})
	t.Run("maybe-using-ptr", func(t *testing.T) {
		adjCfg.maybeUsesPtr["String"] = true

		prefix := "lists-mptr"
		pkgName := "main"
115 116
		genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
			test(t, getPrototypeByName)
Eric Myhre's avatar
Eric Myhre committed
117 118 119
		})
	})
}
120 121 122 123 124 125

// TestListsContainingLists is probing *two* things:
//   - that lists can nest, obviously
//   - that representation semantics are held correctly when we recurse, both in builders and in reading
// To cover that latter situation, this depends on structs (so we can use rename directives on the representation to make it distinctive).
func TestListsContainingLists(t *testing.T) {
126 127
	t.Parallel()

128 129 130 131 132 133 134 135
	ts := schema.TypeSystem{}
	ts.Init()
	adjCfg := &AdjunctCfg{
		maybeUsesPtr: map[schema.TypeName]bool{},
	}
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnStruct("Frub",
		[]schema.StructField{
136
			schema.SpawnStructField("field", "String", false, false), // plain field.
137 138 139 140 141 142
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			"field": "encoded",
		}),
	))
	ts.Accumulate(schema.SpawnList("List__Frub",
143
		"Frub", false))
144
	ts.Accumulate(schema.SpawnList("List__List__Frub",
145
		"List__Frub", true))
146 147 148

	prefix := "lists-of-lists"
	pkgName := "main"
149 150 151
	genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
		np := getPrototypeByName("List__List__Frub")
		nrp := getPrototypeByName("List__List__Frub.Repr")
152 153
		var n schema.TypedNode
		t.Run("typed-create", func(t *testing.T) {
154
			n = fluent.MustBuildList(np, 3, func(la fluent.ListAssembler) {
155 156 157 158 159 160 161 162 163 164 165 166 167 168
				la.AssembleValue().CreateList(3, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("11") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("12") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("13") })
				})
				la.AssembleValue().CreateList(1, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("21") })
				})
				la.AssembleValue().CreateList(2, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("31") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("field").AssignString("32") })
				})
			}).(schema.TypedNode)
			t.Run("typed-read", func(t *testing.T) {
169
				Require(t, n.Kind(), ShouldEqual, ipld.Kind_List)
170 171 172 173
				Require(t, n.Length(), ShouldEqual, int64(3))
				Require(t, must.Node(n.LookupByIndex(0)).Length(), ShouldEqual, int64(3))
				Require(t, must.Node(n.LookupByIndex(1)).Length(), ShouldEqual, int64(1))
				Require(t, must.Node(n.LookupByIndex(2)).Length(), ShouldEqual, int64(2))
174

175 176 177 178
				Wish(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(0)).LookupByString("field"))), ShouldEqual, "11")
				Wish(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(0)).LookupByIndex(2)).LookupByString("field"))), ShouldEqual, "13")
				Wish(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(1)).LookupByIndex(0)).LookupByString("field"))), ShouldEqual, "21")
				Wish(t, must.String(must.Node(must.Node(must.Node(n.LookupByIndex(2)).LookupByIndex(1)).LookupByString("field"))), ShouldEqual, "32")
179 180 181
			})
			t.Run("repr-read", func(t *testing.T) {
				nr := n.Representation()
182
				Require(t, nr.Kind(), ShouldEqual, ipld.Kind_List)
183 184 185 186
				Require(t, nr.Length(), ShouldEqual, int64(3))
				Require(t, must.Node(nr.LookupByIndex(0)).Length(), ShouldEqual, int64(3))
				Require(t, must.Node(nr.LookupByIndex(1)).Length(), ShouldEqual, int64(1))
				Require(t, must.Node(nr.LookupByIndex(2)).Length(), ShouldEqual, int64(2))
187

188 189 190 191
				Wish(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(0)).LookupByString("encoded"))), ShouldEqual, "11")
				Wish(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(0)).LookupByIndex(2)).LookupByString("encoded"))), ShouldEqual, "13")
				Wish(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(1)).LookupByIndex(0)).LookupByString("encoded"))), ShouldEqual, "21")
				Wish(t, must.String(must.Node(must.Node(must.Node(nr.LookupByIndex(2)).LookupByIndex(1)).LookupByString("encoded"))), ShouldEqual, "32")
192 193 194
			})
		})
		t.Run("repr-create", func(t *testing.T) {
195
			nr := fluent.MustBuildList(nrp, 2, func(la fluent.ListAssembler) {
196 197 198 199 200 201 202 203 204 205 206 207 208 209
				// This is the same as the type-level create earlier, except note the field names are now all different.
				la.AssembleValue().CreateList(3, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("11") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("12") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("13") })
				})
				la.AssembleValue().CreateList(1, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("21") })
				})
				la.AssembleValue().CreateList(2, func(la fluent.ListAssembler) {
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("31") })
					la.AssembleValue().CreateMap(1, func(ma fluent.MapAssembler) { ma.AssembleEntry("encoded").AssignString("32") })
				})
			})
210
			Wish(t, ipld.DeepEqual(n, nr), ShouldEqual, true)
211 212 213 214
		})
	})

}