- With issues:
- Use the search tool before opening a new issue.
- Please provide source code and commit sha if you found a bug.
- Review existing issues and provide feedback or react to them.
Description
#2755 only fixes the slice bounds out of range panic. Route params are not be handled correctly in test context. I can explain what happened.
When call CreateTestContext, it will call New function to create a Engine. The maxParams will be the default value 0.
|
// CreateTestContext returns a fresh engine and context for testing purposes |
|
func CreateTestContext(w http.ResponseWriter) (c *Context, r *Engine) { |
|
r = New() |
|
c = r.allocateContext() |
|
c.reset() |
|
c.writermem.reset(w) |
|
return |
|
} |
Then allocateContext init the Params. The cap and len are both 0. params is the reference of Params.
|
func (engine *Engine) allocateContext() *Context { |
|
v := make(Params, 0, engine.maxParams) |
|
return &Context{engine: engine, params: &v} |
|
} |
Even if we add a route, it only incrs the maxParams value, it has not effect on the Context we created by CreateTestContext before. The condition will always be false.
|
if params != nil && cap(*params) > 0 { |
|
if value.params == nil { |
|
value.params = params |
|
} |
|
// Expand slice within preallocated capacity |
|
i := len(*value.params) |
|
*value.params = (*value.params)[:i+1] |
|
val := path[:end] |
|
if unescape { |
|
if v, err := url.QueryUnescape(val); err == nil { |
|
val = v |
|
} |
|
} |
|
(*value.params)[i] = Param{ |
|
Key: n.path[1:], |
|
Value: val, |
|
} |
|
} |
How to reproduce
package main
import (
"fmt"
"net/http"
"net/http/httptest"
"github.com/gin-gonic/gin"
)
func main() {
w := httptest.NewRecorder()
ctx, engine := gin.CreateTestContext(w)
engine.GET("/hello/:name", func(ctx *gin.Context) {
fmt.Printf("Param name is %s\n", ctx.Param("name"))
ctx.String(http.StatusOK, "Hello %s", ctx.Param("name"))
})
var err error
ctx.Request, err = http.NewRequest(http.MethodGet, "/hello/world", nil)
if err != nil {
panic(err)
}
engine.HandleContext(ctx)
}
Expectations
Get following output after running the code.
[GIN-debug] GET /hello/:name --> main.main.func1 (1 handlers)
Param name is world
Actual result
[GIN-debug] GET /hello/:name --> main.main.func1 (1 handlers)
Param name is
ctx.Param("name") returns a empty string.
Environment
- go version: go version go1.16 darwin/amd64
- gin version (or commit ref): v1.7.2-0.20210704023713-9c27053243cb
- operating system: macOs Big Sur 11.4, Darwin Kernel Version 20.5.0
Description
#2755 only fixes the
slice bounds out of rangepanic. Route params are not be handled correctly in test context. I can explain what happened.When call
CreateTestContext, it will callNewfunction to create aEngine. ThemaxParamswill be the default value0.gin/test_helpers.go
Lines 9 to 16 in 9c27053
Then
allocateContextinit theParams. Thecapandlenare both 0.paramsis the reference ofParams.gin/gin.go
Lines 202 to 205 in 9c27053
Even if we add a route, it only incrs the
maxParamsvalue, it has not effect on theContextwe created byCreateTestContextbefore. The condition will always befalse.gin/tree.go
Lines 462 to 479 in 9c27053
How to reproduce
Expectations
Get following output after running the code.
Actual result
ctx.Param("name")returns a empty string.Environment