"Fossies" - the Fresh Open Source Software Archive

Member "gin-1.7.7/context_test.go" (24 Nov 2021, 63398 Bytes) of package /linux/www/gin-1.7.7.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.


    1 // Copyright 2014 Manu Martinez-Almeida.  All rights reserved.
    2 // Use of this source code is governed by a MIT style
    3 // license that can be found in the LICENSE file.
    4 
    5 package gin
    6 
    7 import (
    8     "bytes"
    9     "context"
   10     "errors"
   11     "fmt"
   12     "html/template"
   13     "io"
   14     "mime/multipart"
   15     "net/http"
   16     "net/http/httptest"
   17     "os"
   18     "reflect"
   19     "strings"
   20     "sync"
   21     "testing"
   22     "time"
   23 
   24     "github.com/gin-contrib/sse"
   25     "github.com/gin-gonic/gin/binding"
   26     "github.com/golang/protobuf/proto"
   27     "github.com/stretchr/testify/assert"
   28 
   29     testdata "github.com/gin-gonic/gin/testdata/protoexample"
   30 )
   31 
   32 var _ context.Context = &Context{}
   33 
   34 // Unit tests TODO
   35 // func (c *Context) File(filepath string) {
   36 // func (c *Context) Negotiate(code int, config Negotiate) {
   37 // BAD case: func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
   38 // test that information is not leaked when reusing Contexts (using the Pool)
   39 
   40 func createMultipartRequest() *http.Request {
   41     boundary := "--testboundary"
   42     body := new(bytes.Buffer)
   43     mw := multipart.NewWriter(body)
   44     defer mw.Close()
   45 
   46     must(mw.SetBoundary(boundary))
   47     must(mw.WriteField("foo", "bar"))
   48     must(mw.WriteField("bar", "10"))
   49     must(mw.WriteField("bar", "foo2"))
   50     must(mw.WriteField("array", "first"))
   51     must(mw.WriteField("array", "second"))
   52     must(mw.WriteField("id", ""))
   53     must(mw.WriteField("time_local", "31/12/2016 14:55"))
   54     must(mw.WriteField("time_utc", "31/12/2016 14:55"))
   55     must(mw.WriteField("time_location", "31/12/2016 14:55"))
   56     must(mw.WriteField("names[a]", "thinkerou"))
   57     must(mw.WriteField("names[b]", "tianou"))
   58     req, err := http.NewRequest("POST", "/", body)
   59     must(err)
   60     req.Header.Set("Content-Type", MIMEMultipartPOSTForm+"; boundary="+boundary)
   61     return req
   62 }
   63 
   64 func must(err error) {
   65     if err != nil {
   66         panic(err.Error())
   67     }
   68 }
   69 
   70 func TestContextFormFile(t *testing.T) {
   71     buf := new(bytes.Buffer)
   72     mw := multipart.NewWriter(buf)
   73     w, err := mw.CreateFormFile("file", "test")
   74     if assert.NoError(t, err) {
   75         _, err = w.Write([]byte("test"))
   76         assert.NoError(t, err)
   77     }
   78     mw.Close()
   79     c, _ := CreateTestContext(httptest.NewRecorder())
   80     c.Request, _ = http.NewRequest("POST", "/", buf)
   81     c.Request.Header.Set("Content-Type", mw.FormDataContentType())
   82     f, err := c.FormFile("file")
   83     if assert.NoError(t, err) {
   84         assert.Equal(t, "test", f.Filename)
   85     }
   86 
   87     assert.NoError(t, c.SaveUploadedFile(f, "test"))
   88 }
   89 
   90 func TestContextMultipartForm(t *testing.T) {
   91     buf := new(bytes.Buffer)
   92     mw := multipart.NewWriter(buf)
   93     assert.NoError(t, mw.WriteField("foo", "bar"))
   94     w, err := mw.CreateFormFile("file", "test")
   95     if assert.NoError(t, err) {
   96         _, err = w.Write([]byte("test"))
   97         assert.NoError(t, err)
   98     }
   99     mw.Close()
  100     c, _ := CreateTestContext(httptest.NewRecorder())
  101     c.Request, _ = http.NewRequest("POST", "/", buf)
  102     c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  103     f, err := c.MultipartForm()
  104     if assert.NoError(t, err) {
  105         assert.NotNil(t, f)
  106     }
  107 
  108     assert.NoError(t, c.SaveUploadedFile(f.File["file"][0], "test"))
  109 }
  110 
  111 func TestSaveUploadedOpenFailed(t *testing.T) {
  112     buf := new(bytes.Buffer)
  113     mw := multipart.NewWriter(buf)
  114     mw.Close()
  115 
  116     c, _ := CreateTestContext(httptest.NewRecorder())
  117     c.Request, _ = http.NewRequest("POST", "/", buf)
  118     c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  119 
  120     f := &multipart.FileHeader{
  121         Filename: "file",
  122     }
  123     assert.Error(t, c.SaveUploadedFile(f, "test"))
  124 }
  125 
  126 func TestSaveUploadedCreateFailed(t *testing.T) {
  127     buf := new(bytes.Buffer)
  128     mw := multipart.NewWriter(buf)
  129     w, err := mw.CreateFormFile("file", "test")
  130     if assert.NoError(t, err) {
  131         _, err = w.Write([]byte("test"))
  132         assert.NoError(t, err)
  133     }
  134     mw.Close()
  135     c, _ := CreateTestContext(httptest.NewRecorder())
  136     c.Request, _ = http.NewRequest("POST", "/", buf)
  137     c.Request.Header.Set("Content-Type", mw.FormDataContentType())
  138     f, err := c.FormFile("file")
  139     if assert.NoError(t, err) {
  140         assert.Equal(t, "test", f.Filename)
  141     }
  142 
  143     assert.Error(t, c.SaveUploadedFile(f, "/"))
  144 }
  145 
  146 func TestContextReset(t *testing.T) {
  147     router := New()
  148     c := router.allocateContext()
  149     assert.Equal(t, c.engine, router)
  150 
  151     c.index = 2
  152     c.Writer = &responseWriter{ResponseWriter: httptest.NewRecorder()}
  153     c.Params = Params{Param{}}
  154     c.Error(errors.New("test")) // nolint: errcheck
  155     c.Set("foo", "bar")
  156     c.reset()
  157 
  158     assert.False(t, c.IsAborted())
  159     assert.Nil(t, c.Keys)
  160     assert.Nil(t, c.Accepted)
  161     assert.Len(t, c.Errors, 0)
  162     assert.Empty(t, c.Errors.Errors())
  163     assert.Empty(t, c.Errors.ByType(ErrorTypeAny))
  164     assert.Len(t, c.Params, 0)
  165     assert.EqualValues(t, c.index, -1)
  166     assert.Equal(t, c.Writer.(*responseWriter), &c.writermem)
  167 }
  168 
  169 func TestContextHandlers(t *testing.T) {
  170     c, _ := CreateTestContext(httptest.NewRecorder())
  171     assert.Nil(t, c.handlers)
  172     assert.Nil(t, c.handlers.Last())
  173 
  174     c.handlers = HandlersChain{}
  175     assert.NotNil(t, c.handlers)
  176     assert.Nil(t, c.handlers.Last())
  177 
  178     f := func(c *Context) {}
  179     g := func(c *Context) {}
  180 
  181     c.handlers = HandlersChain{f}
  182     compareFunc(t, f, c.handlers.Last())
  183 
  184     c.handlers = HandlersChain{f, g}
  185     compareFunc(t, g, c.handlers.Last())
  186 }
  187 
  188 // TestContextSetGet tests that a parameter is set correctly on the
  189 // current context and can be retrieved using Get.
  190 func TestContextSetGet(t *testing.T) {
  191     c, _ := CreateTestContext(httptest.NewRecorder())
  192     c.Set("foo", "bar")
  193 
  194     value, err := c.Get("foo")
  195     assert.Equal(t, "bar", value)
  196     assert.True(t, err)
  197 
  198     value, err = c.Get("foo2")
  199     assert.Nil(t, value)
  200     assert.False(t, err)
  201 
  202     assert.Equal(t, "bar", c.MustGet("foo"))
  203     assert.Panics(t, func() { c.MustGet("no_exist") })
  204 }
  205 
  206 func TestContextSetGetValues(t *testing.T) {
  207     c, _ := CreateTestContext(httptest.NewRecorder())
  208     c.Set("string", "this is a string")
  209     c.Set("int32", int32(-42))
  210     c.Set("int64", int64(42424242424242))
  211     c.Set("uint64", uint64(42))
  212     c.Set("float32", float32(4.2))
  213     c.Set("float64", 4.2)
  214     var a interface{} = 1
  215     c.Set("intInterface", a)
  216 
  217     assert.Exactly(t, c.MustGet("string").(string), "this is a string")
  218     assert.Exactly(t, c.MustGet("int32").(int32), int32(-42))
  219     assert.Exactly(t, c.MustGet("int64").(int64), int64(42424242424242))
  220     assert.Exactly(t, c.MustGet("uint64").(uint64), uint64(42))
  221     assert.Exactly(t, c.MustGet("float32").(float32), float32(4.2))
  222     assert.Exactly(t, c.MustGet("float64").(float64), 4.2)
  223     assert.Exactly(t, c.MustGet("intInterface").(int), 1)
  224 
  225 }
  226 
  227 func TestContextGetString(t *testing.T) {
  228     c, _ := CreateTestContext(httptest.NewRecorder())
  229     c.Set("string", "this is a string")
  230     assert.Equal(t, "this is a string", c.GetString("string"))
  231 }
  232 
  233 func TestContextSetGetBool(t *testing.T) {
  234     c, _ := CreateTestContext(httptest.NewRecorder())
  235     c.Set("bool", true)
  236     assert.True(t, c.GetBool("bool"))
  237 }
  238 
  239 func TestContextGetInt(t *testing.T) {
  240     c, _ := CreateTestContext(httptest.NewRecorder())
  241     c.Set("int", 1)
  242     assert.Equal(t, 1, c.GetInt("int"))
  243 }
  244 
  245 func TestContextGetInt64(t *testing.T) {
  246     c, _ := CreateTestContext(httptest.NewRecorder())
  247     c.Set("int64", int64(42424242424242))
  248     assert.Equal(t, int64(42424242424242), c.GetInt64("int64"))
  249 }
  250 
  251 func TestContextGetUint(t *testing.T) {
  252     c, _ := CreateTestContext(httptest.NewRecorder())
  253     c.Set("uint", uint(1))
  254     assert.Equal(t, uint(1), c.GetUint("uint"))
  255 }
  256 
  257 func TestContextGetUint64(t *testing.T) {
  258     c, _ := CreateTestContext(httptest.NewRecorder())
  259     c.Set("uint64", uint64(18446744073709551615))
  260     assert.Equal(t, uint64(18446744073709551615), c.GetUint64("uint64"))
  261 }
  262 
  263 func TestContextGetFloat64(t *testing.T) {
  264     c, _ := CreateTestContext(httptest.NewRecorder())
  265     c.Set("float64", 4.2)
  266     assert.Equal(t, 4.2, c.GetFloat64("float64"))
  267 }
  268 
  269 func TestContextGetTime(t *testing.T) {
  270     c, _ := CreateTestContext(httptest.NewRecorder())
  271     t1, _ := time.Parse("1/2/2006 15:04:05", "01/01/2017 12:00:00")
  272     c.Set("time", t1)
  273     assert.Equal(t, t1, c.GetTime("time"))
  274 }
  275 
  276 func TestContextGetDuration(t *testing.T) {
  277     c, _ := CreateTestContext(httptest.NewRecorder())
  278     c.Set("duration", time.Second)
  279     assert.Equal(t, time.Second, c.GetDuration("duration"))
  280 }
  281 
  282 func TestContextGetStringSlice(t *testing.T) {
  283     c, _ := CreateTestContext(httptest.NewRecorder())
  284     c.Set("slice", []string{"foo"})
  285     assert.Equal(t, []string{"foo"}, c.GetStringSlice("slice"))
  286 }
  287 
  288 func TestContextGetStringMap(t *testing.T) {
  289     c, _ := CreateTestContext(httptest.NewRecorder())
  290     var m = make(map[string]interface{})
  291     m["foo"] = 1
  292     c.Set("map", m)
  293 
  294     assert.Equal(t, m, c.GetStringMap("map"))
  295     assert.Equal(t, 1, c.GetStringMap("map")["foo"])
  296 }
  297 
  298 func TestContextGetStringMapString(t *testing.T) {
  299     c, _ := CreateTestContext(httptest.NewRecorder())
  300     var m = make(map[string]string)
  301     m["foo"] = "bar"
  302     c.Set("map", m)
  303 
  304     assert.Equal(t, m, c.GetStringMapString("map"))
  305     assert.Equal(t, "bar", c.GetStringMapString("map")["foo"])
  306 }
  307 
  308 func TestContextGetStringMapStringSlice(t *testing.T) {
  309     c, _ := CreateTestContext(httptest.NewRecorder())
  310     var m = make(map[string][]string)
  311     m["foo"] = []string{"foo"}
  312     c.Set("map", m)
  313 
  314     assert.Equal(t, m, c.GetStringMapStringSlice("map"))
  315     assert.Equal(t, []string{"foo"}, c.GetStringMapStringSlice("map")["foo"])
  316 }
  317 
  318 func TestContextCopy(t *testing.T) {
  319     c, _ := CreateTestContext(httptest.NewRecorder())
  320     c.index = 2
  321     c.Request, _ = http.NewRequest("POST", "/hola", nil)
  322     c.handlers = HandlersChain{func(c *Context) {}}
  323     c.Params = Params{Param{Key: "foo", Value: "bar"}}
  324     c.Set("foo", "bar")
  325 
  326     cp := c.Copy()
  327     assert.Nil(t, cp.handlers)
  328     assert.Nil(t, cp.writermem.ResponseWriter)
  329     assert.Equal(t, &cp.writermem, cp.Writer.(*responseWriter))
  330     assert.Equal(t, cp.Request, c.Request)
  331     assert.Equal(t, cp.index, abortIndex)
  332     assert.Equal(t, cp.Keys, c.Keys)
  333     assert.Equal(t, cp.engine, c.engine)
  334     assert.Equal(t, cp.Params, c.Params)
  335     cp.Set("foo", "notBar")
  336     assert.False(t, cp.Keys["foo"] == c.Keys["foo"])
  337 }
  338 
  339 func TestContextHandlerName(t *testing.T) {
  340     c, _ := CreateTestContext(httptest.NewRecorder())
  341     c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest}
  342 
  343     assert.Regexp(t, "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$", c.HandlerName())
  344 }
  345 
  346 func TestContextHandlerNames(t *testing.T) {
  347     c, _ := CreateTestContext(httptest.NewRecorder())
  348     c.handlers = HandlersChain{func(c *Context) {}, handlerNameTest, func(c *Context) {}, handlerNameTest2}
  349 
  350     names := c.HandlerNames()
  351 
  352     assert.True(t, len(names) == 4)
  353     for _, name := range names {
  354         assert.Regexp(t, `^(.*/vendor/)?(github\.com/gin-gonic/gin\.){1}(TestContextHandlerNames\.func.*){0,1}(handlerNameTest.*){0,1}`, name)
  355     }
  356 }
  357 
  358 func handlerNameTest(c *Context) {
  359 
  360 }
  361 
  362 func handlerNameTest2(c *Context) {
  363 
  364 }
  365 
  366 var handlerTest HandlerFunc = func(c *Context) {
  367 
  368 }
  369 
  370 func TestContextHandler(t *testing.T) {
  371     c, _ := CreateTestContext(httptest.NewRecorder())
  372     c.handlers = HandlersChain{func(c *Context) {}, handlerTest}
  373 
  374     assert.Equal(t, reflect.ValueOf(handlerTest).Pointer(), reflect.ValueOf(c.Handler()).Pointer())
  375 }
  376 
  377 func TestContextQuery(t *testing.T) {
  378     c, _ := CreateTestContext(httptest.NewRecorder())
  379     c.Request, _ = http.NewRequest("GET", "http://example.com/?foo=bar&page=10&id=", nil)
  380 
  381     value, ok := c.GetQuery("foo")
  382     assert.True(t, ok)
  383     assert.Equal(t, "bar", value)
  384     assert.Equal(t, "bar", c.DefaultQuery("foo", "none"))
  385     assert.Equal(t, "bar", c.Query("foo"))
  386 
  387     value, ok = c.GetQuery("page")
  388     assert.True(t, ok)
  389     assert.Equal(t, "10", value)
  390     assert.Equal(t, "10", c.DefaultQuery("page", "0"))
  391     assert.Equal(t, "10", c.Query("page"))
  392 
  393     value, ok = c.GetQuery("id")
  394     assert.True(t, ok)
  395     assert.Empty(t, value)
  396     assert.Empty(t, c.DefaultQuery("id", "nada"))
  397     assert.Empty(t, c.Query("id"))
  398 
  399     value, ok = c.GetQuery("NoKey")
  400     assert.False(t, ok)
  401     assert.Empty(t, value)
  402     assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
  403     assert.Empty(t, c.Query("NoKey"))
  404 
  405     // postform should not mess
  406     value, ok = c.GetPostForm("page")
  407     assert.False(t, ok)
  408     assert.Empty(t, value)
  409     assert.Empty(t, c.PostForm("foo"))
  410 }
  411 
  412 func TestContextDefaultQueryOnEmptyRequest(t *testing.T) {
  413     c, _ := CreateTestContext(httptest.NewRecorder()) // here c.Request == nil
  414     assert.NotPanics(t, func() {
  415         value, ok := c.GetQuery("NoKey")
  416         assert.False(t, ok)
  417         assert.Empty(t, value)
  418     })
  419     assert.NotPanics(t, func() {
  420         assert.Equal(t, "nada", c.DefaultQuery("NoKey", "nada"))
  421     })
  422     assert.NotPanics(t, func() {
  423         assert.Empty(t, c.Query("NoKey"))
  424     })
  425 }
  426 
  427 func TestContextQueryAndPostForm(t *testing.T) {
  428     c, _ := CreateTestContext(httptest.NewRecorder())
  429     body := bytes.NewBufferString("foo=bar&page=11&both=&foo=second")
  430     c.Request, _ = http.NewRequest("POST",
  431         "/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14", body)
  432     c.Request.Header.Add("Content-Type", MIMEPOSTForm)
  433 
  434     assert.Equal(t, "bar", c.DefaultPostForm("foo", "none"))
  435     assert.Equal(t, "bar", c.PostForm("foo"))
  436     assert.Empty(t, c.Query("foo"))
  437 
  438     value, ok := c.GetPostForm("page")
  439     assert.True(t, ok)
  440     assert.Equal(t, "11", value)
  441     assert.Equal(t, "11", c.DefaultPostForm("page", "0"))
  442     assert.Equal(t, "11", c.PostForm("page"))
  443     assert.Empty(t, c.Query("page"))
  444 
  445     value, ok = c.GetPostForm("both")
  446     assert.True(t, ok)
  447     assert.Empty(t, value)
  448     assert.Empty(t, c.PostForm("both"))
  449     assert.Empty(t, c.DefaultPostForm("both", "nothing"))
  450     assert.Equal(t, "GET", c.Query("both"), "GET")
  451 
  452     value, ok = c.GetQuery("id")
  453     assert.True(t, ok)
  454     assert.Equal(t, "main", value)
  455     assert.Equal(t, "000", c.DefaultPostForm("id", "000"))
  456     assert.Equal(t, "main", c.Query("id"))
  457     assert.Empty(t, c.PostForm("id"))
  458 
  459     value, ok = c.GetQuery("NoKey")
  460     assert.False(t, ok)
  461     assert.Empty(t, value)
  462     value, ok = c.GetPostForm("NoKey")
  463     assert.False(t, ok)
  464     assert.Empty(t, value)
  465     assert.Equal(t, "nada", c.DefaultPostForm("NoKey", "nada"))
  466     assert.Equal(t, "nothing", c.DefaultQuery("NoKey", "nothing"))
  467     assert.Empty(t, c.PostForm("NoKey"))
  468     assert.Empty(t, c.Query("NoKey"))
  469 
  470     var obj struct {
  471         Foo   string   `form:"foo"`
  472         ID    string   `form:"id"`
  473         Page  int      `form:"page"`
  474         Both  string   `form:"both"`
  475         Array []string `form:"array[]"`
  476     }
  477     assert.NoError(t, c.Bind(&obj))
  478     assert.Equal(t, "bar", obj.Foo, "bar")
  479     assert.Equal(t, "main", obj.ID, "main")
  480     assert.Equal(t, 11, obj.Page, 11)
  481     assert.Empty(t, obj.Both)
  482     assert.Equal(t, []string{"first", "second"}, obj.Array)
  483 
  484     values, ok := c.GetQueryArray("array[]")
  485     assert.True(t, ok)
  486     assert.Equal(t, "first", values[0])
  487     assert.Equal(t, "second", values[1])
  488 
  489     values = c.QueryArray("array[]")
  490     assert.Equal(t, "first", values[0])
  491     assert.Equal(t, "second", values[1])
  492 
  493     values = c.QueryArray("nokey")
  494     assert.Equal(t, 0, len(values))
  495 
  496     values = c.QueryArray("both")
  497     assert.Equal(t, 1, len(values))
  498     assert.Equal(t, "GET", values[0])
  499 
  500     dicts, ok := c.GetQueryMap("ids")
  501     assert.True(t, ok)
  502     assert.Equal(t, "hi", dicts["a"])
  503     assert.Equal(t, "3.14", dicts["b"])
  504 
  505     dicts, ok = c.GetQueryMap("nokey")
  506     assert.False(t, ok)
  507     assert.Equal(t, 0, len(dicts))
  508 
  509     dicts, ok = c.GetQueryMap("both")
  510     assert.False(t, ok)
  511     assert.Equal(t, 0, len(dicts))
  512 
  513     dicts, ok = c.GetQueryMap("array")
  514     assert.False(t, ok)
  515     assert.Equal(t, 0, len(dicts))
  516 
  517     dicts = c.QueryMap("ids")
  518     assert.Equal(t, "hi", dicts["a"])
  519     assert.Equal(t, "3.14", dicts["b"])
  520 
  521     dicts = c.QueryMap("nokey")
  522     assert.Equal(t, 0, len(dicts))
  523 }
  524 
  525 func TestContextPostFormMultipart(t *testing.T) {
  526     c, _ := CreateTestContext(httptest.NewRecorder())
  527     c.Request = createMultipartRequest()
  528 
  529     var obj struct {
  530         Foo          string    `form:"foo"`
  531         Bar          string    `form:"bar"`
  532         BarAsInt     int       `form:"bar"`
  533         Array        []string  `form:"array"`
  534         ID           string    `form:"id"`
  535         TimeLocal    time.Time `form:"time_local" time_format:"02/01/2006 15:04"`
  536         TimeUTC      time.Time `form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1"`
  537         TimeLocation time.Time `form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo"`
  538         BlankTime    time.Time `form:"blank_time" time_format:"02/01/2006 15:04"`
  539     }
  540     assert.NoError(t, c.Bind(&obj))
  541     assert.Equal(t, "bar", obj.Foo)
  542     assert.Equal(t, "10", obj.Bar)
  543     assert.Equal(t, 10, obj.BarAsInt)
  544     assert.Equal(t, []string{"first", "second"}, obj.Array)
  545     assert.Empty(t, obj.ID)
  546     assert.Equal(t, "31/12/2016 14:55", obj.TimeLocal.Format("02/01/2006 15:04"))
  547     assert.Equal(t, time.Local, obj.TimeLocal.Location())
  548     assert.Equal(t, "31/12/2016 14:55", obj.TimeUTC.Format("02/01/2006 15:04"))
  549     assert.Equal(t, time.UTC, obj.TimeUTC.Location())
  550     loc, _ := time.LoadLocation("Asia/Tokyo")
  551     assert.Equal(t, "31/12/2016 14:55", obj.TimeLocation.Format("02/01/2006 15:04"))
  552     assert.Equal(t, loc, obj.TimeLocation.Location())
  553     assert.True(t, obj.BlankTime.IsZero())
  554 
  555     value, ok := c.GetQuery("foo")
  556     assert.False(t, ok)
  557     assert.Empty(t, value)
  558     assert.Empty(t, c.Query("bar"))
  559     assert.Equal(t, "nothing", c.DefaultQuery("id", "nothing"))
  560 
  561     value, ok = c.GetPostForm("foo")
  562     assert.True(t, ok)
  563     assert.Equal(t, "bar", value)
  564     assert.Equal(t, "bar", c.PostForm("foo"))
  565 
  566     value, ok = c.GetPostForm("array")
  567     assert.True(t, ok)
  568     assert.Equal(t, "first", value)
  569     assert.Equal(t, "first", c.PostForm("array"))
  570 
  571     assert.Equal(t, "10", c.DefaultPostForm("bar", "nothing"))
  572 
  573     value, ok = c.GetPostForm("id")
  574     assert.True(t, ok)
  575     assert.Empty(t, value)
  576     assert.Empty(t, c.PostForm("id"))
  577     assert.Empty(t, c.DefaultPostForm("id", "nothing"))
  578 
  579     value, ok = c.GetPostForm("nokey")
  580     assert.False(t, ok)
  581     assert.Empty(t, value)
  582     assert.Equal(t, "nothing", c.DefaultPostForm("nokey", "nothing"))
  583 
  584     values, ok := c.GetPostFormArray("array")
  585     assert.True(t, ok)
  586     assert.Equal(t, "first", values[0])
  587     assert.Equal(t, "second", values[1])
  588 
  589     values = c.PostFormArray("array")
  590     assert.Equal(t, "first", values[0])
  591     assert.Equal(t, "second", values[1])
  592 
  593     values = c.PostFormArray("nokey")
  594     assert.Equal(t, 0, len(values))
  595 
  596     values = c.PostFormArray("foo")
  597     assert.Equal(t, 1, len(values))
  598     assert.Equal(t, "bar", values[0])
  599 
  600     dicts, ok := c.GetPostFormMap("names")
  601     assert.True(t, ok)
  602     assert.Equal(t, "thinkerou", dicts["a"])
  603     assert.Equal(t, "tianou", dicts["b"])
  604 
  605     dicts, ok = c.GetPostFormMap("nokey")
  606     assert.False(t, ok)
  607     assert.Equal(t, 0, len(dicts))
  608 
  609     dicts = c.PostFormMap("names")
  610     assert.Equal(t, "thinkerou", dicts["a"])
  611     assert.Equal(t, "tianou", dicts["b"])
  612 
  613     dicts = c.PostFormMap("nokey")
  614     assert.Equal(t, 0, len(dicts))
  615 }
  616 
  617 func TestContextSetCookie(t *testing.T) {
  618     c, _ := CreateTestContext(httptest.NewRecorder())
  619     c.SetSameSite(http.SameSiteLaxMode)
  620     c.SetCookie("user", "gin", 1, "/", "localhost", true, true)
  621     assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
  622 }
  623 
  624 func TestContextSetCookiePathEmpty(t *testing.T) {
  625     c, _ := CreateTestContext(httptest.NewRecorder())
  626     c.SetSameSite(http.SameSiteLaxMode)
  627     c.SetCookie("user", "gin", 1, "", "localhost", true, true)
  628     assert.Equal(t, "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure; SameSite=Lax", c.Writer.Header().Get("Set-Cookie"))
  629 }
  630 
  631 func TestContextGetCookie(t *testing.T) {
  632     c, _ := CreateTestContext(httptest.NewRecorder())
  633     c.Request, _ = http.NewRequest("GET", "/get", nil)
  634     c.Request.Header.Set("Cookie", "user=gin")
  635     cookie, _ := c.Cookie("user")
  636     assert.Equal(t, "gin", cookie)
  637 
  638     _, err := c.Cookie("nokey")
  639     assert.Error(t, err)
  640 }
  641 
  642 func TestContextBodyAllowedForStatus(t *testing.T) {
  643     assert.False(t, false, bodyAllowedForStatus(http.StatusProcessing))
  644     assert.False(t, false, bodyAllowedForStatus(http.StatusNoContent))
  645     assert.False(t, false, bodyAllowedForStatus(http.StatusNotModified))
  646     assert.True(t, true, bodyAllowedForStatus(http.StatusInternalServerError))
  647 }
  648 
  649 type TestPanicRender struct {
  650 }
  651 
  652 func (*TestPanicRender) Render(http.ResponseWriter) error {
  653     return errors.New("TestPanicRender")
  654 }
  655 
  656 func (*TestPanicRender) WriteContentType(http.ResponseWriter) {}
  657 
  658 func TestContextRenderPanicIfErr(t *testing.T) {
  659     defer func() {
  660         r := recover()
  661         assert.Equal(t, "TestPanicRender", fmt.Sprint(r))
  662     }()
  663     w := httptest.NewRecorder()
  664     c, _ := CreateTestContext(w)
  665 
  666     c.Render(http.StatusOK, &TestPanicRender{})
  667 
  668     assert.Fail(t, "Panic not detected")
  669 }
  670 
  671 // Tests that the response is serialized as JSON
  672 // and Content-Type is set to application/json
  673 // and special HTML characters are escaped
  674 func TestContextRenderJSON(t *testing.T) {
  675     w := httptest.NewRecorder()
  676     c, _ := CreateTestContext(w)
  677 
  678     c.JSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
  679 
  680     assert.Equal(t, http.StatusCreated, w.Code)
  681     assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
  682     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  683 }
  684 
  685 // Tests that the response is serialized as JSONP
  686 // and Content-Type is set to application/javascript
  687 func TestContextRenderJSONP(t *testing.T) {
  688     w := httptest.NewRecorder()
  689     c, _ := CreateTestContext(w)
  690     c.Request, _ = http.NewRequest("GET", "http://example.com/?callback=x", nil)
  691 
  692     c.JSONP(http.StatusCreated, H{"foo": "bar"})
  693 
  694     assert.Equal(t, http.StatusCreated, w.Code)
  695     assert.Equal(t, "x({\"foo\":\"bar\"});", w.Body.String())
  696     assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
  697 }
  698 
  699 // Tests that the response is serialized as JSONP
  700 // and Content-Type is set to application/json
  701 func TestContextRenderJSONPWithoutCallback(t *testing.T) {
  702     w := httptest.NewRecorder()
  703     c, _ := CreateTestContext(w)
  704     c.Request, _ = http.NewRequest("GET", "http://example.com", nil)
  705 
  706     c.JSONP(http.StatusCreated, H{"foo": "bar"})
  707 
  708     assert.Equal(t, http.StatusCreated, w.Code)
  709     assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  710     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  711 }
  712 
  713 // Tests that no JSON is rendered if code is 204
  714 func TestContextRenderNoContentJSON(t *testing.T) {
  715     w := httptest.NewRecorder()
  716     c, _ := CreateTestContext(w)
  717 
  718     c.JSON(http.StatusNoContent, H{"foo": "bar"})
  719 
  720     assert.Equal(t, http.StatusNoContent, w.Code)
  721     assert.Empty(t, w.Body.String())
  722     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  723 }
  724 
  725 // Tests that the response is serialized as JSON
  726 // we change the content-type before
  727 func TestContextRenderAPIJSON(t *testing.T) {
  728     w := httptest.NewRecorder()
  729     c, _ := CreateTestContext(w)
  730 
  731     c.Header("Content-Type", "application/vnd.api+json")
  732     c.JSON(http.StatusCreated, H{"foo": "bar"})
  733 
  734     assert.Equal(t, http.StatusCreated, w.Code)
  735     assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
  736     assert.Equal(t, "application/vnd.api+json", w.Header().Get("Content-Type"))
  737 }
  738 
  739 // Tests that no Custom JSON is rendered if code is 204
  740 func TestContextRenderNoContentAPIJSON(t *testing.T) {
  741     w := httptest.NewRecorder()
  742     c, _ := CreateTestContext(w)
  743 
  744     c.Header("Content-Type", "application/vnd.api+json")
  745     c.JSON(http.StatusNoContent, H{"foo": "bar"})
  746 
  747     assert.Equal(t, http.StatusNoContent, w.Code)
  748     assert.Empty(t, w.Body.String())
  749     assert.Equal(t, w.Header().Get("Content-Type"), "application/vnd.api+json")
  750 }
  751 
  752 // Tests that the response is serialized as JSON
  753 // and Content-Type is set to application/json
  754 func TestContextRenderIndentedJSON(t *testing.T) {
  755     w := httptest.NewRecorder()
  756     c, _ := CreateTestContext(w)
  757 
  758     c.IndentedJSON(http.StatusCreated, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  759 
  760     assert.Equal(t, http.StatusCreated, w.Code)
  761     assert.Equal(t, "{\n    \"bar\": \"foo\",\n    \"foo\": \"bar\",\n    \"nested\": {\n        \"foo\": \"bar\"\n    }\n}", w.Body.String())
  762     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  763 }
  764 
  765 // Tests that no Custom JSON is rendered if code is 204
  766 func TestContextRenderNoContentIndentedJSON(t *testing.T) {
  767     w := httptest.NewRecorder()
  768     c, _ := CreateTestContext(w)
  769 
  770     c.IndentedJSON(http.StatusNoContent, H{"foo": "bar", "bar": "foo", "nested": H{"foo": "bar"}})
  771 
  772     assert.Equal(t, http.StatusNoContent, w.Code)
  773     assert.Empty(t, w.Body.String())
  774     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  775 }
  776 
  777 // Tests that the response is serialized as Secure JSON
  778 // and Content-Type is set to application/json
  779 func TestContextRenderSecureJSON(t *testing.T) {
  780     w := httptest.NewRecorder()
  781     c, router := CreateTestContext(w)
  782 
  783     router.SecureJsonPrefix("&&&START&&&")
  784     c.SecureJSON(http.StatusCreated, []string{"foo", "bar"})
  785 
  786     assert.Equal(t, http.StatusCreated, w.Code)
  787     assert.Equal(t, "&&&START&&&[\"foo\",\"bar\"]", w.Body.String())
  788     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  789 }
  790 
  791 // Tests that no Custom JSON is rendered if code is 204
  792 func TestContextRenderNoContentSecureJSON(t *testing.T) {
  793     w := httptest.NewRecorder()
  794     c, _ := CreateTestContext(w)
  795 
  796     c.SecureJSON(http.StatusNoContent, []string{"foo", "bar"})
  797 
  798     assert.Equal(t, http.StatusNoContent, w.Code)
  799     assert.Empty(t, w.Body.String())
  800     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  801 }
  802 
  803 func TestContextRenderNoContentAsciiJSON(t *testing.T) {
  804     w := httptest.NewRecorder()
  805     c, _ := CreateTestContext(w)
  806 
  807     c.AsciiJSON(http.StatusNoContent, []string{"lang", "Go语言"})
  808 
  809     assert.Equal(t, http.StatusNoContent, w.Code)
  810     assert.Empty(t, w.Body.String())
  811     assert.Equal(t, "application/json", w.Header().Get("Content-Type"))
  812 }
  813 
  814 // Tests that the response is serialized as JSON
  815 // and Content-Type is set to application/json
  816 // and special HTML characters are preserved
  817 func TestContextRenderPureJSON(t *testing.T) {
  818     w := httptest.NewRecorder()
  819     c, _ := CreateTestContext(w)
  820     c.PureJSON(http.StatusCreated, H{"foo": "bar", "html": "<b>"})
  821     assert.Equal(t, http.StatusCreated, w.Code)
  822     assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
  823     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
  824 }
  825 
  826 // Tests that the response executes the templates
  827 // and responds with Content-Type set to text/html
  828 func TestContextRenderHTML(t *testing.T) {
  829     w := httptest.NewRecorder()
  830     c, router := CreateTestContext(w)
  831 
  832     templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  833     router.SetHTMLTemplate(templ)
  834 
  835     c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  836 
  837     assert.Equal(t, http.StatusCreated, w.Code)
  838     assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  839     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  840 }
  841 
  842 func TestContextRenderHTML2(t *testing.T) {
  843     w := httptest.NewRecorder()
  844     c, router := CreateTestContext(w)
  845 
  846     // print debug warning log when Engine.trees > 0
  847     router.addRoute("GET", "/", HandlersChain{func(_ *Context) {}})
  848     assert.Len(t, router.trees, 1)
  849 
  850     templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  851     re := captureOutput(t, func() {
  852         SetMode(DebugMode)
  853         router.SetHTMLTemplate(templ)
  854         SetMode(TestMode)
  855     })
  856 
  857     assert.Equal(t, "[GIN-debug] [WARNING] Since SetHTMLTemplate() is NOT thread-safe. It should only be called\nat initialization. ie. before any route is registered or the router is listening in a socket:\n\n\trouter := gin.Default()\n\trouter.SetHTMLTemplate(template) // << good place\n\n", re)
  858 
  859     c.HTML(http.StatusCreated, "t", H{"name": "alexandernyquist"})
  860 
  861     assert.Equal(t, http.StatusCreated, w.Code)
  862     assert.Equal(t, "Hello alexandernyquist", w.Body.String())
  863     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  864 }
  865 
  866 // Tests that no HTML is rendered if code is 204
  867 func TestContextRenderNoContentHTML(t *testing.T) {
  868     w := httptest.NewRecorder()
  869     c, router := CreateTestContext(w)
  870     templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
  871     router.SetHTMLTemplate(templ)
  872 
  873     c.HTML(http.StatusNoContent, "t", H{"name": "alexandernyquist"})
  874 
  875     assert.Equal(t, http.StatusNoContent, w.Code)
  876     assert.Empty(t, w.Body.String())
  877     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  878 }
  879 
  880 // TestContextXML tests that the response is serialized as XML
  881 // and Content-Type is set to application/xml
  882 func TestContextRenderXML(t *testing.T) {
  883     w := httptest.NewRecorder()
  884     c, _ := CreateTestContext(w)
  885 
  886     c.XML(http.StatusCreated, H{"foo": "bar"})
  887 
  888     assert.Equal(t, http.StatusCreated, w.Code)
  889     assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
  890     assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  891 }
  892 
  893 // Tests that no XML is rendered if code is 204
  894 func TestContextRenderNoContentXML(t *testing.T) {
  895     w := httptest.NewRecorder()
  896     c, _ := CreateTestContext(w)
  897 
  898     c.XML(http.StatusNoContent, H{"foo": "bar"})
  899 
  900     assert.Equal(t, http.StatusNoContent, w.Code)
  901     assert.Empty(t, w.Body.String())
  902     assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
  903 }
  904 
  905 // TestContextString tests that the response is returned
  906 // with Content-Type set to text/plain
  907 func TestContextRenderString(t *testing.T) {
  908     w := httptest.NewRecorder()
  909     c, _ := CreateTestContext(w)
  910 
  911     c.String(http.StatusCreated, "test %s %d", "string", 2)
  912 
  913     assert.Equal(t, http.StatusCreated, w.Code)
  914     assert.Equal(t, "test string 2", w.Body.String())
  915     assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  916 }
  917 
  918 // Tests that no String is rendered if code is 204
  919 func TestContextRenderNoContentString(t *testing.T) {
  920     w := httptest.NewRecorder()
  921     c, _ := CreateTestContext(w)
  922 
  923     c.String(http.StatusNoContent, "test %s %d", "string", 2)
  924 
  925     assert.Equal(t, http.StatusNoContent, w.Code)
  926     assert.Empty(t, w.Body.String())
  927     assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
  928 }
  929 
  930 // TestContextString tests that the response is returned
  931 // with Content-Type set to text/html
  932 func TestContextRenderHTMLString(t *testing.T) {
  933     w := httptest.NewRecorder()
  934     c, _ := CreateTestContext(w)
  935 
  936     c.Header("Content-Type", "text/html; charset=utf-8")
  937     c.String(http.StatusCreated, "<html>%s %d</html>", "string", 3)
  938 
  939     assert.Equal(t, http.StatusCreated, w.Code)
  940     assert.Equal(t, "<html>string 3</html>", w.Body.String())
  941     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  942 }
  943 
  944 // Tests that no HTML String is rendered if code is 204
  945 func TestContextRenderNoContentHTMLString(t *testing.T) {
  946     w := httptest.NewRecorder()
  947     c, _ := CreateTestContext(w)
  948 
  949     c.Header("Content-Type", "text/html; charset=utf-8")
  950     c.String(http.StatusNoContent, "<html>%s %d</html>", "string", 3)
  951 
  952     assert.Equal(t, http.StatusNoContent, w.Code)
  953     assert.Empty(t, w.Body.String())
  954     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
  955 }
  956 
  957 // TestContextData tests that the response can be written from `bytestring`
  958 // with specified MIME type
  959 func TestContextRenderData(t *testing.T) {
  960     w := httptest.NewRecorder()
  961     c, _ := CreateTestContext(w)
  962 
  963     c.Data(http.StatusCreated, "text/csv", []byte(`foo,bar`))
  964 
  965     assert.Equal(t, http.StatusCreated, w.Code)
  966     assert.Equal(t, "foo,bar", w.Body.String())
  967     assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  968 }
  969 
  970 // Tests that no Custom Data is rendered if code is 204
  971 func TestContextRenderNoContentData(t *testing.T) {
  972     w := httptest.NewRecorder()
  973     c, _ := CreateTestContext(w)
  974 
  975     c.Data(http.StatusNoContent, "text/csv", []byte(`foo,bar`))
  976 
  977     assert.Equal(t, http.StatusNoContent, w.Code)
  978     assert.Empty(t, w.Body.String())
  979     assert.Equal(t, "text/csv", w.Header().Get("Content-Type"))
  980 }
  981 
  982 func TestContextRenderSSE(t *testing.T) {
  983     w := httptest.NewRecorder()
  984     c, _ := CreateTestContext(w)
  985 
  986     c.SSEvent("float", 1.5)
  987     c.Render(-1, sse.Event{
  988         Id:   "123",
  989         Data: "text",
  990     })
  991     c.SSEvent("chat", H{
  992         "foo": "bar",
  993         "bar": "foo",
  994     })
  995 
  996     assert.Equal(t, strings.Replace(w.Body.String(), " ", "", -1), strings.Replace("event:float\ndata:1.5\n\nid:123\ndata:text\n\nevent:chat\ndata:{\"bar\":\"foo\",\"foo\":\"bar\"}\n\n", " ", "", -1))
  997 }
  998 
  999 func TestContextRenderFile(t *testing.T) {
 1000     w := httptest.NewRecorder()
 1001     c, _ := CreateTestContext(w)
 1002 
 1003     c.Request, _ = http.NewRequest("GET", "/", nil)
 1004     c.File("./gin.go")
 1005 
 1006     assert.Equal(t, http.StatusOK, w.Code)
 1007     assert.Contains(t, w.Body.String(), "func New() *Engine {")
 1008     assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
 1009 }
 1010 
 1011 func TestContextRenderFileFromFS(t *testing.T) {
 1012     w := httptest.NewRecorder()
 1013     c, _ := CreateTestContext(w)
 1014 
 1015     c.Request, _ = http.NewRequest("GET", "/some/path", nil)
 1016     c.FileFromFS("./gin.go", Dir(".", false))
 1017 
 1018     assert.Equal(t, http.StatusOK, w.Code)
 1019     assert.Contains(t, w.Body.String(), "func New() *Engine {")
 1020     assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
 1021     assert.Equal(t, "/some/path", c.Request.URL.Path)
 1022 }
 1023 
 1024 func TestContextRenderAttachment(t *testing.T) {
 1025     w := httptest.NewRecorder()
 1026     c, _ := CreateTestContext(w)
 1027     newFilename := "new_filename.go"
 1028 
 1029     c.Request, _ = http.NewRequest("GET", "/", nil)
 1030     c.FileAttachment("./gin.go", newFilename)
 1031 
 1032     assert.Equal(t, 200, w.Code)
 1033     assert.Contains(t, w.Body.String(), "func New() *Engine {")
 1034     assert.Equal(t, fmt.Sprintf("attachment; filename=\"%s\"", newFilename), w.HeaderMap.Get("Content-Disposition"))
 1035 }
 1036 
 1037 // TestContextRenderYAML tests that the response is serialized as YAML
 1038 // and Content-Type is set to application/x-yaml
 1039 func TestContextRenderYAML(t *testing.T) {
 1040     w := httptest.NewRecorder()
 1041     c, _ := CreateTestContext(w)
 1042 
 1043     c.YAML(http.StatusCreated, H{"foo": "bar"})
 1044 
 1045     assert.Equal(t, http.StatusCreated, w.Code)
 1046     assert.Equal(t, "foo: bar\n", w.Body.String())
 1047     assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
 1048 }
 1049 
 1050 // TestContextRenderProtoBuf tests that the response is serialized as ProtoBuf
 1051 // and Content-Type is set to application/x-protobuf
 1052 // and we just use the example protobuf to check if the response is correct
 1053 func TestContextRenderProtoBuf(t *testing.T) {
 1054     w := httptest.NewRecorder()
 1055     c, _ := CreateTestContext(w)
 1056 
 1057     reps := []int64{int64(1), int64(2)}
 1058     label := "test"
 1059     data := &testdata.Test{
 1060         Label: &label,
 1061         Reps:  reps,
 1062     }
 1063 
 1064     c.ProtoBuf(http.StatusCreated, data)
 1065 
 1066     protoData, err := proto.Marshal(data)
 1067     assert.NoError(t, err)
 1068 
 1069     assert.Equal(t, http.StatusCreated, w.Code)
 1070     assert.Equal(t, string(protoData), w.Body.String())
 1071     assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
 1072 }
 1073 
 1074 func TestContextHeaders(t *testing.T) {
 1075     c, _ := CreateTestContext(httptest.NewRecorder())
 1076     c.Header("Content-Type", "text/plain")
 1077     c.Header("X-Custom", "value")
 1078 
 1079     assert.Equal(t, "text/plain", c.Writer.Header().Get("Content-Type"))
 1080     assert.Equal(t, "value", c.Writer.Header().Get("X-Custom"))
 1081 
 1082     c.Header("Content-Type", "text/html")
 1083     c.Header("X-Custom", "")
 1084 
 1085     assert.Equal(t, "text/html", c.Writer.Header().Get("Content-Type"))
 1086     _, exist := c.Writer.Header()["X-Custom"]
 1087     assert.False(t, exist)
 1088 }
 1089 
 1090 // TODO
 1091 func TestContextRenderRedirectWithRelativePath(t *testing.T) {
 1092     w := httptest.NewRecorder()
 1093     c, _ := CreateTestContext(w)
 1094 
 1095     c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
 1096     assert.Panics(t, func() { c.Redirect(299, "/new_path") })
 1097     assert.Panics(t, func() { c.Redirect(309, "/new_path") })
 1098 
 1099     c.Redirect(http.StatusMovedPermanently, "/path")
 1100     c.Writer.WriteHeaderNow()
 1101     assert.Equal(t, http.StatusMovedPermanently, w.Code)
 1102     assert.Equal(t, "/path", w.Header().Get("Location"))
 1103 }
 1104 
 1105 func TestContextRenderRedirectWithAbsolutePath(t *testing.T) {
 1106     w := httptest.NewRecorder()
 1107     c, _ := CreateTestContext(w)
 1108 
 1109     c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
 1110     c.Redirect(http.StatusFound, "http://google.com")
 1111     c.Writer.WriteHeaderNow()
 1112 
 1113     assert.Equal(t, http.StatusFound, w.Code)
 1114     assert.Equal(t, "http://google.com", w.Header().Get("Location"))
 1115 }
 1116 
 1117 func TestContextRenderRedirectWith201(t *testing.T) {
 1118     w := httptest.NewRecorder()
 1119     c, _ := CreateTestContext(w)
 1120 
 1121     c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
 1122     c.Redirect(http.StatusCreated, "/resource")
 1123     c.Writer.WriteHeaderNow()
 1124 
 1125     assert.Equal(t, http.StatusCreated, w.Code)
 1126     assert.Equal(t, "/resource", w.Header().Get("Location"))
 1127 }
 1128 
 1129 func TestContextRenderRedirectAll(t *testing.T) {
 1130     c, _ := CreateTestContext(httptest.NewRecorder())
 1131     c.Request, _ = http.NewRequest("POST", "http://example.com", nil)
 1132     assert.Panics(t, func() { c.Redirect(http.StatusOK, "/resource") })
 1133     assert.Panics(t, func() { c.Redirect(http.StatusAccepted, "/resource") })
 1134     assert.Panics(t, func() { c.Redirect(299, "/resource") })
 1135     assert.Panics(t, func() { c.Redirect(309, "/resource") })
 1136     assert.NotPanics(t, func() { c.Redirect(http.StatusMultipleChoices, "/resource") })
 1137     assert.NotPanics(t, func() { c.Redirect(http.StatusPermanentRedirect, "/resource") })
 1138 }
 1139 
 1140 func TestContextNegotiationWithJSON(t *testing.T) {
 1141     w := httptest.NewRecorder()
 1142     c, _ := CreateTestContext(w)
 1143     c.Request, _ = http.NewRequest("POST", "", nil)
 1144 
 1145     c.Negotiate(http.StatusOK, Negotiate{
 1146         Offered: []string{MIMEJSON, MIMEXML, MIMEYAML},
 1147         Data:    H{"foo": "bar"},
 1148     })
 1149 
 1150     assert.Equal(t, http.StatusOK, w.Code)
 1151     assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
 1152     assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
 1153 }
 1154 
 1155 func TestContextNegotiationWithXML(t *testing.T) {
 1156     w := httptest.NewRecorder()
 1157     c, _ := CreateTestContext(w)
 1158     c.Request, _ = http.NewRequest("POST", "", nil)
 1159 
 1160     c.Negotiate(http.StatusOK, Negotiate{
 1161         Offered: []string{MIMEXML, MIMEJSON, MIMEYAML},
 1162         Data:    H{"foo": "bar"},
 1163     })
 1164 
 1165     assert.Equal(t, http.StatusOK, w.Code)
 1166     assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
 1167     assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
 1168 }
 1169 
 1170 func TestContextNegotiationWithHTML(t *testing.T) {
 1171     w := httptest.NewRecorder()
 1172     c, router := CreateTestContext(w)
 1173     c.Request, _ = http.NewRequest("POST", "", nil)
 1174     templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
 1175     router.SetHTMLTemplate(templ)
 1176 
 1177     c.Negotiate(http.StatusOK, Negotiate{
 1178         Offered:  []string{MIMEHTML},
 1179         Data:     H{"name": "gin"},
 1180         HTMLName: "t",
 1181     })
 1182 
 1183     assert.Equal(t, http.StatusOK, w.Code)
 1184     assert.Equal(t, "Hello gin", w.Body.String())
 1185     assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
 1186 }
 1187 
 1188 func TestContextNegotiationNotSupport(t *testing.T) {
 1189     w := httptest.NewRecorder()
 1190     c, _ := CreateTestContext(w)
 1191     c.Request, _ = http.NewRequest("POST", "", nil)
 1192 
 1193     c.Negotiate(http.StatusOK, Negotiate{
 1194         Offered: []string{MIMEPOSTForm},
 1195     })
 1196 
 1197     assert.Equal(t, http.StatusNotAcceptable, w.Code)
 1198     assert.Equal(t, c.index, abortIndex)
 1199     assert.True(t, c.IsAborted())
 1200 }
 1201 
 1202 func TestContextNegotiationFormat(t *testing.T) {
 1203     c, _ := CreateTestContext(httptest.NewRecorder())
 1204     c.Request, _ = http.NewRequest("POST", "", nil)
 1205 
 1206     assert.Panics(t, func() { c.NegotiateFormat() })
 1207     assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
 1208     assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEHTML, MIMEJSON))
 1209 }
 1210 
 1211 func TestContextNegotiationFormatWithAccept(t *testing.T) {
 1212     c, _ := CreateTestContext(httptest.NewRecorder())
 1213     c.Request, _ = http.NewRequest("POST", "/", nil)
 1214     c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
 1215 
 1216     assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEJSON, MIMEXML))
 1217     assert.Equal(t, MIMEHTML, c.NegotiateFormat(MIMEXML, MIMEHTML))
 1218     assert.Empty(t, c.NegotiateFormat(MIMEJSON))
 1219 }
 1220 
 1221 func TestContextNegotiationFormatWithWildcardAccept(t *testing.T) {
 1222     c, _ := CreateTestContext(httptest.NewRecorder())
 1223     c.Request, _ = http.NewRequest("POST", "/", nil)
 1224     c.Request.Header.Add("Accept", "*/*")
 1225 
 1226     assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
 1227     assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
 1228     assert.Equal(t, c.NegotiateFormat("application/*"), "application/*")
 1229     assert.Equal(t, c.NegotiateFormat(MIMEJSON), MIMEJSON)
 1230     assert.Equal(t, c.NegotiateFormat(MIMEXML), MIMEXML)
 1231     assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
 1232 
 1233     c, _ = CreateTestContext(httptest.NewRecorder())
 1234     c.Request, _ = http.NewRequest("POST", "/", nil)
 1235     c.Request.Header.Add("Accept", "text/*")
 1236 
 1237     assert.Equal(t, c.NegotiateFormat("*/*"), "*/*")
 1238     assert.Equal(t, c.NegotiateFormat("text/*"), "text/*")
 1239     assert.Equal(t, c.NegotiateFormat("application/*"), "")
 1240     assert.Equal(t, c.NegotiateFormat(MIMEJSON), "")
 1241     assert.Equal(t, c.NegotiateFormat(MIMEXML), "")
 1242     assert.Equal(t, c.NegotiateFormat(MIMEHTML), MIMEHTML)
 1243 }
 1244 
 1245 func TestContextNegotiationFormatCustom(t *testing.T) {
 1246     c, _ := CreateTestContext(httptest.NewRecorder())
 1247     c.Request, _ = http.NewRequest("POST", "/", nil)
 1248     c.Request.Header.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9;q=0.8")
 1249 
 1250     c.Accepted = nil
 1251     c.SetAccepted(MIMEJSON, MIMEXML)
 1252 
 1253     assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON, MIMEXML))
 1254     assert.Equal(t, MIMEXML, c.NegotiateFormat(MIMEXML, MIMEHTML))
 1255     assert.Equal(t, MIMEJSON, c.NegotiateFormat(MIMEJSON))
 1256 }
 1257 
 1258 func TestContextIsAborted(t *testing.T) {
 1259     c, _ := CreateTestContext(httptest.NewRecorder())
 1260     assert.False(t, c.IsAborted())
 1261 
 1262     c.Abort()
 1263     assert.True(t, c.IsAborted())
 1264 
 1265     c.Next()
 1266     assert.True(t, c.IsAborted())
 1267 
 1268     c.index++
 1269     assert.True(t, c.IsAborted())
 1270 }
 1271 
 1272 // TestContextData tests that the response can be written from `bytestring`
 1273 // with specified MIME type
 1274 func TestContextAbortWithStatus(t *testing.T) {
 1275     w := httptest.NewRecorder()
 1276     c, _ := CreateTestContext(w)
 1277 
 1278     c.index = 4
 1279     c.AbortWithStatus(http.StatusUnauthorized)
 1280 
 1281     assert.Equal(t, abortIndex, c.index)
 1282     assert.Equal(t, http.StatusUnauthorized, c.Writer.Status())
 1283     assert.Equal(t, http.StatusUnauthorized, w.Code)
 1284     assert.True(t, c.IsAborted())
 1285 }
 1286 
 1287 type testJSONAbortMsg struct {
 1288     Foo string `json:"foo"`
 1289     Bar string `json:"bar"`
 1290 }
 1291 
 1292 func TestContextAbortWithStatusJSON(t *testing.T) {
 1293     w := httptest.NewRecorder()
 1294     c, _ := CreateTestContext(w)
 1295     c.index = 4
 1296 
 1297     in := new(testJSONAbortMsg)
 1298     in.Bar = "barValue"
 1299     in.Foo = "fooValue"
 1300 
 1301     c.AbortWithStatusJSON(http.StatusUnsupportedMediaType, in)
 1302 
 1303     assert.Equal(t, abortIndex, c.index)
 1304     assert.Equal(t, http.StatusUnsupportedMediaType, c.Writer.Status())
 1305     assert.Equal(t, http.StatusUnsupportedMediaType, w.Code)
 1306     assert.True(t, c.IsAborted())
 1307 
 1308     contentType := w.Header().Get("Content-Type")
 1309     assert.Equal(t, "application/json; charset=utf-8", contentType)
 1310 
 1311     buf := new(bytes.Buffer)
 1312     _, err := buf.ReadFrom(w.Body)
 1313     assert.NoError(t, err)
 1314     jsonStringBody := buf.String()
 1315     assert.Equal(t, fmt.Sprint("{\"foo\":\"fooValue\",\"bar\":\"barValue\"}"), jsonStringBody)
 1316 }
 1317 
 1318 func TestContextError(t *testing.T) {
 1319     c, _ := CreateTestContext(httptest.NewRecorder())
 1320     assert.Empty(t, c.Errors)
 1321 
 1322     firstErr := errors.New("first error")
 1323     c.Error(firstErr) // nolint: errcheck
 1324     assert.Len(t, c.Errors, 1)
 1325     assert.Equal(t, "Error #01: first error\n", c.Errors.String())
 1326 
 1327     secondErr := errors.New("second error")
 1328     c.Error(&Error{ // nolint: errcheck
 1329         Err:  secondErr,
 1330         Meta: "some data 2",
 1331         Type: ErrorTypePublic,
 1332     })
 1333     assert.Len(t, c.Errors, 2)
 1334 
 1335     assert.Equal(t, firstErr, c.Errors[0].Err)
 1336     assert.Nil(t, c.Errors[0].Meta)
 1337     assert.Equal(t, ErrorTypePrivate, c.Errors[0].Type)
 1338 
 1339     assert.Equal(t, secondErr, c.Errors[1].Err)
 1340     assert.Equal(t, "some data 2", c.Errors[1].Meta)
 1341     assert.Equal(t, ErrorTypePublic, c.Errors[1].Type)
 1342 
 1343     assert.Equal(t, c.Errors.Last(), c.Errors[1])
 1344 
 1345     defer func() {
 1346         if recover() == nil {
 1347             t.Error("didn't panic")
 1348         }
 1349     }()
 1350     c.Error(nil) // nolint: errcheck
 1351 }
 1352 
 1353 func TestContextTypedError(t *testing.T) {
 1354     c, _ := CreateTestContext(httptest.NewRecorder())
 1355     c.Error(errors.New("externo 0")).SetType(ErrorTypePublic)  // nolint: errcheck
 1356     c.Error(errors.New("interno 0")).SetType(ErrorTypePrivate) // nolint: errcheck
 1357 
 1358     for _, err := range c.Errors.ByType(ErrorTypePublic) {
 1359         assert.Equal(t, ErrorTypePublic, err.Type)
 1360     }
 1361     for _, err := range c.Errors.ByType(ErrorTypePrivate) {
 1362         assert.Equal(t, ErrorTypePrivate, err.Type)
 1363     }
 1364     assert.Equal(t, []string{"externo 0", "interno 0"}, c.Errors.Errors())
 1365 }
 1366 
 1367 func TestContextAbortWithError(t *testing.T) {
 1368     w := httptest.NewRecorder()
 1369     c, _ := CreateTestContext(w)
 1370 
 1371     c.AbortWithError(http.StatusUnauthorized, errors.New("bad input")).SetMeta("some input") // nolint: errcheck
 1372 
 1373     assert.Equal(t, http.StatusUnauthorized, w.Code)
 1374     assert.Equal(t, abortIndex, c.index)
 1375     assert.True(t, c.IsAborted())
 1376 }
 1377 
 1378 func TestContextClientIP(t *testing.T) {
 1379     c, _ := CreateTestContext(httptest.NewRecorder())
 1380     c.Request, _ = http.NewRequest("POST", "/", nil)
 1381     c.engine.trustedCIDRs, _ = c.engine.prepareTrustedCIDRs()
 1382     resetContextForClientIPTests(c)
 1383 
 1384     // Legacy tests (validating that the defaults don't break the
 1385     // (insecure!) old behaviour)
 1386     assert.Equal(t, "20.20.20.20", c.ClientIP())
 1387 
 1388     c.Request.Header.Del("X-Forwarded-For")
 1389     assert.Equal(t, "10.10.10.10", c.ClientIP())
 1390 
 1391     c.Request.Header.Set("X-Forwarded-For", "30.30.30.30  ")
 1392     assert.Equal(t, "30.30.30.30", c.ClientIP())
 1393 
 1394     c.Request.Header.Del("X-Forwarded-For")
 1395     c.Request.Header.Del("X-Real-IP")
 1396     c.engine.TrustedPlatform = PlatformGoogleAppEngine
 1397     assert.Equal(t, "50.50.50.50", c.ClientIP())
 1398 
 1399     c.Request.Header.Del("X-Appengine-Remote-Addr")
 1400     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1401 
 1402     // no port
 1403     c.Request.RemoteAddr = "50.50.50.50"
 1404     assert.Empty(t, c.ClientIP())
 1405 
 1406     // Tests exercising the TrustedProxies functionality
 1407     resetContextForClientIPTests(c)
 1408 
 1409     // No trusted proxies
 1410     _ = c.engine.SetTrustedProxies([]string{})
 1411     c.engine.RemoteIPHeaders = []string{"X-Forwarded-For"}
 1412     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1413 
 1414     // Disabled TrustedProxies feature
 1415     _ = c.engine.SetTrustedProxies(nil)
 1416     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1417 
 1418     // Last proxy is trusted, but the RemoteAddr is not
 1419     _ = c.engine.SetTrustedProxies([]string{"30.30.30.30"})
 1420     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1421 
 1422     // Only trust RemoteAddr
 1423     _ = c.engine.SetTrustedProxies([]string{"40.40.40.40"})
 1424     assert.Equal(t, "30.30.30.30", c.ClientIP())
 1425 
 1426     // All steps are trusted
 1427     _ = c.engine.SetTrustedProxies([]string{"40.40.40.40", "30.30.30.30", "20.20.20.20"})
 1428     assert.Equal(t, "20.20.20.20", c.ClientIP())
 1429 
 1430     // Use CIDR
 1431     _ = c.engine.SetTrustedProxies([]string{"40.40.25.25/16", "30.30.30.30"})
 1432     assert.Equal(t, "20.20.20.20", c.ClientIP())
 1433 
 1434     // Use hostname that resolves to all the proxies
 1435     _ = c.engine.SetTrustedProxies([]string{"foo"})
 1436     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1437 
 1438     // Use hostname that returns an error
 1439     _ = c.engine.SetTrustedProxies([]string{"bar"})
 1440     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1441 
 1442     // X-Forwarded-For has a non-IP element
 1443     _ = c.engine.SetTrustedProxies([]string{"40.40.40.40"})
 1444     c.Request.Header.Set("X-Forwarded-For", " blah ")
 1445     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1446 
 1447     // Result from LookupHost has non-IP element. This should never
 1448     // happen, but we should test it to make sure we handle it
 1449     // gracefully.
 1450     _ = c.engine.SetTrustedProxies([]string{"baz"})
 1451     c.Request.Header.Set("X-Forwarded-For", " 30.30.30.30 ")
 1452     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1453 
 1454     _ = c.engine.SetTrustedProxies([]string{"40.40.40.40"})
 1455     c.Request.Header.Del("X-Forwarded-For")
 1456     c.engine.RemoteIPHeaders = []string{"X-Forwarded-For", "X-Real-IP"}
 1457     assert.Equal(t, "10.10.10.10", c.ClientIP())
 1458 
 1459     c.engine.RemoteIPHeaders = []string{}
 1460     c.engine.TrustedPlatform = PlatformGoogleAppEngine
 1461     assert.Equal(t, "50.50.50.50", c.ClientIP())
 1462 
 1463     // Use custom TrustedPlatform header
 1464     c.engine.TrustedPlatform = "X-CDN-IP"
 1465     c.Request.Header.Set("X-CDN-IP", "80.80.80.80")
 1466     assert.Equal(t, "80.80.80.80", c.ClientIP())
 1467     // wrong header
 1468     c.engine.TrustedPlatform = "X-Wrong-Header"
 1469     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1470 
 1471     c.Request.Header.Del("X-CDN-IP")
 1472     // TrustedPlatform is empty
 1473     c.engine.TrustedPlatform = ""
 1474     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1475 
 1476     // Test the legacy flag
 1477     c.engine.AppEngine = true
 1478     assert.Equal(t, "50.50.50.50", c.ClientIP())
 1479     c.engine.AppEngine = false
 1480     c.engine.TrustedPlatform = PlatformGoogleAppEngine
 1481 
 1482     c.Request.Header.Del("X-Appengine-Remote-Addr")
 1483     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1484 
 1485     c.engine.TrustedPlatform = PlatformCloudflare
 1486     assert.Equal(t, "60.60.60.60", c.ClientIP())
 1487 
 1488     c.Request.Header.Del("CF-Connecting-IP")
 1489     assert.Equal(t, "40.40.40.40", c.ClientIP())
 1490 
 1491     c.engine.TrustedPlatform = ""
 1492 
 1493     // no port
 1494     c.Request.RemoteAddr = "50.50.50.50"
 1495     assert.Empty(t, c.ClientIP())
 1496 }
 1497 
 1498 func resetContextForClientIPTests(c *Context) {
 1499     c.Request.Header.Set("X-Real-IP", " 10.10.10.10  ")
 1500     c.Request.Header.Set("X-Forwarded-For", "  20.20.20.20, 30.30.30.30")
 1501     c.Request.Header.Set("X-Appengine-Remote-Addr", "50.50.50.50")
 1502     c.Request.Header.Set("CF-Connecting-IP", "60.60.60.60")
 1503     c.Request.RemoteAddr = "  40.40.40.40:42123 "
 1504     c.engine.TrustedPlatform = ""
 1505     c.engine.AppEngine = false
 1506 }
 1507 
 1508 func TestContextContentType(t *testing.T) {
 1509     c, _ := CreateTestContext(httptest.NewRecorder())
 1510     c.Request, _ = http.NewRequest("POST", "/", nil)
 1511     c.Request.Header.Set("Content-Type", "application/json; charset=utf-8")
 1512 
 1513     assert.Equal(t, "application/json", c.ContentType())
 1514 }
 1515 
 1516 func TestContextAutoBindJSON(t *testing.T) {
 1517     c, _ := CreateTestContext(httptest.NewRecorder())
 1518     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1519     c.Request.Header.Add("Content-Type", MIMEJSON)
 1520 
 1521     var obj struct {
 1522         Foo string `json:"foo"`
 1523         Bar string `json:"bar"`
 1524     }
 1525     assert.NoError(t, c.Bind(&obj))
 1526     assert.Equal(t, "foo", obj.Bar)
 1527     assert.Equal(t, "bar", obj.Foo)
 1528     assert.Empty(t, c.Errors)
 1529 }
 1530 
 1531 func TestContextBindWithJSON(t *testing.T) {
 1532     w := httptest.NewRecorder()
 1533     c, _ := CreateTestContext(w)
 1534 
 1535     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1536     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1537 
 1538     var obj struct {
 1539         Foo string `json:"foo"`
 1540         Bar string `json:"bar"`
 1541     }
 1542     assert.NoError(t, c.BindJSON(&obj))
 1543     assert.Equal(t, "foo", obj.Bar)
 1544     assert.Equal(t, "bar", obj.Foo)
 1545     assert.Equal(t, 0, w.Body.Len())
 1546 }
 1547 func TestContextBindWithXML(t *testing.T) {
 1548     w := httptest.NewRecorder()
 1549     c, _ := CreateTestContext(w)
 1550 
 1551     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
 1552         <root>
 1553             <foo>FOO</foo>
 1554             <bar>BAR</bar>
 1555         </root>`))
 1556     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1557 
 1558     var obj struct {
 1559         Foo string `xml:"foo"`
 1560         Bar string `xml:"bar"`
 1561     }
 1562     assert.NoError(t, c.BindXML(&obj))
 1563     assert.Equal(t, "FOO", obj.Foo)
 1564     assert.Equal(t, "BAR", obj.Bar)
 1565     assert.Equal(t, 0, w.Body.Len())
 1566 }
 1567 
 1568 func TestContextBindHeader(t *testing.T) {
 1569     w := httptest.NewRecorder()
 1570     c, _ := CreateTestContext(w)
 1571 
 1572     c.Request, _ = http.NewRequest("POST", "/", nil)
 1573     c.Request.Header.Add("rate", "8000")
 1574     c.Request.Header.Add("domain", "music")
 1575     c.Request.Header.Add("limit", "1000")
 1576 
 1577     var testHeader struct {
 1578         Rate   int    `header:"Rate"`
 1579         Domain string `header:"Domain"`
 1580         Limit  int    `header:"limit"`
 1581     }
 1582 
 1583     assert.NoError(t, c.BindHeader(&testHeader))
 1584     assert.Equal(t, 8000, testHeader.Rate)
 1585     assert.Equal(t, "music", testHeader.Domain)
 1586     assert.Equal(t, 1000, testHeader.Limit)
 1587     assert.Equal(t, 0, w.Body.Len())
 1588 }
 1589 
 1590 func TestContextBindWithQuery(t *testing.T) {
 1591     w := httptest.NewRecorder()
 1592     c, _ := CreateTestContext(w)
 1593 
 1594     c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo", bytes.NewBufferString("foo=unused"))
 1595 
 1596     var obj struct {
 1597         Foo string `form:"foo"`
 1598         Bar string `form:"bar"`
 1599     }
 1600     assert.NoError(t, c.BindQuery(&obj))
 1601     assert.Equal(t, "foo", obj.Bar)
 1602     assert.Equal(t, "bar", obj.Foo)
 1603     assert.Equal(t, 0, w.Body.Len())
 1604 }
 1605 
 1606 func TestContextBindWithYAML(t *testing.T) {
 1607     w := httptest.NewRecorder()
 1608     c, _ := CreateTestContext(w)
 1609 
 1610     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
 1611     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1612 
 1613     var obj struct {
 1614         Foo string `yaml:"foo"`
 1615         Bar string `yaml:"bar"`
 1616     }
 1617     assert.NoError(t, c.BindYAML(&obj))
 1618     assert.Equal(t, "foo", obj.Bar)
 1619     assert.Equal(t, "bar", obj.Foo)
 1620     assert.Equal(t, 0, w.Body.Len())
 1621 }
 1622 
 1623 func TestContextBadAutoBind(t *testing.T) {
 1624     w := httptest.NewRecorder()
 1625     c, _ := CreateTestContext(w)
 1626 
 1627     c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1628     c.Request.Header.Add("Content-Type", MIMEJSON)
 1629     var obj struct {
 1630         Foo string `json:"foo"`
 1631         Bar string `json:"bar"`
 1632     }
 1633 
 1634     assert.False(t, c.IsAborted())
 1635     assert.Error(t, c.Bind(&obj))
 1636     c.Writer.WriteHeaderNow()
 1637 
 1638     assert.Empty(t, obj.Bar)
 1639     assert.Empty(t, obj.Foo)
 1640     assert.Equal(t, http.StatusBadRequest, w.Code)
 1641     assert.True(t, c.IsAborted())
 1642 }
 1643 
 1644 func TestContextAutoShouldBindJSON(t *testing.T) {
 1645     c, _ := CreateTestContext(httptest.NewRecorder())
 1646     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1647     c.Request.Header.Add("Content-Type", MIMEJSON)
 1648 
 1649     var obj struct {
 1650         Foo string `json:"foo"`
 1651         Bar string `json:"bar"`
 1652     }
 1653     assert.NoError(t, c.ShouldBind(&obj))
 1654     assert.Equal(t, "foo", obj.Bar)
 1655     assert.Equal(t, "bar", obj.Foo)
 1656     assert.Empty(t, c.Errors)
 1657 }
 1658 
 1659 func TestContextShouldBindWithJSON(t *testing.T) {
 1660     w := httptest.NewRecorder()
 1661     c, _ := CreateTestContext(w)
 1662 
 1663     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1664     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1665 
 1666     var obj struct {
 1667         Foo string `json:"foo"`
 1668         Bar string `json:"bar"`
 1669     }
 1670     assert.NoError(t, c.ShouldBindJSON(&obj))
 1671     assert.Equal(t, "foo", obj.Bar)
 1672     assert.Equal(t, "bar", obj.Foo)
 1673     assert.Equal(t, 0, w.Body.Len())
 1674 }
 1675 
 1676 func TestContextShouldBindWithXML(t *testing.T) {
 1677     w := httptest.NewRecorder()
 1678     c, _ := CreateTestContext(w)
 1679 
 1680     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString(`<?xml version="1.0" encoding="UTF-8"?>
 1681         <root>
 1682             <foo>FOO</foo>
 1683             <bar>BAR</bar>
 1684         </root>`))
 1685     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1686 
 1687     var obj struct {
 1688         Foo string `xml:"foo"`
 1689         Bar string `xml:"bar"`
 1690     }
 1691     assert.NoError(t, c.ShouldBindXML(&obj))
 1692     assert.Equal(t, "FOO", obj.Foo)
 1693     assert.Equal(t, "BAR", obj.Bar)
 1694     assert.Equal(t, 0, w.Body.Len())
 1695 }
 1696 
 1697 func TestContextShouldBindHeader(t *testing.T) {
 1698     w := httptest.NewRecorder()
 1699     c, _ := CreateTestContext(w)
 1700 
 1701     c.Request, _ = http.NewRequest("POST", "/", nil)
 1702     c.Request.Header.Add("rate", "8000")
 1703     c.Request.Header.Add("domain", "music")
 1704     c.Request.Header.Add("limit", "1000")
 1705 
 1706     var testHeader struct {
 1707         Rate   int    `header:"Rate"`
 1708         Domain string `header:"Domain"`
 1709         Limit  int    `header:"limit"`
 1710     }
 1711 
 1712     assert.NoError(t, c.ShouldBindHeader(&testHeader))
 1713     assert.Equal(t, 8000, testHeader.Rate)
 1714     assert.Equal(t, "music", testHeader.Domain)
 1715     assert.Equal(t, 1000, testHeader.Limit)
 1716     assert.Equal(t, 0, w.Body.Len())
 1717 }
 1718 
 1719 func TestContextShouldBindWithQuery(t *testing.T) {
 1720     w := httptest.NewRecorder()
 1721     c, _ := CreateTestContext(w)
 1722 
 1723     c.Request, _ = http.NewRequest("POST", "/?foo=bar&bar=foo&Foo=bar1&Bar=foo1", bytes.NewBufferString("foo=unused"))
 1724 
 1725     var obj struct {
 1726         Foo  string `form:"foo"`
 1727         Bar  string `form:"bar"`
 1728         Foo1 string `form:"Foo"`
 1729         Bar1 string `form:"Bar"`
 1730     }
 1731     assert.NoError(t, c.ShouldBindQuery(&obj))
 1732     assert.Equal(t, "foo", obj.Bar)
 1733     assert.Equal(t, "bar", obj.Foo)
 1734     assert.Equal(t, "foo1", obj.Bar1)
 1735     assert.Equal(t, "bar1", obj.Foo1)
 1736     assert.Equal(t, 0, w.Body.Len())
 1737 }
 1738 
 1739 func TestContextShouldBindWithYAML(t *testing.T) {
 1740     w := httptest.NewRecorder()
 1741     c, _ := CreateTestContext(w)
 1742 
 1743     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("foo: bar\nbar: foo"))
 1744     c.Request.Header.Add("Content-Type", MIMEXML) // set fake content-type
 1745 
 1746     var obj struct {
 1747         Foo string `yaml:"foo"`
 1748         Bar string `yaml:"bar"`
 1749     }
 1750     assert.NoError(t, c.ShouldBindYAML(&obj))
 1751     assert.Equal(t, "foo", obj.Bar)
 1752     assert.Equal(t, "bar", obj.Foo)
 1753     assert.Equal(t, 0, w.Body.Len())
 1754 }
 1755 
 1756 func TestContextBadAutoShouldBind(t *testing.T) {
 1757     w := httptest.NewRecorder()
 1758     c, _ := CreateTestContext(w)
 1759 
 1760     c.Request, _ = http.NewRequest("POST", "http://example.com", bytes.NewBufferString("\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1761     c.Request.Header.Add("Content-Type", MIMEJSON)
 1762     var obj struct {
 1763         Foo string `json:"foo"`
 1764         Bar string `json:"bar"`
 1765     }
 1766 
 1767     assert.False(t, c.IsAborted())
 1768     assert.Error(t, c.ShouldBind(&obj))
 1769 
 1770     assert.Empty(t, obj.Bar)
 1771     assert.Empty(t, obj.Foo)
 1772     assert.False(t, c.IsAborted())
 1773 }
 1774 
 1775 func TestContextShouldBindBodyWith(t *testing.T) {
 1776     type typeA struct {
 1777         Foo string `json:"foo" xml:"foo" binding:"required"`
 1778     }
 1779     type typeB struct {
 1780         Bar string `json:"bar" xml:"bar" binding:"required"`
 1781     }
 1782     for _, tt := range []struct {
 1783         name               string
 1784         bindingA, bindingB binding.BindingBody
 1785         bodyA, bodyB       string
 1786     }{
 1787         {
 1788             name:     "JSON & JSON",
 1789             bindingA: binding.JSON,
 1790             bindingB: binding.JSON,
 1791             bodyA:    `{"foo":"FOO"}`,
 1792             bodyB:    `{"bar":"BAR"}`,
 1793         },
 1794         {
 1795             name:     "JSON & XML",
 1796             bindingA: binding.JSON,
 1797             bindingB: binding.XML,
 1798             bodyA:    `{"foo":"FOO"}`,
 1799             bodyB: `<?xml version="1.0" encoding="UTF-8"?>
 1800 <root>
 1801    <bar>BAR</bar>
 1802 </root>`,
 1803         },
 1804         {
 1805             name:     "XML & XML",
 1806             bindingA: binding.XML,
 1807             bindingB: binding.XML,
 1808             bodyA: `<?xml version="1.0" encoding="UTF-8"?>
 1809 <root>
 1810    <foo>FOO</foo>
 1811 </root>`,
 1812             bodyB: `<?xml version="1.0" encoding="UTF-8"?>
 1813 <root>
 1814    <bar>BAR</bar>
 1815 </root>`,
 1816         },
 1817     } {
 1818         t.Logf("testing: %s", tt.name)
 1819         // bodyA to typeA and typeB
 1820         {
 1821             w := httptest.NewRecorder()
 1822             c, _ := CreateTestContext(w)
 1823             c.Request, _ = http.NewRequest(
 1824                 "POST", "http://example.com", bytes.NewBufferString(tt.bodyA),
 1825             )
 1826             // When it binds to typeA and typeB, it finds the body is
 1827             // not typeB but typeA.
 1828             objA := typeA{}
 1829             assert.NoError(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
 1830             assert.Equal(t, typeA{"FOO"}, objA)
 1831             objB := typeB{}
 1832             assert.Error(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
 1833             assert.NotEqual(t, typeB{"BAR"}, objB)
 1834         }
 1835         // bodyB to typeA and typeB
 1836         {
 1837             // When it binds to typeA and typeB, it finds the body is
 1838             // not typeA but typeB.
 1839             w := httptest.NewRecorder()
 1840             c, _ := CreateTestContext(w)
 1841             c.Request, _ = http.NewRequest(
 1842                 "POST", "http://example.com", bytes.NewBufferString(tt.bodyB),
 1843             )
 1844             objA := typeA{}
 1845             assert.Error(t, c.ShouldBindBodyWith(&objA, tt.bindingA))
 1846             assert.NotEqual(t, typeA{"FOO"}, objA)
 1847             objB := typeB{}
 1848             assert.NoError(t, c.ShouldBindBodyWith(&objB, tt.bindingB))
 1849             assert.Equal(t, typeB{"BAR"}, objB)
 1850         }
 1851     }
 1852 }
 1853 
 1854 func TestContextGolangContext(t *testing.T) {
 1855     c, _ := CreateTestContext(httptest.NewRecorder())
 1856     c.Request, _ = http.NewRequest("POST", "/", bytes.NewBufferString("{\"foo\":\"bar\", \"bar\":\"foo\"}"))
 1857     assert.NoError(t, c.Err())
 1858     assert.Nil(t, c.Done())
 1859     ti, ok := c.Deadline()
 1860     assert.Equal(t, ti, time.Time{})
 1861     assert.False(t, ok)
 1862     assert.Equal(t, c.Value(0), c.Request)
 1863     assert.Nil(t, c.Value("foo"))
 1864 
 1865     c.Set("foo", "bar")
 1866     assert.Equal(t, "bar", c.Value("foo"))
 1867     assert.Nil(t, c.Value(1))
 1868 }
 1869 
 1870 func TestWebsocketsRequired(t *testing.T) {
 1871     // Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
 1872     c, _ := CreateTestContext(httptest.NewRecorder())
 1873     c.Request, _ = http.NewRequest("GET", "/chat", nil)
 1874     c.Request.Header.Set("Host", "server.example.com")
 1875     c.Request.Header.Set("Upgrade", "websocket")
 1876     c.Request.Header.Set("Connection", "Upgrade")
 1877     c.Request.Header.Set("Sec-WebSocket-Key", "dGhlIHNhbXBsZSBub25jZQ==")
 1878     c.Request.Header.Set("Origin", "http://example.com")
 1879     c.Request.Header.Set("Sec-WebSocket-Protocol", "chat, superchat")
 1880     c.Request.Header.Set("Sec-WebSocket-Version", "13")
 1881 
 1882     assert.True(t, c.IsWebsocket())
 1883 
 1884     // Normal request, no websocket required.
 1885     c, _ = CreateTestContext(httptest.NewRecorder())
 1886     c.Request, _ = http.NewRequest("GET", "/chat", nil)
 1887     c.Request.Header.Set("Host", "server.example.com")
 1888 
 1889     assert.False(t, c.IsWebsocket())
 1890 }
 1891 
 1892 func TestGetRequestHeaderValue(t *testing.T) {
 1893     c, _ := CreateTestContext(httptest.NewRecorder())
 1894     c.Request, _ = http.NewRequest("GET", "/chat", nil)
 1895     c.Request.Header.Set("Gin-Version", "1.0.0")
 1896 
 1897     assert.Equal(t, "1.0.0", c.GetHeader("Gin-Version"))
 1898     assert.Empty(t, c.GetHeader("Connection"))
 1899 }
 1900 
 1901 func TestContextGetRawData(t *testing.T) {
 1902     c, _ := CreateTestContext(httptest.NewRecorder())
 1903     body := bytes.NewBufferString("Fetch binary post data")
 1904     c.Request, _ = http.NewRequest("POST", "/", body)
 1905     c.Request.Header.Add("Content-Type", MIMEPOSTForm)
 1906 
 1907     data, err := c.GetRawData()
 1908     assert.Nil(t, err)
 1909     assert.Equal(t, "Fetch binary post data", string(data))
 1910 }
 1911 
 1912 func TestContextRenderDataFromReader(t *testing.T) {
 1913     w := httptest.NewRecorder()
 1914     c, _ := CreateTestContext(w)
 1915 
 1916     body := "#!PNG some raw data"
 1917     reader := strings.NewReader(body)
 1918     contentLength := int64(len(body))
 1919     contentType := "image/png"
 1920     extraHeaders := map[string]string{"Content-Disposition": `attachment; filename="gopher.png"`}
 1921 
 1922     c.DataFromReader(http.StatusOK, contentLength, contentType, reader, extraHeaders)
 1923 
 1924     assert.Equal(t, http.StatusOK, w.Code)
 1925     assert.Equal(t, body, w.Body.String())
 1926     assert.Equal(t, contentType, w.Header().Get("Content-Type"))
 1927     assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
 1928     assert.Equal(t, extraHeaders["Content-Disposition"], w.Header().Get("Content-Disposition"))
 1929 }
 1930 
 1931 func TestContextRenderDataFromReaderNoHeaders(t *testing.T) {
 1932     w := httptest.NewRecorder()
 1933     c, _ := CreateTestContext(w)
 1934 
 1935     body := "#!PNG some raw data"
 1936     reader := strings.NewReader(body)
 1937     contentLength := int64(len(body))
 1938     contentType := "image/png"
 1939 
 1940     c.DataFromReader(http.StatusOK, contentLength, contentType, reader, nil)
 1941 
 1942     assert.Equal(t, http.StatusOK, w.Code)
 1943     assert.Equal(t, body, w.Body.String())
 1944     assert.Equal(t, contentType, w.Header().Get("Content-Type"))
 1945     assert.Equal(t, fmt.Sprintf("%d", contentLength), w.Header().Get("Content-Length"))
 1946 }
 1947 
 1948 type TestResponseRecorder struct {
 1949     *httptest.ResponseRecorder
 1950     closeChannel chan bool
 1951 }
 1952 
 1953 func (r *TestResponseRecorder) CloseNotify() <-chan bool {
 1954     return r.closeChannel
 1955 }
 1956 
 1957 func (r *TestResponseRecorder) closeClient() {
 1958     r.closeChannel <- true
 1959 }
 1960 
 1961 func CreateTestResponseRecorder() *TestResponseRecorder {
 1962     return &TestResponseRecorder{
 1963         httptest.NewRecorder(),
 1964         make(chan bool, 1),
 1965     }
 1966 }
 1967 
 1968 func TestContextStream(t *testing.T) {
 1969     w := CreateTestResponseRecorder()
 1970     c, _ := CreateTestContext(w)
 1971 
 1972     stopStream := true
 1973     c.Stream(func(w io.Writer) bool {
 1974         defer func() {
 1975             stopStream = false
 1976         }()
 1977 
 1978         _, err := w.Write([]byte("test"))
 1979         assert.NoError(t, err)
 1980 
 1981         return stopStream
 1982     })
 1983 
 1984     assert.Equal(t, "testtest", w.Body.String())
 1985 }
 1986 
 1987 func TestContextStreamWithClientGone(t *testing.T) {
 1988     w := CreateTestResponseRecorder()
 1989     c, _ := CreateTestContext(w)
 1990 
 1991     c.Stream(func(writer io.Writer) bool {
 1992         defer func() {
 1993             w.closeClient()
 1994         }()
 1995 
 1996         _, err := writer.Write([]byte("test"))
 1997         assert.NoError(t, err)
 1998 
 1999         return true
 2000     })
 2001 
 2002     assert.Equal(t, "test", w.Body.String())
 2003 }
 2004 
 2005 func TestContextResetInHandler(t *testing.T) {
 2006     w := CreateTestResponseRecorder()
 2007     c, _ := CreateTestContext(w)
 2008 
 2009     c.handlers = []HandlerFunc{
 2010         func(c *Context) { c.reset() },
 2011     }
 2012     assert.NotPanics(t, func() {
 2013         c.Next()
 2014     })
 2015 }
 2016 
 2017 func TestRaceParamsContextCopy(t *testing.T) {
 2018     DefaultWriter = os.Stdout
 2019     router := Default()
 2020     nameGroup := router.Group("/:name")
 2021     var wg sync.WaitGroup
 2022     wg.Add(2)
 2023     {
 2024         nameGroup.GET("/api", func(c *Context) {
 2025             go func(c *Context, param string) {
 2026                 defer wg.Done()
 2027                 // First assert must be executed after the second request
 2028                 time.Sleep(50 * time.Millisecond)
 2029                 assert.Equal(t, c.Param("name"), param)
 2030             }(c.Copy(), c.Param("name"))
 2031         })
 2032     }
 2033     performRequest(router, "GET", "/name1/api")
 2034     performRequest(router, "GET", "/name2/api")
 2035     wg.Wait()
 2036 }
 2037 
 2038 func TestContextWithKeysMutex(t *testing.T) {
 2039     c := &Context{}
 2040     c.Set("foo", "bar")
 2041 
 2042     value, err := c.Get("foo")
 2043     assert.Equal(t, "bar", value)
 2044     assert.True(t, err)
 2045 
 2046     value, err = c.Get("foo2")
 2047     assert.Nil(t, value)
 2048     assert.False(t, err)
 2049 }
 2050 
 2051 func TestRemoteIPFail(t *testing.T) {
 2052     c, _ := CreateTestContext(httptest.NewRecorder())
 2053     c.Request, _ = http.NewRequest("POST", "/", nil)
 2054     c.Request.RemoteAddr = "[:::]:80"
 2055     ip, trust := c.RemoteIP()
 2056     assert.Nil(t, ip)
 2057     assert.False(t, trust)
 2058 }