mirror of
https://github.com/spf13/viper
synced 2024-12-22 19:47:01 +00:00
feat: add errors.Is support to all errors
Add functionality to support errors.Is on all generated errors to keep in line with best practice on checking whether an error is of the specified type as per changes to error handling in go1.13.
This commit is contained in:
parent
e36638d878
commit
d6e5a55f3c
5 changed files with 109 additions and 0 deletions
17
internal/encoding/error_test.go
Normal file
17
internal/encoding/error_test.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package encoding
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_encodingError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := encodingError("encoding error")
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.ErrorIs(t, err2, encodingError("encoding error"))
|
||||||
|
assert.NotErrorIs(t, err2, encodingError("other encodingerror"))
|
||||||
|
}
|
6
util.go
6
util.go
|
@ -37,6 +37,12 @@ func (pe ConfigParseError) Unwrap() error {
|
||||||
return pe.err
|
return pe.err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is adds a check to see if the specified target is an error of this type, see [errors.Is]
|
||||||
|
func (pe ConfigParseError) Is(err error) bool {
|
||||||
|
_, ok := err.(*ConfigParseError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
// toCaseInsensitiveValue checks if the value is a map;
|
// toCaseInsensitiveValue checks if the value is a map;
|
||||||
// if so, create a copy and lower-case the keys recursively.
|
// if so, create a copy and lower-case the keys recursively.
|
||||||
func toCaseInsensitiveValue(value any) any {
|
func toCaseInsensitiveValue(value any) any {
|
||||||
|
|
11
util_test.go
11
util_test.go
|
@ -11,6 +11,7 @@
|
||||||
package viper
|
package viper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"testing"
|
"testing"
|
||||||
|
@ -84,3 +85,13 @@ func TestAbsPathify(t *testing.T) {
|
||||||
assert.Equal(t, test.output, got)
|
assert.Equal(t, test.output, got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestConfigParseError(t *testing.T) {
|
||||||
|
// test a generic error
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
assert.NotErrorIs(t, err1, &ConfigParseError{})
|
||||||
|
// test the wrapped generic error
|
||||||
|
err2 := ConfigParseError{err: err1}
|
||||||
|
assert.ErrorIs(t, err2, &ConfigParseError{})
|
||||||
|
assert.ErrorIs(t, err2.Unwrap(), err1)
|
||||||
|
}
|
||||||
|
|
17
viper.go
17
viper.go
|
@ -61,6 +61,17 @@ func (e ConfigMarshalError) Error() string {
|
||||||
return fmt.Sprintf("While marshaling config: %s", e.err.Error())
|
return fmt.Sprintf("While marshaling config: %s", e.err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unwrap returns the wrapped error.
|
||||||
|
func (e ConfigMarshalError) Unwrap() error {
|
||||||
|
return e.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is adds a check to see if the specified target is an error of this type, see [errors.Is]
|
||||||
|
func (e ConfigMarshalError) Is(err error) bool {
|
||||||
|
_, ok := err.(*ConfigMarshalError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
var v *Viper
|
var v *Viper
|
||||||
|
|
||||||
type RemoteResponse struct {
|
type RemoteResponse struct {
|
||||||
|
@ -118,6 +129,12 @@ func (fnfe ConfigFileNotFoundError) Error() string {
|
||||||
return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
|
return fmt.Sprintf("Config File %q Not Found in %q", fnfe.name, fnfe.locations)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Is adds a check to see if the specified target is an error of this type, see [errors.Is]
|
||||||
|
func (e ConfigFileNotFoundError) Is(err error) bool {
|
||||||
|
_, ok := err.(*ConfigFileNotFoundError)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
// ConfigFileAlreadyExistsError denotes failure to write new configuration file.
|
// ConfigFileAlreadyExistsError denotes failure to write new configuration file.
|
||||||
type ConfigFileAlreadyExistsError string
|
type ConfigFileAlreadyExistsError string
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ package viper
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
@ -2696,3 +2697,60 @@ func skipWindows(t *testing.T) {
|
||||||
t.Skip("Skip test on Windows")
|
t.Skip("Skip test on Windows")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test the ConfigMarshalError
|
||||||
|
func TestConfigMarshalError(t *testing.T) {
|
||||||
|
// test a generic error
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
assert.NotErrorIs(t, err1, &ConfigMarshalError{})
|
||||||
|
// test the wrapped generic error
|
||||||
|
err2 := ConfigMarshalError{err: err1}
|
||||||
|
assert.ErrorIs(t, err2, &ConfigMarshalError{})
|
||||||
|
assert.ErrorIs(t, err2.Unwrap(), err1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnsupportedConfigError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := UnsupportedConfigError("some string")
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.ErrorIs(t, err2, UnsupportedConfigError("some string"))
|
||||||
|
assert.NotErrorIs(t, err2, UnsupportedConfigError("other string"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUnsupportedRemoteProviderError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := UnsupportedRemoteProviderError("some string")
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.ErrorIs(t, err2, UnsupportedRemoteProviderError("some string"))
|
||||||
|
assert.NotErrorIs(t, err2, UnsupportedRemoteProviderError("other string"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRemoteConfigError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := RemoteConfigError("some string")
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.ErrorIs(t, err2, RemoteConfigError("some string"))
|
||||||
|
assert.NotErrorIs(t, err2, RemoteConfigError("other string"))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigFileNotFoundError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := ConfigFileNotFoundError{name: "name", locations: "locations"}
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.ErrorIs(t, err2, &ConfigFileNotFoundError{})
|
||||||
|
assert.ErrorIs(t, err2, &ConfigFileNotFoundError{name: "name", locations: "locations"})
|
||||||
|
assert.ErrorIs(t, err2, &ConfigFileNotFoundError{name: "other name", locations: "other locations"})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigFileAlreadyExistsError(t *testing.T) {
|
||||||
|
err1 := fmt.Errorf("test error")
|
||||||
|
err2 := ConfigFileAlreadyExistsError("some string")
|
||||||
|
assert.NotErrorIs(t, err1, err2)
|
||||||
|
assert.NotErrorIs(t, err2, err1)
|
||||||
|
assert.ErrorIs(t, err2, ConfigFileAlreadyExistsError("some string"))
|
||||||
|
assert.NotErrorIs(t, err2, ConfigFileAlreadyExistsError("other string"))
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue