Add e2e tests

This commit is contained in:
2026-02-18 00:03:59 +04:00
parent d197e90103
commit 4b3230bb27
26 changed files with 4490 additions and 3 deletions

331
e2e/request_test.go Normal file
View File

@@ -0,0 +1,331 @@
package e2e
import (
"net/http"
"slices"
"testing"
)
func TestMethodGET(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Method != http.MethodGet {
t.Errorf("expected default method GET, got %s", req.Method)
}
}
func TestMethodPOST(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-M", "POST", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Method != http.MethodPost {
t.Errorf("expected method POST, got %s", req.Method)
}
}
func TestMethodExplicit(t *testing.T) {
t.Parallel()
methods := []string{"GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS"}
for _, method := range methods {
t.Run(method, func(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-M", method, "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Method != method {
t.Errorf("expected method %s, got %s", method, req.Method)
}
})
}
}
func TestMultipleMethods(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
// With multiple methods, sarin cycles through them
res := run("-U", cs.URL, "-r", "4", "-M", "GET", "-M", "POST", "-q", "-o", "json")
assertExitCode(t, res, 0)
reqs := cs.allRequests()
if len(reqs) != 4 {
t.Fatalf("expected 4 requests, got %d", len(reqs))
}
// Should see both GET and POST used
methods := make(map[string]bool)
for _, r := range reqs {
methods[r.Method] = true
}
if !methods["GET"] || !methods["POST"] {
t.Errorf("expected both GET and POST to be used, got methods: %v", methods)
}
}
func TestSingleHeader(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-H", "X-Custom: hello", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
vals, ok := req.Headers["X-Custom"]
if !ok {
t.Fatalf("expected X-Custom header, got headers: %v", req.Headers)
}
if len(vals) != 1 || vals[0] != "hello" {
t.Errorf("expected X-Custom: [hello], got %v", vals)
}
}
func TestMultipleHeaders(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1",
"-H", "X-First: one",
"-H", "X-Second: two",
"-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v := req.Headers["X-First"]; len(v) == 0 || v[0] != "one" {
t.Errorf("expected X-First: one, got %v", v)
}
if v := req.Headers["X-Second"]; len(v) == 0 || v[0] != "two" {
t.Errorf("expected X-Second: two, got %v", v)
}
}
func TestHeaderWithEmptyValue(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
// Header without ": " separator should have empty value
res := run("-U", cs.URL, "-r", "1", "-H", "X-Empty", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if _, ok := req.Headers["X-Empty"]; !ok {
t.Errorf("expected X-Empty header to be present, got headers: %v", req.Headers)
}
}
func TestDefaultUserAgentHeader(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
ua, ok := req.Headers["User-Agent"]
if !ok || len(ua) == 0 {
t.Fatalf("expected User-Agent header, got headers: %v", req.Headers)
}
assertContains(t, ua[0], "Sarin/")
}
func TestCustomUserAgentOverridesDefault(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-H", "User-Agent: MyAgent/1.0", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
ua := req.Headers["User-Agent"]
if len(ua) == 0 {
t.Fatal("expected User-Agent header")
}
// When user sets User-Agent, the default should not be added
if slices.Contains(ua, "MyAgent/1.0") {
return // found the custom one
}
t.Errorf("expected custom User-Agent 'MyAgent/1.0', got %v", ua)
}
func TestSingleParam(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-P", "key1=value1", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
vals, ok := req.Query["key1"]
if !ok {
t.Fatalf("expected key1 param, got query: %v", req.Query)
}
if len(vals) != 1 || vals[0] != "value1" {
t.Errorf("expected key1=[value1], got %v", vals)
}
}
func TestMultipleParams(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1",
"-P", "a=1",
"-P", "b=2",
"-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v := req.Query["a"]; len(v) == 0 || v[0] != "1" {
t.Errorf("expected a=1, got %v", v)
}
if v := req.Query["b"]; len(v) == 0 || v[0] != "2" {
t.Errorf("expected b=2, got %v", v)
}
}
func TestParamsFromURL(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
// Params in the URL itself should be extracted and sent
res := run("-U", cs.URL+"?fromurl=yes", "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v := req.Query["fromurl"]; len(v) == 0 || v[0] != "yes" {
t.Errorf("expected fromurl=yes from URL query, got %v", v)
}
}
func TestParamsFromURLAndFlag(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
// Both URL params and -P params should be sent
res := run("-U", cs.URL+"?fromurl=yes", "-r", "1", "-P", "fromflag=also", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v := req.Query["fromurl"]; len(v) == 0 || v[0] != "yes" {
t.Errorf("expected fromurl=yes, got %v", v)
}
if v := req.Query["fromflag"]; len(v) == 0 || v[0] != "also" {
t.Errorf("expected fromflag=also, got %v", v)
}
}
func TestSingleCookie(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-C", "session=abc123", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v, ok := req.Cookies["session"]; !ok || v != "abc123" {
t.Errorf("expected cookie session=abc123, got cookies: %v", req.Cookies)
}
}
func TestMultipleCookies(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1",
"-C", "session=abc",
"-C", "token=xyz",
"-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if v, ok := req.Cookies["session"]; !ok || v != "abc" {
t.Errorf("expected cookie session=abc, got %v", req.Cookies)
}
if v, ok := req.Cookies["token"]; !ok || v != "xyz" {
t.Errorf("expected cookie token=xyz, got %v", req.Cookies)
}
}
func TestBody(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL, "-r", "1", "-M", "POST", "-B", "hello world", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Body != "hello world" {
t.Errorf("expected body 'hello world', got %q", req.Body)
}
}
func TestBodyJSON(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
jsonBody := `{"name":"test","value":42}`
res := run("-U", cs.URL, "-r", "1", "-M", "POST", "-B", jsonBody, "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Body != jsonBody {
t.Errorf("expected body %q, got %q", jsonBody, req.Body)
}
}
func TestURLPath(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
res := run("-U", cs.URL+"/api/v1/users", "-r", "1", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if req.Path != "/api/v1/users" {
t.Errorf("expected path /api/v1/users, got %s", req.Path)
}
}
func TestParamWithEmptyValue(t *testing.T) {
t.Parallel()
cs := newCaptureServer()
defer cs.Close()
// Param without = value
res := run("-U", cs.URL, "-r", "1", "-P", "empty", "-q", "-o", "json")
assertExitCode(t, res, 0)
req := cs.lastRequest()
if _, ok := req.Query["empty"]; !ok {
t.Errorf("expected 'empty' param to be present, got query: %v", req.Query)
}
}