snapshot of https://github.com/ory/keto.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
Some checks failed
CI / Run lints and checks (push) Failing after 47s
CI / Run tests (push) Failing after 1s
CI / Run race tests (push) Failing after 5s
CI / Build CLI docs (push) Has been skipped
CI / Run buf actions (push) Failing after 5s
CodeQL / Analyze (go) (push) Failing after 3s
CodeQL / Analyze (javascript) (push) Failing after 2s
Docker Image Scanners / scanners (push) Failing after 3s
Format / format (push) Failing after 3s
Synchronize Issue Labels / Synchronize Issue Labels (push) Has been skipped
CI / Generate release (push) Has been skipped
CI / Draft newsletter (push) Has been skipped
CI / Pending approval Slack notification (push) Has been skipped
CI / Send newsletter (push) Has been skipped
This commit is contained in:
232
internal/e2e/transaction_cases_test.go
Normal file
232
internal/e2e/transaction_cases_test.go
Normal file
@@ -0,0 +1,232 @@
|
||||
// Copyright © 2023 Ory Corp
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"cmp"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/ory/x/uuidx"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/ory/keto/internal/namespace"
|
||||
"github.com/ory/keto/ketoapi"
|
||||
)
|
||||
|
||||
func runTransactionCases(c transactClient, m *namespaceTestManager) func(*testing.T) {
|
||||
return func(t *testing.T) {
|
||||
t.Parallel()
|
||||
t.Run("case=create and delete", func(t *testing.T) {
|
||||
n := &namespace.Namespace{Name: t.Name()}
|
||||
m.add(t, n)
|
||||
|
||||
tuples := []*ketoapi.RelationTuple{
|
||||
{
|
||||
Namespace: n.Name,
|
||||
Object: "o",
|
||||
Relation: "rel",
|
||||
SubjectSet: &ketoapi.SubjectSet{
|
||||
Namespace: n.Name,
|
||||
Object: "o",
|
||||
Relation: "rel",
|
||||
},
|
||||
},
|
||||
{
|
||||
Namespace: n.Name,
|
||||
Object: "o",
|
||||
Relation: "rel",
|
||||
SubjectID: new("sid"),
|
||||
},
|
||||
}
|
||||
|
||||
c.transactTuples(t, tuples, nil)
|
||||
|
||||
resp := c.queryTuple(t, &ketoapi.RelationQuery{
|
||||
Namespace: &n.Name,
|
||||
})
|
||||
for i := range tuples {
|
||||
assert.Contains(t, resp.RelationTuples, tuples[i])
|
||||
}
|
||||
|
||||
c.transactTuples(t, nil, tuples)
|
||||
|
||||
resp = c.queryTuple(t, &ketoapi.RelationQuery{
|
||||
Namespace: &n.Name,
|
||||
})
|
||||
assert.Len(t, resp.RelationTuples, 0)
|
||||
})
|
||||
|
||||
t.Run("case=duplicate string representations", func(t *testing.T) {
|
||||
n := &namespace.Namespace{Name: t.Name()}
|
||||
m.add(t, n)
|
||||
c.transactTuples(t, []*ketoapi.RelationTuple{
|
||||
{
|
||||
Namespace: n.Name,
|
||||
Object: "o",
|
||||
Relation: "rel",
|
||||
SubjectID: new("sid"),
|
||||
},
|
||||
{
|
||||
Namespace: n.Name,
|
||||
Object: "o",
|
||||
Relation: "rel",
|
||||
SubjectID: new("sid"),
|
||||
},
|
||||
}, nil)
|
||||
})
|
||||
|
||||
t.Run("case=large inserts and deletes", func(t *testing.T) {
|
||||
if testing.Short() {
|
||||
t.Skip("This test is fairly expensive, especially the deletion.")
|
||||
}
|
||||
|
||||
ns := []*namespace.Namespace{
|
||||
{Name: uuidx.NewV4().String()},
|
||||
{Name: uuidx.NewV4().String()},
|
||||
}
|
||||
m.add(t, ns...)
|
||||
|
||||
var tuples []*ketoapi.RelationTuple
|
||||
for i := range 1200 {
|
||||
tuples = append(tuples,
|
||||
&ketoapi.RelationTuple{
|
||||
Namespace: ns[0].Name,
|
||||
Object: "o" + strconv.Itoa(i),
|
||||
Relation: "rela",
|
||||
SubjectSet: &ketoapi.SubjectSet{
|
||||
Namespace: ns[1].Name,
|
||||
Object: "o" + strconv.Itoa(i),
|
||||
Relation: "relx",
|
||||
},
|
||||
},
|
||||
&ketoapi.RelationTuple{
|
||||
Namespace: ns[0].Name,
|
||||
Object: "o" + strconv.Itoa(i),
|
||||
Relation: "relb",
|
||||
SubjectID: new("sid"),
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
t0 := time.Now()
|
||||
c.transactTuples(t, tuples, nil)
|
||||
t.Logf("insert took %s", time.Since(t0))
|
||||
|
||||
t0 = time.Now()
|
||||
var resp []*ketoapi.RelationTuple
|
||||
var pt string
|
||||
for {
|
||||
r := c.queryTuple(t, &ketoapi.RelationQuery{
|
||||
Namespace: &ns[0].Name,
|
||||
}, withSize(1000), withToken(pt))
|
||||
resp = append(resp, r.RelationTuples...)
|
||||
pt = r.NextPageToken
|
||||
if pt == "" {
|
||||
break
|
||||
}
|
||||
}
|
||||
t.Logf("query took %s", time.Since(t0))
|
||||
|
||||
sort := func(a, b *ketoapi.RelationTuple) int {
|
||||
return cmp.Or(
|
||||
cmp.Compare(a.Namespace, b.Namespace),
|
||||
cmp.Compare(a.Object, b.Object),
|
||||
cmp.Compare(a.Relation, b.Relation),
|
||||
)
|
||||
}
|
||||
slices.SortFunc(resp, sort)
|
||||
slices.SortFunc(tuples, sort)
|
||||
|
||||
require.Equal(t, tuples, resp)
|
||||
|
||||
t0 = time.Now()
|
||||
c.transactTuples(t, nil, tuples)
|
||||
t.Logf("delete took %s", time.Since(t0))
|
||||
|
||||
resp = c.queryTuple(t, &ketoapi.RelationQuery{
|
||||
Namespace: &ns[0].Name,
|
||||
}).RelationTuples
|
||||
assert.Len(t, resp, 0)
|
||||
})
|
||||
|
||||
t.Run("case=expand-api-display-access docs code sample", func(t *testing.T) {
|
||||
files := &namespace.Namespace{Name: t.Name() + "files"}
|
||||
directories := &namespace.Namespace{Name: t.Name() + "directories"}
|
||||
m.add(t, files, directories)
|
||||
|
||||
tuples := []*ketoapi.RelationTuple{
|
||||
{
|
||||
Namespace: directories.Name,
|
||||
Object: "/photos",
|
||||
Relation: "owner",
|
||||
SubjectID: new("maureen"),
|
||||
},
|
||||
{
|
||||
Namespace: files.Name,
|
||||
Object: "/photos/beach.jpg",
|
||||
Relation: "owner",
|
||||
SubjectID: new("maureen"),
|
||||
},
|
||||
{
|
||||
Namespace: files.Name,
|
||||
Object: "/photos/mountains.jpg",
|
||||
Relation: "owner",
|
||||
SubjectID: new("laura"),
|
||||
},
|
||||
{
|
||||
Namespace: directories.Name,
|
||||
Object: "/photos",
|
||||
Relation: "access",
|
||||
SubjectID: new("laura"),
|
||||
},
|
||||
}
|
||||
for _, o := range []struct{ n, o string }{
|
||||
{files.Name, "/photos/beach.jpg"},
|
||||
{files.Name, "/photos/mountains.jpg"},
|
||||
{directories.Name, "/photos"},
|
||||
} {
|
||||
tuples = append(tuples, &ketoapi.RelationTuple{
|
||||
Namespace: o.n,
|
||||
Object: o.o,
|
||||
Relation: "access",
|
||||
SubjectSet: &ketoapi.SubjectSet{
|
||||
Namespace: o.n,
|
||||
Object: o.o,
|
||||
Relation: "owner",
|
||||
},
|
||||
})
|
||||
}
|
||||
for _, obj := range []string{"/photos/beach.jpg", "/photos/mountains.jpg"} {
|
||||
tuples = append(tuples, &ketoapi.RelationTuple{
|
||||
Namespace: files.Name,
|
||||
Object: obj,
|
||||
Relation: "access",
|
||||
SubjectSet: &ketoapi.SubjectSet{
|
||||
Namespace: directories.Name,
|
||||
Object: "/photos",
|
||||
Relation: "access",
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
c.transactTuples(t, tuples, nil)
|
||||
|
||||
fileTuples := c.queryTuple(t, &ketoapi.RelationQuery{Namespace: new(files.Name)})
|
||||
directoryTuples := c.queryTuple(t, &ketoapi.RelationQuery{Namespace: new(directories.Name)})
|
||||
allTuples := append(fileTuples.RelationTuples, directoryTuples.RelationTuples...)
|
||||
assert.ElementsMatch(t, allTuples, tuples)
|
||||
|
||||
c.transactTuples(t, nil, tuples)
|
||||
|
||||
fileTuples = c.queryTuple(t, &ketoapi.RelationQuery{Namespace: new(files.Name)})
|
||||
directoryTuples = c.queryTuple(t, &ketoapi.RelationQuery{Namespace: new(directories.Name)})
|
||||
allTuples = append(fileTuples.RelationTuples, directoryTuples.RelationTuples...)
|
||||
assert.Len(t, allTuples, 0)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user