sec/parse_env_test.go

884 lines
17 KiB
Go

// nolint:exhaustruct
package sec
import (
"os"
"strconv"
"testing"
"github.com/stretchr/testify/require"
)
func TestParseString(t *testing.T) {
type testStruct struct {
StringData string
}
t.Setenv("STRINGDATA", "test")
s := &testStruct{}
err := Parse(s, nil)
if err != nil {
t.Log(err.Error())
}
require.Nil(t, err)
}
func TestParseBoolean(t *testing.T) {
testCases := []struct {
TestData string
ValidData bool
}{
{"1", true},
{"t", true},
{"T", true},
{"TRUE", true},
{"true", true},
{"True", true},
{"0", false},
{"f", false},
{"F", false},
{"FALSE", false},
{"false", false},
{"False", false},
{"not a boolean", false},
}
type testStruct struct {
BoolData bool
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("BOOLDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
var checkNotBoolError bool
_, err2 := strconv.ParseBool(testCase.TestData)
if err2 != nil {
checkNotBoolError = true
}
if checkNotBoolError {
if err1 == nil {
t.Log("No error returned!")
}
require.NotNil(t, err1)
require.Equal(t, errNotBool, err1)
}
os.Unsetenv("BOOLDATA")
}
}
func TestParseInt8(t *testing.T) {
testCases := []struct {
TestData string
ValidData int8
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"-128", -128},
{"127", 127},
{"-129", 0},
{"128", 0},
{"not an integer", 0},
}
type testStruct struct {
IntData int8
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("INTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("INTDATA")
}
}
func TestParseInt16(t *testing.T) {
testCases := []struct {
TestData string
ValidData int16
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"-32768", -32768},
{"32767", 32767},
{"-32770", 0},
{"32770", 0},
{"not an integer", 0},
}
type testStruct struct {
IntData int16
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("INTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("INTDATA")
}
}
func TestParseInt32(t *testing.T) {
testCases := []struct {
TestData string
ValidData int32
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"-2147483648", -2147483648},
{"2147483647", 2147483647},
{"-2147483650", 0},
{"2147483650", 0},
{"not an integer", 0},
}
type testStruct struct {
IntData int32
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("INTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("INTDATA")
}
}
func TestParseInt64(t *testing.T) {
testCases := []struct {
TestData string
ValidData int64
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"-9223372036854775808", -9223372036854775808},
{"9223372036854775807", 9223372036854775807},
{"-9223372036854775810", -9223372036854775808},
{"9223372036854775810", 9223372036854775807},
{"not an integer", 0},
}
type testStruct struct {
IntData int64
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("INTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
var (
checkNotIntError bool
checkRangeError bool
)
passedData, err2 := strconv.ParseInt(testCase.TestData, 10, 64)
if err2 != nil {
checkNotIntError = true
}
if passedData != testCase.ValidData {
checkRangeError = true
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("INTDATA")
}
}
func TestParseUint8(t *testing.T) {
testCases := []struct {
TestData string
ValidData uint8
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"255", 255},
{"256", 0},
{"-1", 0},
{"not an integer", 0},
}
type testStruct struct {
UintData uint8
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("UINTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("UINTDATA")
}
}
func TestParseUint16(t *testing.T) {
testCases := []struct {
TestData string
ValidData uint16
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"65535", 65535},
{"65536", 0},
{"-1", 0},
{"not an integer", 0},
}
type testStruct struct {
UintData uint16
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("UINTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("UINTDATA")
}
}
func TestParseUint32(t *testing.T) {
testCases := []struct {
TestData string
ValidData uint32
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"4294967295", 4294967295},
{"4294967296", 0},
{"-1", 0},
{"not an integer", 0},
}
type testStruct struct {
UintData uint32
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("UINTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
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
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("UINTDATA")
}
}
func TestParseUint64(t *testing.T) {
testCases := []struct {
TestData string
ValidData uint64
}{
{"0", 0},
{"1", 1},
{"2", 2},
{"18446744073709551615", 18446744073709551615},
{"18446744073709551616", 18446744073709551615},
{"-1", 0},
{"not an integer", 0},
}
type testStruct struct {
UintData uint64
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("UINTDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
var (
checkNotIntError bool
checkRangeError bool
)
passedData, err2 := strconv.ParseUint(testCase.TestData, 10, 64)
if err2 != nil {
checkNotIntError = true
}
if passedData != testCase.ValidData {
checkRangeError = true
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("UINTDATA")
}
}
// Next tests should be improved.
func TestParseFloat32(t *testing.T) {
testCases := []struct {
TestData string
ValidData float32
}{
{"0.00", 0.00},
{"1.00", 1.00},
{"2.00", 2.00},
{"-1", -1},
{"not a float", 0.00},
}
type testStruct struct {
FloatData float32
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("FLOATDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
var (
checkNotIntError bool
checkRangeError bool
)
passedData, err2 := strconv.ParseFloat(testCase.TestData, 64)
if err2 != nil {
checkNotIntError = true
}
if passedData != float64(testCase.ValidData) {
checkRangeError = true
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("FLOATDATA")
}
}
func TestParseFloat64(t *testing.T) {
testCases := []struct {
TestData string
ValidData float64
}{
{"0.00", 0.00},
{"1.00", 1.00},
{"2.00", 2.00},
{"-1", -1},
{"not a float", 0.00},
}
type testStruct struct {
FloatData float64
}
for _, testCase := range testCases {
t.Logf("Testing: %+v", testCase)
t.Setenv("FLOATDATA", testCase.TestData)
// 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)
// If errors are critical - we should check if test data is within
// int8 range and check for error if it isn't.
s1 := &testStruct{}
err1 := Parse(s1, &Options{ErrorsAreCritical: true})
var (
checkNotIntError bool
checkRangeError bool
)
passedData, err2 := strconv.ParseFloat(testCase.TestData, 64)
if err2 != nil {
checkNotIntError = true
}
if passedData != testCase.ValidData {
checkRangeError = true
}
if checkNotIntError || checkRangeError {
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)
}
}
os.Unsetenv("FLOATDATA")
}
}
func TestParseStructWithInterfaceFields(t *testing.T) {
type testStruct struct {
Data interface{}
}
t.Setenv(debugFlagEnvName, "true")
testCase := &testStruct{}
testCase.Data = 0
t.Setenv("DATA", "64")
err := Parse(testCase, nil)
require.Nil(t, err)
require.NotEqual(t, 64, testCase.Data)
testCase1 := &testStruct{}
d := 0
shouldBeRaw := 64
shouldBe := &shouldBeRaw
testCase1.Data = &d
err1 := Parse(testCase1, nil)
require.Nil(t, err1)
// nolint:forcetypeassert
require.Equal(t, (*shouldBe), (*testCase1.Data.(*int)))
os.Unsetenv("DATA")
os.Unsetenv(debugFlagEnvName)
}
func TestParseStructWitStructAsInterface(t *testing.T) {
type testStruct struct {
Data interface{}
Int int
}
type testUnderlyingStruct struct {
Data string
}
t.Setenv(debugFlagEnvName, "true")
t.Setenv("INT", "64")
t.Setenv("DATA_DATA", "Test data")
testCase := &testStruct{}
testUnderlyingCase := &testUnderlyingStruct{}
testCase.Data = testUnderlyingCase
err := Parse(testCase, nil)
require.Nil(t, err)
require.Equal(t, testCase.Int, 64)
// nolint:forcetypeassert
require.Equal(t, testCase.Data.(*testUnderlyingStruct).Data, "Test data")
os.Unsetenv("INT")
os.Unsetenv("DATA_DATA")
os.Unsetenv(debugFlagEnvName)
}