schemaStruct.go 4.44 KB
Newer Older
1 2 3 4 5 6 7 8 9 10
package tests

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"
11
	basicnode "github.com/ipld/go-ipld-prime/node/basic"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
	"github.com/ipld/go-ipld-prime/schema"
)

func SchemaTestRequiredFields(t *testing.T, engine Engine) {
	ts := schema.TypeSystem{}
	ts.Init()
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnStruct("StructOne",
		[]schema.StructField{
			schema.SpawnStructField("a", "String", false, false),
			schema.SpawnStructField("b", "String", false, false),
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			// no renames.  we expect a simpler error message in this case.
		}),
	))
	ts.Accumulate(schema.SpawnStruct("StructTwo",
		[]schema.StructField{
			schema.SpawnStructField("a", "String", false, false),
			schema.SpawnStructField("b", "String", false, false),
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			"b": "z",
		}),
	))
	engine.Init(t, ts)

	t.Run("building-type-without-required-fields-errors", func(t *testing.T) {
		np := engine.PrototypeByName("StructOne")

		nb := np.NewBuilder()
		ma, _ := nb.BeginMap(0)
		err := ma.Finish()

		Wish(t, err, ShouldBeSameTypeAs, ipld.ErrMissingRequiredField{})
		Wish(t, err.Error(), ShouldEqual, `missing required fields: a,b`)
	})
	t.Run("building-representation-without-required-fields-errors", func(t *testing.T) {
		nrp := engine.PrototypeByName("StructOne.Repr")

		nb := nrp.NewBuilder()
		ma, _ := nb.BeginMap(0)
		err := ma.Finish()

		Wish(t, err, ShouldBeSameTypeAs, ipld.ErrMissingRequiredField{})
		Wish(t, err.Error(), ShouldEqual, `missing required fields: a,b`)
	})
	t.Run("building-representation-with-renames-without-required-fields-errors", func(t *testing.T) {
		nrp := engine.PrototypeByName("StructTwo.Repr")

		nb := nrp.NewBuilder()
		ma, _ := nb.BeginMap(0)
		err := ma.Finish()

		Wish(t, err, ShouldBeSameTypeAs, ipld.ErrMissingRequiredField{})
		Wish(t, err.Error(), ShouldEqual, `missing required fields: a,b (serial:"z")`)
	})
}

func SchemaTestStructNesting(t *testing.T, engine Engine) {
	ts := schema.TypeSystem{}
	ts.Init()
	ts.Accumulate(schema.SpawnString("String"))
	ts.Accumulate(schema.SpawnStruct("SmolStruct",
		[]schema.StructField{
			schema.SpawnStructField("s", "String", false, false),
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			"s": "q",
		}),
	))
	ts.Accumulate(schema.SpawnStruct("GulpoStruct",
		[]schema.StructField{
			schema.SpawnStructField("x", "SmolStruct", false, false),
		},
		schema.SpawnStructRepresentationMap(map[string]string{
			"x": "r",
		}),
	))
	engine.Init(t, ts)

	np := engine.PrototypeByName("GulpoStruct")
	nrp := engine.PrototypeByName("GulpoStruct.Repr")
	var n schema.TypedNode
	t.Run("typed-create", func(t *testing.T) {
		n = fluent.MustBuildMap(np, 1, func(ma fluent.MapAssembler) {
			ma.AssembleEntry("x").CreateMap(1, func(ma fluent.MapAssembler) {
				ma.AssembleEntry("s").AssignString("woo")
			})
		}).(schema.TypedNode)
		t.Run("typed-read", func(t *testing.T) {
			Require(t, n.Kind(), ShouldEqual, ipld.Kind_Map)
			Wish(t, n.Length(), ShouldEqual, int64(1))
105

106 107
			n2 := must.Node(n.LookupByString("x"))
			Require(t, n2.Kind(), ShouldEqual, ipld.Kind_Map)
108 109 110 111 112 113 114

			n2Seg := must.Node(n.LookupBySegment(ipld.PathSegmentOfString("x")))
			Wish(t, ipld.DeepEqual(n2, n2Seg), ShouldEqual, true)

			n2Node := must.Node(n.LookupByNode(basicnode.NewString("x")))
			Wish(t, ipld.DeepEqual(n2, n2Node), ShouldEqual, true)

115 116 117 118 119 120
			Wish(t, must.String(must.Node(n2.LookupByString("s"))), ShouldEqual, "woo")
		})
		t.Run("repr-read", func(t *testing.T) {
			nr := n.Representation()
			Require(t, nr.Kind(), ShouldEqual, ipld.Kind_Map)
			Wish(t, nr.Length(), ShouldEqual, int64(1))
121

122 123
			n2 := must.Node(nr.LookupByString("r"))
			Require(t, n2.Kind(), ShouldEqual, ipld.Kind_Map)
124 125 126 127 128 129 130

			n2Seg := must.Node(nr.LookupBySegment(ipld.PathSegmentOfString("r")))
			Wish(t, ipld.DeepEqual(n2, n2Seg), ShouldEqual, true)

			n2Node := must.Node(nr.LookupByNode(basicnode.NewString("r")))
			Wish(t, ipld.DeepEqual(n2, n2Node), ShouldEqual, true)

131 132 133 134 135 136 137 138 139 140 141 142
			Wish(t, must.String(must.Node(n2.LookupByString("q"))), ShouldEqual, "woo")
		})
	})
	t.Run("repr-create", func(t *testing.T) {
		nr := fluent.MustBuildMap(nrp, 1, func(ma fluent.MapAssembler) {
			ma.AssembleEntry("r").CreateMap(1, func(ma fluent.MapAssembler) {
				ma.AssembleEntry("q").AssignString("woo")
			})
		})
		Wish(t, ipld.DeepEqual(n, nr), ShouldEqual, true)
	})
}