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  }