From 23fef95251c0831f5539ec8f38e160c278a4b21c Mon Sep 17 00:00:00 2001 From: Denis Palnitsky Date: Fri, 1 Dec 2023 19:00:56 +0100 Subject: [PATCH] Add coverage for errors (#19) --- config.go | 10 +++- config_test.go | 101 ++++++++++++++++++++++++---------- testdata/myapp-malformed.yaml | 5 ++ 3 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 testdata/myapp-malformed.yaml diff --git a/config.go b/config.go index ac8b20b..d016cc6 100644 --- a/config.go +++ b/config.go @@ -193,6 +193,8 @@ func (c *ConfReader) flagsBinding(conf interface{}) error { } err := flags.Parse(os.Args[1:]) + // we use pflag.ExitOnError so we should not get error here + // but just in case I'll keep it if err != nil { return errors.Wrap(err, "failed to parse flags") } @@ -242,8 +244,12 @@ func (c *ConfReader) dumpStruct(t reflect.Type, path string, res map[string]*fla for i := 0; i < t.NumField(); i++ { f := t.Field(i) - if f.Type.Kind() != reflect.Struct && f.Type.Kind() != reflect.Ptr && f.Type.Kind() != reflect.Chan && - f.Type.Kind() != reflect.Func && f.Type.Kind() != reflect.Interface && f.Type.Kind() != reflect.UnsafePointer { + if f.Type.Kind() != reflect.Struct && + f.Type.Kind() != reflect.Ptr && + f.Type.Kind() != reflect.Chan && + f.Type.Kind() != reflect.Func && + f.Type.Kind() != reflect.Interface && + f.Type.Kind() != reflect.UnsafePointer { // do we have flag name override ? flagVal := f.Tag.Get("flag") diff --git a/config_test.go b/config_test.go index 8ca0af5..2ae360b 100644 --- a/config_test.go +++ b/config_test.go @@ -73,27 +73,44 @@ func resetFlags() { } func Test_ReadFromFile(t *testing.T) { - resetFlags() - nc := &FullConfig{} - confReader := NewConfReader("myapp").WithSearchDirs("testdata") - err := confReader.Read(nc) - if assert.NoError(t, err) { - assert.Equal(t, "valFromConf", nc.App.FromConfig) - assert.Equal(t, true, nc.Verbose) - } + t.Run("readSuccessfully", func(t *testing.T) { + resetFlags() + nc := &FullConfig{} + confReader := NewConfReader("myapp").WithSearchDirs("testdata") + + err := confReader.Read(nc) + if assert.NoError(t, err) { + assert.Equal(t, "valFromConf", nc.App.FromConfig) + assert.Equal(t, true, nc.Verbose) + } + }) + + t.Run("malformedFile", func(t *testing.T) { + resetFlags() + nc := &FullConfig{} + confReader := NewConfReader("myapp-malformed").WithSearchDirs("testdata") + + err := confReader.Read(nc) + if assert.Error(t, err, "failed to read") { + assert.Contains(t, err.Error(), "failed to unmarshal struct") + } + }) } func Test_EnvVarsNoPrefix(t *testing.T) { - resetFlags() - nc := &FullConfig{} - confReader := NewConfReader("myapp") - os.Setenv("APP_FROMENVVAR", "valFromEnvVar") + t.Run("readSuccessfully", func(t *testing.T) { + resetFlags() + nc := &FullConfig{} + confReader := NewConfReader("myapp") + os.Setenv("APP_FROMENVVAR", "valFromEnvVar") + + err := confReader.Read(nc) + if assert.NoError(t, err) { + assert.Equal(t, "valFromEnvVar", nc.App.FromEnvVar) + } + }) - err := confReader.Read(nc) - if assert.NoError(t, err) { - assert.Equal(t, "valFromEnvVar", nc.App.FromEnvVar) - } } func Test_EnvVarsWithPrefix(t *testing.T) { @@ -198,7 +215,10 @@ type dmSibling struct { func Test_dumpStruct(t *testing.T) { m := map[string]*flagInfo{} - c := &ConfReader{} + c := &ConfReader{ + Verbose: true, + } + c.dumpStruct(reflect.TypeOf(dmParent{}), "", m) if assert.NotNil(t, m["verbose"]) { @@ -254,20 +274,37 @@ func Test_Validation(t *testing.T) { }) } -type DefaultVals struct { - DB lib.PostgresqlDb - Test string `default:"test"` -} +func Test_SetDefault(t *testing.T) { + t.Run("defaultValuesSet", func(t *testing.T) { + type DefaultVals struct { + DB lib.PostgresqlDb + Test string `default:"test"` + } -func Test_DefaultFalse(t *testing.T) { - resetFlags() - cf := &DefaultVals{} - reader := NewConfReader("def-vals") - err := reader.Read(cf) - if assert.NoError(t, err) { - assert.Equal(t, "localhost", cf.DB.Host) - assert.Equal(t, "test", cf.Test) - } + resetFlags() + cf := &DefaultVals{} + reader := NewConfReader("def-vals") + err := reader.Read(cf) + if assert.NoError(t, err) { + assert.Equal(t, "localhost", cf.DB.Host) + assert.Equal(t, "test", cf.Test) + } + }) + + t.Run("failedToSetDefault", func(t *testing.T) { + type DefaultValsFail struct { + Test map[string]string `default:"test"` + } + + resetFlags() + cf := &DefaultValsFail{} + reader := NewConfReader("def-vals-failed") + err := reader.Read(cf) + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "failed to set default values") + } + + }) } type AllTypes struct { @@ -408,3 +445,7 @@ func Test_InputStructErrors(t *testing.T) { } }) } + +func Test_ErrorHandling(t *testing.T) { + +} diff --git a/testdata/myapp-malformed.yaml b/testdata/myapp-malformed.yaml new file mode 100644 index 0000000..4b3c87e --- /dev/null +++ b/testdata/myapp-malformed.yaml @@ -0,0 +1,5 @@ +�I�dZ�a#�I�O�O�� + _v�NVKc�%�|�)R_f���շI�|^m'�42�w������6M�cn�}ܦ��{�3��6���h�y���3��x��1�~��~�삿��u����,Ʀ�<�1�ò�]�Oy9ħ�G�^B·�$>-Qr�=�����Vj�Q�4n����P0�%;�����=��K�$Y + �Ӌ�]���lշS \= +����9��>}� !}�(c�X��}rv���l�� + Ÿۅ���'��J�7��P��$洎��t��S[���YZha�Gc�nT�ܛM9̋��⸮qw \ No newline at end of file