package conf import ( "os" "testing" "github.com/stretchr/testify/assert" "github.com/zeromicro/go-zero/core/fs" "github.com/zeromicro/go-zero/core/hash" ) func TestLoadConfig_notExists(t *testing.T) { assert.NotNil(t, Load("not_a_file", nil)) } func TestLoadConfig_notRecogFile(t *testing.T) { filename, err := fs.TempFilenameWithText("hello") assert.Nil(t, err) defer os.Remove(filename) assert.NotNil(t, Load(filename, nil)) } func TestConfigJson(t *testing.T) { tests := []string{ ".json", ".yaml", ".yml", } text := `{ "a": "foo", "b": 1, "c": "${FOO}", "d": "abcd!@#$112" }` for _, test := range tests { test := test t.Run(test, func(t *testing.T) { os.Setenv("FOO", "2") defer os.Unsetenv("FOO") tmpfile, err := createTempFile(test, text) assert.Nil(t, err) defer os.Remove(tmpfile) var val struct { A string `json:"a"` B int `json:"b"` C string `json:"c"` D string `json:"d"` } MustLoad(tmpfile, &val) assert.Equal(t, "foo", val.A) assert.Equal(t, 1, val.B) assert.Equal(t, "${FOO}", val.C) assert.Equal(t, "abcd!@#$112", val.D) }) } } func TestLoadFromJsonBytesArray(t *testing.T) { input := []byte(`{"users": [{"name": "foo"}, {"Name": "bar"}]}`) var val struct { Users []struct { Name string } } assert.NoError(t, LoadFromJsonBytes(input, &val)) var expect []string for _, user := range val.Users { expect = append(expect, user.Name) } assert.EqualValues(t, []string{"foo", "bar"}, expect) } func TestConfigToml(t *testing.T) { text := `a = "foo" b = 1 c = "${FOO}" d = "abcd!@#$112" ` os.Setenv("FOO", "2") defer os.Unsetenv("FOO") tmpfile, err := createTempFile(".toml", text) assert.Nil(t, err) defer os.Remove(tmpfile) var val struct { A string `json:"a"` B int `json:"b"` C string `json:"c"` D string `json:"d"` } MustLoad(tmpfile, &val) assert.Equal(t, "foo", val.A) assert.Equal(t, 1, val.B) assert.Equal(t, "${FOO}", val.C) assert.Equal(t, "abcd!@#$112", val.D) } func TestConfigJsonCanonical(t *testing.T) { text := []byte(`{"a": "foo", "B": "bar"}`) var val1 struct { A string `json:"a"` B string `json:"b"` } var val2 struct { A string B string } assert.NoError(t, LoadFromJsonBytes(text, &val1)) assert.Equal(t, "foo", val1.A) assert.Equal(t, "bar", val1.B) assert.NoError(t, LoadFromJsonBytes(text, &val2)) assert.Equal(t, "foo", val2.A) assert.Equal(t, "bar", val2.B) } func TestConfigTomlCanonical(t *testing.T) { text := []byte(`a = "foo" B = "bar"`) var val1 struct { A string `json:"a"` B string `json:"b"` } var val2 struct { A string B string } assert.NoError(t, LoadFromTomlBytes(text, &val1)) assert.Equal(t, "foo", val1.A) assert.Equal(t, "bar", val1.B) assert.NoError(t, LoadFromTomlBytes(text, &val2)) assert.Equal(t, "foo", val2.A) assert.Equal(t, "bar", val2.B) } func TestConfigYamlCanonical(t *testing.T) { text := []byte(`a: foo B: bar`) var val1 struct { A string `json:"a"` B string `json:"b"` } var val2 struct { A string B string } assert.NoError(t, LoadFromYamlBytes(text, &val1)) assert.Equal(t, "foo", val1.A) assert.Equal(t, "bar", val1.B) assert.NoError(t, LoadFromYamlBytes(text, &val2)) assert.Equal(t, "foo", val2.A) assert.Equal(t, "bar", val2.B) } func TestConfigTomlEnv(t *testing.T) { text := `a = "foo" b = 1 c = "${FOO}" d = "abcd!@#112" ` os.Setenv("FOO", "2") defer os.Unsetenv("FOO") tmpfile, err := createTempFile(".toml", text) assert.Nil(t, err) defer os.Remove(tmpfile) var val struct { A string `json:"a"` B int `json:"b"` C string `json:"c"` D string `json:"d"` } MustLoad(tmpfile, &val, UseEnv()) assert.Equal(t, "foo", val.A) assert.Equal(t, 1, val.B) assert.Equal(t, "2", val.C) assert.Equal(t, "abcd!@#112", val.D) } func TestConfigJsonEnv(t *testing.T) { tests := []string{ ".json", ".yaml", ".yml", } text := `{ "a": "foo", "b": 1, "c": "${FOO}", "d": "abcd!@#$a12 3" }` for _, test := range tests { test := test t.Run(test, func(t *testing.T) { os.Setenv("FOO", "2") defer os.Unsetenv("FOO") tmpfile, err := createTempFile(test, text) assert.Nil(t, err) defer os.Remove(tmpfile) var val struct { A string `json:"a"` B int `json:"b"` C string `json:"c"` D string `json:"d"` } MustLoad(tmpfile, &val, UseEnv()) assert.Equal(t, "foo", val.A) assert.Equal(t, 1, val.B) assert.Equal(t, "2", val.C) assert.Equal(t, "abcd!@# 3", val.D) }) } } func TestToCamelCase(t *testing.T) { tests := []struct { input string expect string }{ { input: "", expect: "", }, { input: "A", expect: "a", }, { input: "a", expect: "a", }, { input: "hello_world", expect: "helloWorld", }, { input: "Hello_world", expect: "helloWorld", }, { input: "hello_World", expect: "helloWorld", }, { input: "helloWorld", expect: "helloWorld", }, { input: "HelloWorld", expect: "helloWorld", }, { input: "hello World", expect: "hello world", }, { input: "Hello World", expect: "hello world", }, { input: "Hello World", expect: "hello world", }, { input: "Hello World foo_bar", expect: "hello world fooBar", }, { input: "Hello World foo_Bar", expect: "hello world fooBar", }, { input: "Hello World Foo_bar", expect: "hello world fooBar", }, { input: "Hello World Foo_Bar", expect: "hello world fooBar", }, { input: "你好 World Foo_Bar", expect: "你好 world fooBar", }, } for _, test := range tests { test := test t.Run(test.input, func(t *testing.T) { assert.Equal(t, test.expect, toCamelCase(test.input)) }) } } func TestLoadFromJsonBytesError(t *testing.T) { var val struct{} assert.Error(t, LoadFromJsonBytes([]byte(`hello`), &val)) } func TestLoadFromTomlBytesError(t *testing.T) { var val struct{} assert.Error(t, LoadFromTomlBytes([]byte(`hello`), &val)) } func TestLoadFromYamlBytesError(t *testing.T) { var val struct{} assert.Error(t, LoadFromYamlBytes([]byte(`':hello`), &val)) } func TestLoadFromYamlBytes(t *testing.T) { input := []byte(`layer1: layer2: layer3: foo`) var val struct { Layer1 struct { Layer2 struct { Layer3 string } } } assert.NoError(t, LoadFromYamlBytes(input, &val)) assert.Equal(t, "foo", val.Layer1.Layer2.Layer3) } func createTempFile(ext, text string) (string, error) { tmpfile, err := os.CreateTemp(os.TempDir(), hash.Md5Hex([]byte(text))+"*"+ext) if err != nil { return "", err } if err := os.WriteFile(tmpfile.Name(), []byte(text), os.ModeTemporary); err != nil { return "", err } filename := tmpfile.Name() if err = tmpfile.Close(); err != nil { return "", err } return filename, nil }