github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/dispatch/graph/dispatch_test.go (about) 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 }