|
| 1 | +package graph |
| 2 | + |
| 3 | +import ( |
| 4 | + "fmt" |
| 5 | + "math" |
| 6 | + "testing" |
| 7 | + |
| 8 | + "github.com/authzed/spicedb/internal/dispatch" |
| 9 | + "github.com/authzed/spicedb/internal/graph" |
| 10 | + core "github.com/authzed/spicedb/pkg/proto/core/v1" |
| 11 | + v1 "github.com/authzed/spicedb/pkg/proto/dispatch/v1" |
| 12 | + "github.com/authzed/spicedb/pkg/tuple" |
| 13 | + |
| 14 | + "github.com/stretchr/testify/require" |
| 15 | +) |
| 16 | + |
| 17 | +func TestDispatchChunking(t *testing.T) { |
| 18 | + schema := ` |
| 19 | + definition user { |
| 20 | + relation self: user |
| 21 | + } |
| 22 | +
|
| 23 | + definition res { |
| 24 | + relation owner : user |
| 25 | + permission view = owner->self |
| 26 | + }` |
| 27 | + |
| 28 | + resources := make([]*core.RelationTuple, 0, math.MaxUint16+1) |
| 29 | + enabled := make([]*core.RelationTuple, 0, math.MaxUint16+1) |
| 30 | + for i := 0; i < math.MaxUint16+1; i++ { |
| 31 | + resources = append(resources, tuple.Parse(fmt.Sprintf("res:res1#owner@user:user%d", i))) |
| 32 | + enabled = append(enabled, tuple.Parse(fmt.Sprintf("user:user%d#self@user:user%d", i, i))) |
| 33 | + } |
| 34 | + |
| 35 | + ctx, dispatcher, revision := newLocalDispatcherWithSchemaAndRels(t, schema, append(enabled, resources...)) |
| 36 | + |
| 37 | + t.Run("check", func(t *testing.T) { |
| 38 | + for _, tpl := range resources[:1] { |
| 39 | + checkResult, err := dispatcher.DispatchCheck(ctx, &v1.DispatchCheckRequest{ |
| 40 | + ResourceRelation: RR(tpl.ResourceAndRelation.Namespace, "view"), |
| 41 | + ResourceIds: []string{tpl.ResourceAndRelation.ObjectId}, |
| 42 | + ResultsSetting: v1.DispatchCheckRequest_ALLOW_SINGLE_RESULT, |
| 43 | + Subject: ONR(tpl.Subject.Namespace, tpl.Subject.ObjectId, graph.Ellipsis), |
| 44 | + Metadata: &v1.ResolverMeta{ |
| 45 | + AtRevision: revision.String(), |
| 46 | + DepthRemaining: 50, |
| 47 | + }, |
| 48 | + }) |
| 49 | + |
| 50 | + require.NoError(t, err) |
| 51 | + require.NotNil(t, checkResult) |
| 52 | + require.NotEmpty(t, checkResult.ResultsByResourceId, "expected membership for resource %s", tpl.ResourceAndRelation.ObjectId) |
| 53 | + require.Equal(t, v1.ResourceCheckResult_MEMBER, checkResult.ResultsByResourceId[tpl.ResourceAndRelation.ObjectId].Membership) |
| 54 | + } |
| 55 | + }) |
| 56 | + |
| 57 | + t.Run("lookup-resources", func(t *testing.T) { |
| 58 | + for _, tpl := range resources[:1] { |
| 59 | + stream := dispatch.NewCollectingDispatchStream[*v1.DispatchLookupResourcesResponse](ctx) |
| 60 | + err := dispatcher.DispatchLookupResources(&v1.DispatchLookupResourcesRequest{ |
| 61 | + ObjectRelation: RR(tpl.ResourceAndRelation.Namespace, "view"), |
| 62 | + Subject: ONR(tpl.Subject.Namespace, tpl.Subject.ObjectId, graph.Ellipsis), |
| 63 | + Metadata: &v1.ResolverMeta{ |
| 64 | + AtRevision: revision.String(), |
| 65 | + DepthRemaining: 50, |
| 66 | + }, |
| 67 | + OptionalLimit: veryLargeLimit, |
| 68 | + }, stream) |
| 69 | + |
| 70 | + require.NoError(t, err) |
| 71 | + |
| 72 | + foundResources, _, _, _ := processResults(stream) |
| 73 | + require.Len(t, foundResources, 1) |
| 74 | + } |
| 75 | + }) |
| 76 | + |
| 77 | + t.Run("lookup-subjects", func(t *testing.T) { |
| 78 | + for _, tpl := range resources[:1] { |
| 79 | + stream := dispatch.NewCollectingDispatchStream[*v1.DispatchLookupSubjectsResponse](ctx) |
| 80 | + |
| 81 | + err := dispatcher.DispatchLookupSubjects(&v1.DispatchLookupSubjectsRequest{ |
| 82 | + ResourceRelation: RR(tpl.ResourceAndRelation.Namespace, "view"), |
| 83 | + ResourceIds: []string{tpl.ResourceAndRelation.ObjectId}, |
| 84 | + SubjectRelation: RR(tpl.Subject.Namespace, graph.Ellipsis), |
| 85 | + Metadata: &v1.ResolverMeta{ |
| 86 | + AtRevision: revision.String(), |
| 87 | + DepthRemaining: 50, |
| 88 | + }, |
| 89 | + }, stream) |
| 90 | + |
| 91 | + require.NoError(t, err) |
| 92 | + res := stream.Results() |
| 93 | + require.Len(t, res, 1) |
| 94 | + require.Len(t, res[0].FoundSubjectsByResourceId, 1) |
| 95 | + require.NotNil(t, res[0].FoundSubjectsByResourceId["res1"]) |
| 96 | + require.Len(t, res[0].FoundSubjectsByResourceId["res1"].FoundSubjects, math.MaxUint16+1) |
| 97 | + } |
| 98 | + }) |
| 99 | +} |
0 commit comments