github.com/openfga/openfga@v1.5.4-rc1/pkg/typesystem/resolver_test.go (about) 1 package typesystem 2 3 import ( 4 "context" 5 "fmt" 6 "testing" 7 8 "github.com/oklog/ulid/v2" 9 openfgav1 "github.com/openfga/api/proto/openfga/v1" 10 parser "github.com/openfga/language/pkg/go/transformer" 11 "github.com/stretchr/testify/require" 12 "go.uber.org/mock/gomock" 13 "golang.org/x/sync/errgroup" 14 15 mockstorage "github.com/openfga/openfga/internal/mocks" 16 ) 17 18 func TestMemoizedTypesystemResolverFunc(t *testing.T) { 19 mockController := gomock.NewController(t) 20 defer mockController.Finish() 21 22 mockDatastore := mockstorage.NewMockOpenFGADatastore(mockController) 23 24 storeID := ulid.Make().String() 25 modelID1 := ulid.Make().String() 26 modelID2 := ulid.Make().String() 27 28 typedefs := parser.MustTransformDSLToProto(`model 29 schema 1.1 30 type user 31 type document 32 relations 33 define viewer: [user]`).GetTypeDefinitions() 34 35 gomock.InOrder( 36 mockDatastore.EXPECT(). 37 ReadAuthorizationModel(gomock.Any(), storeID, modelID1). 38 Return(&openfgav1.AuthorizationModel{ 39 Id: modelID1, 40 SchemaVersion: SchemaVersion1_1, 41 TypeDefinitions: typedefs, 42 }, nil), 43 44 mockDatastore.EXPECT(). 45 FindLatestAuthorizationModel(gomock.Any(), storeID). 46 Return(&openfgav1.AuthorizationModel{ 47 Id: modelID2, 48 SchemaVersion: SchemaVersion1_1, 49 TypeDefinitions: typedefs, 50 }, nil), 51 ) 52 53 resolver, resolverStop := MemoizedTypesystemResolverFunc( 54 mockDatastore, 55 ) 56 defer resolverStop() 57 58 typesys, err := resolver(context.Background(), storeID, modelID1) 59 require.NoError(t, err) 60 require.NotNil(t, typesys) 61 62 relation, err := typesys.GetRelation("document", "viewer") 63 require.NoError(t, err) 64 require.NotNil(t, relation) 65 66 typesys, err = resolver(context.Background(), storeID, "") 67 require.NoError(t, err) 68 require.NotNil(t, typesys) 69 require.Equal(t, modelID2, typesys.GetAuthorizationModelID()) 70 71 relation, err = typesys.GetRelation("document", "viewer") 72 require.NoError(t, err) 73 require.NotNil(t, relation) 74 } 75 76 func TestSingleFlightMemoizedTypesystemResolverFunc(t *testing.T) { 77 const numGoroutines = 2 78 79 mockController := gomock.NewController(t) 80 defer mockController.Finish() 81 82 mockDatastore := mockstorage.NewMockOpenFGADatastore(mockController) 83 84 storeID := ulid.Make().String() 85 modelID := ulid.Make().String() 86 87 mockDatastore.EXPECT(). 88 FindLatestAuthorizationModel(gomock.Any(), storeID). 89 Return(&openfgav1.AuthorizationModel{ 90 Id: modelID, 91 SchemaVersion: SchemaVersion1_1, 92 }, nil).MinTimes(1).MaxTimes(numGoroutines) 93 94 resolver, resolverStop := MemoizedTypesystemResolverFunc( 95 mockDatastore, 96 ) 97 defer resolverStop() 98 99 var wg errgroup.Group 100 101 for i := 0; i < numGoroutines; i++ { 102 wg.Go(func() error { 103 typesys, err := resolver(context.Background(), storeID, "") 104 if err != nil { 105 return err 106 } 107 if typesys.GetAuthorizationModelID() != modelID { 108 return fmt.Errorf("expected model %s, actual %s", modelID, typesys.GetAuthorizationModelID()) 109 } 110 return nil 111 }) 112 } 113 114 err := wg.Wait() 115 require.NoError(t, err) 116 }