github.com/authzed/spicedb@v1.32.1-0.20240520085336-ebda56537386/internal/services/integrationtesting/consistencytestutil/clusteranddata.go (about) 1 package consistencytestutil 2 3 import ( 4 "context" 5 "testing" 6 "time" 7 8 "github.com/authzed/spicedb/internal/dispatch" 9 10 "github.com/stretchr/testify/require" 11 "google.golang.org/grpc" 12 13 "github.com/authzed/spicedb/internal/datastore/memdb" 14 "github.com/authzed/spicedb/internal/dispatch/caching" 15 "github.com/authzed/spicedb/internal/dispatch/graph" 16 "github.com/authzed/spicedb/internal/dispatch/keys" 17 datastoremw "github.com/authzed/spicedb/internal/middleware/datastore" 18 "github.com/authzed/spicedb/internal/testserver" 19 "github.com/authzed/spicedb/pkg/datastore" 20 "github.com/authzed/spicedb/pkg/typesystem" 21 "github.com/authzed/spicedb/pkg/validationfile" 22 ) 23 24 const defaultConcurrencyLimit = 10 25 26 // ConsistencyClusterAndData holds a connection to a SpiceDB "cluster" (size 1) 27 // running the V1 API for the given data. 28 type ConsistencyClusterAndData struct { 29 Conn *grpc.ClientConn 30 DataStore datastore.Datastore 31 Ctx context.Context 32 Populated *validationfile.PopulatedValidationFile 33 } 34 35 // LoadDataAndCreateClusterForTesting loads the data found in a consistency test file, 36 // builds a cluster for it, and returns both the data and cluster. 37 func LoadDataAndCreateClusterForTesting(t *testing.T, consistencyTestFilePath string, revisionDelta time.Duration) ConsistencyClusterAndData { 38 require := require.New(t) 39 40 ds, err := memdb.NewMemdbDatastore(0, revisionDelta, memdb.DisableGC) 41 require.NoError(err) 42 43 return BuildDataAndCreateClusterForTesting(t, consistencyTestFilePath, ds) 44 } 45 46 // BuildDataAndCreateClusterForTesting loads the data found in a consistency test file, 47 // builds a cluster for it, and returns both the data and cluster. 48 func BuildDataAndCreateClusterForTesting(t *testing.T, consistencyTestFilePath string, ds datastore.Datastore) ConsistencyClusterAndData { 49 require := require.New(t) 50 51 populated, revision, err := validationfile.PopulateFromFiles(context.Background(), ds, []string{consistencyTestFilePath}) 52 require.NoError(err) 53 54 connections, cleanup := testserver.TestClusterWithDispatch(t, 1, ds) 55 t.Cleanup(cleanup) 56 57 dsCtx := datastoremw.ContextWithHandle(context.Background()) 58 require.NoError(datastoremw.SetInContext(dsCtx, ds)) 59 60 // Validate the type system for each namespace. 61 for _, nsDef := range populated.NamespaceDefinitions { 62 _, ts, err := typesystem.ReadNamespaceAndTypes( 63 dsCtx, 64 nsDef.Name, 65 ds.SnapshotReader(revision), 66 ) 67 require.NoError(err) 68 69 _, err = ts.Validate(dsCtx) 70 require.NoError(err) 71 } 72 73 return ConsistencyClusterAndData{ 74 Conn: connections[0], 75 DataStore: ds, 76 Ctx: dsCtx, 77 Populated: populated, 78 } 79 } 80 81 // CreateDispatcherForTesting creates a dispatcher for consistency testing, with or without 82 // caching enabled. 83 func CreateDispatcherForTesting(t *testing.T, withCaching bool) dispatch.Dispatcher { 84 require := require.New(t) 85 dispatcher := graph.NewLocalOnlyDispatcher(defaultConcurrencyLimit) 86 if withCaching { 87 cachingDispatcher, err := caching.NewCachingDispatcher(nil, false, "", &keys.CanonicalKeyHandler{}) 88 require.NoError(err) 89 90 localDispatcher := graph.NewDispatcher(cachingDispatcher, graph.SharedConcurrencyLimits(10)) 91 t.Cleanup(func() { 92 err := localDispatcher.Close() 93 require.NoError(err) 94 }) 95 96 cachingDispatcher.SetDelegate(localDispatcher) 97 dispatcher = cachingDispatcher 98 } 99 t.Cleanup(func() { 100 err := dispatcher.Close() 101 require.NoError(err) 102 }) 103 return dispatcher 104 }