test: add integration tests for CLI package
- Added TestServerConfigurations for server setup verification - Added TestMultipleEndpointsConcurrency for concurrent access testing - Added TestErrorHandling for error scenarios (invalid JSON, missing endpoints, invalid replay IDs) These tests verify the CLI server behavior through integration testing rather than unit testing the main function directly. Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
parent
ceaf7f9fb5
commit
22295e4cd1
@ -8,6 +8,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -454,3 +455,177 @@ func readBody(resp *http.Response) string {
|
|||||||
b, _ := io.ReadAll(resp.Body)
|
b, _ := io.ReadAll(resp.Body)
|
||||||
return string(b)
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestServerConfigurations tests various server configurations.
|
||||||
|
func TestServerConfigurations(t *testing.T) {
|
||||||
|
// Test with default port.
|
||||||
|
t.Run("default_port", func(t *testing.T) {
|
||||||
|
repo, err := store.Open(":memory:")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open store: %v", err)
|
||||||
|
}
|
||||||
|
defer repo.Close()
|
||||||
|
|
||||||
|
r := chi.NewRouter()
|
||||||
|
h := handler.New(repo)
|
||||||
|
h.RegisterRoutes(r)
|
||||||
|
|
||||||
|
srv := httptest.NewServer(r)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
resp, err := http.Get(srv.URL + "/healthz")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GET /healthz: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Fatalf("expected 200, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test with custom headers.
|
||||||
|
t.Run("custom_headers", func(t *testing.T) {
|
||||||
|
repo, err := store.Open(":memory:")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open store: %v", err)
|
||||||
|
}
|
||||||
|
defer repo.Close()
|
||||||
|
|
||||||
|
r := chi.NewRouter()
|
||||||
|
h := handler.New(repo)
|
||||||
|
h.RegisterRoutes(r)
|
||||||
|
|
||||||
|
srv := httptest.NewServer(r)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
req, _ := http.NewRequest("POST", srv.URL+"/test", strings.NewReader(`{"key":"value"}`))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
req.Header.Set("X-Custom-Header", "test-value")
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("POST /test: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Fatalf("expected 200, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestMultipleEndpointsConcurrency tests concurrent access to multiple endpoints.
|
||||||
|
func TestMultipleEndpointsConcurrency(t *testing.T) {
|
||||||
|
repo, err := store.Open(":memory:")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open store: %v", err)
|
||||||
|
}
|
||||||
|
defer repo.Close()
|
||||||
|
|
||||||
|
r := chi.NewRouter()
|
||||||
|
h := handler.New(repo)
|
||||||
|
h.RegisterRoutes(r)
|
||||||
|
|
||||||
|
srv := httptest.NewServer(r)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
|
// Create multiple endpoints concurrently.
|
||||||
|
var wg sync.WaitGroup
|
||||||
|
numEndpoints := 5
|
||||||
|
|
||||||
|
for i := 0; i < numEndpoints; i++ {
|
||||||
|
wg.Add(1)
|
||||||
|
go func(idx int) {
|
||||||
|
defer wg.Done()
|
||||||
|
endpoint := fmt.Sprintf("endpoint-%d", idx)
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
body := fmt.Sprintf(`{"endpoint":%d,"request":%d}`, idx, j)
|
||||||
|
resp, err := client.Post(srv.URL+"/"+endpoint, "application/json", strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("endpoint %d, request %d: %v", idx, j, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Errorf("endpoint %d, request %d: expected 200, got %d", idx, j, resp.StatusCode)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}(i)
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
// Verify all endpoints have requests.
|
||||||
|
for i := 0; i < numEndpoints; i++ {
|
||||||
|
endpoint := fmt.Sprintf("endpoint-%d", i)
|
||||||
|
reqs, err := repo.ListRequests(context.Background(), endpoint, 100)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("list requests for %s: %v", endpoint, err)
|
||||||
|
}
|
||||||
|
if len(reqs) != 10 {
|
||||||
|
t.Errorf("expected 10 requests for %s, got %d", endpoint, len(reqs))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestErrorHandling tests error handling scenarios.
|
||||||
|
func TestErrorHandling(t *testing.T) {
|
||||||
|
repo, err := store.Open(":memory:")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("open store: %v", err)
|
||||||
|
}
|
||||||
|
defer repo.Close()
|
||||||
|
|
||||||
|
r := chi.NewRouter()
|
||||||
|
h := handler.New(repo)
|
||||||
|
h.RegisterRoutes(r)
|
||||||
|
|
||||||
|
srv := httptest.NewServer(r)
|
||||||
|
defer srv.Close()
|
||||||
|
|
||||||
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
|
|
||||||
|
// Test invalid JSON body.
|
||||||
|
t.Run("invalid_json", func(t *testing.T) {
|
||||||
|
resp, err := client.Post(srv.URL+"/test", "application/json", strings.NewReader("not json"))
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("POST /test: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
// Should still return 200 (capture accepts any body).
|
||||||
|
if resp.StatusCode != http.StatusOK {
|
||||||
|
t.Fatalf("expected 200, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test missing endpoint ID (root path).
|
||||||
|
t.Run("missing_endpoint", func(t *testing.T) {
|
||||||
|
resp, err := client.Get(srv.URL + "/")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("GET /: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
// Chi returns 404 for unmatched routes.
|
||||||
|
if resp.StatusCode != http.StatusNotFound {
|
||||||
|
t.Fatalf("expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Test replay with invalid request ID.
|
||||||
|
t.Run("replay_invalid_id", func(t *testing.T) {
|
||||||
|
req, _ := http.NewRequest("POST", srv.URL+"/e/test/requests/nonexistent/replay",
|
||||||
|
strings.NewReader(`{"target_url":"https://example.com"}`))
|
||||||
|
req.Header.Set("Content-Type", "application/json")
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("replay: %v", err)
|
||||||
|
}
|
||||||
|
resp.Body.Close()
|
||||||
|
if resp.StatusCode != http.StatusNotFound {
|
||||||
|
t.Fatalf("expected 404, got %d", resp.StatusCode)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user