Linting, CI, some small logic fixes.

This commit is contained in:
Stanislav Nikitin 2020-11-21 21:25:16 +05:00
parent 94234816c5
commit 3d8d3e478c
No known key found for this signature in database
GPG Key ID: 106900B32F8192EE
11 changed files with 252 additions and 91 deletions

10
.gitlab-ci.yml Normal file
View 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
View 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

View File

@ -2,5 +2,6 @@
"go.testFlags": [
"-test.v",
"-cover"
]
],
"go.inferGopath": false
}

View File

@ -1,7 +1,6 @@
package sec
import (
// stdlib
"reflect"
"strings"
)
@ -30,17 +29,26 @@ func composeTree(value reflect.Value, prefix string) {
}
if value.Kind() != reflect.Struct {
f := &field{
Name: typeOf.Name(),
EnvVar: curPrefix + strings.ToUpper(typeOf.Name()),
Pointer: value,
Kind: value.Kind(),
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()),
Pointer: value,
Kind: value.Kind(),
}
parsedTree = append(parsedTree, f)
printDebug("Field data constructed (start): %+v", f)
}
parsedTree = append(parsedTree, f)
printDebug("Field data constructed: %+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)
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -11,8 +11,6 @@ type Options struct {
ErrorsAreCritical bool
}
var (
defaultOptions = &Options{
ErrorsAreCritical: false,
}
)
var defaultOptions = &Options{
ErrorsAreCritical: false,
}

View File

@ -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)

View File

@ -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
View File

@ -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
}

View File

@ -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
TestBool bool
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
TestBool bool
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
TestBool bool
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())
}