Files
mattermost/config/database_test.go
Christopher Poile 7f7f511d1c MM-11697: Environment overrides do not overwrite config.json on save (#10413)
* MM-11697: Environment overrides do not overwrite config.json on save
#10388

The config store now keeps a copy of the config as loaded from the store
without environment overrides. Whenever persisting, we now check if the
current setting is different from the loaded setting. If it is, then use
the loaded setting instead.

As described in the comments to `removeEnvOverrides` in `common.go`,
this behavior will have to change if we ever let the user change a
setting that has been environmentally overriden.

This was interesting because the `load` function in `common.go` also
persists, so we have to tee the provided `io.ReadCloser` and construct a
config that doesn't have the environment overrides. And then we have to
find the path to the (maybe) changed variable in the config struct
using reflection.

Possible WIP: I had to expose a `GetWithoutEnvOverrides` function in the
Store interface just for the tests -- this is because the `file_test`
and `database_test`s are in the config_test package instead of the
`config` package.

* added function documentation

* fixed a small problem with tests

* MM-11697: big cleanup based on Jesse's PR comments

* MM-11697: edits per PR feedback

* MM-11697: licence header

* MM-11697: now testing that on disk config is not changed by env
overrides

* MM-11697: remove unneeded exports
2019-03-26 13:28:41 -07:00

691 lines
20 KiB
Go

// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
package config_test
import (
"bytes"
"fmt"
"net/url"
"os"
"strings"
"testing"
"time"
"github.com/jmoiron/sqlx"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"github.com/mattermost/mattermost-server/config"
"github.com/mattermost/mattermost-server/model"
)
func setupConfigDatabase(t *testing.T, cfg *model.Config, files map[string][]byte) (string, func()) {
t.Helper()
os.Clearenv()
truncateTables(t)
cfgData, err := config.MarshalConfig(cfg)
require.NoError(t, err)
db := sqlx.NewDb(mainHelper.GetSqlSupplier().GetMaster().Db, *mainHelper.GetSqlSettings().DriverName)
err = config.InitializeConfigurationsTable(db)
require.NoError(t, err)
id := model.NewId()
_, err = db.NamedExec("INSERT INTO Configurations (Id, Value, CreateAt, Active) VALUES(:Id, :Value, :CreateAt, TRUE)", map[string]interface{}{
"Id": id,
"Value": cfgData,
"CreateAt": model.GetMillis(),
})
require.NoError(t, err)
for name, data := range files {
params := map[string]interface{}{
"name": name,
"data": data,
"create_at": model.GetMillis(),
"update_at": model.GetMillis(),
}
_, err = db.NamedExec("INSERT INTO ConfigurationFiles (Name, Data, CreateAt, UpdateAt) VALUES (:name, :data, :create_at, :update_at)", params)
require.NoError(t, err)
}
return id, func() {
truncateTables(t)
}
}
// getActualDatabaseConfig returns the active configuration in the database without relying on a config store.
func getActualDatabaseConfig(t *testing.T) (string, *model.Config) {
t.Helper()
var actual struct {
Id string `db:"Id"`
Value []byte `db:"Value"`
}
db := sqlx.NewDb(mainHelper.GetSqlSupplier().GetMaster().Db, *mainHelper.GetSqlSettings().DriverName)
err := db.Get(&actual, "SELECT Id, Value FROM Configurations WHERE Active")
require.NoError(t, err)
actualCfg, _, err := config.UnmarshalConfig(bytes.NewReader(actual.Value), false)
require.Nil(t, err)
return actual.Id, actualCfg
}
// assertDatabaseEqualsConfig verifies the active in-database configuration equals the given config.
func assertDatabaseEqualsConfig(t *testing.T, expectedCfg *model.Config) {
t.Helper()
expectedCfg = prepareExpectedConfig(t, expectedCfg)
_, actualCfg := getActualDatabaseConfig(t)
assert.Equal(t, expectedCfg, actualCfg)
}
// assertDatabaseNotEqualsConfig verifies the in-database configuration does not equal the given config.
func assertDatabaseNotEqualsConfig(t *testing.T, expectedCfg *model.Config) {
t.Helper()
expectedCfg = prepareExpectedConfig(t, expectedCfg)
_, actualCfg := getActualDatabaseConfig(t)
assert.NotEqual(t, expectedCfg, actualCfg)
}
func TestDatabaseStoreNew(t *testing.T) {
sqlSettings := mainHelper.GetSqlSettings()
t.Run("no existing configuration - initialization required", func(t *testing.T) {
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
})
t.Run("existing config, initialization required", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, testConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, "http://TestStoreNew", *ds.Get().ServiceSettings.SiteURL)
assertDatabaseNotEqualsConfig(t, testConfig)
})
t.Run("already minimally configured", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, "http://minimal", *ds.Get().ServiceSettings.SiteURL)
assertDatabaseEqualsConfig(t, minimalConfig)
})
t.Run("invalid url", func(t *testing.T) {
_, err := config.NewDatabaseStore("")
require.Error(t, err)
})
t.Run("unsupported scheme", func(t *testing.T) {
_, err := config.NewDatabaseStore("invalid")
require.Error(t, err)
})
}
func TestDatabaseStoreGet(t *testing.T) {
_, tearDown := setupConfigDatabase(t, testConfig, nil)
defer tearDown()
sqlSettings := mainHelper.GetSqlSettings()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
cfg := ds.Get()
assert.Equal(t, "http://TestStoreNew", *cfg.ServiceSettings.SiteURL)
cfg2 := ds.Get()
assert.Equal(t, "http://TestStoreNew", *cfg.ServiceSettings.SiteURL)
assert.True(t, cfg == cfg2, "Get() returned different configuration instances")
newCfg := &model.Config{}
oldCfg, err := ds.Set(newCfg)
require.NoError(t, err)
assert.True(t, oldCfg == cfg, "returned config after set() changed original")
assert.False(t, newCfg == cfg, "returned config should have been different from original")
}
func TestDatabaseStoreGetEnivironmentOverrides(t *testing.T) {
_, tearDown := setupConfigDatabase(t, testConfig, nil)
defer tearDown()
sqlSettings := mainHelper.GetSqlSettings()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, "http://TestStoreNew", *ds.Get().ServiceSettings.SiteURL)
assert.Empty(t, ds.GetEnvironmentOverrides())
os.Setenv("MM_SERVICESETTINGS_SITEURL", "http://override")
ds, err = config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, "http://override", *ds.Get().ServiceSettings.SiteURL)
assert.Equal(t, map[string]interface{}{"ServiceSettings": map[string]interface{}{"SiteURL": true}}, ds.GetEnvironmentOverrides())
}
func TestDatabaseStoreSet(t *testing.T) {
sqlSettings := mainHelper.GetSqlSettings()
t.Run("set same pointer value", func(t *testing.T) {
t.Skip("not yet implemented")
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
_, err = ds.Set(ds.Get())
if assert.Error(t, err) {
assert.EqualError(t, err, "old configuration modified instead of cloning")
}
})
t.Run("defaults required", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
oldCfg := ds.Get()
newCfg := &model.Config{}
retCfg, err := ds.Set(newCfg)
require.NoError(t, err)
assert.Equal(t, oldCfg, retCfg)
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
})
t.Run("desanitization required", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, ldapConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
oldCfg := ds.Get()
newCfg := &model.Config{}
newCfg.LdapSettings.BindPassword = sToP(model.FAKE_SETTING)
retCfg, err := ds.Set(newCfg)
require.NoError(t, err)
assert.Equal(t, oldCfg, retCfg)
assert.Equal(t, "password", *ds.Get().LdapSettings.BindPassword)
})
t.Run("invalid", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
newCfg := &model.Config{}
newCfg.ServiceSettings.SiteURL = sToP("invalid")
_, err = ds.Set(newCfg)
if assert.Error(t, err) {
assert.EqualError(t, err, "new configuration is invalid: Config.IsValid: model.config.is_valid.site_url.app_error, ")
}
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
})
t.Run("duplicate ignored", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
_, err = ds.Set(ds.Get())
require.NoError(t, err)
beforeId, _ := getActualDatabaseConfig(t)
_, err = ds.Set(ds.Get())
require.NoError(t, err)
afterId, _ := getActualDatabaseConfig(t)
assert.Equal(t, beforeId, afterId, "new record should not have been written")
})
t.Run("read-only ignored", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, readOnlyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
newCfg := &model.Config{
ServiceSettings: model.ServiceSettings{
SiteURL: sToP("http://new"),
},
}
_, err = ds.Set(newCfg)
require.NoError(t, err)
assert.Equal(t, "http://new", *ds.Get().ServiceSettings.SiteURL)
})
t.Run("set with automatic save", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
newCfg := &model.Config{
ServiceSettings: model.ServiceSettings{
SiteURL: sToP("http://new"),
},
}
_, err = ds.Set(newCfg)
require.NoError(t, err)
err = ds.Load()
require.NoError(t, err)
assert.Equal(t, "http://new", *ds.Get().ServiceSettings.SiteURL)
})
t.Run("persist failed", func(t *testing.T) {
t.Skip("skipping persistence test inside Set")
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
db := sqlx.NewDb(mainHelper.GetSqlSupplier().GetMaster().Db, *sqlSettings.DriverName)
_, err = db.Exec("DROP TABLE Configurations")
require.NoError(t, err)
newCfg := &model.Config{}
_, err = ds.Set(newCfg)
if assert.Error(t, err) {
assert.True(t, strings.HasPrefix(err.Error(), "failed to persist: failed to write to database"))
}
assert.Equal(t, model.SERVICE_SETTINGS_DEFAULT_SITE_URL, *ds.Get().ServiceSettings.SiteURL)
})
t.Run("listeners notified", func(t *testing.T) {
activeId, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
oldCfg := ds.Get()
called := make(chan bool, 1)
callback := func(oldfg, newCfg *model.Config) {
called <- true
}
ds.AddListener(callback)
newCfg := &model.Config{}
retCfg, err := ds.Set(newCfg)
require.NoError(t, err)
assert.Equal(t, oldCfg, retCfg)
id, _ := getActualDatabaseConfig(t)
assert.NotEqual(t, activeId, id, "new record should have been written")
select {
case <-called:
case <-time.After(5 * time.Second):
t.Fatal("callback should have been called when config written")
}
})
}
func TestDatabaseStoreLoad(t *testing.T) {
sqlSettings := mainHelper.GetSqlSettings()
t.Run("active configuration no longer exists", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
truncateTables(t)
err = ds.Load()
require.NoError(t, err)
assertDatabaseNotEqualsConfig(t, emptyConfig)
})
t.Run("honour environment", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
assert.Equal(t, "http://minimal", *ds.Get().ServiceSettings.SiteURL)
os.Setenv("MM_SERVICESETTINGS_SITEURL", "http://override")
err = ds.Load()
require.NoError(t, err)
assert.Equal(t, "http://override", *ds.Get().ServiceSettings.SiteURL)
assert.Equal(t, map[string]interface{}{"ServiceSettings": map[string]interface{}{"SiteURL": true}}, ds.GetEnvironmentOverrides())
})
t.Run("do not persist environment variables", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
os.Setenv("MM_SERVICESETTINGS_SITEURL", "http://overridePersistEnvVariables")
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
_, err = ds.Set(ds.Get())
require.NoError(t, err)
assert.Equal(t, "http://overridePersistEnvVariables", *ds.Get().ServiceSettings.SiteURL)
assert.Equal(t, map[string]interface{}{"ServiceSettings": map[string]interface{}{"SiteURL": true}}, ds.GetEnvironmentOverrides())
// check that in DB config does not include overwritten variable
_, actualConfig := getActualDatabaseConfig(t)
assert.Equal(t, "http://minimal", *actualConfig.ServiceSettings.SiteURL)
})
t.Run("invalid", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
cfgData, err := config.MarshalConfig(invalidConfig)
require.NoError(t, err)
db := sqlx.NewDb(mainHelper.GetSqlSupplier().GetMaster().Db, *sqlSettings.DriverName)
truncateTables(t)
id := model.NewId()
_, err = db.NamedExec("INSERT INTO Configurations (Id, Value, CreateAt, Active) VALUES(:Id, :Value, :CreateAt, TRUE)", map[string]interface{}{
"Id": id,
"Value": cfgData,
"CreateAt": model.GetMillis(),
})
require.NoError(t, err)
err = ds.Load()
if assert.Error(t, err) {
assert.EqualError(t, err, "invalid config: Config.IsValid: model.config.is_valid.site_url.app_error, ")
}
})
t.Run("fixes required", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, fixesRequiredConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
err = ds.Load()
require.NoError(t, err)
assertDatabaseNotEqualsConfig(t, fixesRequiredConfig)
assert.Equal(t, "http://trailingslash", *ds.Get().ServiceSettings.SiteURL)
})
t.Run("listeners notifed", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
called := make(chan bool, 1)
callback := func(oldfg, newCfg *model.Config) {
called <- true
}
ds.AddListener(callback)
err = ds.Load()
require.NoError(t, err)
select {
case <-called:
case <-time.After(5 * time.Second):
t.Fatal("callback should have been called when config loaded")
}
})
}
func TestDatabaseGetFile(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, map[string][]byte{
"empty-file": []byte{},
"test-file": []byte("test"),
})
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
t.Run("get empty filename", func(t *testing.T) {
_, err := ds.GetFile("")
require.Error(t, err)
})
t.Run("get non-existent file", func(t *testing.T) {
_, err := ds.GetFile("unknown")
require.Error(t, err)
})
t.Run("get empty file", func(t *testing.T) {
data, err := ds.GetFile("empty-file")
require.NoError(t, err)
require.Empty(t, data)
})
t.Run("get non-empty file", func(t *testing.T) {
data, err := ds.GetFile("test-file")
require.NoError(t, err)
require.Equal(t, []byte("test"), data)
})
}
func TestDatabaseSetFile(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
t.Run("set new file", func(t *testing.T) {
err := ds.SetFile("new", []byte("new file"))
require.NoError(t, err)
data, err := ds.GetFile("new")
require.NoError(t, err)
require.Equal(t, []byte("new file"), data)
})
t.Run("overwrite existing file", func(t *testing.T) {
err := ds.SetFile("existing", []byte("existing file"))
require.NoError(t, err)
err = ds.SetFile("existing", []byte("overwritten file"))
require.NoError(t, err)
data, err := ds.GetFile("existing")
require.NoError(t, err)
require.Equal(t, []byte("overwritten file"), data)
})
}
func TestDatabaseHasFile(t *testing.T) {
t.Run("has non-existent", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
has, err := ds.HasFile("non-existent")
require.NoError(t, err)
require.False(t, has)
})
t.Run("has existing", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
err = ds.SetFile("existing", []byte("existing file"))
require.NoError(t, err)
has, err := ds.HasFile("existing")
require.NoError(t, err)
require.True(t, has)
})
t.Run("has manually created file", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, map[string][]byte{
"manual": []byte("manual file"),
})
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
has, err := ds.HasFile("manual")
require.NoError(t, err)
require.True(t, has)
})
}
func TestDatabaseRemoveFile(t *testing.T) {
t.Run("remove non-existent", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
err = ds.RemoveFile("non-existent")
require.NoError(t, err)
})
t.Run("remove existing", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, nil)
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
err = ds.SetFile("existing", []byte("existing file"))
require.NoError(t, err)
err = ds.RemoveFile("existing")
require.NoError(t, err)
has, err := ds.HasFile("existing")
require.NoError(t, err)
require.False(t, has)
_, err = ds.GetFile("existing")
require.Error(t, err)
})
t.Run("remove manually created file", func(t *testing.T) {
_, tearDown := setupConfigDatabase(t, minimalConfig, map[string][]byte{
"manual": []byte("manual file"),
})
defer tearDown()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *mainHelper.Settings.DriverName, *mainHelper.Settings.DataSource))
require.NoError(t, err)
defer ds.Close()
err = ds.RemoveFile("manual")
require.NoError(t, err)
has, err := ds.HasFile("manual")
require.NoError(t, err)
require.False(t, has)
_, err = ds.GetFile("manual")
require.Error(t, err)
})
}
func TestDatabaseStoreString(t *testing.T) {
_, tearDown := setupConfigDatabase(t, emptyConfig, nil)
defer tearDown()
sqlSettings := mainHelper.GetSqlSettings()
ds, err := config.NewDatabaseStore(fmt.Sprintf("%s://%s", *sqlSettings.DriverName, *sqlSettings.DataSource))
require.NoError(t, err)
defer ds.Close()
actualStringURL, err := url.Parse(ds.String())
require.NoError(t, err)
assert.Equal(t, *sqlSettings.DriverName, actualStringURL.Scheme)
actualUsername := actualStringURL.User.Username()
actualPassword, _ := actualStringURL.User.Password()
assert.NotEmpty(t, actualUsername)
assert.Empty(t, actualPassword, "should mask password")
}