Files
akvorado/common/helpers/tests_http.go
Vincent Bernat de65ee6072 tests: introduce helpers.Pos/helpers.Mark
This helps locating the position of a test.
2024-07-01 07:42:36 +02:00

127 lines
3.2 KiB
Go

// SPDX-FileCopyrightText: 2022 Free Mobile
// SPDX-License-Identifier: AGPL-3.0-only
//go:build !release
package helpers
import (
"bufio"
"bytes"
"encoding/json"
"fmt"
"net"
"net/http"
"testing"
"github.com/gin-gonic/gin"
)
// HTTPEndpointCases describes case for TestHTTPEndpoints
type HTTPEndpointCases []struct {
Pos Pos
Description string
Method string
URL string
Header http.Header
JSONInput interface{}
ContentType string
StatusCode int
FirstLines []string
JSONOutput interface{}
}
// TestHTTPEndpoints test a few HTTP endpoints
func TestHTTPEndpoints(t *testing.T, serverAddr net.Addr, cases HTTPEndpointCases) {
t.Helper()
for _, tc := range cases {
desc := tc.Description
if desc == "" {
desc = tc.URL
}
t.Run(desc, func(t *testing.T) {
t.Helper()
if tc.FirstLines != nil && tc.JSONOutput != nil {
t.Fatalf("%sCannot have both FirstLines and JSONOutput", tc.Pos)
}
var resp *http.Response
var err error
if tc.Method == "" {
if tc.JSONInput == nil {
tc.Method = "GET"
} else {
tc.Method = "POST"
}
}
if tc.JSONInput == nil {
req, _ := http.NewRequest(tc.Method,
fmt.Sprintf("http://%s%s", serverAddr, tc.URL),
nil)
if tc.Header != nil {
req.Header = tc.Header
}
resp, err = http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
} else {
payload := new(bytes.Buffer)
err = json.NewEncoder(payload).Encode(tc.JSONInput)
if err != nil {
t.Fatalf("%sEncode() error:\n%+v", tc.Pos, err)
}
req, _ := http.NewRequest(tc.Method,
fmt.Sprintf("http://%s%s", serverAddr, tc.URL),
payload)
if tc.Header != nil {
req.Header = tc.Header
}
req.Header.Add("Content-Type", "application/json")
resp, err = http.DefaultClient.Do(req)
if err != nil {
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
}
defer resp.Body.Close()
if tc.StatusCode == 0 {
tc.StatusCode = 200
}
if resp.StatusCode != tc.StatusCode {
t.Errorf("%s%s %s: got status code %d, not %d",
tc.Pos, tc.URL,
tc.Method, resp.StatusCode, tc.StatusCode)
}
if tc.JSONOutput != nil {
tc.ContentType = "application/json; charset=utf-8"
}
gotContentType := resp.Header.Get("Content-Type")
if gotContentType != tc.ContentType {
t.Errorf("%s%s %s Content-Type (-got, +want):\n-%s\n+%s",
tc.Pos,
tc.Method, tc.URL, gotContentType, tc.ContentType)
}
if tc.JSONOutput == nil {
reader := bufio.NewScanner(resp.Body)
got := []string{}
for reader.Scan() && len(got) < len(tc.FirstLines) {
got = append(got, reader.Text())
}
if diff := Diff(got, tc.FirstLines); diff != "" {
t.Errorf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
} else {
decoder := json.NewDecoder(resp.Body)
var got gin.H
if err := decoder.Decode(&got); err != nil {
t.Fatalf("%s%s %s:\n%+v", tc.Pos, tc.Method, tc.URL, err)
}
if diff := Diff(got, tc.JSONOutput); diff != "" {
t.Fatalf("%s%s %s (-got, +want):\n%s", tc.Pos, tc.Method, tc.URL, diff)
}
}
})
}
}