mirror of
https://github.com/gin-gonic/gin.git
synced 2026-06-06 12:08:20 +08:00
Compare commits
4 Commits
67cf55e6f1
...
567fb4dd96
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
567fb4dd96 | ||
|
|
5f4f964325 | ||
|
|
3f607b8662 | ||
|
|
4a0302068c |
2
.github/workflows/gin.yml
vendored
2
.github/workflows/gin.yml
vendored
@ -78,6 +78,6 @@ jobs:
|
|||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v6
|
||||||
with:
|
with:
|
||||||
flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}
|
flags: ${{ matrix.os }},go-${{ matrix.go }},${{ matrix.test-tags }}
|
||||||
|
|||||||
4
.github/workflows/trivy-scan.yml
vendored
4
.github/workflows/trivy-scan.yml
vendored
@ -27,7 +27,7 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Run Trivy vulnerability scanner (source code)
|
- name: Run Trivy vulnerability scanner (source code)
|
||||||
uses: aquasecurity/trivy-action@0.35.0
|
uses: aquasecurity/trivy-action@v0.36.0
|
||||||
with:
|
with:
|
||||||
scan-type: "fs"
|
scan-type: "fs"
|
||||||
scan-ref: "."
|
scan-ref: "."
|
||||||
@ -44,7 +44,7 @@ jobs:
|
|||||||
sarif_file: "trivy-results.sarif"
|
sarif_file: "trivy-results.sarif"
|
||||||
|
|
||||||
- name: Run Trivy scanner (table output for logs)
|
- name: Run Trivy scanner (table output for logs)
|
||||||
uses: aquasecurity/trivy-action@0.35.0
|
uses: aquasecurity/trivy-action@v0.36.0
|
||||||
if: always()
|
if: always()
|
||||||
with:
|
with:
|
||||||
scan-type: "fs"
|
scan-type: "fs"
|
||||||
|
|||||||
@ -34,6 +34,30 @@ func CreateTestContextOnly(w http.ResponseWriter, r *Engine) (c *Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RunTestHandler creates a test context, assigns the given request, executes
|
||||||
|
// the provided handler chain, and flushes the status code to the underlying
|
||||||
|
// ResponseWriter. This solves the problem where ctx.Status() sets the status
|
||||||
|
// internally but does not flush it to an httptest.ResponseRecorder when using
|
||||||
|
// CreateTestContext directly.
|
||||||
|
//
|
||||||
|
// Example usage:
|
||||||
|
//
|
||||||
|
// w := httptest.NewRecorder()
|
||||||
|
// req := httptest.NewRequest("POST", "/resource", nil)
|
||||||
|
// c := gin.RunTestHandler(w, req, func(c *gin.Context) {
|
||||||
|
// c.Status(http.StatusCreated)
|
||||||
|
// })
|
||||||
|
// // w.Code is now 201, not 200
|
||||||
|
func RunTestHandler(w http.ResponseWriter, req *http.Request, handlers ...HandlerFunc) *Context {
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
c.Request = req
|
||||||
|
c.handlers = handlers
|
||||||
|
c.index = -1
|
||||||
|
c.Next()
|
||||||
|
c.Writer.WriteHeaderNow()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
// waitForServerReady waits for a server to be ready by making HTTP requests
|
// waitForServerReady waits for a server to be ready by making HTTP requests
|
||||||
// with exponential backoff. This is more reliable than time.Sleep() for testing.
|
// with exponential backoff. This is more reliable than time.Sleep() for testing.
|
||||||
func waitForServerReady(url string, maxAttempts int) error {
|
func waitForServerReady(url string, maxAttempts int) error {
|
||||||
|
|||||||
101
test_helpers_test.go
Normal file
101
test_helpers_test.go
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
// Copyright 2017 Manu Martinez-Almeida. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package gin
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestRunTestHandlerFlushesStatusCode(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
statusCode int
|
||||||
|
}{
|
||||||
|
{"201 Created", http.StatusCreated},
|
||||||
|
{"204 No Content", http.StatusNoContent},
|
||||||
|
{"400 Bad Request", http.StatusBadRequest},
|
||||||
|
{"404 Not Found", http.StatusNotFound},
|
||||||
|
{"500 Internal Server Error", http.StatusInternalServerError},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
|
code := tt.statusCode
|
||||||
|
|
||||||
|
c := RunTestHandler(w, req, func(c *Context) {
|
||||||
|
c.Status(code)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, code, w.Code)
|
||||||
|
assert.Equal(t, code, c.Writer.Status())
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTestHandlerMultipleHandlers(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/resource", nil)
|
||||||
|
|
||||||
|
callOrder := []string{}
|
||||||
|
|
||||||
|
middleware := func(c *Context) {
|
||||||
|
callOrder = append(callOrder, "middleware")
|
||||||
|
c.Next()
|
||||||
|
}
|
||||||
|
|
||||||
|
handler := func(c *Context) {
|
||||||
|
callOrder = append(callOrder, "handler")
|
||||||
|
c.Status(http.StatusCreated)
|
||||||
|
}
|
||||||
|
|
||||||
|
c := RunTestHandler(w, req, middleware, handler)
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusCreated, w.Code)
|
||||||
|
assert.Equal(t, http.StatusCreated, c.Writer.Status())
|
||||||
|
assert.Equal(t, []string{"middleware", "handler"}, callOrder)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTestHandlerDefaultStatus(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodGet, "/", nil)
|
||||||
|
|
||||||
|
RunTestHandler(w, req, func(c *Context) {
|
||||||
|
// Handler that does not set a status explicitly.
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRunTestHandlerSetsRequest(t *testing.T) {
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
req := httptest.NewRequest(http.MethodPut, "/items/42", nil)
|
||||||
|
|
||||||
|
c := RunTestHandler(w, req, func(c *Context) {
|
||||||
|
c.Status(http.StatusOK)
|
||||||
|
})
|
||||||
|
|
||||||
|
assert.Equal(t, req, c.Request)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCreateTestContextBackwardCompatible(t *testing.T) {
|
||||||
|
// Verify that CreateTestContext still behaves the same way:
|
||||||
|
// status is stored internally but NOT flushed to the ResponseRecorder.
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
c, _ := CreateTestContext(w)
|
||||||
|
c.Status(http.StatusCreated)
|
||||||
|
|
||||||
|
// The internal status should be set.
|
||||||
|
assert.Equal(t, http.StatusCreated, c.Writer.Status())
|
||||||
|
|
||||||
|
// But w.Code should still be the default 200 because WriteHeaderNow
|
||||||
|
// was never called. This confirms backward compatibility.
|
||||||
|
assert.Equal(t, http.StatusOK, w.Code)
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user