github.com/gigforks/mattermost-server@v4.9.1-0.20180619094218-800d97fa55d0+incompatible/utils/config_test.go (about) 1 // Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package utils 5 6 import ( 7 "bytes" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "strings" 12 "testing" 13 14 "github.com/stretchr/testify/assert" 15 "github.com/stretchr/testify/require" 16 17 "github.com/mattermost/mattermost-server/model" 18 ) 19 20 func TestConfig(t *testing.T) { 21 TranslationsPreInit() 22 _, _, _, err := LoadConfig("config.json") 23 require.Nil(t, err) 24 } 25 26 func TestReadConfig(t *testing.T) { 27 TranslationsPreInit() 28 29 _, _, err := ReadConfig(bytes.NewReader([]byte(``)), false) 30 require.EqualError(t, err, "parsing error at line 1, character 1: unexpected end of JSON input") 31 32 _, _, err = ReadConfig(bytes.NewReader([]byte(` 33 { 34 malformed 35 `)), false) 36 require.EqualError(t, err, "parsing error at line 3, character 5: invalid character 'm' looking for beginning of object key string") 37 } 38 39 func TestTimezoneConfig(t *testing.T) { 40 TranslationsPreInit() 41 supportedTimezones := LoadTimezones("timezones.json") 42 assert.Equal(t, len(supportedTimezones) > 0, true) 43 44 supportedTimezones2 := LoadTimezones("timezones_file_does_not_exists.json") 45 assert.Equal(t, len(supportedTimezones2) > 0, true) 46 } 47 48 func TestFindConfigFile(t *testing.T) { 49 dir, err := ioutil.TempDir("", "") 50 require.NoError(t, err) 51 defer os.RemoveAll(dir) 52 53 path := filepath.Join(dir, "config.json") 54 require.NoError(t, ioutil.WriteFile(path, []byte("{}"), 0600)) 55 56 assert.Equal(t, path, FindConfigFile(path)) 57 58 prevDir, err := os.Getwd() 59 require.NoError(t, err) 60 defer os.Chdir(prevDir) 61 os.Chdir(dir) 62 assert.Equal(t, path, FindConfigFile(path)) 63 } 64 65 func TestConfigFromEnviroVars(t *testing.T) { 66 TranslationsPreInit() 67 68 config := `{ 69 "ServiceSettings": { 70 "EnableCommands": true, 71 "ReadTimeout": 100 72 }, 73 "TeamSettings": { 74 "SiteName": "Mattermost", 75 "CustomBrandText": "" 76 } 77 }` 78 79 t.Run("string settings", func(t *testing.T) { 80 os.Setenv("MM_TEAMSETTINGS_SITENAME", "From Environment") 81 os.Setenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT", "Custom Brand") 82 83 cfg, envCfg, err := ReadConfig(strings.NewReader(config), true) 84 require.Nil(t, err) 85 86 if cfg.TeamSettings.SiteName != "From Environment" { 87 t.Fatal("Couldn't read config from environment var") 88 } 89 90 if *cfg.TeamSettings.CustomBrandText != "Custom Brand" { 91 t.Fatal("Couldn't read config from environment var") 92 } 93 94 if teamSettings, ok := envCfg["TeamSettings"]; !ok { 95 t.Fatal("TeamSettings is missing from envConfig") 96 } else if teamSettingsAsMap, ok := teamSettings.(map[string]interface{}); !ok { 97 t.Fatal("TeamSettings is not a map in envConfig") 98 } else { 99 if siteNameInEnv, ok := teamSettingsAsMap["SiteName"].(bool); !ok || !siteNameInEnv { 100 t.Fatal("SiteName should be in envConfig") 101 } 102 103 if customBrandTextInEnv, ok := teamSettingsAsMap["CustomBrandText"].(bool); !ok || !customBrandTextInEnv { 104 t.Fatal("SiteName should be in envConfig") 105 } 106 } 107 108 os.Unsetenv("MM_TEAMSETTINGS_SITENAME") 109 os.Unsetenv("MM_TEAMSETTINGS_CUSTOMBRANDTEXT") 110 111 cfg, envCfg, err = ReadConfig(strings.NewReader(config), true) 112 require.Nil(t, err) 113 114 if cfg.TeamSettings.SiteName != "Mattermost" { 115 t.Fatal("should have been reset") 116 } 117 118 if _, ok := envCfg["TeamSettings"]; ok { 119 t.Fatal("TeamSettings should be missing from envConfig") 120 } 121 }) 122 123 t.Run("boolean setting", func(t *testing.T) { 124 os.Setenv("MM_SERVICESETTINGS_ENABLECOMMANDS", "false") 125 defer os.Unsetenv("MM_SERVICESETTINGS_ENABLECOMMANDS") 126 127 cfg, envCfg, err := ReadConfig(strings.NewReader(config), true) 128 require.Nil(t, err) 129 130 if *cfg.ServiceSettings.EnableCommands { 131 t.Fatal("Couldn't read config from environment var") 132 } 133 134 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 135 t.Fatal("ServiceSettings is missing from envConfig") 136 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 137 t.Fatal("ServiceSettings is not a map in envConfig") 138 } else { 139 if enableCommandsInEnv, ok := serviceSettingsAsMap["EnableCommands"].(bool); !ok || !enableCommandsInEnv { 140 t.Fatal("EnableCommands should be in envConfig") 141 } 142 } 143 }) 144 145 t.Run("integer setting", func(t *testing.T) { 146 os.Setenv("MM_SERVICESETTINGS_READTIMEOUT", "400") 147 defer os.Unsetenv("MM_SERVICESETTINGS_READTIMEOUT") 148 149 cfg, envCfg, err := ReadConfig(strings.NewReader(config), true) 150 require.Nil(t, err) 151 152 if *cfg.ServiceSettings.ReadTimeout != 400 { 153 t.Fatal("Couldn't read config from environment var") 154 } 155 156 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 157 t.Fatal("ServiceSettings is missing from envConfig") 158 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 159 t.Fatal("ServiceSettings is not a map in envConfig") 160 } else { 161 if readTimeoutInEnv, ok := serviceSettingsAsMap["ReadTimeout"].(bool); !ok || !readTimeoutInEnv { 162 t.Fatal("ReadTimeout should be in envConfig") 163 } 164 } 165 }) 166 167 t.Run("setting missing from config.json", func(t *testing.T) { 168 os.Setenv("MM_SERVICESETTINGS_SITEURL", "https://example.com") 169 defer os.Unsetenv("MM_SERVICESETTINGS_SITEURL") 170 171 cfg, envCfg, err := ReadConfig(strings.NewReader(config), true) 172 require.Nil(t, err) 173 174 if *cfg.ServiceSettings.SiteURL != "https://example.com" { 175 t.Fatal("Couldn't read config from environment var") 176 } 177 178 if serviceSettings, ok := envCfg["ServiceSettings"]; !ok { 179 t.Fatal("ServiceSettings is missing from envConfig") 180 } else if serviceSettingsAsMap, ok := serviceSettings.(map[string]interface{}); !ok { 181 t.Fatal("ServiceSettings is not a map in envConfig") 182 } else { 183 if siteURLInEnv, ok := serviceSettingsAsMap["SiteURL"].(bool); !ok || !siteURLInEnv { 184 t.Fatal("SiteURL should be in envConfig") 185 } 186 } 187 }) 188 } 189 190 func TestValidateLocales(t *testing.T) { 191 TranslationsPreInit() 192 cfg, _, _, err := LoadConfig("config.json") 193 require.Nil(t, err) 194 195 *cfg.LocalizationSettings.DefaultServerLocale = "en" 196 *cfg.LocalizationSettings.DefaultClientLocale = "en" 197 *cfg.LocalizationSettings.AvailableLocales = "" 198 199 // t.Logf("*cfg.LocalizationSettings.DefaultClientLocale: %+v", *cfg.LocalizationSettings.DefaultClientLocale) 200 if err := ValidateLocales(cfg); err != nil { 201 t.Fatal("Should have not returned an error") 202 } 203 204 // validate DefaultServerLocale 205 *cfg.LocalizationSettings.DefaultServerLocale = "junk" 206 if err := ValidateLocales(cfg); err != nil { 207 if *cfg.LocalizationSettings.DefaultServerLocale != "en" { 208 t.Fatal("DefaultServerLocale should have assigned to en as a default value") 209 } 210 } else { 211 t.Fatal("Should have returned an error validating DefaultServerLocale") 212 } 213 214 *cfg.LocalizationSettings.DefaultServerLocale = "" 215 if err := ValidateLocales(cfg); err != nil { 216 if *cfg.LocalizationSettings.DefaultServerLocale != "en" { 217 t.Fatal("DefaultServerLocale should have assigned to en as a default value") 218 } 219 } else { 220 t.Fatal("Should have returned an error validating DefaultServerLocale") 221 } 222 223 *cfg.LocalizationSettings.AvailableLocales = "en" 224 *cfg.LocalizationSettings.DefaultServerLocale = "de" 225 if err := ValidateLocales(cfg); err != nil { 226 if strings.Contains(*cfg.LocalizationSettings.AvailableLocales, *cfg.LocalizationSettings.DefaultServerLocale) { 227 t.Fatal("DefaultServerLocale should not be added to AvailableLocales") 228 } 229 t.Fatal("Should have not returned an error validating DefaultServerLocale") 230 } 231 232 // validate DefaultClientLocale 233 *cfg.LocalizationSettings.AvailableLocales = "" 234 *cfg.LocalizationSettings.DefaultClientLocale = "junk" 235 if err := ValidateLocales(cfg); err != nil { 236 if *cfg.LocalizationSettings.DefaultClientLocale != "en" { 237 t.Fatal("DefaultClientLocale should have assigned to en as a default value") 238 } 239 } else { 240 241 t.Fatal("Should have returned an error validating DefaultClientLocale") 242 } 243 244 *cfg.LocalizationSettings.DefaultClientLocale = "" 245 if err := ValidateLocales(cfg); err != nil { 246 if *cfg.LocalizationSettings.DefaultClientLocale != "en" { 247 t.Fatal("DefaultClientLocale should have assigned to en as a default value") 248 } 249 } else { 250 t.Fatal("Should have returned an error validating DefaultClientLocale") 251 } 252 253 *cfg.LocalizationSettings.AvailableLocales = "en" 254 *cfg.LocalizationSettings.DefaultClientLocale = "de" 255 if err := ValidateLocales(cfg); err != nil { 256 if !strings.Contains(*cfg.LocalizationSettings.AvailableLocales, *cfg.LocalizationSettings.DefaultClientLocale) { 257 t.Fatal("DefaultClientLocale should have added to AvailableLocales") 258 } 259 } else { 260 t.Fatal("Should have returned an error validating DefaultClientLocale") 261 } 262 263 // validate AvailableLocales 264 *cfg.LocalizationSettings.DefaultServerLocale = "en" 265 *cfg.LocalizationSettings.DefaultClientLocale = "en" 266 *cfg.LocalizationSettings.AvailableLocales = "junk" 267 if err := ValidateLocales(cfg); err != nil { 268 if *cfg.LocalizationSettings.AvailableLocales != "" { 269 t.Fatal("AvailableLocales should have assigned to empty string as a default value") 270 } 271 } else { 272 t.Fatal("Should have returned an error validating AvailableLocales") 273 } 274 275 *cfg.LocalizationSettings.AvailableLocales = "en,de,junk" 276 if err := ValidateLocales(cfg); err != nil { 277 if *cfg.LocalizationSettings.AvailableLocales != "" { 278 t.Fatal("AvailableLocales should have assigned to empty string as a default value") 279 } 280 } else { 281 t.Fatal("Should have returned an error validating AvailableLocales") 282 } 283 284 *cfg.LocalizationSettings.DefaultServerLocale = "fr" 285 *cfg.LocalizationSettings.DefaultClientLocale = "de" 286 *cfg.LocalizationSettings.AvailableLocales = "en" 287 if err := ValidateLocales(cfg); err != nil { 288 if strings.Contains(*cfg.LocalizationSettings.AvailableLocales, *cfg.LocalizationSettings.DefaultServerLocale) { 289 t.Fatal("DefaultServerLocale should not be added to AvailableLocales") 290 } 291 if !strings.Contains(*cfg.LocalizationSettings.AvailableLocales, *cfg.LocalizationSettings.DefaultClientLocale) { 292 t.Fatal("DefaultClientLocale should have added to AvailableLocales") 293 } 294 } else { 295 t.Fatal("Should have returned an error validating AvailableLocales") 296 } 297 } 298 299 func TestGetClientConfig(t *testing.T) { 300 t.Parallel() 301 testCases := []struct { 302 description string 303 config *model.Config 304 diagnosticId string 305 license *model.License 306 expectedFields map[string]string 307 }{ 308 { 309 "unlicensed", 310 &model.Config{ 311 EmailSettings: model.EmailSettings{ 312 EmailNotificationContentsType: sToP(model.EMAIL_NOTIFICATION_CONTENTS_FULL), 313 }, 314 ThemeSettings: model.ThemeSettings{ 315 // Ignored, since not licensed. 316 AllowCustomThemes: bToP(false), 317 }, 318 }, 319 "", 320 nil, 321 map[string]string{ 322 "DiagnosticId": "", 323 "EmailNotificationContentsType": "full", 324 "AllowCustomThemes": "true", 325 }, 326 }, 327 { 328 "licensed, but not for theme management", 329 &model.Config{ 330 EmailSettings: model.EmailSettings{ 331 EmailNotificationContentsType: sToP(model.EMAIL_NOTIFICATION_CONTENTS_FULL), 332 }, 333 ThemeSettings: model.ThemeSettings{ 334 // Ignored, since not licensed. 335 AllowCustomThemes: bToP(false), 336 }, 337 }, 338 "tag1", 339 &model.License{ 340 Features: &model.Features{ 341 ThemeManagement: bToP(false), 342 }, 343 }, 344 map[string]string{ 345 "DiagnosticId": "tag1", 346 "EmailNotificationContentsType": "full", 347 "AllowCustomThemes": "true", 348 }, 349 }, 350 { 351 "licensed for theme management", 352 &model.Config{ 353 EmailSettings: model.EmailSettings{ 354 EmailNotificationContentsType: sToP(model.EMAIL_NOTIFICATION_CONTENTS_FULL), 355 }, 356 ThemeSettings: model.ThemeSettings{ 357 AllowCustomThemes: bToP(false), 358 }, 359 }, 360 "tag2", 361 &model.License{ 362 Features: &model.Features{ 363 ThemeManagement: bToP(true), 364 }, 365 }, 366 map[string]string{ 367 "DiagnosticId": "tag2", 368 "EmailNotificationContentsType": "full", 369 "AllowCustomThemes": "false", 370 }, 371 }, 372 } 373 374 for _, testCase := range testCases { 375 testCase := testCase 376 t.Run(testCase.description, func(t *testing.T) { 377 t.Parallel() 378 379 testCase.config.SetDefaults() 380 if testCase.license != nil { 381 testCase.license.Features.SetDefaults() 382 } 383 384 configMap := GenerateClientConfig(testCase.config, testCase.diagnosticId, testCase.license) 385 for expectedField, expectedValue := range testCase.expectedFields { 386 assert.Equal(t, expectedValue, configMap[expectedField]) 387 } 388 }) 389 } 390 } 391 392 func sToP(s string) *string { 393 return &s 394 } 395 396 func bToP(b bool) *bool { 397 return &b 398 } 399 400 func TestGetDefaultsFromStruct(t *testing.T) { 401 s := struct { 402 TestSettings struct { 403 IntValue int 404 BoolValue bool 405 StringValue string 406 } 407 PointerToTestSettings *struct { 408 Value int 409 } 410 }{} 411 412 defaults := getDefaultsFromStruct(s) 413 414 assert.Equal(t, defaults["TestSettings.IntValue"], 0) 415 assert.Equal(t, defaults["TestSettings.BoolValue"], false) 416 assert.Equal(t, defaults["TestSettings.StringValue"], "") 417 assert.Equal(t, defaults["PointerToTestSettings.Value"], 0) 418 assert.NotContains(t, defaults, "PointerToTestSettings") 419 assert.Len(t, defaults, 4) 420 }