github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/services/integrationtesting/benchmark_test.go (about)

     1  //go:build docker && !skipintegrationtests
     2  // +build docker,!skipintegrationtests
     3  
     4  package integrationtesting_test
     5  
     6  import (
     7  	"context"
     8  	"embed"
     9  	"testing"
    10  	"time"
    11  
    12  	"github.com/stretchr/testify/require"
    13  
    14  	v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
    15  	datastoremw "github.com/authzed/spicedb/internal/middleware/datastore"
    16  	"github.com/authzed/spicedb/internal/services/integrationtesting/consistencytestutil"
    17  	"github.com/authzed/spicedb/internal/testserver"
    18  	testdatastore "github.com/authzed/spicedb/internal/testserver/datastore"
    19  	"github.com/authzed/spicedb/internal/testserver/datastore/config"
    20  	dsconfig "github.com/authzed/spicedb/pkg/cmd/datastore"
    21  	"github.com/authzed/spicedb/pkg/datastore"
    22  	core "github.com/authzed/spicedb/pkg/proto/core/v1"
    23  	"github.com/authzed/spicedb/pkg/tuple"
    24  	"github.com/authzed/spicedb/pkg/validationfile"
    25  )
    26  
    27  //go:embed benchconfigs/*.yaml testconfigs/*.yaml
    28  var testFiles embed.FS
    29  
    30  func BenchmarkServices(b *testing.B) {
    31  	bts := []struct {
    32  		title    string
    33  		fileName string
    34  		runner   func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error
    35  	}{
    36  		{
    37  			"basic lookup of view for a user",
    38  			"testconfigs/basicrbac.yaml",
    39  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
    40  				results, _, err := tester.LookupResources(ctx, &core.RelationReference{
    41  					Namespace: "example/document",
    42  					Relation:  "view",
    43  				}, &core.ObjectAndRelation{
    44  					Namespace: "example/user",
    45  					ObjectId:  "tom",
    46  					Relation:  tuple.Ellipsis,
    47  				}, revision, nil, 0)
    48  				require.GreaterOrEqual(b, len(results), 0)
    49  				return err
    50  			},
    51  		},
    52  		{
    53  			"recursively through groups",
    54  			"testconfigs/simplerecursive.yaml",
    55  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
    56  				results, _, err := tester.LookupResources(ctx, &core.RelationReference{
    57  					Namespace: "srrr/resource",
    58  					Relation:  "viewer",
    59  				}, &core.ObjectAndRelation{
    60  					Namespace: "srrr/user",
    61  					ObjectId:  "someguy",
    62  					Relation:  tuple.Ellipsis,
    63  				}, revision, nil, 0)
    64  				require.GreaterOrEqual(b, len(results), 0)
    65  				return err
    66  			},
    67  		},
    68  		{
    69  			"recursively through wide groups",
    70  			"benchconfigs/widegroups.yaml",
    71  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
    72  				results, _, err := tester.LookupResources(ctx, &core.RelationReference{
    73  					Namespace: "resource",
    74  					Relation:  "view",
    75  				}, &core.ObjectAndRelation{
    76  					Namespace: "user",
    77  					ObjectId:  "tom",
    78  					Relation:  tuple.Ellipsis,
    79  				}, revision, nil, 0)
    80  				require.GreaterOrEqual(b, len(results), 0)
    81  				return err
    82  			},
    83  		},
    84  		{
    85  			"lookup with intersection",
    86  			"benchconfigs/lookupintersection.yaml",
    87  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
    88  				results, _, err := tester.LookupResources(ctx, &core.RelationReference{
    89  					Namespace: "resource",
    90  					Relation:  "view",
    91  				}, &core.ObjectAndRelation{
    92  					Namespace: "user",
    93  					ObjectId:  "tom",
    94  					Relation:  tuple.Ellipsis,
    95  				}, revision, nil, 0)
    96  				require.Equal(b, len(results), 499)
    97  				return err
    98  			},
    99  		},
   100  		{
   101  			"basic check for a user",
   102  			"testconfigs/basicrbac.yaml",
   103  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
   104  				result, err := tester.Check(ctx, &core.ObjectAndRelation{
   105  					Namespace: "example/document",
   106  					ObjectId:  "firstdoc",
   107  					Relation:  "view",
   108  				}, &core.ObjectAndRelation{
   109  					Namespace: "example/user",
   110  					ObjectId:  "tom",
   111  					Relation:  tuple.Ellipsis,
   112  				}, revision, nil)
   113  				require.Equal(b, v1.CheckPermissionResponse_PERMISSIONSHIP_HAS_PERMISSION, result)
   114  				return err
   115  			},
   116  		},
   117  		{
   118  			"recursive check for a user",
   119  			"testconfigs/quay.yaml",
   120  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
   121  				result, err := tester.Check(ctx, &core.ObjectAndRelation{
   122  					Namespace: "quay/repo",
   123  					ObjectId:  "buynlarge/orgrepo",
   124  					Relation:  "view",
   125  				}, &core.ObjectAndRelation{
   126  					Namespace: "quay/user",
   127  					ObjectId:  "cto",
   128  					Relation:  tuple.Ellipsis,
   129  				}, revision, nil)
   130  				require.Equal(b, v1.CheckPermissionResponse_PERMISSIONSHIP_HAS_PERMISSION, result)
   131  				return err
   132  			},
   133  		},
   134  		{
   135  			"wide groups check for a user",
   136  			"benchconfigs/checkwidegroups.yaml",
   137  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
   138  				result, err := tester.Check(ctx, &core.ObjectAndRelation{
   139  					Namespace: "resource",
   140  					ObjectId:  "someresource",
   141  					Relation:  "view",
   142  				}, &core.ObjectAndRelation{
   143  					Namespace: "user",
   144  					ObjectId:  "tom",
   145  					Relation:  tuple.Ellipsis,
   146  				}, revision, nil)
   147  				require.Equal(b, v1.CheckPermissionResponse_PERMISSIONSHIP_HAS_PERMISSION, result)
   148  				return err
   149  			},
   150  		},
   151  		{
   152  			"wide direct relation check",
   153  			"benchconfigs/checkwidedirect.yaml",
   154  			func(ctx context.Context, b *testing.B, tester consistencytestutil.ServiceTester, revision datastore.Revision) error {
   155  				result, err := tester.Check(ctx, &core.ObjectAndRelation{
   156  					Namespace: "resource",
   157  					ObjectId:  "someresource",
   158  					Relation:  "view",
   159  				}, &core.ObjectAndRelation{
   160  					Namespace: "user",
   161  					ObjectId:  "tom",
   162  					Relation:  tuple.Ellipsis,
   163  				}, revision, nil)
   164  				require.Equal(b, v1.CheckPermissionResponse_PERMISSIONSHIP_HAS_PERMISSION, result)
   165  				return err
   166  			},
   167  		},
   168  	}
   169  
   170  	for _, bt := range bts {
   171  		b.Run(bt.title, func(b *testing.B) {
   172  			for _, engineID := range datastore.Engines {
   173  				b.Run(engineID, func(b *testing.B) {
   174  					brequire := require.New(b)
   175  
   176  					rde := testdatastore.RunDatastoreEngine(b, engineID)
   177  					ds := rde.NewDatastore(b, config.DatastoreConfigInitFunc(b,
   178  						dsconfig.WithWatchBufferLength(0),
   179  						dsconfig.WithGCWindow(time.Duration(90_000_000_000_000)),
   180  						dsconfig.WithRevisionQuantization(10),
   181  						dsconfig.WithMaxRetries(50),
   182  						dsconfig.WithRequestHedgingEnabled(false),
   183  					))
   184  
   185  					contents, err := testFiles.ReadFile(bt.fileName)
   186  					require.NoError(b, err)
   187  
   188  					_, revision, err := validationfile.PopulateFromFilesContents(context.Background(), ds, map[string][]byte{
   189  						"testfile": contents,
   190  					})
   191  					brequire.NoError(err)
   192  
   193  					conn, cleanup := testserver.TestClusterWithDispatchAndCacheConfig(b, 1, ds)
   194  					b.Cleanup(cleanup)
   195  
   196  					dsCtx := datastoremw.ContextWithHandle(context.Background())
   197  					brequire.NoError(datastoremw.SetInContext(dsCtx, ds))
   198  
   199  					testers := consistencytestutil.ServiceTesters(conn[0])
   200  
   201  					for _, tester := range testers {
   202  						b.Run(tester.Name(), func(b *testing.B) {
   203  							require := require.New(b)
   204  							for n := 0; n < b.N; n++ {
   205  								require.NoError(bt.runner(dsCtx, b, tester, revision))
   206  							}
   207  						})
   208  					}
   209  				})
   210  			}
   211  		})
   212  	}
   213  }