From 948087744d595af76809cca7d78edca2e1a05089 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 7 Nov 2024 11:12:40 +0100 Subject: [PATCH 1/2] literal: fix flacky test also: make tests less noisy everywhere --- pkg/policy/literal/literal.go | 21 ++++++++++++++++----- pkg/policy/selector/parsing_test.go | 10 ---------- pkg/policy/selector/selector_test.go | 14 -------------- pkg/policy/selector/supported_test.go | 22 +--------------------- token/delegation/delegation_test.go | 4 ---- token/delegation/schema_test.go | 7 ------- 6 files changed, 17 insertions(+), 61 deletions(-) diff --git a/pkg/policy/literal/literal.go b/pkg/policy/literal/literal.go index 26e5625..65ef32c 100644 --- a/pkg/policy/literal/literal.go +++ b/pkg/policy/literal/literal.go @@ -4,6 +4,7 @@ package literal import ( "fmt" "reflect" + "sort" "github.com/ipfs/go-cid" "github.com/ipld/go-ipld-prime" @@ -33,8 +34,14 @@ func Null() ipld.Node { // Map creates an IPLD node from a map[string]any func Map[T any](m map[string]T) (ipld.Node, error) { return qp.BuildMap(basicnode.Prototype.Any, int64(len(m)), func(ma datamodel.MapAssembler) { - for k, v := range m { - qp.MapEntry(ma, k, anyAssemble(v)) + // deterministic iteration + keys := make([]string, 0, len(m)) + for key := range m { + keys = append(keys, key) + } + sort.Strings(keys) + for _, key := range keys { + qp.MapEntry(ma, key, anyAssemble(m[key])) } }) } @@ -90,10 +97,14 @@ func anyAssemble(val any) qp.Assemble { if rt.Key().Kind() != reflect.String { break } - it := rv.MapRange() + // deterministic iteration + keys := rv.MapKeys() + sort.Slice(keys, func(i, j int) bool { + return keys[i].String() < keys[j].String() + }) return qp.Map(int64(rv.Len()), func(ma datamodel.MapAssembler) { - for it.Next() { - qp.MapEntry(ma, it.Key().String(), anyAssemble(it.Value())) + for _, key := range keys { + qp.MapEntry(ma, key.String(), anyAssemble(rv.MapIndex(key))) } }) case reflect.Bool: diff --git a/pkg/policy/selector/parsing_test.go b/pkg/policy/selector/parsing_test.go index 3edcfd6..3d60d9c 100644 --- a/pkg/policy/selector/parsing_test.go +++ b/pkg/policy/selector/parsing_test.go @@ -1,7 +1,6 @@ package selector import ( - "fmt" "math" "testing" @@ -354,7 +353,6 @@ func TestParse(t *testing.T) { str := `.foo.["bar"].[138]?.baz[1:]` sel, err := Parse(str) require.NoError(t, err) - printSegments(sel) require.Equal(t, str, sel.String()) require.Equal(t, 7, len(sel)) require.False(t, sel[0].Identity()) @@ -404,13 +402,11 @@ func TestParse(t *testing.T) { t.Run("non dotted", func(t *testing.T) { _, err := Parse("foo") require.NotNil(t, err) - fmt.Println(err) }) t.Run("non quoted", func(t *testing.T) { _, err := Parse(".[foo]") require.NotNil(t, err) - fmt.Println(err) }) t.Run("slice with negative start and positive end", func(t *testing.T) { @@ -554,9 +550,3 @@ func TestParse(t *testing.T) { require.Error(t, err) }) } - -func printSegments(s Selector) { - for i, seg := range s { - fmt.Printf("%d: %s\n", i, seg.String()) - } -} diff --git a/pkg/policy/selector/selector_test.go b/pkg/policy/selector/selector_test.go index 5da0231..184b7b3 100644 --- a/pkg/policy/selector/selector_test.go +++ b/pkg/policy/selector/selector_test.go @@ -2,7 +2,6 @@ package selector import ( "errors" - "fmt" "strings" "testing" @@ -13,7 +12,6 @@ import ( "github.com/ipld/go-ipld-prime/must" basicnode "github.com/ipld/go-ipld-prime/node/basic" "github.com/ipld/go-ipld-prime/node/bindnode" - "github.com/ipld/go-ipld-prime/printer" "github.com/stretchr/testify/require" ) @@ -87,8 +85,6 @@ func TestSelect(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, res) - fmt.Println(printer.Sprint(res)) - age := must.Int(must.Node(res.LookupByString("age"))) require.Equal(t, int64(alice.Age), age) }) @@ -101,8 +97,6 @@ func TestSelect(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, res) - fmt.Println(printer.Sprint(res)) - name := must.String(res) require.Equal(t, alice.Name.First, name) @@ -110,8 +104,6 @@ func TestSelect(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, res) - fmt.Println(printer.Sprint(res)) - name = must.String(res) require.Equal(t, bob.Name.First, name) }) @@ -124,8 +116,6 @@ func TestSelect(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, res) - fmt.Println(printer.Sprint(res)) - name := must.String(res) require.Equal(t, *alice.Name.Middle, name) @@ -142,8 +132,6 @@ func TestSelect(t *testing.T) { require.Error(t, err) require.Empty(t, res) - fmt.Println(err) - require.ErrorAs(t, err, &resolutionerr{}, "error should be a resolution error") }) @@ -164,8 +152,6 @@ func TestSelect(t *testing.T) { require.NoError(t, err) require.NotEmpty(t, res) - fmt.Println(printer.Sprint(res)) - iname := must.String(must.Node(must.Node(res.LookupByIndex(0)).LookupByString("name"))) require.Equal(t, alice.Interests[0].Name, iname) diff --git a/pkg/policy/selector/supported_test.go b/pkg/policy/selector/supported_test.go index db22216..44ec241 100644 --- a/pkg/policy/selector/supported_test.go +++ b/pkg/policy/selector/supported_test.go @@ -1,15 +1,12 @@ package selector_test import ( - "bytes" "strings" "testing" "github.com/ipld/go-ipld-prime" "github.com/ipld/go-ipld-prime/codec/dagjson" - "github.com/ipld/go-ipld-prime/datamodel" basicnode "github.com/ipld/go-ipld-prime/node/basic" - "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/ucan-wg/go-ucan/pkg/policy/selector" @@ -55,7 +52,7 @@ func TestSupportedForms(t *testing.T) { require.NotNil(t, res) exp := makeNode(t, tc.Output) - equalIPLD(t, exp, res) + require.True(t, ipld.DeepEqual(exp, res)) }) } @@ -106,23 +103,6 @@ func TestSupportedForms(t *testing.T) { } } -func equalIPLD(t *testing.T, expected datamodel.Node, actual datamodel.Node) bool { - t.Helper() - - exp, act := &bytes.Buffer{}, &bytes.Buffer{} - if err := dagjson.Encode(expected, exp); err != nil { - return assert.Fail(t, "Failed to encode json for expected IPLD node") - } - - if err := dagjson.Encode(actual, act); err != nil { - return assert.Fail(t, "Failed to encode JSON for actual IPLD node") - } - - require.JSONEq(t, exp.String(), act.String()) - - return true -} - func makeNode(t *testing.T, dagJsonInput string) ipld.Node { t.Helper() diff --git a/token/delegation/delegation_test.go b/token/delegation/delegation_test.go index 3c662fc..42008b4 100644 --- a/token/delegation/delegation_test.go +++ b/token/delegation/delegation_test.go @@ -100,8 +100,6 @@ func TestConstructors(t *testing.T) { data, err := tkn.ToDagJson(privKey) require.NoError(t, err) - t.Log(string(data)) - golden.Assert(t, string(data), "new.dagjson") }) @@ -119,8 +117,6 @@ func TestConstructors(t *testing.T) { data, err := tkn.ToDagJson(privKey) require.NoError(t, err) - t.Log(string(data)) - golden.Assert(t, string(data), "root.dagjson") }) } diff --git a/token/delegation/schema_test.go b/token/delegation/schema_test.go index 8866cc7..d9a7e8c 100644 --- a/token/delegation/schema_test.go +++ b/token/delegation/schema_test.go @@ -3,7 +3,6 @@ package delegation_test import ( "bytes" _ "embed" - "fmt" "testing" "github.com/ipld/go-ipld-prime" @@ -36,18 +35,13 @@ func TestSchemaRoundTrip(t *testing.T) { cborBytes, id, err := p1.ToSealed(privKey) require.NoError(t, err) assert.Equal(t, newCID, envelope.CIDToBase58BTC(id)) - fmt.Println("cborBytes length", len(cborBytes)) - fmt.Println("cbor", string(cborBytes)) p2, c2, err := delegation.FromSealed(cborBytes) require.NoError(t, err) assert.Equal(t, id, c2) - fmt.Println("read Cbor", p2) readJson, err := p2.ToDagJson(privKey) require.NoError(t, err) - fmt.Println("readJson length", len(readJson)) - fmt.Println("json: ", string(readJson)) assert.JSONEq(t, string(delegationJson), string(readJson)) }) @@ -65,7 +59,6 @@ func TestSchemaRoundTrip(t *testing.T) { cborBytes := &bytes.Buffer{} id, err := p1.ToSealedWriter(cborBytes, privKey) - t.Log(len(id.Bytes()), id.Bytes()) require.NoError(t, err) assert.Equal(t, newCID, envelope.CIDToBase58BTC(id)) From f9065d39d8d174c09f87773aed54574ea63d6cac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20Mur=C3=A9?= Date: Thu, 7 Nov 2024 15:33:21 +0100 Subject: [PATCH 2/2] policy: make Match also return the failing statement It's a powerful capability, so let's expose it. I also found a bug in the process. --- pkg/policy/match.go | 13 +- pkg/policy/match_test.go | 306 ++++++++++++++++++++------------------- 2 files changed, 166 insertions(+), 153 deletions(-) diff --git a/pkg/policy/match.go b/pkg/policy/match.go index c3862d5..59316ed 100644 --- a/pkg/policy/match.go +++ b/pkg/policy/match.go @@ -10,17 +10,18 @@ import ( ) // Match determines if the IPLD node satisfies the policy. -func (p Policy) Match(node datamodel.Node) bool { +// The first Statement failing to match is returned as well. +func (p Policy) Match(node datamodel.Node) (bool, Statement) { for _, stmt := range p { - res, _ := matchStatement(stmt, node) + res, leaf := matchStatement(stmt, node) switch res { case matchResultNoData, matchResultFalse: - return false + return false, leaf case matchResultOptionalNoData, matchResultTrue: // continue } } - return true + return true, nil } // PartialMatch returns false IIF one non-optional Statement has the corresponding data and doesn't match. @@ -131,9 +132,9 @@ func matchStatement(cur Statement, node ipld.Node) (_ matchResult, leafMost Stat case matchResultNoData, matchResultOptionalNoData: return res, leaf case matchResultTrue: - return matchResultFalse, leaf + return matchResultFalse, cur case matchResultFalse: - return matchResultTrue, leaf + return matchResultTrue, nil } } case KindAnd: diff --git a/pkg/policy/match_test.go b/pkg/policy/match_test.go index 7d10d43..108037a 100644 --- a/pkg/policy/match_test.go +++ b/pkg/policy/match_test.go @@ -17,228 +17,252 @@ import ( func TestMatch(t *testing.T) { t.Run("equality", func(t *testing.T) { t.Run("string", func(t *testing.T) { - np := basicnode.Prototype.String - nb := np.NewBuilder() - nb.AssignString("test") - nd := nb.Build() + nd := literal.String("test") pol := MustConstruct(Equal(".", literal.String("test"))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".", literal.String("test2"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Equal(".", literal.Int(138))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("int", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct(Equal(".", literal.Int(138))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".", literal.Int(1138))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Equal(".", literal.String("138"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("float", func(t *testing.T) { - np := basicnode.Prototype.Float - nb := np.NewBuilder() - nb.AssignFloat(1.138) - nd := nb.Build() + nd := literal.Float(1.138) pol := MustConstruct(Equal(".", literal.Float(1.138))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".", literal.Float(11.38))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Equal(".", literal.String("138"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("IPLD Link", func(t *testing.T) { l0 := cidlink.Link{Cid: cid.MustParse("bafybeif4owy5gno5lwnixqm52rwqfodklf76hsetxdhffuxnplvijskzqq")} l1 := cidlink.Link{Cid: cid.MustParse("bafkreifau35r7vi37tvbvfy3hdwvgb4tlflqf7zcdzeujqcjk3rsphiwte")} - np := basicnode.Prototype.Link - nb := np.NewBuilder() - nb.AssignLink(l0) - nd := nb.Build() + nd := literal.Link(l0) pol := MustConstruct(Equal(".", literal.Link(l0))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".", literal.Link(l1))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Equal(".", literal.String("bafybeif4owy5gno5lwnixqm52rwqfodklf76hsetxdhffuxnplvijskzqq"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("string in map", func(t *testing.T) { - np := basicnode.Prototype.Map - nb := np.NewBuilder() - ma, _ := nb.BeginMap(1) - ma.AssembleKey().AssignString("foo") - ma.AssembleValue().AssignString("bar") - ma.Finish() - nd := nb.Build() + nd, _ := literal.Map(map[string]any{ + "foo": "bar", + }) pol := MustConstruct(Equal(".foo", literal.String("bar"))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".[\"foo\"]", literal.String("bar"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".foo", literal.String("baz"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Equal(".foobar", literal.String("bar"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("string in list", func(t *testing.T) { - np := basicnode.Prototype.List - nb := np.NewBuilder() - la, _ := nb.BeginList(1) - la.AssembleValue().AssignString("foo") - la.Finish() - nd := nb.Build() + nd, _ := literal.List([]any{"foo"}) pol := MustConstruct(Equal(".[0]", literal.String("foo"))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Equal(".[1]", literal.String("foo"))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) }) t.Run("inequality", func(t *testing.T) { t.Run("gt int", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct(GreaterThan(".", literal.Int(1))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(GreaterThan(".", literal.Int(138))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) + + pol = MustConstruct(GreaterThan(".", literal.Int(140))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("gte int", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct(GreaterThanOrEqual(".", literal.Int(1))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(GreaterThanOrEqual(".", literal.Int(138))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(GreaterThanOrEqual(".", literal.Int(140))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("gt float", func(t *testing.T) { - np := basicnode.Prototype.Float - nb := np.NewBuilder() - nb.AssignFloat(1.38) - nd := nb.Build() + nd := literal.Float(1.38) pol := MustConstruct(GreaterThan(".", literal.Float(1))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(GreaterThan(".", literal.Float(2))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("gte float", func(t *testing.T) { - np := basicnode.Prototype.Float - nb := np.NewBuilder() - nb.AssignFloat(1.38) - nd := nb.Build() + nd := literal.Float(1.38) pol := MustConstruct(GreaterThanOrEqual(".", literal.Float(1))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(GreaterThanOrEqual(".", literal.Float(1.38))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(GreaterThanOrEqual(".", literal.Float(2))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("lt int", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct(LessThan(".", literal.Int(1138))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(LessThan(".", literal.Int(138))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) + + pol = MustConstruct(LessThan(".", literal.Int(100))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("lte int", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct(LessThanOrEqual(".", literal.Int(1138))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(LessThanOrEqual(".", literal.Int(138))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) + + pol = MustConstruct(LessThanOrEqual(".", literal.Int(100))) + ok, leaf = pol.Match(nd) + require.False(t, ok) + require.Equal(t, pol[0], leaf) }) }) t.Run("negation", func(t *testing.T) { - np := basicnode.Prototype.Bool - nb := np.NewBuilder() - nb.AssignBool(false) - nd := nb.Build() + nd := literal.Bool(false) pol := MustConstruct(Not(Equal(".", literal.Bool(true)))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Not(Equal(".", literal.Bool(false)))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) t.Run("conjunction", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct( And( @@ -246,8 +270,9 @@ func TestMatch(t *testing.T) { LessThan(".", literal.Int(1138)), ), ) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct( And( @@ -255,19 +280,18 @@ func TestMatch(t *testing.T) { Equal(".", literal.Int(1138)), ), ) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, MustConstruct(Equal(".", literal.Int(1138)))[0], leaf) pol = MustConstruct(And()) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) }) t.Run("disjunction", func(t *testing.T) { - np := basicnode.Prototype.Int - nb := np.NewBuilder() - nb.AssignInt(138) - nd := nb.Build() + nd := literal.Int(138) pol := MustConstruct( Or( @@ -275,8 +299,9 @@ func TestMatch(t *testing.T) { LessThan(".", literal.Int(1138)), ), ) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct( Or( @@ -284,12 +309,14 @@ func TestMatch(t *testing.T) { Equal(".", literal.Int(1138)), ), ) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) pol = MustConstruct(Or()) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) }) t.Run("wildcard", func(t *testing.T) { @@ -303,14 +330,12 @@ func TestMatch(t *testing.T) { } { func(s string) { t.Run(fmt.Sprintf("pass %s", s), func(t *testing.T) { - np := basicnode.Prototype.String - nb := np.NewBuilder() - nb.AssignString(s) - nd := nb.Build() + nd := literal.String(s) pol := MustConstruct(Like(".", pattern)) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) }) }(s) } @@ -324,70 +349,56 @@ func TestMatch(t *testing.T) { } { func(s string) { t.Run(fmt.Sprintf("fail %s", s), func(t *testing.T) { - np := basicnode.Prototype.String - nb := np.NewBuilder() - nb.AssignString(s) - nd := nb.Build() + nd := literal.String(s) pol := MustConstruct(Like(".", pattern)) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) }(s) } }) t.Run("quantification", func(t *testing.T) { - buildValueNode := func(v int64) ipld.Node { - np := basicnode.Prototype.Map - nb := np.NewBuilder() - ma, _ := nb.BeginMap(1) - ma.AssembleKey().AssignString("value") - ma.AssembleValue().AssignInt(v) - ma.Finish() - return nb.Build() - } - t.Run("all", func(t *testing.T) { - np := basicnode.Prototype.List - nb := np.NewBuilder() - la, _ := nb.BeginList(5) - la.AssembleValue().AssignNode(buildValueNode(5)) - la.AssembleValue().AssignNode(buildValueNode(10)) - la.AssembleValue().AssignNode(buildValueNode(20)) - la.AssembleValue().AssignNode(buildValueNode(50)) - la.AssembleValue().AssignNode(buildValueNode(100)) - la.Finish() - nd := nb.Build() + nd, _ := literal.List([]any{ + map[string]int{"value": 5}, + map[string]int{"value": 10}, + map[string]int{"value": 20}, + map[string]int{"value": 50}, + map[string]int{"value": 100}, + }) pol := MustConstruct(All(".[]", GreaterThan(".value", literal.Int(2)))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(All(".[]", GreaterThan(".value", literal.Int(20)))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, MustConstruct(GreaterThan(".value", literal.Int(20)))[0], leaf) }) t.Run("any", func(t *testing.T) { - np := basicnode.Prototype.List - nb := np.NewBuilder() - la, _ := nb.BeginList(5) - la.AssembleValue().AssignNode(buildValueNode(5)) - la.AssembleValue().AssignNode(buildValueNode(10)) - la.AssembleValue().AssignNode(buildValueNode(20)) - la.AssembleValue().AssignNode(buildValueNode(50)) - la.AssembleValue().AssignNode(buildValueNode(100)) - la.Finish() - nd := nb.Build() + nd, _ := literal.List([]any{ + map[string]int{"value": 5}, + map[string]int{"value": 10}, + map[string]int{"value": 20}, + map[string]int{"value": 50}, + map[string]int{"value": 100}, + }) pol := MustConstruct(Any(".[]", GreaterThan(".value", literal.Int(60)))) - ok := pol.Match(nd) + ok, leaf := pol.Match(nd) require.True(t, ok) + require.Nil(t, leaf) pol = MustConstruct(Any(".[]", GreaterThan(".value", literal.Int(100)))) - ok = pol.Match(nd) + ok, leaf = pol.Match(nd) require.False(t, ok) + require.Equal(t, pol[0], leaf) }) }) } @@ -405,7 +416,8 @@ func TestPolicyExamples(t *testing.T) { pol, err := FromDagJson(policy) require.NoError(t, err) - return pol.Match(data) + res, _ := pol.Match(data) + return res } t.Run("And", func(t *testing.T) { @@ -509,7 +521,7 @@ func FuzzMatch(f *testing.F) { t.Skip() } - policy.Match(dataNode) + _, _ = policy.Match(dataNode) }) } @@ -584,7 +596,7 @@ func TestOptionalSelectors(t *testing.T) { err = nb.AssignNode(n) require.NoError(t, err) - result := tt.policy.Match(nb.Build()) + result, _ := tt.policy.Match(nb.Build()) require.Equal(t, tt.expected, result) }) }