mirror of https://github.com/gofiber/fiber.git
🔥 Feature: Add TestConfig to app.Test() for configurable testing (#3161)
* 🔥 Feature: Add thread-safe reading from a closed testConn * 🔥 Feature: Add TestConfig to app.Test() This commit is summarized as: - Add the struct `TestConfig` as a parameter for `app.Test()` instead of `timeout` - Add documentation of `TestConfig` to docs/api/app.md and in-line - Modify middleware to use `TestConfig` instead of the previous implementation Fixes #3149 * 📚 Doc: Add more details about TestConfig in docs * 🩹 Fix: Correct testConn tests - Fixes Test_Utils_TestConn_Closed_Write - Fixes missing regular write test * 🎨 Style: Respect linter in Add App Test Config * 🎨 Styles: Update app.go to respect linter * ♻️ Refactor: Rename TestConfig's ErrOnTimeout to FailOnTimeout - Rename TestConfig.ErrOnTimeout to TestConfig.FailOnTimeout - Update documentation to use changed name - Also fix stale documentation about passing Timeout as a single argument * 🩹 Fix: Fix typo in TestConfig struct comment in app.go * ♻️ Refactor: Change app.Test() fail on timeouterror to os.ErrDeadlineExceeded * ♻️ Refactor:Update middleware that use the same TestConfig to use a global variable * 🩹 Fix: Update error from FailOnTimeout to os.ErrDeadlineExceeded in tests * 🩹 Fix: Remove errors import from middlware/proxy/proxy_test.go * 📚 Doc: Add `app.Test()` config changes to docs/whats_new.md * ♻ Refactor: Change app.Test() and all uses to accept 0 as no timeout instead of -1 * 📚 Doc: Add TestConfig option details to docs/whats_new.md * 🎨 Styles: Update docs/whats_new.md to respect markdown-lint * 🎨 Styles: Update docs/whats_new.md to use consistent style for TestConfig options description --------- Co-authored-by: Juan Calderon-Perez <835733+gaby@users.noreply.github.com>pull/3171/head
parent
b6ecd638e9
commit
f8b490f89e
46
app.go
46
app.go
|
@ -14,9 +14,11 @@ import (
|
|||
"encoding/xml"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
@ -901,13 +903,33 @@ func (app *App) Hooks() *Hooks {
|
|||
return app.hooks
|
||||
}
|
||||
|
||||
// TestConfig is a struct holding Test settings
|
||||
type TestConfig struct {
|
||||
// Timeout defines the maximum duration a
|
||||
// test can run before timing out.
|
||||
// Default: time.Second
|
||||
Timeout time.Duration
|
||||
|
||||
// FailOnTimeout specifies whether the test
|
||||
// should return a timeout error if the HTTP response
|
||||
// exceeds the Timeout duration.
|
||||
// Default: true
|
||||
FailOnTimeout bool
|
||||
}
|
||||
|
||||
// Test is used for internal debugging by passing a *http.Request.
|
||||
// Timeout is optional and defaults to 1s, -1 will disable it completely.
|
||||
func (app *App) Test(req *http.Request, timeout ...time.Duration) (*http.Response, error) {
|
||||
// Set timeout
|
||||
to := 1 * time.Second
|
||||
if len(timeout) > 0 {
|
||||
to = timeout[0]
|
||||
// Config is optional and defaults to a 1s error on timeout,
|
||||
// 0 timeout will disable it completely.
|
||||
func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, error) {
|
||||
// Default config
|
||||
cfg := TestConfig{
|
||||
Timeout: time.Second,
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
|
||||
// Override config if provided
|
||||
if len(config) > 0 {
|
||||
cfg = config[0]
|
||||
}
|
||||
|
||||
// Add Content-Length if not provided with body
|
||||
|
@ -946,12 +968,15 @@ func (app *App) Test(req *http.Request, timeout ...time.Duration) (*http.Respons
|
|||
}()
|
||||
|
||||
// Wait for callback
|
||||
if to >= 0 {
|
||||
if cfg.Timeout > 0 {
|
||||
// With timeout
|
||||
select {
|
||||
case err = <-channel:
|
||||
case <-time.After(to):
|
||||
return nil, fmt.Errorf("test: timeout error after %s", to)
|
||||
case <-time.After(cfg.Timeout):
|
||||
conn.Close() //nolint:errcheck, revive // It is fine to ignore the error here
|
||||
if cfg.FailOnTimeout {
|
||||
return nil, os.ErrDeadlineExceeded
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Without timeout
|
||||
|
@ -969,6 +994,9 @@ func (app *App) Test(req *http.Request, timeout ...time.Duration) (*http.Respons
|
|||
// Convert raw http response to *http.Response
|
||||
res, err := http.ReadResponse(buffer, req)
|
||||
if err != nil {
|
||||
if errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
return nil, errors.New("test: got empty response")
|
||||
}
|
||||
return nil, fmt.Errorf("failed to read response: %w", err)
|
||||
}
|
||||
|
||||
|
|
37
app_test.go
37
app_test.go
|
@ -16,6 +16,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
|
@ -1124,7 +1125,9 @@ func Test_Test_Timeout(t *testing.T) {
|
|||
|
||||
app.Get("/", testEmptyHandler)
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest(MethodGet, "/", nil), -1)
|
||||
resp, err := app.Test(httptest.NewRequest(MethodGet, "/", nil), TestConfig{
|
||||
Timeout: 0,
|
||||
})
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
||||
|
@ -1133,7 +1136,10 @@ func Test_Test_Timeout(t *testing.T) {
|
|||
return nil
|
||||
})
|
||||
|
||||
_, err = app.Test(httptest.NewRequest(MethodGet, "/timeout", nil), 20*time.Millisecond)
|
||||
_, err = app.Test(httptest.NewRequest(MethodGet, "/timeout", nil), TestConfig{
|
||||
Timeout: 20 * time.Millisecond,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.Error(t, err, "app.Test(req)")
|
||||
}
|
||||
|
||||
|
@ -1432,7 +1438,9 @@ func Test_App_Test_no_timeout_infinitely(t *testing.T) {
|
|||
})
|
||||
|
||||
req := httptest.NewRequest(MethodGet, "/", nil)
|
||||
_, err = app.Test(req, -1)
|
||||
_, err = app.Test(req, TestConfig{
|
||||
Timeout: 0,
|
||||
})
|
||||
}()
|
||||
|
||||
tk := time.NewTimer(5 * time.Second)
|
||||
|
@ -1460,8 +1468,27 @@ func Test_App_Test_timeout(t *testing.T) {
|
|||
return nil
|
||||
})
|
||||
|
||||
_, err := app.Test(httptest.NewRequest(MethodGet, "/", nil), 100*time.Millisecond)
|
||||
require.Equal(t, errors.New("test: timeout error after 100ms"), err)
|
||||
_, err := app.Test(httptest.NewRequest(MethodGet, "/", nil), TestConfig{
|
||||
Timeout: 100 * time.Millisecond,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.Equal(t, os.ErrDeadlineExceeded, err)
|
||||
}
|
||||
|
||||
func Test_App_Test_timeout_empty_response(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
app := New()
|
||||
app.Get("/", func(_ Ctx) error {
|
||||
time.Sleep(1 * time.Second)
|
||||
return nil
|
||||
})
|
||||
|
||||
_, err := app.Test(httptest.NewRequest(MethodGet, "/", nil), TestConfig{
|
||||
Timeout: 100 * time.Millisecond,
|
||||
FailOnTimeout: false,
|
||||
})
|
||||
require.Equal(t, errors.New("test: got empty response"), err)
|
||||
}
|
||||
|
||||
func Test_App_SetTLSHandler(t *testing.T) {
|
||||
|
|
|
@ -3243,7 +3243,10 @@ func Test_Static_Compress(t *testing.T) {
|
|||
|
||||
req := httptest.NewRequest(MethodGet, "/file", nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, TestConfig{
|
||||
Timeout: 10 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
|
|
@ -641,10 +641,10 @@ func (app *App) SetTLSHandler(tlsHandler *TLSHandler)
|
|||
|
||||
## Test
|
||||
|
||||
Testing your application is done with the `Test` method. Use this method for creating `_test.go` files or when you need to debug your routing logic. The default timeout is `1s`; to disable a timeout altogether, pass `-1` as the second argument.
|
||||
Testing your application is done with the `Test` method. Use this method for creating `_test.go` files or when you need to debug your routing logic. The default timeout is `1s`; to disable a timeout altogether, pass a `TestConfig` struct with `Timeout: 0`.
|
||||
|
||||
```go title="Signature"
|
||||
func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error)
|
||||
func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, error)
|
||||
```
|
||||
|
||||
```go title="Example"
|
||||
|
@ -685,6 +685,31 @@ func main() {
|
|||
}
|
||||
```
|
||||
|
||||
If not provided, TestConfig is set to the following defaults:
|
||||
|
||||
```go title="Default TestConfig"
|
||||
config := fiber.TestConfig{
|
||||
Timeout: time.Second(),
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
```
|
||||
|
||||
:::caution
|
||||
|
||||
This is **not** the same as supplying an empty `TestConfig{}` to
|
||||
`app.Test(), but rather be the equivalent of supplying:
|
||||
|
||||
```go title="Empty TestConfig"
|
||||
cfg := fiber.TestConfig{
|
||||
Timeout: 0,
|
||||
FailOnTimeout: false,
|
||||
}
|
||||
```
|
||||
|
||||
This would make a Test that has no timeout.
|
||||
|
||||
:::
|
||||
|
||||
## Hooks
|
||||
|
||||
`Hooks` is a method to return the [hooks](./hooks.md) property.
|
||||
|
|
|
@ -75,7 +75,8 @@ We have made several changes to the Fiber app, including:
|
|||
|
||||
### Methods changes
|
||||
|
||||
- Test -> timeout changed to 1 second
|
||||
- Test -> Replaced timeout with a config parameter
|
||||
- -1 represents no timeout -> 0 represents no timeout
|
||||
- Listen -> has a config parameter
|
||||
- Listener -> has a config parameter
|
||||
|
||||
|
@ -184,6 +185,68 @@ To enable the routing changes above we had to slightly adjust the signature of t
|
|||
+ Add(methods []string, path string, handler Handler, middleware ...Handler) Router
|
||||
```
|
||||
|
||||
### Test Config
|
||||
|
||||
The `app.Test()` method now allows users to customize their test configurations:
|
||||
|
||||
<details>
|
||||
<summary>Example</summary>
|
||||
|
||||
```go
|
||||
// Create a test app with a handler to test
|
||||
app := fiber.New()
|
||||
app.Get("/", func(c fiber.Ctx) {
|
||||
return c.SendString("hello world")
|
||||
})
|
||||
|
||||
// Define the HTTP request and custom TestConfig to test the handler
|
||||
req := httptest.NewRequest(MethodGet, "/", nil)
|
||||
testConfig := fiber.TestConfig{
|
||||
Timeout: 0,
|
||||
FailOnTimeout: false,
|
||||
}
|
||||
|
||||
// Test the handler using the request and testConfig
|
||||
resp, err := app.Test(req, testConfig)
|
||||
```
|
||||
|
||||
</details>
|
||||
|
||||
To provide configurable testing capabilities, we had to change
|
||||
the signature of the `Test` method.
|
||||
|
||||
```diff
|
||||
- Test(req *http.Request, timeout ...time.Duration) (*http.Response, error)
|
||||
+ Test(req *http.Request, config ...fiber.TestConfig) (*http.Response, error)
|
||||
```
|
||||
|
||||
The `TestConfig` struct provides the following configuration options:
|
||||
|
||||
- `Timeout`: The duration to wait before timing out the test. Use 0 for no timeout.
|
||||
- `FailOnTimeout`: Controls the behavior when a timeout occurs:
|
||||
- When true, the test will return an `os.ErrDeadlineExceeded` if the test exceeds the `Timeout` duration.
|
||||
- When false, the test will return the partial response received before timing out.
|
||||
|
||||
If a custom `TestConfig` isn't provided, then the following will be used:
|
||||
|
||||
```go
|
||||
testConfig := fiber.TestConfig{
|
||||
Timeout: time.Second,
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
```
|
||||
|
||||
**Note:** Using this default is **NOT** the same as providing an empty `TestConfig` as an argument to `app.Test()`.
|
||||
|
||||
An empty `TestConfig` is the equivalent of:
|
||||
|
||||
```go
|
||||
testConfig := fiber.TestConfig{
|
||||
Timeout: 0,
|
||||
FailOnTimeout: false,
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🧠 Context
|
||||
|
|
33
helpers.go
33
helpers.go
|
@ -613,13 +613,36 @@ func isNoCache(cacheControl string) bool {
|
|||
}
|
||||
|
||||
type testConn struct {
|
||||
r bytes.Buffer
|
||||
w bytes.Buffer
|
||||
r bytes.Buffer
|
||||
w bytes.Buffer
|
||||
isClosed bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
func (c *testConn) Read(b []byte) (int, error) { return c.r.Read(b) } //nolint:wrapcheck // This must not be wrapped
|
||||
func (c *testConn) Write(b []byte) (int, error) { return c.w.Write(b) } //nolint:wrapcheck // This must not be wrapped
|
||||
func (*testConn) Close() error { return nil }
|
||||
func (c *testConn) Read(b []byte) (int, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
return c.r.Read(b) //nolint:wrapcheck // This must not be wrapped
|
||||
}
|
||||
|
||||
func (c *testConn) Write(b []byte) (int, error) {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
if c.isClosed {
|
||||
return 0, errors.New("testConn is closed")
|
||||
}
|
||||
return c.w.Write(b) //nolint:wrapcheck // This must not be wrapped
|
||||
}
|
||||
|
||||
func (c *testConn) Close() error {
|
||||
c.Lock()
|
||||
defer c.Unlock()
|
||||
|
||||
c.isClosed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (*testConn) LocalAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
|
||||
func (*testConn) RemoteAddr() net.Addr { return &net.TCPAddr{Port: 0, Zone: "", IP: net.IPv4zero} }
|
||||
|
|
|
@ -514,6 +514,48 @@ func Test_Utils_TestConn_Deadline(t *testing.T) {
|
|||
require.NoError(t, conn.SetWriteDeadline(time.Time{}))
|
||||
}
|
||||
|
||||
func Test_Utils_TestConn_ReadWrite(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn := &testConn{}
|
||||
|
||||
// Verify read of request
|
||||
_, err := conn.r.Write([]byte("Request"))
|
||||
require.NoError(t, err)
|
||||
|
||||
req := make([]byte, 7)
|
||||
_, err = conn.Read(req)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte("Request"), req)
|
||||
|
||||
// Verify write of response
|
||||
_, err = conn.Write([]byte("Response"))
|
||||
require.NoError(t, err)
|
||||
|
||||
res := make([]byte, 8)
|
||||
_, err = conn.w.Read(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte("Response"), res)
|
||||
}
|
||||
|
||||
func Test_Utils_TestConn_Closed_Write(t *testing.T) {
|
||||
t.Parallel()
|
||||
conn := &testConn{}
|
||||
|
||||
// Verify write of response
|
||||
_, err := conn.Write([]byte("Response 1\n"))
|
||||
require.NoError(t, err)
|
||||
|
||||
// Close early, write should fail
|
||||
conn.Close() //nolint:errcheck, revive // It is fine to ignore the error here
|
||||
_, err = conn.Write([]byte("Response 2\n"))
|
||||
require.Error(t, err)
|
||||
|
||||
res := make([]byte, 11)
|
||||
_, err = conn.w.Read(res)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, []byte("Response 1\n"), res)
|
||||
}
|
||||
|
||||
func Test_Utils_IsNoCache(t *testing.T) {
|
||||
t.Parallel()
|
||||
testCases := []struct {
|
||||
|
|
|
@ -16,6 +16,11 @@ import (
|
|||
|
||||
var filedata []byte
|
||||
|
||||
var testConfig = fiber.TestConfig{
|
||||
Timeout: 10 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
|
||||
func init() {
|
||||
dat, err := os.ReadFile("../../.github/README.md")
|
||||
if err != nil {
|
||||
|
@ -39,7 +44,7 @@ func Test_Compress_Gzip(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", "gzip")
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, "gzip", resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
@ -72,7 +77,7 @@ func Test_Compress_Different_Level(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, algo, resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
@ -99,7 +104,7 @@ func Test_Compress_Deflate(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", "deflate")
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, "deflate", resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
@ -123,7 +128,7 @@ func Test_Compress_Brotli(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", "br")
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, "br", resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
@ -147,7 +152,7 @@ func Test_Compress_Zstd(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", "zstd")
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, "zstd", resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
@ -171,7 +176,7 @@ func Test_Compress_Disabled(t *testing.T) {
|
|||
req := httptest.NewRequest(fiber.MethodGet, "/", nil)
|
||||
req.Header.Set("Accept-Encoding", "br")
|
||||
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
require.Equal(t, "", resp.Header.Get(fiber.HeaderContentEncoding))
|
||||
|
|
|
@ -82,7 +82,10 @@ func Test_Idempotency(t *testing.T) {
|
|||
if idempotencyKey != "" {
|
||||
req.Header.Set("X-Idempotency-Key", idempotencyKey)
|
||||
}
|
||||
resp, err := app.Test(req, 15*time.Second)
|
||||
resp, err := app.Test(req, fiber.TestConfig{
|
||||
Timeout: 15 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
|
|
@ -14,6 +14,10 @@ import (
|
|||
|
||||
const CorrectKey = "specials: !$%,.#\"!?~`<>@$^*(){}[]|/\\123"
|
||||
|
||||
var testConfig = fiber.TestConfig{
|
||||
Timeout: 0,
|
||||
}
|
||||
|
||||
func Test_AuthSources(t *testing.T) {
|
||||
// define test cases
|
||||
testSources := []string{"header", "cookie", "query", "param", "form"}
|
||||
|
@ -104,7 +108,7 @@ func Test_AuthSources(t *testing.T) {
|
|||
req.URL.Path = r
|
||||
}
|
||||
|
||||
res, err := app.Test(req, -1)
|
||||
res, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, test.description)
|
||||
|
||||
|
@ -209,7 +213,7 @@ func TestMultipleKeyLookup(t *testing.T) {
|
|||
q.Add("key", CorrectKey)
|
||||
req.URL.RawQuery = q.Encode()
|
||||
|
||||
res, err := app.Test(req, -1)
|
||||
res, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -226,7 +230,7 @@ func TestMultipleKeyLookup(t *testing.T) {
|
|||
// construct a second request without proper key
|
||||
req, err = http.NewRequestWithContext(context.Background(), fiber.MethodGet, "/foo", nil)
|
||||
require.NoError(t, err)
|
||||
res, err = app.Test(req, -1)
|
||||
res, err = app.Test(req, testConfig)
|
||||
require.NoError(t, err)
|
||||
errBody, err := io.ReadAll(res.Body)
|
||||
require.NoError(t, err)
|
||||
|
@ -350,7 +354,7 @@ func Test_MultipleKeyAuth(t *testing.T) {
|
|||
req.Header.Set("key", test.APIKey)
|
||||
}
|
||||
|
||||
res, err := app.Test(req, -1)
|
||||
res, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, test.description)
|
||||
|
||||
|
|
|
@ -300,7 +300,10 @@ func Test_Logger_WithLatency(t *testing.T) {
|
|||
sleepDuration = 1 * tu.div
|
||||
|
||||
// Create a new HTTP request to the test route
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 3*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 3 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
|
@ -341,7 +344,10 @@ func Test_Logger_WithLatency_DefaultFormat(t *testing.T) {
|
|||
sleepDuration = 1 * tu.div
|
||||
|
||||
// Create a new HTTP request to the test route
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 2*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
|
|
|
@ -11,6 +11,11 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testConfig = fiber.TestConfig{
|
||||
Timeout: 5 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
|
||||
func Test_Non_Pprof_Path(t *testing.T) {
|
||||
app := fiber.New()
|
||||
|
||||
|
@ -105,7 +110,7 @@ func Test_Pprof_Subs(t *testing.T) {
|
|||
if sub == "profile" {
|
||||
target += "?seconds=1"
|
||||
}
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, target, nil), 5*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, target, nil), testConfig)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
})
|
||||
|
@ -132,7 +137,7 @@ func Test_Pprof_Subs_WithPrefix(t *testing.T) {
|
|||
if sub == "profile" {
|
||||
target += "?seconds=1"
|
||||
}
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, target, nil), 5*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, target, nil), testConfig)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 200, resp.StatusCode)
|
||||
})
|
||||
|
|
|
@ -2,10 +2,10 @@ package proxy
|
|||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"errors"
|
||||
"io"
|
||||
"net"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -110,7 +110,10 @@ func Test_Proxy(t *testing.T) {
|
|||
return c.SendStatus(fiber.StatusTeapot)
|
||||
})
|
||||
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusTeapot, resp.StatusCode)
|
||||
|
||||
|
@ -172,7 +175,10 @@ func Test_Proxy_Balancer_IPv6_Upstream(t *testing.T) {
|
|||
return c.SendStatus(fiber.StatusTeapot)
|
||||
})
|
||||
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusTeapot, resp.StatusCode)
|
||||
|
||||
|
@ -195,7 +201,10 @@ func Test_Proxy_Balancer_IPv6_Upstream_With_DialDualStack(t *testing.T) {
|
|||
return c.SendStatus(fiber.StatusTeapot)
|
||||
})
|
||||
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusTeapot, resp.StatusCode)
|
||||
|
||||
|
@ -221,7 +230,10 @@ func Test_Proxy_Balancer_IPv4_Upstream_With_DialDualStack(t *testing.T) {
|
|||
return c.SendStatus(fiber.StatusTeapot)
|
||||
})
|
||||
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusTeapot, resp.StatusCode)
|
||||
|
||||
|
@ -399,7 +411,10 @@ func Test_Proxy_Timeout_Slow_Server(t *testing.T) {
|
|||
Timeout: 600 * time.Millisecond,
|
||||
}))
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusOK, resp.StatusCode)
|
||||
|
||||
|
@ -423,7 +438,10 @@ func Test_Proxy_With_Timeout(t *testing.T) {
|
|||
Timeout: 100 * time.Millisecond,
|
||||
}))
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusInternalServerError, resp.StatusCode)
|
||||
|
||||
|
@ -521,7 +539,10 @@ func Test_Proxy_DoRedirects_RestoreOriginalURL(t *testing.T) {
|
|||
return DoRedirects(c, "http://google.com", 1)
|
||||
})
|
||||
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 2*time.Second)
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err1)
|
||||
_, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
@ -559,7 +580,10 @@ func Test_Proxy_DoTimeout_RestoreOriginalURL(t *testing.T) {
|
|||
return DoTimeout(c, "http://"+addr, time.Second)
|
||||
})
|
||||
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 2*time.Second)
|
||||
resp, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err1)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
@ -580,7 +604,10 @@ func Test_Proxy_DoTimeout_Timeout(t *testing.T) {
|
|||
return DoTimeout(c, "http://"+addr, time.Second)
|
||||
})
|
||||
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 2*time.Second)
|
||||
resp, err := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
require.NoError(t, err)
|
||||
|
@ -624,8 +651,11 @@ func Test_Proxy_DoDeadline_PastDeadline(t *testing.T) {
|
|||
return DoDeadline(c, "http://"+addr, time.Now().Add(2*time.Second))
|
||||
})
|
||||
|
||||
_, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), 1*time.Second)
|
||||
require.Equal(t, errors.New("test: timeout error after 1s"), err1)
|
||||
_, err1 := app.Test(httptest.NewRequest(fiber.MethodGet, "/test", nil), fiber.TestConfig{
|
||||
Timeout: 1 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.Equal(t, os.ErrDeadlineExceeded, err1)
|
||||
}
|
||||
|
||||
// go test -race -run Test_Proxy_Do_HTTP_Prefix_URL
|
||||
|
@ -717,7 +747,10 @@ func Test_ProxyBalancer_Custom_Client(t *testing.T) {
|
|||
return c.SendStatus(fiber.StatusTeapot)
|
||||
})
|
||||
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), 2*time.Second)
|
||||
resp, err := target.Test(httptest.NewRequest(fiber.MethodGet, "/", nil), fiber.TestConfig{
|
||||
Timeout: 2 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fiber.StatusTeapot, resp.StatusCode)
|
||||
|
||||
|
|
|
@ -15,6 +15,11 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
var testConfig = fiber.TestConfig{
|
||||
Timeout: 10 * time.Second,
|
||||
FailOnTimeout: true,
|
||||
}
|
||||
|
||||
// go test -run Test_Static_Index_Default
|
||||
func Test_Static_Index_Default(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
@ -738,7 +743,7 @@ func Test_Static_Compress(t *testing.T) {
|
|||
// request non-compressable file (less than 200 bytes), Content Lengh will remain the same
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/css/style.css", nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
@ -748,7 +753,7 @@ func Test_Static_Compress(t *testing.T) {
|
|||
// request compressable file, ContentLenght will change
|
||||
req = httptest.NewRequest(fiber.MethodGet, "/index.html", nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
resp, err = app.Test(req, 10*time.Second)
|
||||
resp, err = app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
@ -769,7 +774,7 @@ func Test_Static_Compress_WithoutEncoding(t *testing.T) {
|
|||
|
||||
// request compressable file without encoding
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/index.html", nil)
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
@ -792,7 +797,7 @@ func Test_Static_Compress_WithoutEncoding(t *testing.T) {
|
|||
|
||||
req = httptest.NewRequest(fiber.MethodGet, "/"+fileName, nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
resp, err = app.Test(req, 10*time.Second)
|
||||
resp, err = app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
@ -833,7 +838,7 @@ func Test_Static_Compress_WithFileSuffixes(t *testing.T) {
|
|||
|
||||
req := httptest.NewRequest(fiber.MethodGet, "/"+fileName, nil)
|
||||
req.Header.Set("Accept-Encoding", algo)
|
||||
resp, err := app.Test(req, 10*time.Second)
|
||||
resp, err := app.Test(req, testConfig)
|
||||
|
||||
require.NoError(t, err, "app.Test(req)")
|
||||
require.Equal(t, 200, resp.StatusCode, "Status code")
|
||||
|
|
Loading…
Reference in New Issue