Added comments for better readability and fixed probabistic patterns

This commit is contained in:
2024-12-04 17:26:34 -06:00
parent adba4e25dc
commit 5dad2d5275
5 changed files with 166 additions and 66 deletions

82
main.go
View File

@ -4,16 +4,26 @@ import (
"flag"
"fmt"
"loadr/lib"
"math"
"os"
)
// Version number of the loadr tool
var version string = "1.0.2"
// parseCommandLine processes command line arguments and returns configuration parameters
// Returns:
// - requestsPerSecond: target rate of requests
// - maxRequests: total number of requests to send
// - url: target endpoint
// - patterns: array of request patterns
// - jsonFilePath: path to JSON file containing request body
// - bearerToken: authorization token
func parseCommandLine() (float64, int, string, []lib.RequestPattern, string, string) {
requestsPerSecond := flag.Float64("rate", 10, "Number of requests per second")
maxRequests := flag.Int("max", 50, "Maximum number of requests to send (0 for unlimited)")
url := flag.String("url", "https://example.com", "The URL to make requests to")
pattern := flag.String("pattern", "", `Request pattern (e.g., "5p" for 5 POSTs, "1p5g" for 1 POST + 5 GETs)`)
pattern := flag.String("pattern", "", `Request pattern (e.g., "5p" for 5 POSTs, "1p5g" for sequential, "20%p80%g" for probabilistic)`)
jsonFilePath := flag.String("json", "", "Path to the JSON file with request data")
bearerToken := flag.String("token", "", "Bearer token for authorization")
versionFlag := flag.Bool("version", false, "Print the version and exit")
@ -26,51 +36,58 @@ func parseCommandLine() (float64, int, string, []lib.RequestPattern, string, str
os.Exit(0)
}
fmt.Printf("Received pattern value: '%s'\n", *pattern)
patterns, err := parsePattern(*pattern)
if err != nil {
fmt.Printf("Warning: %v. Using default GET pattern.\n", err)
patterns = []lib.RequestPattern{{Verb: "GET", Percentage: 100}}
} else {
fmt.Printf("Using pattern: %+v\n", patterns)
patterns = []lib.RequestPattern{{Verb: "GET", Sequence: 1}}
}
return *requestsPerSecond, *maxRequests, *url, patterns, *jsonFilePath, *bearerToken
}
// parsePattern interprets the pattern string and converts it to RequestPattern structs
// Pattern formats:
// - Sequential: "5p" (5 POSTs), "1p5g" (1 POST then 5 GETs)
// - Probabilistic: "20%p80%g" (20% POSTs, 80% GETs)
//
// Returns error if pattern is invalid or percentages don't sum to 100
func parsePattern(pattern string) ([]lib.RequestPattern, error) {
if pattern == "" {
return []lib.RequestPattern{{Verb: "GET", Percentage: 100}}, nil
return []lib.RequestPattern{{Verb: "GET", Sequence: 1}}, nil
}
var patterns []lib.RequestPattern
var current int
isProbabilistic := false
// Parse pattern string character by character
for i := 0; i < len(pattern); i++ {
c := pattern[i]
switch {
case c >= '0' && c <= '9':
current = current*10 + int(c-'0')
case c == 'p' || c == 'P':
if current == 0 {
current = 1
case c == '%':
isProbabilistic = true
case c == 'p' || c == 'P' || c == 'g' || c == 'G':
verb := "GET"
if c == 'p' || c == 'P' {
verb = "POST"
}
patterns = append(patterns, lib.RequestPattern{
Verb: "POST",
Sequence: current,
Percentage: 0,
})
current = 0
case c == 'g' || c == 'G':
if current == 0 {
current = 1
if isProbabilistic {
patterns = append(patterns, lib.RequestPattern{
Verb: verb,
Percentage: float64(current),
})
} else {
if current == 0 {
current = 1 // Default to 1 if no number specified
}
patterns = append(patterns, lib.RequestPattern{
Verb: verb,
Sequence: current,
})
}
patterns = append(patterns, lib.RequestPattern{
Verb: "GET",
Sequence: current,
Percentage: 0,
})
current = 0
default:
return nil, fmt.Errorf("invalid pattern character: %c", c)
@ -81,17 +98,22 @@ func parsePattern(pattern string) ([]lib.RequestPattern, error) {
return nil, fmt.Errorf("no valid patterns found in: %s", pattern)
}
total := 0
for _, p := range patterns {
total += p.Sequence
}
for i := range patterns {
patterns[i].Percentage = float64(patterns[i].Sequence) / float64(total) * 100
// For probabilistic patterns, ensure percentages sum to 100
if isProbabilistic {
total := 0.0
for _, p := range patterns {
total += p.Percentage
}
if math.Abs(total-100.0) > 0.001 {
return nil, fmt.Errorf("percentages must sum to 100, got: %.1f", total)
}
}
return patterns, nil
}
// readJSONFile loads and returns the contents of a JSON file if specified
// Returns nil if filePath is empty
func readJSONFile(filePath string) ([]byte, error) {
if filePath == "" {
return nil, nil