mirror of
https://github.com/aykhans/dodo.git
synced 2025-09-07 11:30:47 +00:00
add 'Validate' method to the 'Config'
This commit is contained in:
@@ -553,8 +553,8 @@ func TestParseConfigFile(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestPrintValidationErrors(t *testing.T) {
|
||||
t.Run("printValidationErrors with empty value", func(t *testing.T) {
|
||||
func TestPrintParseErrors(t *testing.T) {
|
||||
t.Run("printParseErrors with empty value", func(t *testing.T) {
|
||||
// This function prints to stdout, so we can't easily test its output
|
||||
// But we can test that it doesn't panic
|
||||
errors := []types.FieldParseError{
|
||||
@@ -567,11 +567,11 @@ func TestPrintValidationErrors(t *testing.T) {
|
||||
|
||||
// Should not panic
|
||||
assert.NotPanics(t, func() {
|
||||
printValidationErrors("TEST", errors...)
|
||||
printParseErrors("TEST", errors...)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("printValidationErrors with value", func(t *testing.T) {
|
||||
t.Run("printParseErrors with value", func(t *testing.T) {
|
||||
errors := []types.FieldParseError{
|
||||
{
|
||||
Field: "test_field",
|
||||
@@ -582,11 +582,11 @@ func TestPrintValidationErrors(t *testing.T) {
|
||||
|
||||
// Should not panic
|
||||
assert.NotPanics(t, func() {
|
||||
printValidationErrors("TEST", errors...)
|
||||
printParseErrors("TEST", errors...)
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("printValidationErrors with multiple errors", func(t *testing.T) {
|
||||
t.Run("printParseErrors with multiple errors", func(t *testing.T) {
|
||||
errors := []types.FieldParseError{
|
||||
{
|
||||
Field: "field1",
|
||||
@@ -602,7 +602,345 @@ func TestPrintValidationErrors(t *testing.T) {
|
||||
|
||||
// Should not panic
|
||||
assert.NotPanics(t, func() {
|
||||
printValidationErrors("TEST", errors...)
|
||||
printParseErrors("TEST", errors...)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestValidate(t *testing.T) {
|
||||
t.Run("Valid config returns no error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
timeout := 30 * time.Second
|
||||
duration := 1 * time.Minute
|
||||
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
Timeout: &timeout,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
Duration: &duration,
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Missing Method returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "method is required")
|
||||
})
|
||||
|
||||
t.Run("Missing URL returns validation error", func(t *testing.T) {
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "URL is required")
|
||||
})
|
||||
|
||||
t.Run("Invalid URL scheme returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("ftp://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "URL scheme must be one of")
|
||||
})
|
||||
|
||||
t.Run("Missing DodosCount returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "dodos count is required")
|
||||
})
|
||||
|
||||
t.Run("Zero DodosCount returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(0)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "dodos count must be greater than 0")
|
||||
})
|
||||
|
||||
t.Run("Missing both RequestCount and Duration returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "either request count or duration must be specified")
|
||||
})
|
||||
|
||||
t.Run("Both RequestCount and Duration zero returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
duration := time.Duration(0)
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(0)),
|
||||
Duration: &duration,
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "both request count and duration cannot be zero")
|
||||
})
|
||||
|
||||
t.Run("Zero RequestCount only returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(0)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "request count must be greater than 0")
|
||||
})
|
||||
|
||||
t.Run("Zero Duration only returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
duration := time.Duration(0)
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
Duration: &duration,
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "duration must be greater than 0")
|
||||
})
|
||||
|
||||
t.Run("Missing Yes returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "yes field is required")
|
||||
})
|
||||
|
||||
t.Run("Missing SkipVerify returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
Yes: utils.ToPtr(true),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "skip verify field is required")
|
||||
})
|
||||
|
||||
t.Run("Invalid proxy scheme returns validation error", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
proxyURL, _ := url.Parse("ftp://proxy.example.com:8080")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
Proxies: types.Proxies{types.Proxy(*proxyURL)},
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Contains(t, err.Error(), "proxy scheme must be one of")
|
||||
assert.Contains(t, err.Error(), "Proxy[0]")
|
||||
})
|
||||
|
||||
t.Run("Multiple invalid proxies return validation errors", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
proxyURL1, _ := url.Parse("ftp://proxy1.example.com:8080")
|
||||
proxyURL2, _ := url.Parse("ldap://proxy2.example.com:389")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
Proxies: types.Proxies{types.Proxy(*proxyURL1), types.Proxy(*proxyURL2)},
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Len(t, validationErr.Errors, 2)
|
||||
assert.Contains(t, err.Error(), "Proxy[0]")
|
||||
assert.Contains(t, err.Error(), "Proxy[1]")
|
||||
})
|
||||
|
||||
t.Run("Valid proxy schemes pass validation", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
proxyURL1, _ := url.Parse("http://proxy1.example.com:8080")
|
||||
proxyURL2, _ := url.Parse("socks5://proxy2.example.com:1080")
|
||||
proxyURL3, _ := url.Parse("socks5h://proxy3.example.com:1080")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("GET"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(5)),
|
||||
RequestCount: utils.ToPtr(uint(100)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
Proxies: types.Proxies{types.Proxy(*proxyURL1), types.Proxy(*proxyURL2), types.Proxy(*proxyURL3)},
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Multiple validation errors are collected", func(t *testing.T) {
|
||||
config := Config{
|
||||
// Missing Method, URL, DodosCount, Yes, SkipVerify
|
||||
// Missing both RequestCount and Duration
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
require.Error(t, err)
|
||||
|
||||
var validationErr types.FieldValidationErrors
|
||||
require.ErrorAs(t, err, &validationErr)
|
||||
assert.Len(t, validationErr.Errors, 6) // All required fields missing
|
||||
assert.Contains(t, err.Error(), "method is required")
|
||||
assert.Contains(t, err.Error(), "URL is required")
|
||||
assert.Contains(t, err.Error(), "dodos count is required")
|
||||
assert.Contains(t, err.Error(), "either request count or duration must be specified")
|
||||
assert.Contains(t, err.Error(), "yes field is required")
|
||||
assert.Contains(t, err.Error(), "skip verify field is required")
|
||||
})
|
||||
|
||||
t.Run("Valid config with Duration only passes validation", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
duration := 30 * time.Second
|
||||
config := Config{
|
||||
Method: utils.ToPtr("POST"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(10)),
|
||||
Duration: &duration,
|
||||
Yes: utils.ToPtr(false),
|
||||
SkipVerify: utils.ToPtr(true),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
|
||||
t.Run("Valid config with RequestCount only passes validation", func(t *testing.T) {
|
||||
testURL, _ := url.Parse("https://example.com")
|
||||
config := Config{
|
||||
Method: utils.ToPtr("PUT"),
|
||||
URL: testURL,
|
||||
DodosCount: utils.ToPtr(uint(3)),
|
||||
RequestCount: utils.ToPtr(uint(50)),
|
||||
Yes: utils.ToPtr(true),
|
||||
SkipVerify: utils.ToPtr(false),
|
||||
}
|
||||
|
||||
err := config.Validate()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
Reference in New Issue
Block a user