From 5fac4058e8cbc9ef8484b2ddaaf583574684dded Mon Sep 17 00:00:00 2001 From: Aleksey Savchuk Date: Tue, 10 Sep 2024 12:14:46 +0300 Subject: [PATCH] [#1364] cmd/common: Add tests for CreateViper and ReloadViper Add tests for `CreateViper` and `ReloadViper` to ensure that no extra files, except *.yaml, *.yml, *.json, are loaded from config directory. Signed-off-by: Aleksey Savchuk --- cmd/internal/common/config/viper_test.go | 107 +++++++++++++++++++++++ pkg/util/config/test/generate.go | 58 ++++++++++++ 2 files changed, 165 insertions(+) create mode 100644 cmd/internal/common/config/viper_test.go create mode 100644 pkg/util/config/test/generate.go diff --git a/cmd/internal/common/config/viper_test.go b/cmd/internal/common/config/viper_test.go new file mode 100644 index 000000000..d533a15c2 --- /dev/null +++ b/cmd/internal/common/config/viper_test.go @@ -0,0 +1,107 @@ +package config_test + +import ( + "encoding/json" + "os" + "path" + "testing" + + "git.frostfs.info/TrueCloudLab/frostfs-node/cmd/internal/common/config" + configtest "git.frostfs.info/TrueCloudLab/frostfs-node/pkg/util/config/test" + "github.com/spf13/viper" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gopkg.in/yaml.v3" +) + +func TestCreateReloadViper(t *testing.T) { + type m = map[string]any + + dummyFileSize := 1 << 10 + + configPath := t.TempDir() + configFile := "000_a.yaml" + + configDirPath := path.Join(configPath, "conf.d") + require.NoError(t, os.Mkdir(configDirPath, 0o700)) + + configtest.PrepareConfigFiles(t, configPath, []configtest.ConfigFile{ + configtest.NewConfigFile(configFile, m{"a": "000"}, yaml.Marshal), + }) + + // Not valid configs, dummy files those appear lexicographically first. + configtest.PrepareDummyFiles(t, configDirPath, []configtest.DummyFile{ + configtest.NewDummyFile("000_file_1", dummyFileSize), + configtest.NewDummyFile("000_file_2", dummyFileSize), + configtest.NewDummyFile("000_file_3", dummyFileSize), + }) + + configtest.PrepareConfigFiles(t, configDirPath, []configtest.ConfigFile{ + // Valid configs with invalid extensions those appear lexicographically first. + configtest.NewConfigFile("001_a.yaml.un~", m{"a": "101"}, yaml.Marshal), + configtest.NewConfigFile("001_b.yml~", m{"b": m{"a": "102", "b": "103"}}, yaml.Marshal), + configtest.NewConfigFile("001_c.yaml.swp", m{"c": m{"a": "104", "b": "105"}}, yaml.Marshal), + configtest.NewConfigFile("001_d.json.swp", m{"d": m{"a": "106", "b": "107"}}, json.Marshal), + + // Valid configs with valid extensions those should be loaded. + configtest.NewConfigFile("010_a.yaml", m{"a": "1"}, yaml.Marshal), + configtest.NewConfigFile("020_b.yml", m{"b": m{"a": "2", "b": "3"}}, yaml.Marshal), + configtest.NewConfigFile("030_c.json", m{"c": m{"a": "4", "b": "5"}}, json.Marshal), + + // Valid configs with invalid extensions those appear lexicographically last. + configtest.NewConfigFile("099_a.yaml.un~", m{"a": "201"}, yaml.Marshal), + configtest.NewConfigFile("099_b.yml~", m{"b": m{"a": "202", "b": "203"}}, yaml.Marshal), + configtest.NewConfigFile("099_c.yaml.swp", m{"c": m{"a": "204", "b": "205"}}, yaml.Marshal), + configtest.NewConfigFile("099_c.json.swp", m{"d": m{"a": "206", "b": "207"}}, json.Marshal), + }) + + // Not valid configs, dummy files those appear lexicographically last. + configtest.PrepareDummyFiles(t, configDirPath, []configtest.DummyFile{ + configtest.NewDummyFile("999_file_1", dummyFileSize), + configtest.NewDummyFile("999_file_2", dummyFileSize), + configtest.NewDummyFile("999_file_3", dummyFileSize), + }) + + finalConfig := m{"a": "1", "b": m{"a": "2", "b": "3"}, "c": m{"a": "4", "b": "5"}} + + var ( + v *viper.Viper + err error + ) + + t.Run("create config with config dir only", func(t *testing.T) { + v, err = config.CreateViper( + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("reload config with config dir only", func(t *testing.T) { + err = config.ReloadViper( + config.WithViper(v), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("create config with both config and config dir", func(t *testing.T) { + v, err = config.CreateViper( + config.WithConfigFile(path.Join(configPath, configFile)), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) + + t.Run("reload config with both config and config dir", func(t *testing.T) { + err = config.ReloadViper( + config.WithViper(v), + config.WithConfigFile(path.Join(configPath, configFile)), + config.WithConfigDir(configDirPath), + ) + require.NoError(t, err) + assert.Equal(t, finalConfig, v.AllSettings()) + }) +} diff --git a/pkg/util/config/test/generate.go b/pkg/util/config/test/generate.go new file mode 100644 index 000000000..63e286615 --- /dev/null +++ b/pkg/util/config/test/generate.go @@ -0,0 +1,58 @@ +package configtest + +import ( + "crypto/rand" + "os" + "path" + "testing" + + "github.com/stretchr/testify/require" +) + +type MarshalFunc = func(any) ([]byte, error) + +type ConfigFile struct { + filename string + content map[string]any + marshal func(any) ([]byte, error) +} + +type DummyFile struct { + filename string + size int +} + +func NewConfigFile(filename string, content map[string]any, marshal MarshalFunc) ConfigFile { + return ConfigFile{ + filename: filename, + content: content, + marshal: marshal, + } +} + +func NewDummyFile(filename string, size int) DummyFile { + return DummyFile{ + filename: filename, + size: size, + } +} + +func PrepareConfigFiles(t *testing.T, dir string, files []ConfigFile) { + for _, file := range files { + data, err := file.marshal(file.content) + require.NoError(t, err) + + err = os.WriteFile(path.Join(dir, file.filename), data, 0o600) + require.NoError(t, err) + } +} + +func PrepareDummyFiles(t *testing.T, dir string, files []DummyFile) { + for _, file := range files { + data := make([]byte, file.size) + _, _ = rand.Read(data) + + err := os.WriteFile(path.Join(dir, file.filename), data, 0o600) + require.NoError(t, err) + } +}