Files
ucan/match_test.go

409 lines
10 KiB
Go
Raw Normal View History

2024-08-19 23:16:36 +02:00
package policy
import (
2024-08-21 08:13:44 +02:00
"fmt"
2024-08-19 23:16:36 +02:00
"testing"
2024-08-21 08:13:44 +02:00
"github.com/gobwas/glob"
2024-08-19 23:16:36 +02:00
"github.com/ipfs/go-cid"
2024-08-21 08:44:17 +02:00
"github.com/ipld/go-ipld-prime"
2024-08-19 23:16:36 +02:00
cidlink "github.com/ipld/go-ipld-prime/linking/cid"
"github.com/ipld/go-ipld-prime/node/basicnode"
"github.com/storacha-network/go-ucanto/core/policy/literal"
"github.com/storacha-network/go-ucanto/core/policy/selector"
"github.com/stretchr/testify/require"
)
func TestMatch(t *testing.T) {
t.Run("equality string", func(t *testing.T) {
np := basicnode.Prototype.String
nb := np.NewBuilder()
nb.AssignString("test")
nd := nb.Build()
pol := Policy{Equal(selector.MustParse("."), literal.String("test"))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.String("test2"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.Int(138))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("equality int", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{Equal(selector.MustParse("."), literal.Int(138))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.Int(1138))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.String("138"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("equality float", func(t *testing.T) {
np := basicnode.Prototype.Float
nb := np.NewBuilder()
nb.AssignFloat(1.138)
nd := nb.Build()
pol := Policy{Equal(selector.MustParse("."), literal.Float(1.138))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.Float(11.38))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.String("138"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("equality 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()
pol := Policy{Equal(selector.MustParse("."), literal.Link(l0))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.Link(l1))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
pol = Policy{Equal(selector.MustParse("."), literal.String("bafybeif4owy5gno5lwnixqm52rwqfodklf76hsetxdhffuxnplvijskzqq"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("equality 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()
pol := Policy{Equal(selector.MustParse(".foo"), literal.String("bar"))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse(".[\"foo\"]"), literal.String("bar"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse(".foo"), literal.String("baz"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
pol = Policy{Equal(selector.MustParse(".foobar"), literal.String("bar"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("equality 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()
pol := Policy{Equal(selector.MustParse(".[0]"), literal.String("foo"))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Equal(selector.MustParse(".[1]"), literal.String("foo"))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("inequality gt int", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{GreaterThan(selector.MustParse("."), literal.Int(1))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
})
t.Run("inequality gte int", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{GreaterThanOrEqual(selector.MustParse("."), literal.Int(1))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{GreaterThanOrEqual(selector.MustParse("."), literal.Int(138))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
})
t.Run("inequality gt float", func(t *testing.T) {
np := basicnode.Prototype.Float
nb := np.NewBuilder()
nb.AssignFloat(1.38)
nd := nb.Build()
pol := Policy{GreaterThan(selector.MustParse("."), literal.Float(1))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
})
t.Run("inequality gte float", func(t *testing.T) {
np := basicnode.Prototype.Float
nb := np.NewBuilder()
nb.AssignFloat(1.38)
nd := nb.Build()
pol := Policy{GreaterThanOrEqual(selector.MustParse("."), literal.Float(1))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{GreaterThanOrEqual(selector.MustParse("."), literal.Float(1.38))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
require.True(t, ok)
})
t.Run("inequality lt int", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{LessThan(selector.MustParse("."), literal.Int(1138))}
ok := Match(pol, nd)
require.True(t, ok)
})
t.Run("inequality lte int", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{LessThanOrEqual(selector.MustParse("."), literal.Int(1138))}
ok := Match(pol, nd)
require.True(t, ok)
pol = Policy{LessThanOrEqual(selector.MustParse("."), literal.Int(138))}
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
})
t.Run("negation", func(t *testing.T) {
np := basicnode.Prototype.Bool
nb := np.NewBuilder()
nb.AssignBool(false)
nd := nb.Build()
pol := Policy{Not(Equal(selector.MustParse("."), literal.Bool(true)))}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{Not(Equal(selector.MustParse("."), literal.Bool(false)))}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
})
t.Run("conjunction", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{
And(
GreaterThan(selector.MustParse("."), literal.Int(1)),
LessThan(selector.MustParse("."), literal.Int(1138)),
),
}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{
And(
GreaterThan(selector.MustParse("."), literal.Int(1)),
Equal(selector.MustParse("."), literal.Int(1138)),
),
}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
2024-08-20 15:55:04 +02:00
pol = Policy{And()}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-20 15:55:04 +02:00
require.True(t, ok)
2024-08-19 23:16:36 +02:00
})
t.Run("disjunction", func(t *testing.T) {
np := basicnode.Prototype.Int
nb := np.NewBuilder()
nb.AssignInt(138)
nd := nb.Build()
pol := Policy{
Or(
GreaterThan(selector.MustParse("."), literal.Int(138)),
LessThan(selector.MustParse("."), literal.Int(1138)),
),
}
2024-08-20 22:27:56 +02:00
ok := Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.True(t, ok)
pol = Policy{
Or(
GreaterThan(selector.MustParse("."), literal.Int(138)),
Equal(selector.MustParse("."), literal.Int(1138)),
),
}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-19 23:16:36 +02:00
require.False(t, ok)
2024-08-20 15:55:04 +02:00
pol = Policy{Or()}
2024-08-20 22:27:56 +02:00
ok = Match(pol, nd)
2024-08-20 15:55:04 +02:00
require.True(t, ok)
2024-08-19 23:16:36 +02:00
})
2024-08-21 08:13:44 +02:00
t.Run("wildcard", func(t *testing.T) {
glb, err := glob.Compile(`Alice\*, Bob*, Carol.`)
require.NoError(t, err)
for _, s := range []string{
"Alice*, Bob, Carol.",
"Alice*, Bob, Dan, Erin, Carol.",
"Alice*, Bob , Carol.",
"Alice*, Bob*, Carol.",
} {
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()
pol := Policy{Like(selector.MustParse("."), glb)}
ok := Match(pol, nd)
require.True(t, ok)
})
}(s)
}
for _, s := range []string{
"Alice*, Bob, Carol",
"Alice*, Bob*, Carol!",
"Alice, Bob, Carol.",
" Alice*, Bob, Carol. ",
} {
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()
pol := Policy{Like(selector.MustParse("."), glb)}
ok := Match(pol, nd)
require.False(t, ok)
})
}(s)
}
})
2024-08-21 08:44:17 +02:00
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("quantification 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()
pol := Policy{
All(
selector.MustParse(".[]"),
GreaterThan(selector.MustParse(".value"), literal.Int(2)),
),
}
ok := Match(pol, nd)
require.True(t, ok)
pol = Policy{
All(
selector.MustParse(".[]"),
GreaterThan(selector.MustParse(".value"), literal.Int(20)),
),
}
ok = Match(pol, nd)
require.False(t, ok)
})
t.Run("quantification 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()
pol := Policy{
Any(
selector.MustParse(".[]"),
GreaterThan(selector.MustParse(".value"), literal.Int(10)),
LessThan(selector.MustParse(".value"), literal.Int(50)),
),
}
ok := Match(pol, nd)
require.True(t, ok)
pol = Policy{
Any(
selector.MustParse(".[]"),
GreaterThan(selector.MustParse(".value"), literal.Int(100)),
),
}
ok = Match(pol, nd)
require.False(t, ok)
})
2024-08-19 23:16:36 +02:00
}