github.com/openfga/openfga@v1.5.4-rc1/cmd/validatemodels/validate_models_test.go (about) 1 package validatemodels 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/spf13/cobra" 12 "github.com/spf13/viper" 13 "github.com/stretchr/testify/require" 14 15 "github.com/openfga/openfga/cmd" 16 "github.com/openfga/openfga/cmd/util" 17 "github.com/openfga/openfga/pkg/typesystem" 18 ) 19 20 func TestValidationResult(t *testing.T) { 21 engines := []string{"postgres", "mysql"} 22 23 totalStores := 200 24 totalModelsForOneStore := 200 25 26 for _, engine := range engines { 27 t.Run(engine, func(t *testing.T) { 28 _, ds, _ := util.MustBootstrapDatastore(t, engine) 29 30 ctx := context.Background() 31 32 // write a bunch of stores (to trigger pagination) 33 var storeID string 34 for i := 0; i < totalStores; i++ { 35 storeID = ulid.Make().String() 36 _, err := ds.CreateStore(ctx, &openfgav1.Store{ 37 Id: storeID, 38 Name: fmt.Sprintf("store-%d", i), 39 }) 40 require.NoError(t, err) 41 t.Logf("added store %s\n", storeID) 42 } 43 44 // for the last store, write a bunch of models (to trigger pagination) 45 for j := 0; j < totalModelsForOneStore; j++ { 46 modelID := ulid.Make().String() 47 err := ds.WriteAuthorizationModel(ctx, storeID, &openfgav1.AuthorizationModel{ 48 Id: modelID, 49 SchemaVersion: typesystem.SchemaVersion1_1, 50 // invalid 51 TypeDefinitions: parser.MustTransformDSLToProto(`model 52 schema 1.1 53 type document 54 relations 55 define viewer:[user] 56 `).GetTypeDefinitions(), 57 }) 58 require.NoError(t, err) 59 t.Logf("added model %s for store %s\n", modelID, storeID) 60 } 61 62 t.Run("validate returns success", func(t *testing.T) { 63 validationResults, err := ValidateAllAuthorizationModels(ctx, ds) 64 require.NoError(t, err) 65 require.Len(t, validationResults, totalModelsForOneStore) 66 require.Contains(t, "the relation type 'user' on 'viewer' in object type 'document' is not valid", validationResults[0].Error) 67 require.True(t, validationResults[0].IsLatestModel) 68 69 require.Contains(t, "the relation type 'user' on 'viewer' in object type 'document' is not valid", validationResults[1].Error) 70 require.False(t, validationResults[1].IsLatestModel) 71 }) 72 }) 73 } 74 } 75 76 func TestValidateModelsCommandWhenInvalidEngine(t *testing.T) { 77 for _, tc := range []struct { 78 engine string 79 errorExpected string 80 }{ 81 { 82 engine: "memory", 83 errorExpected: "storage engine 'memory' is unsupported", 84 }, 85 { 86 engine: "", 87 errorExpected: "missing datastore engine type", 88 }, 89 } { 90 t.Run(tc.engine, func(t *testing.T) { 91 validateModelsCommand := NewValidateCommand() 92 validateModelsCommand.SetArgs([]string{"--datastore-engine", tc.engine, "--datastore-uri", ""}) 93 err := validateModelsCommand.Execute() 94 require.ErrorContains(t, err, tc.errorExpected) 95 }) 96 } 97 } 98 99 func TestValidateModelsCommandNoConfigDefaultValues(t *testing.T) { 100 util.PrepareTempConfigDir(t) 101 validateCommand := NewValidateCommand() 102 validateCommand.RunE = func(cmd *cobra.Command, _ []string) error { 103 require.Equal(t, "", viper.GetString(datastoreEngineFlag)) 104 require.Equal(t, "", viper.GetString(datastoreURIFlag)) 105 return nil 106 } 107 108 cmd := cmd.NewRootCommand() 109 cmd.AddCommand(validateCommand) 110 cmd.SetArgs([]string{"validate-models"}) 111 require.NoError(t, cmd.Execute()) 112 } 113 114 func TestValidateModelsCommandConfigFileValuesAreParsed(t *testing.T) { 115 config := `datastore: 116 engine: someEngine 117 uri: postgres://postgres:password@127.0.0.1:5432/postgres 118 ` 119 util.PrepareTempConfigFile(t, config) 120 121 validateCmd := NewValidateCommand() 122 validateCmd.RunE = func(cmd *cobra.Command, _ []string) error { 123 require.Equal(t, "someEngine", viper.GetString(datastoreEngineFlag)) 124 require.Equal(t, "postgres://postgres:password@127.0.0.1:5432/postgres", viper.GetString(datastoreURIFlag)) 125 return nil 126 } 127 128 cmd := cmd.NewRootCommand() 129 cmd.AddCommand(validateCmd) 130 cmd.SetArgs([]string{"validate-models"}) 131 require.NoError(t, cmd.Execute()) 132 } 133 134 func TestValidateModelsCommandConfigIsMerged(t *testing.T) { 135 config := `datastore: 136 engine: anotherEngine 137 ` 138 util.PrepareTempConfigFile(t, config) 139 140 t.Setenv("OPENFGA_DATASTORE_URI", "postgres://postgres:PASS2@127.0.0.1:5432/postgres") 141 142 validateCmd := NewValidateCommand() 143 validateCmd.RunE = func(cmd *cobra.Command, _ []string) error { 144 require.Equal(t, "anotherEngine", viper.GetString(datastoreEngineFlag)) 145 require.Equal(t, "postgres://postgres:PASS2@127.0.0.1:5432/postgres", viper.GetString(datastoreURIFlag)) 146 return nil 147 } 148 149 cmd := cmd.NewRootCommand() 150 cmd.AddCommand(validateCmd) 151 cmd.SetArgs([]string{"validate-models"}) 152 require.NoError(t, cmd.Execute()) 153 }