github.com/openfga/openfga@v1.5.4-rc1/pkg/storage/test/storage.go (about)

     1  package test
     2  
     3  import (
     4  	"context"
     5  	"testing"
     6  
     7  	"github.com/google/go-cmp/cmp"
     8  	"github.com/oklog/ulid/v2"
     9  	openfgav1 "github.com/openfga/api/proto/openfga/v1"
    10  	"github.com/stretchr/testify/require"
    11  	"google.golang.org/protobuf/protoadapt"
    12  	"google.golang.org/protobuf/testing/protocmp"
    13  
    14  	"github.com/openfga/openfga/pkg/tuple"
    15  
    16  	"github.com/openfga/openfga/pkg/storage"
    17  	"github.com/openfga/openfga/pkg/testutils"
    18  )
    19  
    20  var (
    21  	cmpOpts = []cmp.Option{
    22  		protocmp.IgnoreFields(protoadapt.MessageV2Of(&openfgav1.Tuple{}), "timestamp"),
    23  		protocmp.IgnoreFields(protoadapt.MessageV2Of(&openfgav1.TupleChange{}), "timestamp"),
    24  		testutils.TupleKeyCmpTransformer,
    25  		protocmp.Transform(),
    26  	}
    27  )
    28  
    29  func RunAllTests(t *testing.T, ds storage.OpenFGADatastore) {
    30  	t.Run("TestDatastoreIsReady", func(t *testing.T) {
    31  		status, err := ds.IsReady(context.Background())
    32  		require.NoError(t, err)
    33  		require.True(t, status.IsReady)
    34  	})
    35  	// Tuples.
    36  	t.Run("TestTupleWriteAndRead", func(t *testing.T) { TupleWritingAndReadingTest(t, ds) })
    37  	t.Run("TestReadChanges", func(t *testing.T) { ReadChangesTest(t, ds) })
    38  	t.Run("TestReadStartingWithUser", func(t *testing.T) { ReadStartingWithUserTest(t, ds) })
    39  
    40  	// TODO I suspect there is overlap in test scenarios. Consolidate them into one
    41  	t.Run("ReadPageTestCorrectnessOfContinuationTokens", func(t *testing.T) { ReadPageTestCorrectnessOfContinuationTokens(t, ds) })
    42  	t.Run("ReadPageTestCorrectnessOfContinuationTokensV2", func(t *testing.T) { ReadPageTestCorrectnessOfContinuationTokensV2(t, ds) })
    43  
    44  	// TODO Consolidate them into one, since both Read and ReadPage should respect the same set of filters
    45  	t.Run("ReadTestCorrectnessOfTuples", func(t *testing.T) { ReadTestCorrectnessOfTuples(t, ds) })
    46  	t.Run("ReadPageTestCorrectnessOfTuples", func(t *testing.T) { ReadPageTestCorrectnessOfTuples(t, ds) })
    47  
    48  	// Authorization models.
    49  	t.Run("TestWriteAndReadAuthorizationModel", func(t *testing.T) { WriteAndReadAuthorizationModelTest(t, ds) })
    50  	t.Run("TestReadAuthorizationModels", func(t *testing.T) { ReadAuthorizationModelsTest(t, ds) })
    51  	t.Run("TestFindLatestAuthorizationModel", func(t *testing.T) { FindLatestAuthorizationModelTest(t, ds) })
    52  
    53  	// Assertions.
    54  	t.Run("TestWriteAndReadAssertions", func(t *testing.T) { AssertionsTest(t, ds) })
    55  
    56  	// Stores.
    57  	t.Run("TestStore", func(t *testing.T) { StoreTest(t, ds) })
    58  }
    59  
    60  // BootstrapFGAStore is a utility to write an FGA model and relationship tuples to a datastore.
    61  // It doesn't validate the model. It validates the format of the tuples, but not the types within them.
    62  // It returns the store_id and FGA AuthorizationModel, respectively.
    63  func BootstrapFGAStore(
    64  	t require.TestingT,
    65  	ds storage.OpenFGADatastore,
    66  	model string,
    67  	tupleStrs []string,
    68  ) (string, *openfgav1.AuthorizationModel) {
    69  	storeID := ulid.Make().String()
    70  
    71  	fgaModel := testutils.MustTransformDSLToProtoWithID(model)
    72  	err := ds.WriteAuthorizationModel(context.Background(), storeID, fgaModel)
    73  	require.NoError(t, err)
    74  
    75  	tuples := tuple.MustParseTupleStrings(tupleStrs...)
    76  
    77  	batchSize := ds.MaxTuplesPerWrite()
    78  	for batch := 0; batch < len(tuples); batch += batchSize {
    79  		batchEnd := min(batch+batchSize, len(tuples))
    80  
    81  		err := ds.Write(context.Background(), storeID, nil, tuples[batch:batchEnd])
    82  		require.NoError(t, err)
    83  	}
    84  
    85  	return storeID, fgaModel
    86  }