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  }