Linting, CI, some small logic fixes.
This commit is contained in:
parent
94234816c5
commit
3d8d3e478c
10
.gitlab-ci.yml
Normal file
10
.gitlab-ci.yml
Normal file
@ -0,0 +1,10 @@
|
||||
stages:
|
||||
- test
|
||||
|
||||
lint:
|
||||
stage: test
|
||||
tags:
|
||||
- docker
|
||||
image: golangci/golangci-lint:v1.32.2
|
||||
script:
|
||||
- golangci-lint run
|
20
.golangci.yml
Normal file
20
.golangci.yml
Normal file
@ -0,0 +1,20 @@
|
||||
run:
|
||||
deadline: 5m
|
||||
linters:
|
||||
enable-all: true
|
||||
disable:
|
||||
- dupl
|
||||
- gochecknoglobals
|
||||
- exhaustive
|
||||
- testpackage
|
||||
linters-settings:
|
||||
lll:
|
||||
line-length: 120
|
||||
gocyclo:
|
||||
min-complexity: 80
|
||||
gocognit:
|
||||
min-complexity: 100
|
||||
funlen:
|
||||
lines: 200
|
||||
statements: 100
|
||||
|
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -2,5 +2,6 @@
|
||||
"go.testFlags": [
|
||||
"-test.v",
|
||||
"-cover"
|
||||
]
|
||||
],
|
||||
"go.inferGopath": false
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
@ -30,6 +29,14 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
}
|
||||
|
||||
if value.Kind() != reflect.Struct {
|
||||
if value.Kind() == reflect.Map {
|
||||
newElementPrefix := curPrefix
|
||||
|
||||
mapIter := value.MapRange()
|
||||
for mapIter.Next() {
|
||||
composeTree(mapIter.Value().Elem(), newElementPrefix+"_"+strings.ToUpper(mapIter.Key().String()))
|
||||
}
|
||||
} else {
|
||||
f := &field{
|
||||
Name: typeOf.Name(),
|
||||
EnvVar: curPrefix + strings.ToUpper(typeOf.Name()),
|
||||
@ -39,7 +46,8 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
|
||||
parsedTree = append(parsedTree, f)
|
||||
|
||||
printDebug("Field data constructed: %+v", f)
|
||||
printDebug("Field data constructed (start): %+v", f)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@ -72,25 +80,35 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
fieldToProcess.Set(reflect.New(fieldToProcess.Type().Elem()))
|
||||
} else {
|
||||
printDebug("Field '%s' is unexported and will be ignored", fieldToProcessType.Name)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
fieldToProcess = fieldToProcess.Elem()
|
||||
}
|
||||
}
|
||||
|
||||
printDebug("Field: '%s', type: %s (anonymous or embedded: %t)", fieldToProcessType.Name, fieldToProcess.Type().Kind().String(), fieldToProcessType.Anonymous)
|
||||
printDebug("Field: '%s', type: %s (anonymous or embedded: %t)",
|
||||
fieldToProcessType.Name,
|
||||
fieldToProcess.Type().Kind().String(),
|
||||
fieldToProcessType.Anonymous,
|
||||
)
|
||||
|
||||
// Dealing with embedded things.
|
||||
if fieldToProcessType.Anonymous {
|
||||
// We should not allow anything other than struct.
|
||||
if fieldToProcess.Kind() != reflect.Struct {
|
||||
printDebug("Field is embedded, but not a struct (%s), which cannot be used", fieldToProcess.Kind().String())
|
||||
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if fieldToProcess.Kind() != reflect.Struct && !fieldToProcess.CanSet() {
|
||||
printDebug("Field '%s' of type '%s' can't be set, skipping", fieldToProcessType.Name, fieldToProcess.Type().Kind().String())
|
||||
printDebug("Field '%s' of type '%s' can't be set, skipping",
|
||||
fieldToProcessType.Name,
|
||||
fieldToProcess.Type().Kind().String())
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
@ -98,13 +116,15 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
|
||||
// Hello, I'm recursion and I'm here to make you happy.
|
||||
// I'll be launched only for structures to get their fields.
|
||||
if fieldToProcess.Kind() == reflect.Struct {
|
||||
switch fieldToProcess.Kind() {
|
||||
case reflect.Struct:
|
||||
newElementPrefix := curPrefix
|
||||
if !fieldToProcessType.Anonymous {
|
||||
newElementPrefix = strings.ToUpper(newElementPrefix + typeOf.Field(i).Name)
|
||||
}
|
||||
|
||||
composeTree(fieldToProcess, newElementPrefix)
|
||||
} else if fieldToProcess.Kind() == reflect.Map {
|
||||
case reflect.Map:
|
||||
newElementPrefix := curPrefix
|
||||
if !fieldToProcessType.Anonymous {
|
||||
newElementPrefix = strings.ToUpper(newElementPrefix + typeOf.Field(i).Name)
|
||||
@ -114,7 +134,7 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
for mapIter.Next() {
|
||||
composeTree(mapIter.Value().Elem(), newElementPrefix+"_"+strings.ToUpper(mapIter.Key().String()))
|
||||
}
|
||||
} else {
|
||||
default:
|
||||
f := &field{
|
||||
Name: typeOf.Field(i).Name,
|
||||
EnvVar: curPrefix + strings.ToUpper(typeOf.Field(i).Name),
|
||||
@ -124,7 +144,7 @@ func composeTree(value reflect.Value, prefix string) {
|
||||
|
||||
parsedTree = append(parsedTree, f)
|
||||
|
||||
printDebug("Field data constructed: %+v", f)
|
||||
printDebug("Field data constructed (end): %+v", f)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
3
field.go
3
field.go
@ -1,7 +1,6 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"reflect"
|
||||
)
|
||||
|
||||
@ -18,5 +17,5 @@ type field struct {
|
||||
Kind reflect.Kind
|
||||
|
||||
// Next variables are tag-related.
|
||||
optional bool
|
||||
// optional bool
|
||||
}
|
||||
|
@ -1,7 +1,6 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"reflect"
|
||||
"strconv"
|
||||
@ -15,10 +14,12 @@ func fillValue(element *field, data string) error {
|
||||
val, err := strconv.ParseBool(data)
|
||||
if err != nil {
|
||||
printDebug("Error occurred while parsing boolean: %s", err.Error())
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return errNotBool
|
||||
}
|
||||
}
|
||||
|
||||
element.Pointer.SetBool(val)
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
// Bitsize 64 here specified for a reason - actual ints
|
||||
@ -27,10 +28,12 @@ func fillValue(element *field, data string) error {
|
||||
val, err := strconv.ParseInt(data, 10, 64)
|
||||
if err != nil {
|
||||
printDebug("Error occurred while parsing int: %s", err.Error())
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return errNotInt
|
||||
}
|
||||
}
|
||||
|
||||
switch element.Kind {
|
||||
case reflect.Int8:
|
||||
// int8 is an integer in [-128...127] range.
|
||||
@ -75,14 +78,16 @@ func fillValue(element *field, data string) error {
|
||||
val, err := strconv.ParseUint(data, 10, 64)
|
||||
if err != nil {
|
||||
printDebug("Error occurred while parsing unsigned integer: %s", err.Error())
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return errNotUint
|
||||
}
|
||||
}
|
||||
|
||||
switch element.Kind {
|
||||
case reflect.Uint8:
|
||||
// uint8 is an integer in [0...255] range.
|
||||
if val <= 255 {
|
||||
if val <= uint64(^uint8(0)) {
|
||||
element.Pointer.SetUint(val)
|
||||
} else {
|
||||
printDebug("Data in environment variable '%s' isn't uint8", element.EnvVar)
|
||||
@ -93,7 +98,7 @@ func fillValue(element *field, data string) error {
|
||||
}
|
||||
case reflect.Uint16:
|
||||
// uint16 is an integer in [0...65535] range.
|
||||
if val <= 65535 {
|
||||
if val <= uint64(^uint16(0)) {
|
||||
element.Pointer.SetUint(val)
|
||||
} else {
|
||||
printDebug("Data in environment variable '%s' isn't uint16", element.EnvVar)
|
||||
@ -104,7 +109,7 @@ func fillValue(element *field, data string) error {
|
||||
}
|
||||
case reflect.Uint32:
|
||||
// uint32 is an integer in [0...4294967295] range.
|
||||
if val <= 4294967295 {
|
||||
if val <= uint64(^uint32(0)) {
|
||||
element.Pointer.SetUint(val)
|
||||
} else {
|
||||
printDebug("Data in environment variable '%s' isn't uint32", element.EnvVar)
|
||||
@ -123,19 +128,25 @@ func fillValue(element *field, data string) error {
|
||||
val, err := strconv.ParseFloat(data, 64)
|
||||
if err != nil {
|
||||
printDebug("Error occurred while parsing float: %s", err.Error())
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return errNotFloat
|
||||
}
|
||||
}
|
||||
|
||||
element.Pointer.SetFloat(val)
|
||||
case reflect.Interface:
|
||||
// We should not attempt to work with data in interface{}
|
||||
// unless it is a pointer to value.
|
||||
if element.Pointer.Elem().Kind() != reflect.Ptr {
|
||||
printDebug("Element for environment variable '%s' isn't a pointer and put into interface{}. Nothing will be done with this element.", element.EnvVar)
|
||||
printDebug("Element for environment variable '%s' isn't a pointer and put "+
|
||||
"into interface{}. Nothing will be done with this element.",
|
||||
element.EnvVar)
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return errors.New("element for environment variable '" + element.EnvVar + "' isn't a pointer and put into interface")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -143,7 +154,9 @@ func fillValue(element *field, data string) error {
|
||||
// It goes interface{} -> ptr -> real element.
|
||||
element.Pointer = element.Pointer.Elem().Elem()
|
||||
element.Kind = element.Pointer.Kind()
|
||||
|
||||
return fillValue(element, data)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
@ -11,8 +11,6 @@ type Options struct {
|
||||
ErrorsAreCritical bool
|
||||
}
|
||||
|
||||
var (
|
||||
defaultOptions = &Options{
|
||||
var defaultOptions = &Options{
|
||||
ErrorsAreCritical: false,
|
||||
}
|
||||
)
|
||||
|
@ -1,7 +1,6 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"os"
|
||||
)
|
||||
@ -32,9 +31,11 @@ func parseEnv() error {
|
||||
|
||||
for _, element := range parsedTree {
|
||||
printDebug("Processing element '%s'", element.EnvVar)
|
||||
|
||||
data, found := os.LookupEnv(element.EnvVar)
|
||||
if !found {
|
||||
printDebug("Value for '%s' environment variable wasn't found", element.EnvVar)
|
||||
|
||||
continue
|
||||
} else {
|
||||
printDebug("Value for '%s' will be: %s", element.EnvVar, data)
|
||||
|
@ -1,12 +1,10 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
// other
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -18,10 +16,12 @@ func TestParseString(t *testing.T) {
|
||||
os.Setenv("STRINGDATA", "test")
|
||||
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
}
|
||||
|
||||
@ -56,10 +56,12 @@ func TestParseBoolean(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.BoolData)
|
||||
|
||||
@ -69,6 +71,7 @@ func TestParseBoolean(t *testing.T) {
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotBoolError bool
|
||||
|
||||
_, err2 := strconv.ParseBool(testCase.TestData)
|
||||
if err2 != nil {
|
||||
checkNotBoolError = true
|
||||
@ -78,6 +81,7 @@ func TestParseBoolean(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
require.Equal(t, errNotBool, err1)
|
||||
}
|
||||
@ -112,10 +116,12 @@ func TestParseInt8(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.IntData)
|
||||
|
||||
@ -124,12 +130,16 @@ func TestParseInt8(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseInt(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != int64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -138,11 +148,13 @@ func TestParseInt8(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotInt, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotInt8, err1)
|
||||
}
|
||||
@ -178,10 +190,12 @@ func TestParseInt16(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.IntData)
|
||||
|
||||
@ -190,12 +204,16 @@ func TestParseInt16(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseInt(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != int64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -204,11 +222,13 @@ func TestParseInt16(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotInt, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotInt16, err1)
|
||||
}
|
||||
@ -244,10 +264,12 @@ func TestParseInt32(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.IntData)
|
||||
|
||||
@ -256,12 +278,16 @@ func TestParseInt32(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseInt(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != int64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -270,11 +296,13 @@ func TestParseInt32(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotInt, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotInt32, err1)
|
||||
}
|
||||
@ -310,10 +338,12 @@ func TestParseInt64(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.IntData)
|
||||
|
||||
@ -322,12 +352,16 @@ func TestParseInt64(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseInt(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != testCase.ValidData {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -336,11 +370,13 @@ func TestParseInt64(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotInt, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotInt64, err1)
|
||||
}
|
||||
@ -375,10 +411,12 @@ func TestParseUint8(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.UintData)
|
||||
|
||||
@ -387,12 +425,16 @@ func TestParseUint8(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseUint(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != uint64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -401,11 +443,13 @@ func TestParseUint8(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotUint, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotUint8, err1)
|
||||
}
|
||||
@ -440,10 +484,12 @@ func TestParseUint16(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.UintData)
|
||||
|
||||
@ -452,12 +498,16 @@ func TestParseUint16(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseUint(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != uint64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -466,11 +516,13 @@ func TestParseUint16(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotUint, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotUint16, err1)
|
||||
}
|
||||
@ -505,10 +557,12 @@ func TestParseUint32(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.UintData)
|
||||
|
||||
@ -517,12 +571,16 @@ func TestParseUint32(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseUint(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != uint64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -531,11 +589,13 @@ func TestParseUint32(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotUint, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotUint32, err1)
|
||||
}
|
||||
@ -570,10 +630,12 @@ func TestParseUint64(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.UintData)
|
||||
|
||||
@ -582,12 +644,16 @@ func TestParseUint64(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseUint(testCase.TestData, 10, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != testCase.ValidData {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -596,11 +662,13 @@ func TestParseUint64(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotUint, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotUint64, err1)
|
||||
}
|
||||
@ -634,10 +702,12 @@ func TestParseFloat32(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.FloatData)
|
||||
|
||||
@ -646,12 +716,16 @@ func TestParseFloat32(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseFloat(testCase.TestData, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != float64(testCase.ValidData) {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -660,11 +734,13 @@ func TestParseFloat32(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotFloat, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotFloat32, err1)
|
||||
}
|
||||
@ -697,10 +773,12 @@ func TestParseFloat64(t *testing.T) {
|
||||
// If ErrorsAreCritical == false, then we should check only
|
||||
// equality of parsed data and valid data.
|
||||
s := &testStruct{}
|
||||
|
||||
err := Parse(s, nil)
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, testCase.ValidData, s.FloatData)
|
||||
|
||||
@ -709,12 +787,16 @@ func TestParseFloat64(t *testing.T) {
|
||||
s1 := &testStruct{}
|
||||
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
|
||||
|
||||
var checkNotIntError bool
|
||||
var checkRangeError bool
|
||||
var (
|
||||
checkNotIntError bool
|
||||
checkRangeError bool
|
||||
)
|
||||
|
||||
passedData, err2 := strconv.ParseFloat(testCase.TestData, 64)
|
||||
if err2 != nil {
|
||||
checkNotIntError = true
|
||||
}
|
||||
|
||||
if passedData != testCase.ValidData {
|
||||
checkRangeError = true
|
||||
}
|
||||
@ -723,11 +805,13 @@ func TestParseFloat64(t *testing.T) {
|
||||
if err1 == nil {
|
||||
t.Log("No error returned!")
|
||||
}
|
||||
|
||||
require.NotNil(t, err1)
|
||||
|
||||
if checkNotIntError {
|
||||
require.Equal(t, errNotFloat, err1)
|
||||
}
|
||||
|
||||
if checkRangeError {
|
||||
require.Equal(t, errNotFloat64, err1)
|
||||
}
|
||||
@ -772,6 +856,7 @@ func TestParseStructWitStructAsInterface(t *testing.T) {
|
||||
Data interface{}
|
||||
Int int
|
||||
}
|
||||
|
||||
type testUnderlyingStruct struct {
|
||||
Data string
|
||||
}
|
||||
|
5
sec.go
5
sec.go
@ -1,7 +1,6 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"errors"
|
||||
"log"
|
||||
"os"
|
||||
@ -38,9 +37,11 @@ func Parse(structure interface{}, config *Options) error {
|
||||
debugFlagRaw, found := os.LookupEnv(debugFlagEnvName)
|
||||
if found {
|
||||
var err error
|
||||
|
||||
debug, err = strconv.ParseBool(debugFlagRaw)
|
||||
if err != nil {
|
||||
log.Println("Invalid '" + debugFlagEnvName + "' environment variable data: '" + debugFlagRaw + "'. Error: " + err.Error())
|
||||
log.Printf("Invalid '%s' environment variable data: '%s'. Error: %s", debugFlagEnvName, debugFlagRaw, err.Error())
|
||||
|
||||
if options.ErrorsAreCritical {
|
||||
return err
|
||||
}
|
||||
|
81
sec_test.go
81
sec_test.go
@ -1,12 +1,10 @@
|
||||
package sec
|
||||
|
||||
import (
|
||||
// stdlib
|
||||
"os"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
// other
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
@ -26,18 +24,23 @@ var (
|
||||
)
|
||||
|
||||
type testDatas struct {
|
||||
TestString string
|
||||
TestInt8 int8
|
||||
TestInt16 int16
|
||||
TestInt32 int32
|
||||
TestInt64 int64
|
||||
TestUint8 uint8
|
||||
TestUint16 uint16
|
||||
TestUint32 uint32
|
||||
TestUint64 uint64
|
||||
TestFloat32 float32
|
||||
TestFloat64 float64
|
||||
TestUint64 uint64
|
||||
TestInt64 int64
|
||||
|
||||
TestFloat32 float32
|
||||
TestUint32 uint32
|
||||
TestInt32 int32
|
||||
|
||||
TestUint16 uint16
|
||||
TestInt16 int16
|
||||
|
||||
TestUint8 uint8
|
||||
TestInt8 int8
|
||||
|
||||
TestBool bool
|
||||
|
||||
TestString string
|
||||
}
|
||||
|
||||
type testStringType string
|
||||
@ -46,32 +49,42 @@ type testStruct1 struct {
|
||||
testDatas
|
||||
testStringType
|
||||
TestNestAnonymous struct {
|
||||
TestString string
|
||||
TestInt8 int8
|
||||
TestInt16 int16
|
||||
TestInt32 int32
|
||||
TestInt64 int64
|
||||
TestUint8 uint8
|
||||
TestUint16 uint16
|
||||
TestUint32 uint32
|
||||
TestUint64 uint64
|
||||
TestFloat32 float32
|
||||
TestFloat64 float64
|
||||
TestUint64 uint64
|
||||
TestInt64 int64
|
||||
|
||||
TestFloat32 float32
|
||||
TestUint32 uint32
|
||||
TestInt32 int32
|
||||
|
||||
TestUint16 uint16
|
||||
TestInt16 int16
|
||||
|
||||
TestUint8 uint8
|
||||
TestInt8 int8
|
||||
|
||||
TestBool bool
|
||||
|
||||
TestString string
|
||||
}
|
||||
TestNestAnonymousPointer *struct {
|
||||
TestString string
|
||||
TestInt8 int8
|
||||
TestInt16 int16
|
||||
TestInt32 int32
|
||||
TestInt64 int64
|
||||
TestUint8 uint8
|
||||
TestUint16 uint16
|
||||
TestUint32 uint32
|
||||
TestUint64 uint64
|
||||
TestFloat32 float32
|
||||
TestFloat64 float64
|
||||
TestUint64 uint64
|
||||
TestInt64 int64
|
||||
|
||||
TestFloat32 float32
|
||||
TestUint32 uint32
|
||||
TestInt32 int32
|
||||
|
||||
TestUint16 uint16
|
||||
TestInt16 int16
|
||||
|
||||
TestUint8 uint8
|
||||
TestInt8 int8
|
||||
|
||||
TestBool bool
|
||||
|
||||
TestString string
|
||||
}
|
||||
TestNestPointer *testDatas
|
||||
TestNest testDatas
|
||||
@ -90,7 +103,7 @@ func setenv(prefix string) {
|
||||
os.Setenv(prefix+"TESTINT8", strconv.FormatInt(int64(testInt8), 10))
|
||||
os.Setenv(prefix+"TESTINT16", strconv.FormatInt(int64(testInt16), 10))
|
||||
os.Setenv(prefix+"TESTINT32", strconv.FormatInt(int64(testInt32), 10))
|
||||
os.Setenv(prefix+"TESTINT64", strconv.FormatInt(int64(testInt64), 10))
|
||||
os.Setenv(prefix+"TESTINT64", strconv.FormatInt(testInt64, 10))
|
||||
os.Setenv(prefix+"TESTUINT8", strconv.FormatInt(int64(testUint8), 10))
|
||||
os.Setenv(prefix+"TESTUINT16", strconv.FormatInt(int64(testUint16), 10))
|
||||
os.Setenv(prefix+"TESTUINT32", strconv.FormatInt(int64(testUint32), 10))
|
||||
@ -209,8 +222,8 @@ func TestInvalidDebugFlagValue(t *testing.T) {
|
||||
func TestInvalidDebugFlagValueWithErrorsAreCritical(t *testing.T) {
|
||||
_ = os.Setenv(debugFlagEnvName, "INVALID")
|
||||
c := &testStruct1{}
|
||||
err := Parse(c, &Options{ErrorsAreCritical: true})
|
||||
|
||||
err := Parse(c, &Options{ErrorsAreCritical: true})
|
||||
if err != nil {
|
||||
t.Log(err.Error())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user