Skip to content

Commit ccd3de7

Browse files
committed
allow other HTTP methods
1 parent c1996fe commit ccd3de7

File tree

4 files changed

+113
-52
lines changed

4 files changed

+113
-52
lines changed

cmd/root.go

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,9 @@
11
package cmd
22

33
import (
4-
"fmt"
5-
6-
"github.com/getsentry/sentry-go"
7-
"github.com/mfbmina/enxame/reporter"
8-
"github.com/mfbmina/enxame/swarm"
94
"github.com/spf13/cobra"
105
)
116

12-
var format string
13-
var output string
14-
var requestsPerUser int
15-
var users int
16-
177
var rootCmd = &cobra.Command{
188
Use: "enxame",
199
Short: "A http load tester and benchmarking utility made in Go",
@@ -29,34 +19,3 @@ func init() {
2919

3020
rootCmd.AddCommand(runCmd())
3121
}
32-
33-
func runCmd() *cobra.Command {
34-
cmd := &cobra.Command{
35-
Use: "run",
36-
Short: "Run a test",
37-
Long: "Run a test against the given URI",
38-
Args: cobra.MinimumNArgs(1),
39-
Run: func(cmd *cobra.Command, args []string) {
40-
fmt.Println("Swarming", args[0], "...")
41-
responses := swarm.Swarm(args[0], requestsPerUser, users)
42-
43-
fmt.Printf("Reporting results as %s...\n", format)
44-
r := reporter.NewReporter(format, output, responses)
45-
feedback, err := r.Report()
46-
if err != nil {
47-
sentry.CaptureException(err)
48-
return
49-
}
50-
51-
fmt.Println(feedback)
52-
fmt.Println("Done!")
53-
},
54-
}
55-
56-
cmd.Flags().IntVarP(&requestsPerUser, "requests_per_user", "r", 5, "Max number of requests per user")
57-
cmd.Flags().IntVarP(&users, "users", "u", 10, "Max number of concurrent users")
58-
cmd.Flags().StringVarP(&format, "format", "f", "txt", "The report format (txt, csv, json)")
59-
cmd.Flags().StringVarP(&output, "output", "o", "", "The output file name (extension will be appended automatically)")
60-
61-
return cmd
62-
}

cmd/run.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/getsentry/sentry-go"
7+
"github.com/mfbmina/enxame/reporter"
8+
"github.com/mfbmina/enxame/swarm"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
var format string
13+
var method string
14+
var output string
15+
var requestsPerUser int
16+
var users int
17+
18+
func runCmd() *cobra.Command {
19+
cmd := &cobra.Command{
20+
Use: "run",
21+
Short: "Run a test",
22+
Long: "Run a test against the given URI",
23+
Args: cobra.MinimumNArgs(1),
24+
PreRunE: func(cmd *cobra.Command, args []string) error {
25+
fmt.Println("Validating method...")
26+
fmt.Println("Method:", method)
27+
if !validMethod(method) {
28+
err := fmt.Errorf("Invalid method. Please use one of the following: GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD")
29+
sentry.CaptureException(err)
30+
return err
31+
}
32+
33+
return nil
34+
},
35+
RunE: func(cmd *cobra.Command, args []string) error {
36+
fmt.Println("Swarming", args[0], "...")
37+
responses, err := swarm.Swarm(args[0], method, requestsPerUser, users)
38+
if err != nil {
39+
sentry.CaptureException(err)
40+
return err
41+
}
42+
43+
fmt.Printf("Reporting results as %s...\n", format)
44+
r := reporter.NewReporter(format, output, responses)
45+
feedback, err := r.Report()
46+
if err != nil {
47+
sentry.CaptureException(err)
48+
return err
49+
}
50+
51+
fmt.Println(feedback)
52+
fmt.Println("Done!")
53+
return nil
54+
},
55+
}
56+
57+
cmd.Flags().IntVarP(&requestsPerUser, "requests_per_user", "r", 5, "Max number of requests per user")
58+
cmd.Flags().IntVarP(&users, "users", "u", 10, "Max number of concurrent users")
59+
cmd.Flags().StringVarP(&format, "format", "f", "txt", "The report format (txt, csv, json)")
60+
cmd.Flags().StringVarP(&method, "method", "X", "GET", "The http method to use (GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD)")
61+
cmd.Flags().StringVarP(&output, "output", "o", "", "The output file name (extension will be appended automatically)")
62+
63+
return cmd
64+
}
65+
66+
func validMethod(method string) bool {
67+
allowedMethods := []string{"GET", "POST", "PUT", "DELETE", "PATCH", "OPTIONS", "HEAD"}
68+
f := false
69+
70+
for _, m := range allowedMethods {
71+
if m == method {
72+
f = true
73+
break
74+
}
75+
}
76+
77+
return f
78+
}

swarm/request.go

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,33 +11,37 @@ type HTTPResponse struct {
1111
Path string `json:"path"`
1212
}
1313

14-
func Swarm(path string, requestsPerUser int, concurrentUsers int) []HTTPResponse {
14+
func Swarm(path, method string, requestsPerUser, concurrentUsers int) ([]HTTPResponse, error) {
1515
totalRequests := requestsPerUser * concurrentUsers
1616
channel := make(chan HTTPResponse, totalRequests)
1717
responses := make([]HTTPResponse, totalRequests)
1818

1919
for i := 0; i < concurrentUsers; i++ {
20-
go userRequests(path, requestsPerUser, channel)
20+
req, _ := http.NewRequest(method, path, nil)
21+
go userRequests(req, requestsPerUser, channel)
2122
}
2223

2324
for i := 0; i < totalRequests; i++ {
2425
responses[i] = <-channel
2526
}
2627

27-
return responses
28+
return responses, nil
2829
}
2930

30-
func userRequests(path string, requestsPerUser int, channel chan HTTPResponse) {
31+
func userRequests(req *http.Request, requestsPerUser int, channel chan HTTPResponse) {
3132
for i := 0; i < requestsPerUser; i++ {
3233
startTime := time.Now()
33-
resp, err := http.Get(path)
34+
35+
client := &http.Client{}
36+
resp, err := client.Do(req)
37+
3438
elapsedTime := time.Since(startTime) / time.Millisecond
3539

3640
if err != nil {
37-
channel <- HTTPResponse{StatusCode: 0, Path: path, Time: elapsedTime}
41+
channel <- HTTPResponse{StatusCode: 0, Path: req.URL.String(), Time: elapsedTime}
3842
continue
3943
}
4044

41-
channel <- HTTPResponse{StatusCode: resp.StatusCode, Path: path, Time: elapsedTime}
45+
channel <- HTTPResponse{StatusCode: resp.StatusCode, Path: req.URL.String(), Time: elapsedTime}
4246
}
4347
}

swarm/request_test.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"github.com/stretchr/testify/assert"
99
)
1010

11-
func TestSwarmWhenApiCallisSuccessful(t *testing.T) {
11+
func TestSwarmWhenApiCallWithGet(t *testing.T) {
1212
url := "http://example.com/users"
1313

1414
mock := apitest.NewMock().
@@ -18,24 +18,44 @@ func TestSwarmWhenApiCallisSuccessful(t *testing.T) {
1818

1919
defer mock.EndStandalone()()
2020

21-
r := Swarm(url, 1, 1)
21+
r, err := Swarm(url, "GET", 1, 1)
2222
assert.Equal(t, 1, len(r))
2323
assert.Equal(t, 200, r[0].StatusCode)
2424
assert.NotNil(t, r[0].Time)
25+
assert.Nil(t, err)
26+
}
27+
28+
func TestSwarmWhenApiCallWithPost(t *testing.T) {
29+
url := "http://example.com/users"
30+
31+
mock := apitest.NewMock().
32+
Post(url).
33+
RespondWith().
34+
Status(http.StatusCreated)
35+
36+
defer mock.EndStandalone()()
37+
38+
r, err := Swarm(url, "POST", 1, 1)
39+
assert.Equal(t, 1, len(r))
40+
assert.Equal(t, 201, r[0].StatusCode)
41+
assert.NotNil(t, r[0].Time)
42+
assert.Nil(t, err)
2543
}
2644

2745
func TestSwarmWhenApiCallReturnsError(t *testing.T) {
2846
url := "strange_url"
2947

30-
r := Swarm(url, 1, 1)
48+
r, err := Swarm(url, "GET", 1, 1)
3149
assert.Equal(t, 1, len(r))
3250
assert.Equal(t, 0, r[0].StatusCode)
3351
assert.NotNil(t, r[0].Time)
52+
assert.Nil(t, err)
3453
}
3554

3655
func TestSwarmReturnsTotalRequests(t *testing.T) {
3756
url := "strange_url"
3857

39-
r := Swarm(url, 2, 5)
58+
r, err := Swarm(url, "GET", 2, 5)
4059
assert.Equal(t, 10, len(r))
60+
assert.Nil(t, err)
4161
}

0 commit comments

Comments
 (0)