From ca60ff814686f129bf3007700f04203281da9922 Mon Sep 17 00:00:00 2001 From: Artyom Misko Date: Wed, 10 May 2023 11:22:28 +0300 Subject: [PATCH 1/2] [#86] Publish methods for get configuration from non local storage location and update package list --- cleanenv.go | 12 ++-- cleanenv_test.go | 182 ++++++++++++++++++++++++++++++++++++++++++++++- go.mod | 4 +- go.sum | 8 +-- 4 files changed, 192 insertions(+), 14 deletions(-) diff --git a/cleanenv.go b/cleanenv.go index dd4e1d4..187923a 100644 --- a/cleanenv.go +++ b/cleanenv.go @@ -135,11 +135,11 @@ func parseFile(path string, cfg interface{}) error { // parse the file depending on the file type switch ext := strings.ToLower(filepath.Ext(path)); ext { case ".yaml", ".yml": - err = parseYAML(f, cfg) + err = ParseYAML(f, cfg) case ".json": - err = parseJSON(f, cfg) + err = ParseJSON(f, cfg) case ".toml": - err = parseTOML(f, cfg) + err = ParseTOML(f, cfg) case ".edn": err = parseEDN(f, cfg) case ".env": @@ -154,17 +154,17 @@ func parseFile(path string, cfg interface{}) error { } // parseYAML parses YAML from reader to data structure -func parseYAML(r io.Reader, str interface{}) error { +func ParseYAML(r io.Reader, str interface{}) error { return yaml.NewDecoder(r).Decode(str) } // parseJSON parses JSON from reader to data structure -func parseJSON(r io.Reader, str interface{}) error { +func ParseJSON(r io.Reader, str interface{}) error { return json.NewDecoder(r).Decode(str) } // parseTOML parses TOML from reader to data structure -func parseTOML(r io.Reader, str interface{}) error { +func ParseTOML(r io.Reader, str interface{}) error { _, err := toml.NewDecoder(r).Decode(str) return err } diff --git a/cleanenv_test.go b/cleanenv_test.go index d51490c..68bae1e 100644 --- a/cleanenv_test.go +++ b/cleanenv_test.go @@ -4,6 +4,7 @@ import ( "bytes" "errors" "fmt" + "io" "io/ioutil" "net/url" "os" @@ -1191,8 +1192,8 @@ func TestTimeLocation(t *testing.T) { func TestSkipUnexportedField(t *testing.T) { conf := struct { Database struct { - Host string `yaml:"host" env:"DB_HOST" env-description:"Database host"` - Port string `yaml:"port" env:"DB_PORT" env-description:"Database port"` + Host string `yaml:"host" env:"DB_HOST" env-description:"Database host"` + Port string `yaml:"port" env:"DB_PORT" env-description:"Database port"` } `yaml:"database"` server struct { Host string `yaml:"host" env:"SRV_HOST,HOST" env-description:"Server host" env-default:"localhost"` @@ -1210,3 +1211,180 @@ func TestSkipUnexportedField(t *testing.T) { t.Fatal("expect value on exported fields") } } + +func TestParseYAML(t *testing.T) { + type configObject struct { + One int `yaml:"one"` + Two int `yaml:"two"` + } + type config struct { + Number int64 `yaml:"number"` + Float float64 `yaml:"float"` + String string `yaml:"string"` + Boolean bool `yaml:"boolean"` + Object configObject `yaml:"object"` + Array []int `yaml:"array"` + } + + wantConfig := config{ + Number: 1, + Float: 2.3, + String: "test", + Boolean: true, + Object: configObject{1, 2}, + Array: []int{1, 2, 3}, + } + + tests := []struct { + name string + r io.Reader + want *config + wantErr bool + }{ + { + name: "yaml", + r: bytes.NewBufferString(` +number: 1 +float: 2.3 +string: test +boolean: yes +object: + one: 1 + two: 2 +array: [1, 2, 3]`), + want: &wantConfig, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var cfg config + var err error + if err = ParseYAML(tt.r, &cfg); (err != nil) != tt.wantErr { + t.Errorf("ParseYAML() error = %v, wantErr %v", err, tt.wantErr) + } + if err == nil && !reflect.DeepEqual(&cfg, tt.want) { + t.Errorf("wrong data %v, want %v", &cfg, tt.want) + } + }) + } +} + +func TestParseJSON(t *testing.T) { + type configObject struct { + One int `json:"one"` + Two int `json:"two"` + } + type config struct { + Number int64 `json:"number"` + Float float64 `json:"float"` + String string `json:"string"` + Boolean bool `json:"boolean"` + Object configObject `json:"object"` + Array []int `json:"array"` + } + + wantConfig := config{ + Number: 1, + Float: 2.3, + String: "test", + Boolean: true, + Object: configObject{1, 2}, + Array: []int{1, 2, 3}, + } + + tests := []struct { + name string + r io.Reader + want *config + wantErr bool + }{ + { + name: "json", + r: bytes.NewBufferString(` +{ + "number": 1, + "float": 2.3, + "string": "test", + "boolean": true, + "object": { + "one": 1, + "two": 2 + }, + "array": [1, 2, 3] +}`), + want: &wantConfig, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var cfg config + var err error + if err := ParseJSON(tt.r, &cfg); (err != nil) != tt.wantErr { + t.Errorf("ParseJSON() error = %v, wantErr %v", err, tt.wantErr) + } + if err == nil && !reflect.DeepEqual(&cfg, tt.want) { + t.Errorf("wrong data %v, want %v", &cfg, tt.want) + } + }) + } +} + +func TestParseTOML(t *testing.T) { + type configObject struct { + One int `toml:"one"` + Two int `toml:"two"` + } + type config struct { + Number int64 `toml:"number"` + Float float64 `toml:"float"` + String string `toml:"string"` + Boolean bool `toml:"boolean"` + Object configObject `toml:"object"` + Array []int `toml:"array"` + } + + wantConfig := config{ + Number: 1, + Float: 2.3, + String: "test", + Boolean: true, + Object: configObject{1, 2}, + Array: []int{1, 2, 3}, + } + + tests := []struct { + name string + r io.Reader + want *config + wantErr bool + }{ + { + name: "toml", + r: bytes.NewBufferString(` +number = 1 +float = 2.3 +string = "test" +boolean = true +array = [1, 2, 3] +[object] +one = 1 +two = 2`), + want: &wantConfig, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + var cfg config + var err error + if err := ParseTOML(tt.r, &cfg); (err != nil) != tt.wantErr { + t.Errorf("ParseTOML() error = %v, wantErr %v", err, tt.wantErr) + } + if err == nil && !reflect.DeepEqual(&cfg, tt.want) { + t.Errorf("wrong data %v, want %v", &cfg, tt.want) + } + }) + } +} diff --git a/go.mod b/go.mod index 2e21eb0..93a1d3a 100644 --- a/go.mod +++ b/go.mod @@ -1,8 +1,8 @@ module github.com/ilyakaznacheev/cleanenv require ( - github.com/BurntSushi/toml v1.1.0 - github.com/joho/godotenv v1.4.0 + github.com/BurntSushi/toml v1.2.1 + github.com/joho/godotenv v1.5.1 gopkg.in/yaml.v3 v3.0.1 olympos.io/encoding/edn v0.0.0-20201019073823-d3554ca0b0a3 ) diff --git a/go.sum b/go.sum index 84677cd..f3942aa 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I= -github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= -github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= -github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= +github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= From 1c4029ffe509791aaeaf760a4da0d8714729991d Mon Sep 17 00:00:00 2001 From: Artyom Misko Date: Fri, 14 Jul 2023 20:34:56 +0300 Subject: [PATCH 2/2] function names in comments are aligned --- cleanenv.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cleanenv.go b/cleanenv.go index 187923a..8977432 100644 --- a/cleanenv.go +++ b/cleanenv.go @@ -153,17 +153,17 @@ func parseFile(path string, cfg interface{}) error { return nil } -// parseYAML parses YAML from reader to data structure +// ParseYAML parses YAML from reader to data structure func ParseYAML(r io.Reader, str interface{}) error { return yaml.NewDecoder(r).Decode(str) } -// parseJSON parses JSON from reader to data structure +// ParseJSON parses JSON from reader to data structure func ParseJSON(r io.Reader, str interface{}) error { return json.NewDecoder(r).Decode(str) } -// parseTOML parses TOML from reader to data structure +// ParseTOML parses TOML from reader to data structure func ParseTOML(r io.Reader, str interface{}) error { _, err := toml.NewDecoder(r).Decode(str) return err