mirror of
https://github.com/aykhans/dodo.git
synced 2025-09-05 18:44:21 +00:00
1167 lines
34 KiB
Go
1167 lines
34 KiB
Go
package parser
|
|
|
|
import (
|
|
"net/url"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/aykhans/dodo/pkg/config"
|
|
"github.com/aykhans/dodo/pkg/types"
|
|
"github.com/aykhans/dodo/pkg/utils"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestNewConfigENVParser(t *testing.T) {
|
|
t.Run("NewConfigENVParser with empty prefix", func(t *testing.T) {
|
|
parser := NewConfigENVParser("")
|
|
require.NotNil(t, parser)
|
|
assert.Empty(t, parser.envPrefix)
|
|
})
|
|
|
|
t.Run("NewConfigENVParser with prefix", func(t *testing.T) {
|
|
parser := NewConfigENVParser("DODO")
|
|
require.NotNil(t, parser)
|
|
assert.Equal(t, "DODO", parser.envPrefix)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_getFullEnvName(t *testing.T) {
|
|
t.Run("getFullEnvName with empty prefix", func(t *testing.T) {
|
|
parser := ConfigENVParser{envPrefix: ""}
|
|
assert.Equal(t, "URL", parser.getFullEnvName("URL"))
|
|
assert.Equal(t, "METHOD", parser.getFullEnvName("METHOD"))
|
|
})
|
|
|
|
t.Run("getFullEnvName with prefix", func(t *testing.T) {
|
|
parser := ConfigENVParser{envPrefix: "DODO"}
|
|
assert.Equal(t, "DODO_URL", parser.getFullEnvName("URL"))
|
|
assert.Equal(t, "DODO_METHOD", parser.getFullEnvName("METHOD"))
|
|
})
|
|
|
|
t.Run("getFullEnvName with complex prefix", func(t *testing.T) {
|
|
parser := ConfigENVParser{envPrefix: "MY_APP"}
|
|
assert.Equal(t, "MY_APP_CONFIG_FILE", parser.getFullEnvName("CONFIG_FILE"))
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_getEnv(t *testing.T) {
|
|
t.Run("getEnv with empty prefix", func(t *testing.T) {
|
|
t.Setenv("TEST_ENV_VAR", "test_value")
|
|
|
|
parser := ConfigENVParser{envPrefix: ""}
|
|
assert.Equal(t, "test_value", parser.getEnv("TEST_ENV_VAR"))
|
|
})
|
|
|
|
t.Run("getEnv with prefix", func(t *testing.T) {
|
|
t.Setenv("PREFIX_TEST_VAR", "prefixed_value")
|
|
|
|
parser := ConfigENVParser{envPrefix: "PREFIX"}
|
|
assert.Equal(t, "prefixed_value", parser.getEnv("TEST_VAR"))
|
|
})
|
|
|
|
t.Run("getEnv for non-existent variable", func(t *testing.T) {
|
|
parser := ConfigENVParser{envPrefix: "PREFIX"}
|
|
assert.Empty(t, parser.getEnv("NON_EXISTENT"))
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_ConfigFile(t *testing.T) {
|
|
t.Run("Parse with valid YAML config file", func(t *testing.T) {
|
|
t.Setenv("CONFIG_FILE", "/path/to/config.yaml")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, "/path/to/config.yaml", config.Files[0].String())
|
|
assert.Equal(t, types.ConfigFileTypeYAML, config.Files[0].Type())
|
|
})
|
|
|
|
t.Run("Parse with config file without extension", func(t *testing.T) {
|
|
t.Setenv("CONFIG_FILE", "/path/to/config")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "CONFIG_FILE", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "/path/to/config", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "file extension not found")
|
|
})
|
|
|
|
t.Run("Parse with unsupported config file type", func(t *testing.T) {
|
|
t.Setenv("CONFIG_FILE", "/path/to/config.json")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "CONFIG_FILE", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "/path/to/config.json", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "file type")
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "not supported")
|
|
})
|
|
|
|
t.Run("Parse with remote config file URL", func(t *testing.T) {
|
|
t.Setenv("CONFIG_FILE", "https://example.com/config.yaml")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, "https://example.com/config.yaml", config.Files[0].String())
|
|
assert.Equal(t, types.ConfigFileTypeYAML, config.Files[0].Type())
|
|
assert.Equal(t, types.ConfigFileLocationRemote, config.Files[0].LocationType())
|
|
})
|
|
|
|
t.Run("Parse with config file using prefix", func(t *testing.T) {
|
|
t.Setenv("DODO_CONFIG_FILE", "/path/to/config.yml")
|
|
|
|
parser := NewConfigENVParser("DODO")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Files, 1)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_BooleanFields(t *testing.T) {
|
|
t.Run("Parse with YES=true", func(t *testing.T) {
|
|
t.Setenv("YES", "true")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Yes)
|
|
assert.True(t, *config.Yes)
|
|
})
|
|
|
|
t.Run("Parse with YES=false", func(t *testing.T) {
|
|
t.Setenv("YES", "false")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Yes)
|
|
assert.False(t, *config.Yes)
|
|
})
|
|
|
|
t.Run("Parse with invalid YES value", func(t *testing.T) {
|
|
t.Setenv("YES", "maybe")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "YES", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "maybe", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value for boolean")
|
|
})
|
|
|
|
t.Run("Parse with SKIP_VERIFY=true", func(t *testing.T) {
|
|
t.Setenv("SKIP_VERIFY", "true")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.True(t, *config.SkipVerify)
|
|
})
|
|
|
|
t.Run("Parse with invalid SKIP_VERIFY value", func(t *testing.T) {
|
|
t.Setenv("SKIP_VERIFY", "invalid")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "SKIP_VERIFY", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "invalid", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value for boolean")
|
|
})
|
|
|
|
t.Run("Parse with numeric boolean values", func(t *testing.T) {
|
|
t.Setenv("YES", "1")
|
|
t.Setenv("SKIP_VERIFY", "0")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Yes)
|
|
assert.True(t, *config.Yes, "1 should be parsed as true")
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.False(t, *config.SkipVerify, "0 should be parsed as false")
|
|
})
|
|
|
|
t.Run("Parse boolean fields with prefix", func(t *testing.T) {
|
|
t.Setenv("APP_YES", "true")
|
|
t.Setenv("APP_SKIP_VERIFY", "false")
|
|
|
|
parser := NewConfigENVParser("APP")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Yes)
|
|
assert.True(t, *config.Yes)
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.False(t, *config.SkipVerify)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_StringFields(t *testing.T) {
|
|
t.Run("Parse with METHOD", func(t *testing.T) {
|
|
t.Setenv("METHOD", "POST")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "POST", *config.Method)
|
|
})
|
|
|
|
t.Run("Parse with empty METHOD", func(t *testing.T) {
|
|
t.Setenv("METHOD", "")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Nil(t, config.Method)
|
|
})
|
|
|
|
t.Run("Parse METHOD with prefix", func(t *testing.T) {
|
|
t.Setenv("TEST_METHOD", "DELETE")
|
|
|
|
parser := NewConfigENVParser("TEST")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "DELETE", *config.Method)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_URL(t *testing.T) {
|
|
t.Run("Parse with valid URL", func(t *testing.T) {
|
|
t.Setenv("URL", "https://api.example.com/v1/endpoint")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.URL)
|
|
assert.Equal(t, "https://api.example.com/v1/endpoint", config.URL.String())
|
|
})
|
|
|
|
t.Run("Parse with invalid URL", func(t *testing.T) {
|
|
t.Setenv("URL", "://invalid-url")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "URL", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "://invalid-url", fieldErr.Errors[0].Value)
|
|
})
|
|
|
|
t.Run("Parse URL with query parameters", func(t *testing.T) {
|
|
t.Setenv("URL", "https://api.example.com?param1=value1¶m2=value2")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.URL)
|
|
|
|
parsedURL, _ := url.Parse("https://api.example.com?param1=value1¶m2=value2")
|
|
assert.Equal(t, parsedURL, config.URL)
|
|
})
|
|
|
|
t.Run("Parse URL with prefix", func(t *testing.T) {
|
|
t.Setenv("MY_APP_URL", "https://example.com")
|
|
|
|
parser := NewConfigENVParser("MY_APP")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.URL)
|
|
assert.Equal(t, "https://example.com", config.URL.String())
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_UintFields(t *testing.T) {
|
|
t.Run("Parse with DODOS", func(t *testing.T) {
|
|
t.Setenv("DODOS", "10")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(10), *config.DodosCount)
|
|
})
|
|
|
|
t.Run("Parse with invalid DODOS value", func(t *testing.T) {
|
|
t.Setenv("DODOS", "-5")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "DODOS", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "-5", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value for unsigned integer")
|
|
})
|
|
|
|
t.Run("Parse with REQUESTS", func(t *testing.T) {
|
|
t.Setenv("REQUESTS", "1000")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(1000), *config.RequestCount)
|
|
})
|
|
|
|
t.Run("Parse with invalid REQUESTS value", func(t *testing.T) {
|
|
t.Setenv("REQUESTS", "not_a_number")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "REQUESTS", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "not_a_number", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value for unsigned integer")
|
|
})
|
|
|
|
t.Run("Parse with zero values", func(t *testing.T) {
|
|
t.Setenv("DODOS", "0")
|
|
t.Setenv("REQUESTS", "0")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(0), *config.DodosCount)
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(0), *config.RequestCount)
|
|
})
|
|
|
|
t.Run("Parse uint fields with prefix", func(t *testing.T) {
|
|
t.Setenv("TEST_DODOS", "5")
|
|
t.Setenv("TEST_REQUESTS", "500")
|
|
|
|
parser := NewConfigENVParser("TEST")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(5), *config.DodosCount)
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(500), *config.RequestCount)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_DurationFields(t *testing.T) {
|
|
t.Run("Parse with DURATION", func(t *testing.T) {
|
|
t.Setenv("DURATION", "5m")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, 5*time.Minute, *config.Duration)
|
|
})
|
|
|
|
t.Run("Parse with complex DURATION", func(t *testing.T) {
|
|
t.Setenv("DURATION", "1h30m45s")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Duration)
|
|
expected := time.Hour + 30*time.Minute + 45*time.Second
|
|
assert.Equal(t, expected, *config.Duration)
|
|
})
|
|
|
|
t.Run("Parse with invalid DURATION", func(t *testing.T) {
|
|
t.Setenv("DURATION", "invalid")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "DURATION", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "invalid", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value duration")
|
|
})
|
|
|
|
t.Run("Parse with TIMEOUT", func(t *testing.T) {
|
|
t.Setenv("TIMEOUT", "30s")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 30*time.Second, *config.Timeout)
|
|
})
|
|
|
|
t.Run("Parse with invalid TIMEOUT", func(t *testing.T) {
|
|
t.Setenv("TIMEOUT", "30")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "TIMEOUT", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "30", fieldErr.Errors[0].Value)
|
|
assert.Contains(t, fieldErr.Errors[0].Err.Error(), "invalid value duration")
|
|
})
|
|
|
|
t.Run("Parse with zero durations", func(t *testing.T) {
|
|
t.Setenv("DURATION", "0s")
|
|
t.Setenv("TIMEOUT", "0s")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, time.Duration(0), *config.Duration)
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, time.Duration(0), *config.Timeout)
|
|
})
|
|
|
|
t.Run("Parse duration fields with prefix", func(t *testing.T) {
|
|
t.Setenv("APP_DURATION", "10m")
|
|
t.Setenv("APP_TIMEOUT", "5s")
|
|
|
|
parser := NewConfigENVParser("APP")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, 10*time.Minute, *config.Duration)
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 5*time.Second, *config.Timeout)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_CollectionFields(t *testing.T) {
|
|
t.Run("Parse with PARAM", func(t *testing.T) {
|
|
t.Setenv("PARAM", "key1=value1")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Params, 1)
|
|
assert.Equal(t, "key1", config.Params[0].Key)
|
|
assert.Equal(t, []string{"value1"}, config.Params[0].Value)
|
|
})
|
|
|
|
t.Run("Parse with HEADER", func(t *testing.T) {
|
|
t.Setenv("HEADER", "Content-Type: application/json")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Equal(t, "Content-Type", config.Headers[0].Key)
|
|
assert.Equal(t, []string{"application/json"}, config.Headers[0].Value)
|
|
})
|
|
|
|
t.Run("Parse with COOKIE", func(t *testing.T) {
|
|
t.Setenv("COOKIE", "session=abc123")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Cookies, 1)
|
|
assert.Equal(t, "session", config.Cookies[0].Key)
|
|
assert.Equal(t, []string{"abc123"}, config.Cookies[0].Value)
|
|
})
|
|
|
|
t.Run("Parse with BODY", func(t *testing.T) {
|
|
t.Setenv("BODY", `{"data": "test"}`)
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Bodies, 1)
|
|
assert.Equal(t, types.Body(`{"data": "test"}`), config.Bodies[0]) //nolint:testifylint
|
|
})
|
|
|
|
t.Run("Parse collection fields with prefix", func(t *testing.T) {
|
|
t.Setenv("APP_PARAM", "api_key=secret")
|
|
t.Setenv("APP_HEADER", "Authorization: Bearer token")
|
|
t.Setenv("APP_COOKIE", "user=john")
|
|
t.Setenv("APP_BODY", "request body")
|
|
|
|
parser := NewConfigENVParser("APP")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Params, 1)
|
|
assert.Equal(t, "api_key", config.Params[0].Key)
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Equal(t, "Authorization", config.Headers[0].Key)
|
|
assert.Len(t, config.Cookies, 1)
|
|
assert.Equal(t, "user", config.Cookies[0].Key)
|
|
assert.Len(t, config.Bodies, 1)
|
|
assert.Equal(t, types.Body("request body"), config.Bodies[0])
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_Proxy(t *testing.T) {
|
|
t.Run("Parse with valid PROXY", func(t *testing.T) {
|
|
t.Setenv("PROXY", "http://proxy.example.com:8080")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Proxies, 1)
|
|
assert.Equal(t, "http://proxy.example.com:8080", config.Proxies[0].String())
|
|
})
|
|
|
|
t.Run("Parse with invalid PROXY", func(t *testing.T) {
|
|
t.Setenv("PROXY", "://invalid-proxy")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
assert.Len(t, fieldErr.Errors, 1)
|
|
assert.Equal(t, "PROXY", fieldErr.Errors[0].Field)
|
|
assert.Equal(t, "://invalid-proxy", fieldErr.Errors[0].Value)
|
|
})
|
|
|
|
t.Run("Parse PROXY with SOCKS5", func(t *testing.T) {
|
|
t.Setenv("PROXY", "socks5://127.0.0.1:1080")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Proxies, 1)
|
|
assert.Equal(t, "socks5://127.0.0.1:1080", config.Proxies[0].String())
|
|
})
|
|
|
|
t.Run("Parse PROXY with prefix", func(t *testing.T) {
|
|
t.Setenv("TEST_PROXY", "http://proxy.test.com:3128")
|
|
|
|
parser := NewConfigENVParser("TEST")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
assert.Len(t, config.Proxies, 1)
|
|
assert.Equal(t, "http://proxy.test.com:3128", config.Proxies[0].String())
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_AllFields(t *testing.T) {
|
|
t.Run("Parse with all environment variables set", func(t *testing.T) {
|
|
// Set all environment variables
|
|
t.Setenv("CONFIG_FILE", "/path/to/config.yaml")
|
|
t.Setenv("YES", "true")
|
|
t.Setenv("SKIP_VERIFY", "true")
|
|
t.Setenv("METHOD", "POST")
|
|
t.Setenv("URL", "https://api.example.com/test")
|
|
t.Setenv("DODOS", "10")
|
|
t.Setenv("REQUESTS", "1000")
|
|
t.Setenv("DURATION", "5m")
|
|
t.Setenv("TIMEOUT", "30s")
|
|
t.Setenv("PARAM", "key=value")
|
|
t.Setenv("HEADER", "Content-Type: application/json")
|
|
t.Setenv("COOKIE", "session=token")
|
|
t.Setenv("BODY", `{"test": "data"}`)
|
|
t.Setenv("PROXY", "http://proxy.example.com:8080")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Verify all fields
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, "/path/to/config.yaml", config.Files[0].String())
|
|
|
|
require.NotNil(t, config.Yes)
|
|
assert.True(t, *config.Yes)
|
|
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.True(t, *config.SkipVerify)
|
|
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "POST", *config.Method)
|
|
|
|
require.NotNil(t, config.URL)
|
|
assert.Equal(t, "https://api.example.com/test", config.URL.String())
|
|
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(10), *config.DodosCount)
|
|
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(1000), *config.RequestCount)
|
|
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, 5*time.Minute, *config.Duration)
|
|
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 30*time.Second, *config.Timeout)
|
|
|
|
assert.Len(t, config.Params, 1)
|
|
assert.Equal(t, "key", config.Params[0].Key)
|
|
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Equal(t, "Content-Type", config.Headers[0].Key)
|
|
|
|
assert.Len(t, config.Cookies, 1)
|
|
assert.Equal(t, "session", config.Cookies[0].Key)
|
|
|
|
assert.Len(t, config.Bodies, 1)
|
|
assert.Equal(t, types.Body(`{"test": "data"}`), config.Bodies[0]) //nolint:testifylint
|
|
|
|
assert.Len(t, config.Proxies, 1)
|
|
assert.Equal(t, "http://proxy.example.com:8080", config.Proxies[0].String())
|
|
})
|
|
|
|
t.Run("Parse with all fields using prefix", func(t *testing.T) {
|
|
// Set all environment variables with prefix
|
|
t.Setenv("MY_APP_CONFIG_FILE", "/app/config.yml")
|
|
t.Setenv("MY_APP_YES", "false")
|
|
t.Setenv("MY_APP_SKIP_VERIFY", "false")
|
|
t.Setenv("MY_APP_METHOD", "GET")
|
|
t.Setenv("MY_APP_URL", "https://example.com")
|
|
t.Setenv("MY_APP_DODOS", "5")
|
|
t.Setenv("MY_APP_REQUESTS", "500")
|
|
t.Setenv("MY_APP_DURATION", "10m")
|
|
t.Setenv("MY_APP_TIMEOUT", "10s")
|
|
t.Setenv("MY_APP_PARAM", "param1=value1")
|
|
t.Setenv("MY_APP_HEADER", "Accept: application/json")
|
|
t.Setenv("MY_APP_COOKIE", "auth=token123")
|
|
t.Setenv("MY_APP_BODY", "test body")
|
|
t.Setenv("MY_APP_PROXY", "http://127.0.0.1:8080")
|
|
|
|
parser := NewConfigENVParser("MY_APP")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Verify all fields
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, "/app/config.yml", config.Files[0].String())
|
|
|
|
require.NotNil(t, config.Yes)
|
|
assert.False(t, *config.Yes)
|
|
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.False(t, *config.SkipVerify)
|
|
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "GET", *config.Method)
|
|
|
|
require.NotNil(t, config.URL)
|
|
assert.Equal(t, "https://example.com", config.URL.String())
|
|
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(5), *config.DodosCount)
|
|
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(500), *config.RequestCount)
|
|
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, 10*time.Minute, *config.Duration)
|
|
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 10*time.Second, *config.Timeout)
|
|
|
|
assert.Len(t, config.Params, 1)
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Len(t, config.Cookies, 1)
|
|
assert.Len(t, config.Bodies, 1)
|
|
assert.Len(t, config.Proxies, 1)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_MultipleErrors(t *testing.T) {
|
|
t.Run("Parse with multiple field errors", func(t *testing.T) {
|
|
// Set multiple invalid values
|
|
t.Setenv("CONFIG_FILE", "/path/to/config") // Missing extension
|
|
t.Setenv("YES", "invalid_bool")
|
|
t.Setenv("SKIP_VERIFY", "not_a_bool")
|
|
t.Setenv("URL", "://invalid-url")
|
|
t.Setenv("DODOS", "-10")
|
|
t.Setenv("REQUESTS", "not_a_number")
|
|
t.Setenv("DURATION", "invalid_duration")
|
|
t.Setenv("TIMEOUT", "30") // Missing time unit
|
|
t.Setenv("PROXY", "://invalid-proxy")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
assert.Nil(t, config)
|
|
var fieldErr types.FieldParseErrors
|
|
require.ErrorAs(t, err, &fieldErr)
|
|
|
|
// Should have 9 errors
|
|
assert.Len(t, fieldErr.Errors, 9)
|
|
|
|
// Check that all expected fields have errors
|
|
errorFields := make(map[string]bool)
|
|
for _, e := range fieldErr.Errors {
|
|
errorFields[e.Field] = true
|
|
}
|
|
|
|
assert.True(t, errorFields["CONFIG_FILE"])
|
|
assert.True(t, errorFields["YES"])
|
|
assert.True(t, errorFields["SKIP_VERIFY"])
|
|
assert.True(t, errorFields["URL"])
|
|
assert.True(t, errorFields["DODOS"])
|
|
assert.True(t, errorFields["REQUESTS"])
|
|
assert.True(t, errorFields["DURATION"])
|
|
assert.True(t, errorFields["TIMEOUT"])
|
|
assert.True(t, errorFields["PROXY"])
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_EmptyValues(t *testing.T) {
|
|
t.Run("Parse with empty string environment variables", func(t *testing.T) {
|
|
// Set empty values
|
|
t.Setenv("CONFIG_FILE", "")
|
|
t.Setenv("YES", "")
|
|
t.Setenv("SKIP_VERIFY", "")
|
|
t.Setenv("METHOD", "")
|
|
t.Setenv("URL", "")
|
|
t.Setenv("DODOS", "")
|
|
t.Setenv("REQUESTS", "")
|
|
t.Setenv("DURATION", "")
|
|
t.Setenv("TIMEOUT", "")
|
|
t.Setenv("PARAM", "")
|
|
t.Setenv("HEADER", "")
|
|
t.Setenv("COOKIE", "")
|
|
t.Setenv("BODY", "")
|
|
t.Setenv("PROXY", "")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
// Empty values should not cause errors, fields should just be nil/empty
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
assert.Empty(t, config.Files)
|
|
assert.Nil(t, config.Yes)
|
|
assert.Nil(t, config.SkipVerify)
|
|
assert.Nil(t, config.Method)
|
|
assert.Nil(t, config.URL)
|
|
assert.Nil(t, config.DodosCount)
|
|
assert.Nil(t, config.RequestCount)
|
|
assert.Nil(t, config.Duration)
|
|
assert.Nil(t, config.Timeout)
|
|
assert.Empty(t, config.Params)
|
|
assert.Empty(t, config.Headers)
|
|
assert.Empty(t, config.Cookies)
|
|
assert.Empty(t, config.Bodies)
|
|
assert.Empty(t, config.Proxies)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_Parse_NoEnvironmentVariables(t *testing.T) {
|
|
t.Run("Parse with no environment variables set", func(t *testing.T) {
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// All fields should be nil or empty
|
|
assert.Empty(t, config.Files)
|
|
assert.Nil(t, config.Yes)
|
|
assert.Nil(t, config.SkipVerify)
|
|
assert.Nil(t, config.Method)
|
|
assert.Nil(t, config.URL)
|
|
assert.Nil(t, config.DodosCount)
|
|
assert.Nil(t, config.RequestCount)
|
|
assert.Nil(t, config.Duration)
|
|
assert.Nil(t, config.Timeout)
|
|
assert.Empty(t, config.Params)
|
|
assert.Empty(t, config.Headers)
|
|
assert.Empty(t, config.Cookies)
|
|
assert.Empty(t, config.Bodies)
|
|
assert.Empty(t, config.Proxies)
|
|
})
|
|
|
|
t.Run("Parse with prefix but no matching environment variables", func(t *testing.T) {
|
|
parser := NewConfigENVParser("NONEXISTENT_PREFIX")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// All fields should be nil or empty
|
|
assert.Empty(t, config.Files)
|
|
assert.Nil(t, config.Yes)
|
|
assert.Nil(t, config.SkipVerify)
|
|
assert.Nil(t, config.Method)
|
|
assert.Nil(t, config.URL)
|
|
assert.Nil(t, config.DodosCount)
|
|
assert.Nil(t, config.RequestCount)
|
|
assert.Nil(t, config.Duration)
|
|
assert.Nil(t, config.Timeout)
|
|
assert.Empty(t, config.Params)
|
|
assert.Empty(t, config.Headers)
|
|
assert.Empty(t, config.Cookies)
|
|
assert.Empty(t, config.Bodies)
|
|
assert.Empty(t, config.Proxies)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_InterfaceConformance(t *testing.T) {
|
|
t.Run("ConfigENVParser implements IParser interface", func(t *testing.T) {
|
|
parser := ConfigENVParser{envPrefix: "TEST"}
|
|
|
|
// This test verifies that ConfigENVParser implements the IParser interface
|
|
var _ IParser = parser
|
|
|
|
// Also test that the pointer type implements the interface
|
|
var _ IParser = &parser
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_EdgeCases(t *testing.T) {
|
|
t.Run("Parse with very long prefix", func(t *testing.T) {
|
|
longPrefix := "THIS_IS_A_VERY_LONG_PREFIX_FOR_TESTING_PURPOSES"
|
|
envName := longPrefix + "_METHOD"
|
|
t.Setenv(envName, "GET")
|
|
|
|
parser := NewConfigENVParser(longPrefix)
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "GET", *config.Method)
|
|
})
|
|
|
|
t.Run("Parse with special characters in values", func(t *testing.T) {
|
|
t.Setenv("URL", "https://example.com/path?key=value&special=%20%21%40%23")
|
|
t.Setenv("HEADER", "X-Special-Header: value with spaces and special!@#$%^&*()")
|
|
t.Setenv("BODY", `{"special": "characters!@#$%^&*()_+-=[]{}|;':\",./<>?"}`)
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
require.NotNil(t, config.URL)
|
|
assert.Contains(t, config.URL.String(), "special=%20%21%40%23")
|
|
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Contains(t, config.Headers[0].Value[0], "special!@#$%^&*()")
|
|
|
|
assert.Len(t, config.Bodies, 1)
|
|
assert.Contains(t, string(config.Bodies[0]), "special")
|
|
})
|
|
|
|
t.Run("Parse with maximum uint values", func(t *testing.T) {
|
|
t.Setenv("DODOS", "4294967295") // Max uint32
|
|
t.Setenv("REQUESTS", "4294967295")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(4294967295), *config.DodosCount)
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(4294967295), *config.RequestCount)
|
|
})
|
|
|
|
t.Run("Parse with very large duration values", func(t *testing.T) {
|
|
t.Setenv("DURATION", "9999h59m59s")
|
|
t.Setenv("TIMEOUT", "999999s")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
require.NotNil(t, config.Duration)
|
|
require.NotNil(t, config.Timeout)
|
|
|
|
// Just verify they were parsed without checking exact values
|
|
assert.Greater(t, *config.Duration, time.Hour)
|
|
assert.Greater(t, *config.Timeout, time.Second)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_RealWorldScenarios(t *testing.T) {
|
|
t.Run("Parse typical production environment configuration", func(t *testing.T) {
|
|
// Simulate a production environment configuration
|
|
t.Setenv("PROD_CONFIG_FILE", "https://config.example.com/prod.yaml")
|
|
t.Setenv("PROD_YES", "false")
|
|
t.Setenv("PROD_SKIP_VERIFY", "false")
|
|
t.Setenv("PROD_METHOD", "POST")
|
|
t.Setenv("PROD_URL", "https://api.production.com/v2/endpoint")
|
|
t.Setenv("PROD_DODOS", "100")
|
|
t.Setenv("PROD_REQUESTS", "10000")
|
|
t.Setenv("PROD_DURATION", "1h")
|
|
t.Setenv("PROD_TIMEOUT", "60s")
|
|
t.Setenv("PROD_HEADER", "Authorization: Bearer production-token-12345")
|
|
t.Setenv("PROD_PROXY", "http://corporate-proxy.example.com:8080")
|
|
|
|
parser := NewConfigENVParser("PROD")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Verify production settings
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, types.ConfigFileLocationRemote, config.Files[0].LocationType())
|
|
|
|
require.NotNil(t, config.Yes)
|
|
assert.False(t, *config.Yes, "Production should not auto-confirm")
|
|
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.False(t, *config.SkipVerify, "Production should verify certificates")
|
|
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(100), *config.DodosCount)
|
|
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(10000), *config.RequestCount)
|
|
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, time.Hour, *config.Duration)
|
|
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 60*time.Second, *config.Timeout)
|
|
})
|
|
|
|
t.Run("Parse development environment configuration", func(t *testing.T) {
|
|
// Simulate a development environment configuration
|
|
t.Setenv("DEV_CONFIG_FILE", "/local/config/dev.yaml")
|
|
t.Setenv("DEV_YES", "true")
|
|
t.Setenv("DEV_SKIP_VERIFY", "true")
|
|
t.Setenv("DEV_METHOD", "GET")
|
|
t.Setenv("DEV_URL", "http://localhost:8080/test")
|
|
t.Setenv("DEV_DODOS", "1")
|
|
t.Setenv("DEV_REQUESTS", "10")
|
|
t.Setenv("DEV_DURATION", "30s")
|
|
t.Setenv("DEV_TIMEOUT", "5s")
|
|
t.Setenv("DEV_HEADER", "X-Debug: true")
|
|
|
|
parser := NewConfigENVParser("DEV")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Verify development settings
|
|
assert.Len(t, config.Files, 1)
|
|
assert.Equal(t, types.ConfigFileLocationLocal, config.Files[0].LocationType())
|
|
|
|
require.NotNil(t, config.Yes)
|
|
assert.True(t, *config.Yes, "Development can auto-confirm")
|
|
|
|
require.NotNil(t, config.SkipVerify)
|
|
assert.True(t, *config.SkipVerify, "Development can skip certificate verification")
|
|
|
|
require.NotNil(t, config.DodosCount)
|
|
assert.Equal(t, uint(1), *config.DodosCount, "Development uses fewer workers")
|
|
|
|
require.NotNil(t, config.RequestCount)
|
|
assert.Equal(t, uint(10), *config.RequestCount, "Development uses fewer requests")
|
|
|
|
require.NotNil(t, config.Duration)
|
|
assert.Equal(t, 30*time.Second, *config.Duration)
|
|
|
|
require.NotNil(t, config.Timeout)
|
|
assert.Equal(t, 5*time.Second, *config.Timeout)
|
|
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Equal(t, "X-Debug", config.Headers[0].Key)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_PartialConfiguration(t *testing.T) {
|
|
t.Run("Parse with only critical fields set", func(t *testing.T) {
|
|
t.Setenv("URL", "https://api.example.com")
|
|
t.Setenv("METHOD", "POST")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Only URL and METHOD should be set
|
|
require.NotNil(t, config.URL)
|
|
assert.Equal(t, "https://api.example.com", config.URL.String())
|
|
|
|
require.NotNil(t, config.Method)
|
|
assert.Equal(t, "POST", *config.Method)
|
|
|
|
// Everything else should be nil or empty
|
|
assert.Empty(t, config.Files)
|
|
assert.Nil(t, config.Yes)
|
|
assert.Nil(t, config.SkipVerify)
|
|
assert.Nil(t, config.DodosCount)
|
|
assert.Nil(t, config.RequestCount)
|
|
assert.Nil(t, config.Duration)
|
|
assert.Nil(t, config.Timeout)
|
|
assert.Empty(t, config.Params)
|
|
assert.Empty(t, config.Headers)
|
|
assert.Empty(t, config.Cookies)
|
|
assert.Empty(t, config.Bodies)
|
|
assert.Empty(t, config.Proxies)
|
|
})
|
|
|
|
t.Run("Parse with only optional fields set", func(t *testing.T) {
|
|
t.Setenv("HEADER", "User-Agent: CustomAgent/1.0")
|
|
t.Setenv("COOKIE", "preferences=dark-mode")
|
|
t.Setenv("PARAM", "debug=true")
|
|
|
|
parser := NewConfigENVParser("")
|
|
config, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, config)
|
|
|
|
// Only collection fields should have values
|
|
assert.Len(t, config.Headers, 1)
|
|
assert.Equal(t, "User-Agent", config.Headers[0].Key)
|
|
|
|
assert.Len(t, config.Cookies, 1)
|
|
assert.Equal(t, "preferences", config.Cookies[0].Key)
|
|
|
|
assert.Len(t, config.Params, 1)
|
|
assert.Equal(t, "debug", config.Params[0].Key)
|
|
|
|
// Core fields should be nil
|
|
assert.Nil(t, config.URL)
|
|
assert.Nil(t, config.Method)
|
|
assert.Nil(t, config.DodosCount)
|
|
assert.Nil(t, config.RequestCount)
|
|
})
|
|
}
|
|
|
|
func TestConfigENVParser_MergeScenarios(t *testing.T) {
|
|
t.Run("Parse configuration suitable for merging", func(t *testing.T) {
|
|
// Set only specific fields that would override defaults
|
|
t.Setenv("METHOD", "PUT")
|
|
t.Setenv("TIMEOUT", "45s")
|
|
t.Setenv("HEADER", "X-Custom: value")
|
|
|
|
parser := NewConfigENVParser("")
|
|
envConfig, err := parser.Parse()
|
|
|
|
require.NoError(t, err)
|
|
require.NotNil(t, envConfig)
|
|
|
|
// Create a default config
|
|
defaultConfig := &config.Config{
|
|
Method: utils.ToPtr("GET"),
|
|
Timeout: utils.ToPtr(30 * time.Second),
|
|
DodosCount: utils.ToPtr(uint(1)),
|
|
Headers: types.Headers{{Key: "User-Agent", Value: []string{"DefaultAgent/1.0"}}},
|
|
}
|
|
|
|
// Merge the parsed config into defaults
|
|
defaultConfig.Merge(envConfig)
|
|
|
|
// Verify merged values
|
|
assert.Equal(t, "PUT", *defaultConfig.Method, "Method should be overridden")
|
|
assert.Equal(t, 45*time.Second, *defaultConfig.Timeout, "Timeout should be overridden")
|
|
assert.Equal(t, uint(1), *defaultConfig.DodosCount, "DodosCount should remain from default")
|
|
|
|
// Headers should contain the new header (merge behavior depends on implementation)
|
|
assert.Len(t, defaultConfig.Headers, 1)
|
|
assert.Equal(t, "X-Custom", defaultConfig.Headers[0].Key)
|
|
})
|
|
}
|