aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config/config.go13
-rw-r--r--config/config_test.go80
-rw-r--r--config/error.go92
-rw-r--r--config/error_test.go20
-rw-r--r--config/test_data/invalid.yaml (renamed from config/test_data/invalid_yaml)0
-rw-r--r--go.mod2
-rw-r--r--go.sum10
7 files changed, 160 insertions, 57 deletions
diff --git a/config/config.go b/config/config.go
index 653aeb6..f97467a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -5,7 +5,6 @@ import (
"os"
"regexp"
- "github.com/pkg/errors"
"gopkg.in/yaml.v3"
)
@@ -23,16 +22,16 @@ func (c *Config) validate() error {
// address
if ip := net.ParseIP(c.Address); ip == nil {
if _, err := net.LookupIP(c.Address); err != nil {
- return errors.New("Invalid address " + c.Address + ", it must be a valid ipv4 address, ipv6 address, or resolvable name.")
+ return newInvalidAddressError(c.Address, err)
}
}
// port
if _, err := net.LookupPort("tcp", c.Port); err != nil {
- return errors.New("Invalid port " + c.Port + ", it must be a valid port number or tcp service name. Got error : " + err.Error())
+ return newInvalidPortError(c.Port, err)
}
// token
if ok := validToken.MatchString(c.Token); !ok {
- return errors.New("Invalid token, must be an hexadecimal string that lookslike 12345678-9abc-def0-1234-56789abcdef0, got " + c.Token + " instead.")
+ return newInvalidTokenError(c.Token)
}
return nil
}
@@ -42,15 +41,15 @@ func LoadFile(path string) (*Config, error) {
var c *Config
f, errOpen := os.Open(path)
if errOpen != nil {
- return nil, errors.Wrapf(errOpen, "Failed to open configuration file %s", path)
+ return nil, newOpenError(path, errOpen)
}
defer f.Close()
decoder := yaml.NewDecoder(f)
if err := decoder.Decode(&c); err != nil {
- return nil, errors.Wrap(err, "Failed to decode configuration file")
+ return nil, newDecodeError(path, err)
}
if err := c.validate(); err != nil {
- return nil, errors.Wrap(err, "Failed to validate configuration")
+ return nil, err
}
return c, nil
}
diff --git a/config/config_test.go b/config/config_test.go
index 0b78260..3904b5d 100644
--- a/config/config_test.go
+++ b/config/config_test.go
@@ -3,66 +3,52 @@ package config
import (
"reflect"
"testing"
+
+ "github.com/stretchr/testify/assert"
+ "github.com/stretchr/testify/require"
)
func TestLoadFile(t *testing.T) {
- // Non existant file
- _, err := LoadFile("test_data/non-existant")
- if err == nil {
- t.Fatal("non-existant config file failed without error")
- }
-
- // Invalid yaml file
- _, err = LoadFile("test_data/invalid_yaml")
- if err == nil {
- t.Fatal("invalid_yaml config file failed without error")
- }
-
- // Invalid address
- if _, err = LoadFile("test_data/invalid_address.yaml"); err == nil {
- t.Fatal("Invalid address should fail to load")
- }
-
- // Invalid address unreasolvable
- if _, err = LoadFile("test_data/invalid_address_unresolvable.yaml"); err == nil {
- t.Fatal("Unresolvable address should fail to load")
- }
-
- // Invalid port
- if _, err = LoadFile("test_data/invalid_port.yaml"); err == nil {
- t.Fatal("Invalid port should fail to load")
- }
-
- // Invalid token
- if _, err = LoadFile("test_data/invalid_token.yaml"); err == nil {
- t.Fatal("Invalid token should fail to load")
- }
-
// Minimal yaml file
- want := Config{
+ minimalConfig := Config{
Address: "127.0.0.2",
Port: "8082",
Token: "12345678-9abc-def0-1234-56789abcdef0",
}
- config, err := LoadFile("test_data/minimal.yaml")
- if err != nil {
- t.Fatalf("minimal example failed with error: %v", err)
- }
- if config != nil && !reflect.DeepEqual(want, *config) {
- t.Fatalf("minimal example failed:\nwant:%+v\ngot: %+v", want, *config)
- }
// Minimal yaml file with hostname resolving
- want = Config{
+ minimalConfigWithResolving := Config{
Address: "localhost",
Port: "8082",
Token: "12345678-9abc-def0-1234-56789abcdef0",
}
- config, err = LoadFile("test_data/minimal_with_hostname.yaml")
- if err != nil {
- t.Fatalf("minimal example failed with error: %v", err)
- }
- if config != nil && !reflect.DeepEqual(want, *config) {
- t.Fatalf("minimal example failed:\nwant:%+v\ngot: %+v", want, *config)
+
+ // Test cases
+ testCases := []struct {
+ name string
+ input string
+ expected *Config
+ expectedError interface{}
+ }{
+ {"Non existant file", "test_data/non-existant", nil, &OpenError{}},
+ {"Invalid file content", "test_data/invalid.yaml", nil, &DecodeError{}},
+ {"Invalid address should fail to load", "test_data/invalid_address.yaml", nil, &InvalidAddressError{}},
+ {"Unresolvable address should fail to load", "test_data/invalid_address_unresolvable.yaml", nil, &InvalidAddressError{}},
+ {"Invalid port should fail to load", "test_data/invalid_port.yaml", nil, &InvalidPortError{}},
+ {"Invalid token should fail to load", "test_data/invalid_token.yaml", nil, &InvalidTokenError{}},
+ {"Minimal config", "test_data/minimal.yaml", &minimalConfig, nil},
+ {"Minimal config with resolving", "test_data/minimal_with_hostname.yaml", &minimalConfigWithResolving, nil},
+ }
+ for _, tc := range testCases {
+ t.Run(tc.name, func(t *testing.T) {
+ valid, err := LoadFile(tc.input)
+ if tc.expectedError != nil {
+ require.Error(t, err)
+ assert.Equalf(t, reflect.TypeOf(err), reflect.TypeOf(tc.expectedError), "Invalid error type. Got %s but expected %s", reflect.TypeOf(err), reflect.TypeOf(tc.expectedError))
+ } else {
+ require.NoError(t, err)
+ }
+ assert.Equal(t, tc.expected, valid, "Invalid value")
+ })
}
}
diff --git a/config/error.go b/config/error.go
new file mode 100644
index 0000000..c49b6a9
--- /dev/null
+++ b/config/error.go
@@ -0,0 +1,92 @@
+package config
+
+import "fmt"
+
+type ErrorType int
+
+// file open configuration file error
+type OpenError struct {
+ path string
+ err error
+}
+
+func (e *OpenError) Error() string {
+ return fmt.Sprintf("Failed to open configuration file : %s", e.path)
+}
+func (e *OpenError) Unwrap() error { return e.err }
+
+func newOpenError(path string, err error) error {
+ return &OpenError{
+ path: path,
+ err: err,
+ }
+}
+
+// Yaml configuration file decoding error
+type DecodeError struct {
+ path string
+ err error
+}
+
+func (e *DecodeError) Error() string {
+ return fmt.Sprintf("Failed to decode configuration file : %s", e.path)
+}
+func (e *DecodeError) Unwrap() error { return e.err }
+
+func newDecodeError(path string, err error) error {
+ return &DecodeError{
+ path: path,
+ err: err,
+ }
+}
+
+// Invalid address field error
+type InvalidAddressError struct {
+ address string
+ err error
+}
+
+func (e *InvalidAddressError) Error() string {
+ return fmt.Sprintf("Invalid address %s : it must be a valid ipv4 address, ipv6 address, or resolvable name", e.address)
+}
+func (e *InvalidAddressError) Unwrap() error { return e.err }
+
+func newInvalidAddressError(address string, err error) error {
+ return &InvalidAddressError{
+ address: address,
+ err: err,
+ }
+}
+
+// Invalid port field error
+type InvalidPortError struct {
+ port string
+ err error
+}
+
+func (e *InvalidPortError) Error() string {
+ return fmt.Sprintf("Invalid port %s : it must be a valid port number or tcp service name", e.port)
+}
+func (e *InvalidPortError) Unwrap() error { return e.err }
+
+func newInvalidPortError(port string, err error) error {
+ return &InvalidPortError{
+ port: port,
+ err: err,
+ }
+}
+
+// Invalid token field error
+type InvalidTokenError struct {
+ token string
+}
+
+func (e *InvalidTokenError) Error() string {
+ return fmt.Sprintf("Invalid token %s : it must be an hexadecimal string that lookslike 12345678-9abc-def0-1234-56789abcdef0", e.token)
+}
+
+func newInvalidTokenError(token string) error {
+ return &InvalidTokenError{
+ token: token,
+ }
+}
diff --git a/config/error_test.go b/config/error_test.go
new file mode 100644
index 0000000..f9807c1
--- /dev/null
+++ b/config/error_test.go
@@ -0,0 +1,20 @@
+package config
+
+import "testing"
+
+func TestErrorsCoverage(t *testing.T) {
+ openErr := OpenError{}
+ _ = openErr.Error()
+ _ = openErr.Unwrap()
+ decodeErr := DecodeError{}
+ _ = decodeErr.Error()
+ _ = decodeErr.Unwrap()
+ invalidAddressErr := InvalidAddressError{}
+ _ = invalidAddressErr.Error()
+ _ = invalidAddressErr.Unwrap()
+ invalidPortErr := InvalidPortError{}
+ _ = invalidPortErr.Error()
+ _ = invalidPortErr.Unwrap()
+ invalidTokenErr := InvalidTokenError{}
+ _ = invalidTokenErr.Error()
+}
diff --git a/config/test_data/invalid_yaml b/config/test_data/invalid.yaml
index db1ddad..db1ddad 100644
--- a/config/test_data/invalid_yaml
+++ b/config/test_data/invalid.yaml
diff --git a/go.mod b/go.mod
index c7ec694..255bfa4 100644
--- a/go.mod
+++ b/go.mod
@@ -4,7 +4,7 @@ go 1.16
require (
github.com/kr/pretty v0.2.1 // indirect
- github.com/pkg/errors v0.9.1
+ github.com/stretchr/testify v1.7.0
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)
diff --git a/go.sum b/go.sum
index ba9b6cd..cd0dd5e 100644
--- a/go.sum
+++ b/go.sum
@@ -1,12 +1,18 @@
+github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=