Skip to content

Commit

Permalink
Add tests for file provider
Browse files Browse the repository at this point in the history
  • Loading branch information
Milad Abbasi committed Jan 21, 2021
1 parent 0b93e12 commit 82b9179
Show file tree
Hide file tree
Showing 8 changed files with 177 additions and 6 deletions.
18 changes: 18 additions & 0 deletions env_test.go
Expand Up @@ -100,6 +100,24 @@ func TestEnvProvider_Fill(t *testing.T) {
}
})

t.Run("config key", func(t *testing.T) {
os.Clearenv()
err := os.Setenv("CUSTOM_KEY", "env")
require.NoError(t, err)

s := struct {
Env string `config:"CUSTOM_KEY"`
}{}
in, err := NewInput(&s)
require.NoError(t, err)
require.NotNil(t, in)
ep := EnvProvider{}

err = ep.Fill(in)
require.NoError(t, err)
assert.Equal(t, "env", s.Env)
})

t.Run("env prefix", func(t *testing.T) {
os.Clearenv()
err := os.Setenv("APP_Env", "env")
Expand Down
15 changes: 10 additions & 5 deletions file.go
Expand Up @@ -2,7 +2,9 @@ package gonfig

import (
"encoding/json"
"errors"
"fmt"
"io"
"os"
"path/filepath"

Expand All @@ -15,8 +17,8 @@ const (
JSON = ".json"
YML = ".yml"
YAML = ".yaml"
ENV = ".env"
TOML = ".toml"
ENV = ".env"
)

// FileProvider loads values from file to provided struct
Expand Down Expand Up @@ -89,6 +91,12 @@ func (fp *FileProvider) Fill(in *Input) error {

// decode opens specified file and loads its content to input argument
func (fp *FileProvider) decode(i interface{}) (err error) {
switch fp.FileExt {
case JSON, YML, YAML, TOML:
default:
return fmt.Errorf(unsupportedFileExtErrFormat, ErrUnsupportedFileExt, fp.FileExt)
}

f, err := os.Open(fp.FilePath)
if err != nil {
if os.IsNotExist(err) && !fp.Required {
Expand All @@ -112,12 +120,9 @@ func (fp *FileProvider) decode(i interface{}) (err error) {

case TOML:
_, err = toml.DecodeReader(f, i)

default:
err = fmt.Errorf(unsupportedFileExtErrFormat, ErrUnsupportedFileExt, fp.FileExt)
}

if err != nil {
if err != nil && !errors.Is(err, io.EOF) {
return fmt.Errorf(decodeFailedErrFormat, err)
}

Expand Down
122 changes: 122 additions & 0 deletions file_test.go
@@ -0,0 +1,122 @@
package gonfig

import (
"errors"
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestNewFileProvider(t *testing.T) {
fp := NewFileProvider("file.yml")
require.NotNil(t, fp)
assert.Equal(t, "file.yml", fp.FilePath)
assert.Equal(t, ".yml", fp.FileExt)
assert.False(t, fp.Required)
}

func TestFileProvider_Name(t *testing.T) {
fp := FileProvider{
FileExt: ".json",
}

assert.Equal(t, "File provider (json)", fp.Name())
}

func TestFileProvider_UnmarshalStruct(t *testing.T) {
t.Run("file existence", func(t *testing.T) {
fp := FileProvider{
FilePath: "NotExistingFile.toml",
FileExt: ".toml",
Required: false,
}

var i interface{}
err := fp.UnmarshalStruct(i)
assert.NoError(t, err)

fp.Required = true
err = fp.UnmarshalStruct(i)
assert.Error(t, err)
})

t.Run("unsupported file extension", func(t *testing.T) {
fp := FileProvider{
FileExt: ".ini",
}

var i interface{}
err := fp.UnmarshalStruct(i)
require.Error(t, err)
assert.Truef(
t,
errors.Is(err, ErrUnsupportedFileExt),
"Error must wrap ErrUnsupportedFileExt error",
)
})

t.Run("supported file extensions", func(t *testing.T) {
for _, e := range []string{".json", ".yml", ".yaml", ".toml"} {
s := struct{}{}
fp := FileProvider{
FilePath: "testdata/config" + e,
FileExt: e,
Required: true,
}

err := fp.UnmarshalStruct(&s)
require.NoError(t, err)
}
})
}

func TestFileProvider_Fill(t *testing.T) {
t.Run("should be set", func(t *testing.T) {
for _, e := range []string{".json", ".yml", ".yaml", ".toml"} {
s := struct {
Config struct {
Host string
}
}{}
in, err := NewInput(&s)
require.NoError(t, err)
require.NotNil(t, in)

fp := FileProvider{
FilePath: "testdata/config" + e,
FileExt: e,
Required: true,
}

err = fp.Fill(in)
require.NoError(t, err)
for _, f := range in.Fields {
assert.True(t, f.IsSet)
}
}
})

t.Run("config key", func(t *testing.T) {
for _, e := range []string{".json", ".yml", ".yaml", ".toml"} {
s := struct {
Custom string `json:"custom_key" yaml:"custom_key" toml:"custom_key"`
}{}
in, err := NewInput(&s)
require.NoError(t, err)
require.NotNil(t, in)

fp := FileProvider{
FilePath: "testdata/config" + e,
FileExt: e,
Required: true,
}

err = fp.Fill(in)
require.NoError(t, err)
for _, f := range in.Fields {
assert.True(t, f.IsSet)
}
}
})
}
6 changes: 6 additions & 0 deletions testdata/config.json
@@ -0,0 +1,6 @@
{
"config": {
"host": "golang.org"
},
"custom_key": "custom"
}
4 changes: 4 additions & 0 deletions testdata/config.toml
@@ -0,0 +1,4 @@
custom_key = "custom"

[config]
host = "golang.org"
4 changes: 4 additions & 0 deletions testdata/config.yaml
@@ -0,0 +1,4 @@
config:
host: golang.org

custom_key: custom
4 changes: 4 additions & 0 deletions testdata/config.yml
@@ -0,0 +1,4 @@
config:
host: golang.org

custom_key: custom
10 changes: 9 additions & 1 deletion utils.go
Expand Up @@ -58,7 +58,15 @@ func traverseMap(m map[string]interface{}, path []string) (string, bool) {

nestedMap, ok := value.(map[string]interface{})
if !ok {
return "", false
nestedInterfaceMap, ok := value.(map[interface{}]interface{})
if !ok {
return "", false
}

nestedMap = make(map[string]interface{})
for k, v := range nestedInterfaceMap {
nestedMap[fmt.Sprint(k)] = v
}
}

return traverseMap(nestedMap, path)
Expand Down

0 comments on commit 82b9179

Please sign in to comment.