Unverified Commit beba587d authored by Eric Myhre's avatar Eric Myhre Committed by GitHub

Merge pull request #75 from ipld/union-tests-and-fixes

Update tests for unions; several fixes
parents cacb1e9f 44513d62
......@@ -198,13 +198,13 @@ func (g unionGenerator) EmitNodeMethodMapIterator(w io.Writer) {
switch itr.n.tag {
{{- range $i, $member := .Type.Members }}
case {{ add $i 1 }}:
return &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}, &itr.n.x{{ add $i 1 }}, nil
k, v = &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}, &itr.n.x{{ add $i 1 }}
{{- end}}
{{- else if (eq (.AdjCfg.UnionMemlayout .Type) "interface") }}
switch n2 := itr.n.x.(type) {
{{- range $member := .Type.Members }}
case {{ $member | TypeSymbol }}:
return &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}, n2, nil
k, v = &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}, n2
{{- end}}
{{- end}}
default:
......@@ -324,6 +324,7 @@ func (g unionBuilderGenerator) EmitNodeAssemblerType(w io.Writer) {
default:
panic("unreachable")
}
na.ca = 0
na.cm = schema.Maybe_Absent
}
`, w, g.AdjCfg, g)
......
......@@ -136,13 +136,13 @@ func (g unionReprKeyedReprGenerator) EmitNodeMethodMapIterator(w io.Writer) {
switch itr.n.tag {
{{- range $i, $member := .Type.Members }}
case {{ add $i 1 }}:
return &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}_serial, itr.n.x{{ add $i 1 }}.Representation(), nil
k, v = &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}_serial, itr.n.x{{ add $i 1 }}.Representation()
{{- end}}
{{- else if (eq (.AdjCfg.UnionMemlayout .Type) "interface") }}
switch n2 := itr.n.x.(type) {
{{- range $member := .Type.Members }}
case {{ $member | TypeSymbol }}:
return &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}_serial, n2.Representation(), nil
k, v = &memberName__{{ dot.Type | TypeSymbol }}_{{ $member.Name }}_serial, n2.Representation()
{{- end}}
{{- end}}
default:
......@@ -235,6 +235,7 @@ func (g unionReprKeyedReprBuilderGenerator) EmitNodeAssemblerType(w io.Writer) {
default:
panic("unreachable")
}
na.ca = 0
na.cm = schema.Maybe_Absent
}
`, w, g.AdjCfg, g)
......
......@@ -396,6 +396,7 @@ func (g unionReprKindedReprBuilderGenerator) EmitNodeAssemblerType(w io.Writer)
default:
panic("unreachable")
}
na.ca = 0
}
`, w, g.AdjCfg, g)
}
......
......@@ -3,11 +3,7 @@ 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"
)
......@@ -35,36 +31,46 @@ func TestUnionKinded(t *testing.T) {
}),
))
// These are the same *type-level* as in TestUnionKeyedComplexChildren,
// but (of course) have very different representations.
specs := []testcase{
{
name: "InhabitantA",
typeJson: `{"String":"whee"}`,
reprJson: `"whee"`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"String", "whee"},
//{"SmolStruct", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_String},
{"", "whee"},
},
},
{
name: "InhabitantB",
typeJson: `{"SmolStruct":{"s":"whee"}}`,
reprJson: `{"q":"whee"}`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
//{"String", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
{"SmolStruct", ipld.ReprKind_Map},
{"SmolStruct/s", "whee"},
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"q", "whee"},
},
},
}
test := func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
np := getPrototypeByName("WheeUnion")
nrp := getPrototypeByName("WheeUnion.Repr")
var n schema.TypedNode
t.Run("typed-create", func(t *testing.T) {
n = fluent.MustBuildMap(np, 1, func(na fluent.MapAssembler) {
na.AssembleEntry("SmolStruct").CreateMap(1, func(na fluent.MapAssembler) {
na.AssembleEntry("s").AssignString("whee")
})
}).(schema.TypedNode)
t.Run("typed-read", func(t *testing.T) {
Require(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, n.Length(), ShouldEqual, 1)
n2 := must.Node(n.LookupByString("SmolStruct"))
Require(t, n2.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, must.String(must.Node(n2.LookupByString("s"))), ShouldEqual, "whee")
})
t.Run("repr-read", func(t *testing.T) {
nr := n.Representation()
Require(t, nr.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, nr.Length(), ShouldEqual, 1)
Wish(t, must.String(must.Node(nr.LookupByString("q"))), ShouldEqual, "whee")
})
})
t.Run("repr-create", func(t *testing.T) {
nr := fluent.MustBuildMap(nrp, 1, func(na fluent.MapAssembler) {
na.AssembleEntry("q").AssignString("whee")
})
Wish(t, n, ShouldEqual, nr)
})
for _, tcase := range specs {
tcase.Test(t, np, nrp)
}
}
t.Run("union-using-embed", func(t *testing.T) {
......
......@@ -3,11 +3,7 @@ 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"
)
......@@ -28,32 +24,45 @@ func TestUnionKeyed(t *testing.T) {
}),
))
specs := []testcase{
{
name: "InhabitantA",
typeJson: `{"String":"whee"}`,
reprJson: `{"a":"whee"}`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"String", "whee"},
//{"Strung", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"a", "whee"},
//{"b", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
},
},
{
name: "InhabitantB",
typeJson: `{"Strung":"whee"}`,
reprJson: `{"b":"whee"}`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
//{"String", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
{"Strung", "whee"},
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_Map},
//{"a", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
{"b", "whee"},
},
},
}
test := func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
np := getPrototypeByName("StrStr")
nrp := getPrototypeByName("StrStr.Repr")
var n schema.TypedNode
t.Run("typed-create", func(t *testing.T) {
n = fluent.MustBuildMap(np, 1, func(na fluent.MapAssembler) {
na.AssembleEntry("Strung").AssignString("whee")
}).(schema.TypedNode)
t.Run("typed-read", func(t *testing.T) {
Require(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, n.Length(), ShouldEqual, 1)
Wish(t, must.String(must.Node(n.LookupByString("Strung"))), ShouldEqual, "whee")
})
t.Run("repr-read", func(t *testing.T) {
nr := n.Representation()
Require(t, nr.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, nr.Length(), ShouldEqual, 1)
Wish(t, must.String(must.Node(nr.LookupByString("b"))), ShouldEqual, "whee")
})
})
t.Run("repr-create", func(t *testing.T) {
nr := fluent.MustBuildMap(nrp, 2, func(na fluent.MapAssembler) {
na.AssembleEntry("b").AssignString("whee")
})
Wish(t, n, ShouldEqual, nr)
})
for _, tcase := range specs {
tcase.Test(t, np, nrp)
}
}
t.Run("union-using-embed", func(t *testing.T) {
......@@ -107,40 +116,47 @@ func TestUnionKeyedComplexChildren(t *testing.T) {
}),
))
specs := []testcase{
{
name: "InhabitantA",
typeJson: `{"String":"whee"}`,
reprJson: `{"a":"whee"}`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"String", "whee"},
//{"SmolStruct", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_Map},
{"a", "whee"},
//{"b", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
},
},
{
name: "InhabitantB",
typeJson: `{"SmolStruct":{"s":"whee"}}`,
reprJson: `{"b":{"q":"whee"}}`,
typePoints: []testcasePoint{
{"", ipld.ReprKind_Map},
//{"String", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
{"SmolStruct", ipld.ReprKind_Map},
{"SmolStruct/s", "whee"},
},
reprPoints: []testcasePoint{
{"", ipld.ReprKind_Map},
//{"a", ipld.ErrNotExists{}}, // TODO: need better error typing from traversal package.
{"b", ipld.ReprKind_Map},
{"b/q", "whee"},
},
},
}
test := func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
np := getPrototypeByName("WheeUnion")
nrp := getPrototypeByName("WheeUnion.Repr")
var n schema.TypedNode
t.Run("typed-create", func(t *testing.T) {
n = fluent.MustBuildMap(np, 1, func(na fluent.MapAssembler) {
na.AssembleEntry("SmolStruct").CreateMap(1, func(na fluent.MapAssembler) {
na.AssembleEntry("s").AssignString("whee")
})
}).(schema.TypedNode)
t.Run("typed-read", func(t *testing.T) {
Require(t, n.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, n.Length(), ShouldEqual, 1)
n2 := must.Node(n.LookupByString("SmolStruct"))
Require(t, n2.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, must.String(must.Node(n2.LookupByString("s"))), ShouldEqual, "whee")
})
t.Run("repr-read", func(t *testing.T) {
nr := n.Representation()
Require(t, nr.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, nr.Length(), ShouldEqual, 1)
n2 := must.Node(nr.LookupByString("b"))
Require(t, n2.ReprKind(), ShouldEqual, ipld.ReprKind_Map)
Wish(t, must.String(must.Node(n2.LookupByString("q"))), ShouldEqual, "whee")
})
})
t.Run("repr-create", func(t *testing.T) {
nr := fluent.MustBuildMap(nrp, 2, func(na fluent.MapAssembler) {
na.AssembleEntry("b").CreateMap(1, func(na fluent.MapAssembler) {
na.AssembleEntry("q").AssignString("whee")
})
})
Wish(t, n, ShouldEqual, nr)
})
for _, tcase := range specs {
tcase.Test(t, np, nrp)
}
}
t.Run("union-using-embed", func(t *testing.T) {
......@@ -162,3 +178,77 @@ func TestUnionKeyedComplexChildren(t *testing.T) {
})
})
}
// TestUnionKeyedReset puts a union inside a list, so that we can use the list's reuse of assembler as a test of the assembler's reset feature.
// The value inside the union is also more complex than a scalar value so that we test resetting gets passed down, too.
func TestUnionKeyedReset(t *testing.T) {
ts := schema.TypeSystem{}
ts.Init()
adjCfg := &AdjunctCfg{}
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.SpawnUnion("WheeUnion",
[]schema.TypeName{
"String",
"SmolStruct",
},
schema.SpawnUnionRepresentationKeyed(map[string]schema.TypeName{
"a": "String",
"b": "SmolStruct",
}),
))
ts.Accumulate(schema.SpawnList("OuterList",
"WheeUnion", false,
))
specs := []testcase{
{
typeJson: `[{"SmolStruct":{"s":"one"}}, {"SmolStruct":{"s":"two"}}, {"String":"three"}]`,
reprJson: `[{"b":{"q":"one"}}, {"b":{"q":"two"}}, {"a":"three"}]`,
typePoints: []testcasePoint{
{"0/SmolStruct/s", "one"},
{"1/SmolStruct/s", "two"},
{"2/String", "three"},
},
reprPoints: []testcasePoint{
{"0/b/q", "one"},
{"1/b/q", "two"},
{"2/a", "three"},
},
},
}
test := func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
np := getPrototypeByName("OuterList")
nrp := getPrototypeByName("OuterList.Repr")
for _, tcase := range specs {
tcase.Test(t, np, nrp)
}
}
t.Run("union-using-embed", func(t *testing.T) {
adjCfg.CfgUnionMemlayout = map[schema.TypeName]string{"WheeUnion": "embedAll"}
prefix := "union-keyed-reset-using-embed"
pkgName := "main"
genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
test(t, getPrototypeByName)
})
})
t.Run("union-using-interface", func(t *testing.T) {
adjCfg.CfgUnionMemlayout = map[schema.TypeName]string{"WheeUnion": "interface"}
prefix := "union-keyed-reset-using-interface"
pkgName := "main"
genAndCompileAndTest(t, prefix, pkgName, ts, adjCfg, func(t *testing.T, getPrototypeByName func(string) ipld.NodePrototype) {
test(t, getPrototypeByName)
})
})
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment