2014-08-29 21:49:50 +04:00
// Copyright 2014 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.
2014-08-08 15:48:15 +04:00
package gin
import (
2014-08-11 14:25:52 +04:00
"bytes"
2014-08-08 15:48:15 +04:00
"errors"
2017-01-09 18:24:48 +03:00
"fmt"
2014-08-08 15:48:15 +04:00
"html/template"
2018-08-14 04:51:56 +03:00
"io"
2015-05-26 15:21:35 +03:00
"mime/multipart"
2014-08-08 15:48:15 +04:00
"net/http"
"net/http/httptest"
2017-06-02 11:00:55 +03:00
"reflect"
2015-09-25 13:04:55 +03:00
"strings"
2014-08-08 15:48:15 +04:00
"testing"
2015-05-19 03:29:32 +03:00
"time"
2014-08-08 15:48:15 +04:00
2017-06-28 00:17:02 +03:00
"github.com/gin-contrib/sse"
2018-05-11 05:33:33 +03:00
"github.com/gin-gonic/gin/binding"
2018-08-19 05:45:56 +03:00
"github.com/golang/protobuf/proto"
2015-04-08 03:58:35 +03:00
"github.com/stretchr/testify/assert"
2016-10-19 17:13:38 +03:00
"golang.org/x/net/context"
2018-08-19 05:45:56 +03:00
testdata "github.com/gin-gonic/gin/testdata/protoexample"
2015-04-08 03:58:35 +03:00
)
2014-08-08 15:48:15 +04:00
2016-10-19 17:13:38 +03:00
var _ context . Context = & Context { }
2015-05-07 17:00:37 +03:00
// Unit tests TODO
2015-04-09 13:15:02 +03:00
// func (c *Context) File(filepath string) {
// func (c *Context) Negotiate(code int, config Negotiate) {
// BAD case: func (c *Context) Render(code int, render render.Render, obj ...interface{}) {
2015-05-07 17:00:37 +03:00
// test that information is not leaked when reusing Contexts (using the Pool)
2015-04-09 13:15:02 +03:00
2015-05-26 18:22:39 +03:00
func createMultipartRequest ( ) * http . Request {
2015-05-26 15:21:35 +03:00
boundary := "--testboundary"
2015-05-26 18:22:39 +03:00
body := new ( bytes . Buffer )
2015-05-26 15:21:35 +03:00
mw := multipart . NewWriter ( body )
defer mw . Close ( )
2015-05-26 18:22:39 +03:00
must ( mw . SetBoundary ( boundary ) )
must ( mw . WriteField ( "foo" , "bar" ) )
2016-01-29 04:07:44 +03:00
must ( mw . WriteField ( "bar" , "10" ) )
2015-07-08 05:26:37 +03:00
must ( mw . WriteField ( "bar" , "foo2" ) )
must ( mw . WriteField ( "array" , "first" ) )
must ( mw . WriteField ( "array" , "second" ) )
2016-01-29 04:07:44 +03:00
must ( mw . WriteField ( "id" , "" ) )
2017-02-17 16:32:36 +03:00
must ( mw . WriteField ( "time_local" , "31/12/2016 14:55" ) )
must ( mw . WriteField ( "time_utc" , "31/12/2016 14:55" ) )
2017-09-28 17:23:18 +03:00
must ( mw . WriteField ( "time_location" , "31/12/2016 14:55" ) )
2018-08-06 07:07:11 +03:00
must ( mw . WriteField ( "names[a]" , "thinkerou" ) )
must ( mw . WriteField ( "names[b]" , "tianou" ) )
2015-05-26 18:22:39 +03:00
req , err := http . NewRequest ( "POST" , "/" , body )
must ( err )
req . Header . Set ( "Content-Type" , MIMEMultipartPOSTForm + "; boundary=" + boundary )
return req
}
func must ( err error ) {
if err != nil {
panic ( err . Error ( ) )
2015-05-26 15:21:35 +03:00
}
}
2016-12-24 07:25:01 +03:00
func TestContextFormFile ( t * testing . T ) {
buf := new ( bytes . Buffer )
mw := multipart . NewWriter ( buf )
w , err := mw . CreateFormFile ( "file" , "test" )
if assert . NoError ( t , err ) {
w . Write ( [ ] byte ( "test" ) )
}
mw . Close ( )
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "POST" , "/" , buf )
c . Request . Header . Set ( "Content-Type" , mw . FormDataContentType ( ) )
f , err := c . FormFile ( "file" )
if assert . NoError ( t , err ) {
assert . Equal ( t , "test" , f . Filename )
}
2017-07-16 06:42:08 +03:00
assert . NoError ( t , c . SaveUploadedFile ( f , "test" ) )
2016-12-24 07:25:01 +03:00
}
func TestContextMultipartForm ( t * testing . T ) {
buf := new ( bytes . Buffer )
mw := multipart . NewWriter ( buf )
mw . WriteField ( "foo" , "bar" )
2017-07-16 06:42:08 +03:00
w , err := mw . CreateFormFile ( "file" , "test" )
if assert . NoError ( t , err ) {
w . Write ( [ ] byte ( "test" ) )
}
2016-12-24 07:25:01 +03:00
mw . Close ( )
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "POST" , "/" , buf )
c . Request . Header . Set ( "Content-Type" , mw . FormDataContentType ( ) )
f , err := c . MultipartForm ( )
if assert . NoError ( t , err ) {
assert . NotNil ( t , f )
}
2017-07-16 06:42:08 +03:00
assert . NoError ( t , c . SaveUploadedFile ( f . File [ "file" ] [ 0 ] , "test" ) )
}
func TestSaveUploadedOpenFailed ( t * testing . T ) {
buf := new ( bytes . Buffer )
mw := multipart . NewWriter ( buf )
mw . Close ( )
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "POST" , "/" , buf )
c . Request . Header . Set ( "Content-Type" , mw . FormDataContentType ( ) )
f := & multipart . FileHeader {
Filename : "file" ,
}
assert . Error ( t , c . SaveUploadedFile ( f , "test" ) )
}
func TestSaveUploadedCreateFailed ( t * testing . T ) {
buf := new ( bytes . Buffer )
mw := multipart . NewWriter ( buf )
w , err := mw . CreateFormFile ( "file" , "test" )
if assert . NoError ( t , err ) {
w . Write ( [ ] byte ( "test" ) )
}
mw . Close ( )
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "POST" , "/" , buf )
c . Request . Header . Set ( "Content-Type" , mw . FormDataContentType ( ) )
f , err := c . FormFile ( "file" )
if assert . NoError ( t , err ) {
assert . Equal ( t , "test" , f . Filename )
}
assert . Error ( t , c . SaveUploadedFile ( f , "/" ) )
2016-12-24 07:25:01 +03:00
}
2015-04-08 03:58:35 +03:00
func TestContextReset ( t * testing . T ) {
router := New ( )
c := router . allocateContext ( )
2015-05-22 03:24:13 +03:00
assert . Equal ( t , c . engine , router )
2015-04-08 03:58:35 +03:00
c . index = 2
c . Writer = & responseWriter { ResponseWriter : httptest . NewRecorder ( ) }
2015-04-08 15:24:49 +03:00
c . Params = Params { Param { } }
2015-05-22 04:25:21 +03:00
c . Error ( errors . New ( "test" ) )
2015-04-08 03:58:35 +03:00
c . Set ( "foo" , "bar" )
c . reset ( )
assert . False ( t , c . IsAborted ( ) )
assert . Nil ( t , c . Keys )
assert . Nil ( t , c . Accepted )
assert . Len ( t , c . Errors , 0 )
2015-05-19 01:49:01 +03:00
assert . Empty ( t , c . Errors . Errors ( ) )
assert . Empty ( t , c . Errors . ByType ( ErrorTypeAny ) )
2015-04-08 03:58:35 +03:00
assert . Len ( t , c . Params , 0 )
2015-05-31 23:35:49 +03:00
assert . EqualValues ( t , c . index , - 1 )
2015-04-08 03:58:35 +03:00
assert . Equal ( t , c . Writer . ( * responseWriter ) , & c . writermem )
2014-08-08 15:48:15 +04:00
}
2015-07-03 05:20:18 +03:00
func TestContextHandlers ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-07-03 05:20:18 +03:00
assert . Nil ( t , c . handlers )
assert . Nil ( t , c . handlers . Last ( ) )
c . handlers = HandlersChain { }
assert . NotNil ( t , c . handlers )
assert . Nil ( t , c . handlers . Last ( ) )
f := func ( c * Context ) { }
g := func ( c * Context ) { }
c . handlers = HandlersChain { f }
compareFunc ( t , f , c . handlers . Last ( ) )
c . handlers = HandlersChain { f , g }
compareFunc ( t , g , c . handlers . Last ( ) )
}
2014-08-08 15:48:15 +04:00
// TestContextSetGet tests that a parameter is set correctly on the
// current context and can be retrieved using Get.
func TestContextSetGet ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-04-08 03:58:35 +03:00
c . Set ( "foo" , "bar" )
2014-08-08 15:48:15 +04:00
2015-04-08 03:58:35 +03:00
value , err := c . Get ( "foo" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , value )
2015-04-08 03:58:35 +03:00
assert . True ( t , err )
2014-08-08 15:48:15 +04:00
2015-04-08 03:58:35 +03:00
value , err = c . Get ( "foo2" )
assert . Nil ( t , value )
assert . False ( t , err )
2014-08-08 15:48:15 +04:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , c . MustGet ( "foo" ) )
2015-04-08 03:58:35 +03:00
assert . Panics ( t , func ( ) { c . MustGet ( "no_exist" ) } )
}
2014-08-08 15:48:15 +04:00
2015-05-07 17:00:37 +03:00
func TestContextSetGetValues ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-07 17:00:37 +03:00
c . Set ( "string" , "this is a string" )
c . Set ( "int32" , int32 ( - 42 ) )
c . Set ( "int64" , int64 ( 42424242424242 ) )
c . Set ( "uint64" , uint64 ( 42 ) )
c . Set ( "float32" , float32 ( 4.2 ) )
c . Set ( "float64" , 4.2 )
2015-05-11 02:04:08 +03:00
var a interface { } = 1
c . Set ( "intInterface" , a )
2015-05-07 17:00:37 +03:00
assert . Exactly ( t , c . MustGet ( "string" ) . ( string ) , "this is a string" )
assert . Exactly ( t , c . MustGet ( "int32" ) . ( int32 ) , int32 ( - 42 ) )
assert . Exactly ( t , c . MustGet ( "int64" ) . ( int64 ) , int64 ( 42424242424242 ) )
assert . Exactly ( t , c . MustGet ( "uint64" ) . ( uint64 ) , uint64 ( 42 ) )
assert . Exactly ( t , c . MustGet ( "float32" ) . ( float32 ) , float32 ( 4.2 ) )
assert . Exactly ( t , c . MustGet ( "float64" ) . ( float64 ) , 4.2 )
2015-05-11 02:04:08 +03:00
assert . Exactly ( t , c . MustGet ( "intInterface" ) . ( int ) , 1 )
2015-05-07 17:00:37 +03:00
}
2017-06-02 04:00:04 +03:00
func TestContextGetString ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "string" , "this is a string" )
assert . Equal ( t , "this is a string" , c . GetString ( "string" ) )
}
func TestContextSetGetBool ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "bool" , true )
2017-11-21 16:18:45 +03:00
assert . True ( t , c . GetBool ( "bool" ) )
2017-06-02 04:00:04 +03:00
}
func TestContextGetInt ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "int" , 1 )
assert . Equal ( t , 1 , c . GetInt ( "int" ) )
}
func TestContextGetInt64 ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "int64" , int64 ( 42424242424242 ) )
assert . Equal ( t , int64 ( 42424242424242 ) , c . GetInt64 ( "int64" ) )
}
func TestContextGetFloat64 ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "float64" , 4.2 )
assert . Equal ( t , 4.2 , c . GetFloat64 ( "float64" ) )
}
func TestContextGetTime ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
t1 , _ := time . Parse ( "1/2/2006 15:04:05" , "01/01/2017 12:00:00" )
c . Set ( "time" , t1 )
assert . Equal ( t , t1 , c . GetTime ( "time" ) )
}
func TestContextGetDuration ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "duration" , time . Second )
assert . Equal ( t , time . Second , c . GetDuration ( "duration" ) )
}
func TestContextGetStringSlice ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Set ( "slice" , [ ] string { "foo" } )
assert . Equal ( t , [ ] string { "foo" } , c . GetStringSlice ( "slice" ) )
}
func TestContextGetStringMap ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
var m = make ( map [ string ] interface { } )
m [ "foo" ] = 1
c . Set ( "map" , m )
assert . Equal ( t , m , c . GetStringMap ( "map" ) )
assert . Equal ( t , 1 , c . GetStringMap ( "map" ) [ "foo" ] )
}
func TestContextGetStringMapString ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
var m = make ( map [ string ] string )
m [ "foo" ] = "bar"
c . Set ( "map" , m )
assert . Equal ( t , m , c . GetStringMapString ( "map" ) )
assert . Equal ( t , "bar" , c . GetStringMapString ( "map" ) [ "foo" ] )
}
func TestContextGetStringMapStringSlice ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
var m = make ( map [ string ] [ ] string )
m [ "foo" ] = [ ] string { "foo" }
c . Set ( "map" , m )
assert . Equal ( t , m , c . GetStringMapStringSlice ( "map" ) )
assert . Equal ( t , [ ] string { "foo" } , c . GetStringMapStringSlice ( "map" ) [ "foo" ] )
}
2015-04-09 13:15:02 +03:00
func TestContextCopy ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-04-09 13:15:02 +03:00
c . index = 2
c . Request , _ = http . NewRequest ( "POST" , "/hola" , nil )
2015-05-07 12:30:01 +03:00
c . handlers = HandlersChain { func ( c * Context ) { } }
2015-04-09 13:15:02 +03:00
c . Params = Params { Param { Key : "foo" , Value : "bar" } }
c . Set ( "foo" , "bar" )
cp := c . Copy ( )
assert . Nil ( t , cp . handlers )
2015-05-05 16:06:38 +03:00
assert . Nil ( t , cp . writermem . ResponseWriter )
assert . Equal ( t , & cp . writermem , cp . Writer . ( * responseWriter ) )
2015-04-09 13:15:02 +03:00
assert . Equal ( t , cp . Request , c . Request )
2015-07-02 21:24:54 +03:00
assert . Equal ( t , cp . index , abortIndex )
2015-04-09 13:15:02 +03:00
assert . Equal ( t , cp . Keys , c . Keys )
2015-05-22 03:24:13 +03:00
assert . Equal ( t , cp . engine , c . engine )
2015-04-09 13:15:02 +03:00
assert . Equal ( t , cp . Params , c . Params )
}
2015-06-25 20:44:52 +03:00
func TestContextHandlerName ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-06-25 20:44:52 +03:00
c . handlers = HandlersChain { func ( c * Context ) { } , handlerNameTest }
2015-08-21 21:57:53 +03:00
assert . Regexp ( t , "^(.*/vendor/)?github.com/gin-gonic/gin.handlerNameTest$" , c . HandlerName ( ) )
2015-06-25 20:44:52 +03:00
}
func handlerNameTest ( c * Context ) {
}
2017-06-02 11:00:55 +03:00
var handlerTest HandlerFunc = func ( c * Context ) {
}
func TestContextHandler ( t * testing . T ) {
2017-06-13 05:50:42 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . handlers = HandlersChain { func ( c * Context ) { } , handlerTest }
2017-06-02 11:00:55 +03:00
2017-06-13 05:50:42 +03:00
assert . Equal ( t , reflect . ValueOf ( handlerTest ) . Pointer ( ) , reflect . ValueOf ( c . Handler ( ) ) . Pointer ( ) )
2017-06-02 11:00:55 +03:00
}
2015-05-26 18:22:39 +03:00
func TestContextQuery ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2016-01-29 04:07:44 +03:00
c . Request , _ = http . NewRequest ( "GET" , "http://example.com/?foo=bar&page=10&id=" , nil )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok := c . GetQuery ( "foo" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , value )
assert . Equal ( t , "bar" , c . DefaultQuery ( "foo" , "none" ) )
assert . Equal ( t , "bar" , c . Query ( "foo" ) )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok = c . GetQuery ( "page" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "10" , value )
assert . Equal ( t , "10" , c . DefaultQuery ( "page" , "0" ) )
assert . Equal ( t , "10" , c . Query ( "page" ) )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok = c . GetQuery ( "id" )
assert . True ( t , ok )
assert . Empty ( t , value )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , c . DefaultQuery ( "id" , "nada" ) )
2016-01-29 04:07:44 +03:00
assert . Empty ( t , c . Query ( "id" ) )
value , ok = c . GetQuery ( "NoKey" )
assert . False ( t , ok )
assert . Empty ( t , value )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "nada" , c . DefaultQuery ( "NoKey" , "nada" ) )
2015-05-26 13:11:59 +03:00
assert . Empty ( t , c . Query ( "NoKey" ) )
2016-01-29 04:07:44 +03:00
// postform should not mess
value , ok = c . GetPostForm ( "page" )
assert . False ( t , ok )
assert . Empty ( t , value )
assert . Empty ( t , c . PostForm ( "foo" ) )
2015-05-05 16:06:38 +03:00
}
2015-05-26 18:22:39 +03:00
func TestContextQueryAndPostForm ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2016-01-29 04:07:44 +03:00
body := bytes . NewBufferString ( "foo=bar&page=11&both=&foo=second" )
2018-08-06 07:07:11 +03:00
c . Request , _ = http . NewRequest ( "POST" ,
"/?both=GET&id=main&id=omit&array[]=first&array[]=second&ids[a]=hi&ids[b]=3.14" , body )
2015-05-05 16:06:38 +03:00
c . Request . Header . Add ( "Content-Type" , MIMEPOSTForm )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , c . DefaultPostForm ( "foo" , "none" ) )
assert . Equal ( t , "bar" , c . PostForm ( "foo" ) )
2015-05-26 13:11:59 +03:00
assert . Empty ( t , c . Query ( "foo" ) )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok := c . GetPostForm ( "page" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "11" , value )
assert . Equal ( t , "11" , c . DefaultPostForm ( "page" , "0" ) )
assert . Equal ( t , "11" , c . PostForm ( "page" ) )
assert . Empty ( t , c . Query ( "page" ) )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok = c . GetPostForm ( "both" )
assert . True ( t , ok )
assert . Empty ( t , value )
assert . Empty ( t , c . PostForm ( "both" ) )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , c . DefaultPostForm ( "both" , "nothing" ) )
assert . Equal ( t , "GET" , c . Query ( "both" ) , "GET" )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok = c . GetQuery ( "id" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "main" , value )
assert . Equal ( t , "000" , c . DefaultPostForm ( "id" , "000" ) )
assert . Equal ( t , "main" , c . Query ( "id" ) )
2015-05-26 13:11:59 +03:00
assert . Empty ( t , c . PostForm ( "id" ) )
2015-05-05 16:06:38 +03:00
2016-01-29 04:07:44 +03:00
value , ok = c . GetQuery ( "NoKey" )
assert . False ( t , ok )
assert . Empty ( t , value )
value , ok = c . GetPostForm ( "NoKey" )
assert . False ( t , ok )
assert . Empty ( t , value )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "nada" , c . DefaultPostForm ( "NoKey" , "nada" ) )
assert . Equal ( t , "nothing" , c . DefaultQuery ( "NoKey" , "nothing" ) )
2015-05-26 13:11:59 +03:00
assert . Empty ( t , c . PostForm ( "NoKey" ) )
assert . Empty ( t , c . Query ( "NoKey" ) )
2015-05-26 13:08:33 +03:00
2015-05-26 18:22:39 +03:00
var obj struct {
2015-07-08 05:26:37 +03:00
Foo string ` form:"foo" `
ID string ` form:"id" `
2016-01-29 04:07:44 +03:00
Page int ` form:"page" `
2015-07-08 05:26:37 +03:00
Both string ` form:"both" `
Array [ ] string ` form:"array[]" `
2015-05-26 18:22:39 +03:00
}
assert . NoError ( t , c . Bind ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , obj . Foo , "bar" )
assert . Equal ( t , "main" , obj . ID , "main" )
assert . Equal ( t , 11 , obj . Page , 11 )
assert . Empty ( t , obj . Both )
assert . Equal ( t , [ ] string { "first" , "second" } , obj . Array )
2016-03-29 19:05:13 +03:00
values , ok := c . GetQueryArray ( "array[]" )
assert . True ( t , ok )
assert . Equal ( t , "first" , values [ 0 ] )
assert . Equal ( t , "second" , values [ 1 ] )
values = c . QueryArray ( "array[]" )
assert . Equal ( t , "first" , values [ 0 ] )
assert . Equal ( t , "second" , values [ 1 ] )
values = c . QueryArray ( "nokey" )
assert . Equal ( t , 0 , len ( values ) )
values = c . QueryArray ( "both" )
assert . Equal ( t , 1 , len ( values ) )
assert . Equal ( t , "GET" , values [ 0 ] )
2018-08-06 07:07:11 +03:00
dicts , ok := c . GetQueryMap ( "ids" )
assert . True ( t , ok )
assert . Equal ( t , "hi" , dicts [ "a" ] )
assert . Equal ( t , "3.14" , dicts [ "b" ] )
dicts , ok = c . GetQueryMap ( "nokey" )
assert . False ( t , ok )
assert . Equal ( t , 0 , len ( dicts ) )
dicts , ok = c . GetQueryMap ( "both" )
assert . False ( t , ok )
assert . Equal ( t , 0 , len ( dicts ) )
dicts , ok = c . GetQueryMap ( "array" )
assert . False ( t , ok )
assert . Equal ( t , 0 , len ( dicts ) )
dicts = c . QueryMap ( "ids" )
assert . Equal ( t , "hi" , dicts [ "a" ] )
assert . Equal ( t , "3.14" , dicts [ "b" ] )
dicts = c . QueryMap ( "nokey" )
assert . Equal ( t , 0 , len ( dicts ) )
2015-05-26 18:22:39 +03:00
}
func TestContextPostFormMultipart ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-26 18:22:39 +03:00
c . Request = createMultipartRequest ( )
var obj struct {
2017-09-28 17:23:18 +03:00
Foo string ` form:"foo" `
Bar string ` form:"bar" `
BarAsInt int ` form:"bar" `
Array [ ] string ` form:"array" `
ID string ` form:"id" `
TimeLocal time . Time ` form:"time_local" time_format:"02/01/2006 15:04" `
TimeUTC time . Time ` form:"time_utc" time_format:"02/01/2006 15:04" time_utc:"1" `
TimeLocation time . Time ` form:"time_location" time_format:"02/01/2006 15:04" time_location:"Asia/Tokyo" `
BlankTime time . Time ` form:"blank_time" time_format:"02/01/2006 15:04" `
2015-05-26 18:22:39 +03:00
}
assert . NoError ( t , c . Bind ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , obj . Foo )
assert . Equal ( t , "10" , obj . Bar )
assert . Equal ( t , 10 , obj . BarAsInt )
assert . Equal ( t , [ ] string { "first" , "second" } , obj . Array )
assert . Empty ( t , obj . ID )
assert . Equal ( t , "31/12/2016 14:55" , obj . TimeLocal . Format ( "02/01/2006 15:04" ) )
assert . Equal ( t , time . Local , obj . TimeLocal . Location ( ) )
assert . Equal ( t , "31/12/2016 14:55" , obj . TimeUTC . Format ( "02/01/2006 15:04" ) )
assert . Equal ( t , time . UTC , obj . TimeUTC . Location ( ) )
2017-09-28 17:23:18 +03:00
loc , _ := time . LoadLocation ( "Asia/Tokyo" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "31/12/2016 14:55" , obj . TimeLocation . Format ( "02/01/2006 15:04" ) )
assert . Equal ( t , loc , obj . TimeLocation . Location ( ) )
2017-02-17 16:32:36 +03:00
assert . True ( t , obj . BlankTime . IsZero ( ) )
2015-05-26 13:08:33 +03:00
2016-01-29 04:07:44 +03:00
value , ok := c . GetQuery ( "foo" )
assert . False ( t , ok )
assert . Empty ( t , value )
2015-05-26 18:22:39 +03:00
assert . Empty ( t , c . Query ( "bar" ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "nothing" , c . DefaultQuery ( "id" , "nothing" ) )
2016-01-29 04:07:44 +03:00
value , ok = c . GetPostForm ( "foo" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , value )
assert . Equal ( t , "bar" , c . PostForm ( "foo" ) )
2016-01-29 04:07:44 +03:00
value , ok = c . GetPostForm ( "array" )
assert . True ( t , ok )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "first" , value )
assert . Equal ( t , "first" , c . PostForm ( "array" ) )
2016-01-29 04:07:44 +03:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "10" , c . DefaultPostForm ( "bar" , "nothing" ) )
2016-01-29 04:07:44 +03:00
value , ok = c . GetPostForm ( "id" )
assert . True ( t , ok )
assert . Empty ( t , value )
assert . Empty ( t , c . PostForm ( "id" ) )
assert . Empty ( t , c . DefaultPostForm ( "id" , "nothing" ) )
value , ok = c . GetPostForm ( "nokey" )
assert . False ( t , ok )
assert . Empty ( t , value )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "nothing" , c . DefaultPostForm ( "nokey" , "nothing" ) )
2016-03-29 19:05:13 +03:00
values , ok := c . GetPostFormArray ( "array" )
assert . True ( t , ok )
assert . Equal ( t , "first" , values [ 0 ] )
assert . Equal ( t , "second" , values [ 1 ] )
values = c . PostFormArray ( "array" )
assert . Equal ( t , "first" , values [ 0 ] )
assert . Equal ( t , "second" , values [ 1 ] )
values = c . PostFormArray ( "nokey" )
assert . Equal ( t , 0 , len ( values ) )
values = c . PostFormArray ( "foo" )
assert . Equal ( t , 1 , len ( values ) )
assert . Equal ( t , "bar" , values [ 0 ] )
2018-08-06 07:07:11 +03:00
dicts , ok := c . GetPostFormMap ( "names" )
assert . True ( t , ok )
assert . Equal ( t , "thinkerou" , dicts [ "a" ] )
assert . Equal ( t , "tianou" , dicts [ "b" ] )
dicts , ok = c . GetPostFormMap ( "nokey" )
assert . False ( t , ok )
assert . Equal ( t , 0 , len ( dicts ) )
dicts = c . PostFormMap ( "names" )
assert . Equal ( t , "thinkerou" , dicts [ "a" ] )
assert . Equal ( t , "tianou" , dicts [ "b" ] )
dicts = c . PostFormMap ( "nokey" )
assert . Equal ( t , 0 , len ( dicts ) )
2015-05-05 16:06:38 +03:00
}
2015-08-27 11:04:50 +03:00
func TestContextSetCookie ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-08-27 11:04:50 +03:00
c . SetCookie ( "user" , "gin" , 1 , "/" , "localhost" , true , true )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure" , c . Writer . Header ( ) . Get ( "Set-Cookie" ) )
2015-08-27 11:04:50 +03:00
}
2017-05-24 12:39:05 +03:00
func TestContextSetCookiePathEmpty ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . SetCookie ( "user" , "gin" , 1 , "" , "localhost" , true , true )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "user=gin; Path=/; Domain=localhost; Max-Age=1; HttpOnly; Secure" , c . Writer . Header ( ) . Get ( "Set-Cookie" ) )
2017-05-24 12:39:05 +03:00
}
2015-08-27 11:04:50 +03:00
func TestContextGetCookie ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-08-27 11:04:50 +03:00
c . Request , _ = http . NewRequest ( "GET" , "/get" , nil )
c . Request . Header . Set ( "Cookie" , "user=gin" )
2016-01-28 02:35:09 +03:00
cookie , _ := c . Cookie ( "user" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "gin" , cookie )
2017-05-24 12:39:05 +03:00
_ , err := c . Cookie ( "nokey" )
assert . Error ( t , err )
2015-08-27 11:04:50 +03:00
}
2017-01-09 18:24:48 +03:00
func TestContextBodyAllowedForStatus ( t * testing . T ) {
2018-08-14 04:51:56 +03:00
// todo(thinkerou): go1.6 not support StatusProcessing
2017-11-21 16:18:45 +03:00
assert . False ( t , false , bodyAllowedForStatus ( 102 ) )
2018-08-14 04:51:56 +03:00
assert . False ( t , false , bodyAllowedForStatus ( http . StatusNoContent ) )
assert . False ( t , false , bodyAllowedForStatus ( http . StatusNotModified ) )
assert . True ( t , true , bodyAllowedForStatus ( http . StatusInternalServerError ) )
2017-01-09 18:24:48 +03:00
}
type TestPanicRender struct {
}
func ( * TestPanicRender ) Render ( http . ResponseWriter ) error {
return errors . New ( "TestPanicRender" )
}
func ( * TestPanicRender ) WriteContentType ( http . ResponseWriter ) { }
func TestContextRenderPanicIfErr ( t * testing . T ) {
defer func ( ) {
r := recover ( )
assert . Equal ( t , "TestPanicRender" , fmt . Sprint ( r ) )
} ( )
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Render ( http . StatusOK , & TestPanicRender { } )
assert . Fail ( t , "Panic not detected" )
}
2015-04-08 03:58:35 +03:00
// Tests that the response is serialized as JSON
// and Content-Type is set to application/json
2018-08-20 10:15:31 +03:00
// and special HTML characters are escaped
2015-04-08 03:58:35 +03:00
func TestContextRenderJSON ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-20 10:15:31 +03:00
c . JSON ( http . StatusCreated , H { "foo" : "bar" , "html" : "<b>" } )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2018-08-20 10:15:31 +03:00
assert . Equal ( t , "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}" , w . Body . String ( ) )
2016-12-11 05:14:20 +03:00
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2014-08-08 15:48:15 +04:00
}
2018-04-26 06:52:19 +03:00
// Tests that the response is serialized as JSONP
// and Content-Type is set to application/javascript
func TestContextRenderJSONP ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "GET" , "http://example.com/?callback=x" , nil )
2018-08-14 04:51:56 +03:00
c . JSONP ( http . StatusCreated , H { "foo" : "bar" } )
2018-04-26 06:52:19 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2018-04-26 06:52:19 +03:00
assert . Equal ( t , "x({\"foo\":\"bar\"})" , w . Body . String ( ) )
assert . Equal ( t , "application/javascript; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
2018-07-20 19:52:55 +03:00
// Tests that the response is serialized as JSONP
// and Content-Type is set to application/json
func TestContextRenderJSONPWithoutCallback ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "GET" , "http://example.com" , nil )
2018-08-14 04:51:56 +03:00
c . JSONP ( http . StatusCreated , H { "foo" : "bar" } )
2018-07-20 19:52:55 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2018-07-20 19:52:55 +03:00
assert . Equal ( t , "{\"foo\":\"bar\"}" , w . Body . String ( ) )
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
2017-01-09 18:24:48 +03:00
// Tests that no JSON is rendered if code is 204
func TestContextRenderNoContentJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . JSON ( http . StatusNoContent , H { "foo" : "bar" } )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
2017-01-09 18:24:48 +03:00
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
2015-06-13 05:29:10 +03:00
// Tests that the response is serialized as JSON
// we change the content-type before
func TestContextRenderAPIJSON ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-06-13 05:29:10 +03:00
c . Header ( "Content-Type" , "application/vnd.api+json" )
2018-08-14 04:51:56 +03:00
c . JSON ( http . StatusCreated , H { "foo" : "bar" } )
2015-06-13 05:29:10 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2016-12-11 05:14:20 +03:00
assert . Equal ( t , "{\"foo\":\"bar\"}" , w . Body . String ( ) )
assert . Equal ( t , "application/vnd.api+json" , w . HeaderMap . Get ( "Content-Type" ) )
2015-06-13 05:29:10 +03:00
}
2017-01-09 18:24:48 +03:00
// Tests that no Custom JSON is rendered if code is 204
func TestContextRenderNoContentAPIJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Header ( "Content-Type" , "application/vnd.api+json" )
2018-08-14 04:51:56 +03:00
c . JSON ( http . StatusNoContent , H { "foo" : "bar" } )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
2017-01-09 18:24:48 +03:00
assert . Equal ( t , w . HeaderMap . Get ( "Content-Type" ) , "application/vnd.api+json" )
}
2015-05-11 02:04:08 +03:00
// Tests that the response is serialized as JSON
// and Content-Type is set to application/json
func TestContextRenderIndentedJSON ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . IndentedJSON ( http . StatusCreated , H { "foo" : "bar" , "bar" : "foo" , "nested" : H { "foo" : "bar" } } )
2015-05-11 02:04:08 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-07-11 08:59:03 +03:00
assert . Equal ( t , "{\n \"bar\": \"foo\",\n \"foo\": \"bar\",\n \"nested\": {\n \"foo\": \"bar\"\n }\n}" , w . Body . String ( ) )
2017-07-08 12:03:14 +03:00
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2015-05-11 02:04:08 +03:00
}
2017-01-09 18:24:48 +03:00
// Tests that no Custom JSON is rendered if code is 204
func TestContextRenderNoContentIndentedJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . IndentedJSON ( http . StatusNoContent , H { "foo" : "bar" , "bar" : "foo" , "nested" : H { "foo" : "bar" } } )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
2017-07-08 12:03:14 +03:00
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-07-07 20:21:30 +03:00
}
// Tests that the response is serialized as Secure JSON
// and Content-Type is set to application/json
func TestContextRenderSecureJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , router := CreateTestContext ( w )
router . SecureJsonPrefix ( "&&&START&&&" )
2018-08-14 04:51:56 +03:00
c . SecureJSON ( http . StatusCreated , [ ] string { "foo" , "bar" } )
2017-07-07 20:21:30 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "&&&START&&&[\"foo\",\"bar\"]" , w . Body . String ( ) )
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-07-07 20:21:30 +03:00
}
// Tests that no Custom JSON is rendered if code is 204
func TestContextRenderNoContentSecureJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . SecureJSON ( http . StatusNoContent , [ ] string { "foo" , "bar" } )
2017-07-07 20:21:30 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2018-07-03 12:17:08 +03:00
func TestContextRenderNoContentAsciiJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . AsciiJSON ( http . StatusNoContent , [ ] string { "lang" , "Go语言" } )
assert . Equal ( t , http . StatusNoContent , w . Code )
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "application/json" , w . HeaderMap . Get ( "Content-Type" ) )
}
2015-04-08 03:58:35 +03:00
// Tests that the response executes the templates
2014-08-08 15:48:15 +04:00
// and responds with Content-Type set to text/html
2015-04-08 03:58:35 +03:00
func TestContextRenderHTML ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , router := CreateTestContext ( w )
2017-11-29 11:42:51 +03:00
2015-04-09 13:15:02 +03:00
templ := template . Must ( template . New ( "t" ) . Parse ( ` Hello {{ .name }} ` ) )
2015-04-08 03:58:35 +03:00
router . SetHTMLTemplate ( templ )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
c . HTML ( http . StatusCreated , "t" , H { "name" : "alexandernyquist" } )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "Hello alexandernyquist" , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2015-04-08 03:58:35 +03:00
}
2014-08-08 15:48:15 +04:00
2017-11-29 11:42:51 +03:00
func TestContextRenderHTML2 ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , router := CreateTestContext ( w )
// print debug warning log when Engine.trees > 0
router . addRoute ( "GET" , "/" , HandlersChain { func ( _ * Context ) { } } )
assert . Len ( t , router . trees , 1 )
var b bytes . Buffer
setup ( & b )
defer teardown ( )
templ := template . Must ( template . New ( "t" ) . Parse ( ` Hello {{ .name }} ` ) )
router . SetHTMLTemplate ( templ )
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" , b . String ( ) )
2018-08-14 04:51:56 +03:00
c . HTML ( http . StatusCreated , "t" , H { "name" : "alexandernyquist" } )
2017-11-29 11:42:51 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-29 11:42:51 +03:00
assert . Equal ( t , "Hello alexandernyquist" , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
2017-01-09 18:24:48 +03:00
// Tests that no HTML is rendered if code is 204
func TestContextRenderNoContentHTML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , router := CreateTestContext ( w )
templ := template . Must ( template . New ( "t" ) . Parse ( ` Hello {{ .name }} ` ) )
router . SetHTMLTemplate ( templ )
2018-08-14 04:51:56 +03:00
c . HTML ( http . StatusNoContent , "t" , H { "name" : "alexandernyquist" } )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2015-04-08 03:58:35 +03:00
// TestContextXML tests that the response is serialized as XML
// and Content-Type is set to application/xml
func TestContextRenderXML ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . XML ( http . StatusCreated , H { "foo" : "bar" } )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "<map><foo>bar</foo></map>" , w . Body . String ( ) )
assert . Equal ( t , "application/xml; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2014-08-08 15:48:15 +04:00
}
2017-01-09 18:24:48 +03:00
// Tests that no XML is rendered if code is 204
func TestContextRenderNoContentXML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . XML ( http . StatusNoContent , H { "foo" : "bar" } )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "application/xml; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2014-08-08 15:48:15 +04:00
// TestContextString tests that the response is returned
// with Content-Type set to text/plain
2015-04-08 03:58:35 +03:00
func TestContextRenderString ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . String ( http . StatusCreated , "test %s %d" , "string" , 2 )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "test string 2" , w . Body . String ( ) )
assert . Equal ( t , "text/plain; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2014-08-08 15:48:15 +04:00
}
2017-01-09 18:24:48 +03:00
// Tests that no String is rendered if code is 204
func TestContextRenderNoContentString ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . String ( http . StatusNoContent , "test %s %d" , "string" , 2 )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "text/plain; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2015-04-08 03:58:35 +03:00
// TestContextString tests that the response is returned
// with Content-Type set to text/html
func TestContextRenderHTMLString ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-05-18 16:45:24 +03:00
c . Header ( "Content-Type" , "text/html; charset=utf-8" )
2018-08-14 04:51:56 +03:00
c . String ( http . StatusCreated , "<html>%s %d</html>" , "string" , 3 )
2015-04-08 03:58:35 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "<html>string 3</html>" , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2014-08-08 17:31:01 +04:00
}
2017-01-09 18:24:48 +03:00
// Tests that no HTML String is rendered if code is 204
func TestContextRenderNoContentHTMLString ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Header ( "Content-Type" , "text/html; charset=utf-8" )
2018-08-14 04:51:56 +03:00
c . String ( http . StatusNoContent , "<html>%s %d</html>" , "string" , 3 )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2014-08-08 17:31:01 +04:00
// TestContextData tests that the response can be written from `bytesting`
// with specified MIME type
2015-04-08 03:58:35 +03:00
func TestContextRenderData ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . Data ( http . StatusCreated , "text/csv" , [ ] byte ( ` foo,bar ` ) )
2014-08-08 17:31:01 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo,bar" , w . Body . String ( ) )
assert . Equal ( t , "text/csv" , w . HeaderMap . Get ( "Content-Type" ) )
2014-08-08 17:31:01 +04:00
}
2017-01-09 18:24:48 +03:00
// Tests that no Custom Data is rendered if code is 204
func TestContextRenderNoContentData ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . Data ( http . StatusNoContent , "text/csv" , [ ] byte ( ` foo,bar ` ) )
2017-01-09 18:24:48 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNoContent , w . Code )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , w . Body . String ( ) )
assert . Equal ( t , "text/csv" , w . HeaderMap . Get ( "Content-Type" ) )
2017-01-09 18:24:48 +03:00
}
2015-05-19 03:29:32 +03:00
func TestContextRenderSSE ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-05-19 03:29:32 +03:00
c . SSEvent ( "float" , 1.5 )
c . Render ( - 1 , sse . Event {
Id : "123" ,
Data : "text" ,
} )
c . SSEvent ( "chat" , H {
"foo" : "bar" ,
"bar" : "foo" ,
} )
2015-09-25 13:04:55 +03:00
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 ) )
2015-05-19 03:29:32 +03:00
}
func TestContextRenderFile ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "GET" , "/" , nil )
c . File ( "./gin.go" )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusOK , w . Code )
2015-05-19 03:29:32 +03:00
assert . Contains ( t , w . Body . String ( ) , "func New() *Engine {" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "text/plain; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2015-05-19 03:29:32 +03:00
}
2016-04-15 00:47:49 +03:00
// TestContextRenderYAML tests that the response is serialized as YAML
// and Content-Type is set to application/x-yaml
func TestContextRenderYAML ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . YAML ( http . StatusCreated , H { "foo" : "bar" } )
2016-04-15 00:47:49 +03:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo: bar\n" , w . Body . String ( ) )
assert . Equal ( t , "application/x-yaml; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
2016-04-15 00:47:49 +03:00
}
2018-08-19 05:45:56 +03:00
// TestContextRenderProtoBuf tests that the response is serialized as ProtoBuf
// and Content-Type is set to application/x-protobuf
// and we just use the example protobuf to check if the response is correct
func TestContextRenderProtoBuf ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
reps := [ ] int64 { int64 ( 1 ) , int64 ( 2 ) }
label := "test"
data := & testdata . Test {
Label : & label ,
Reps : reps ,
}
c . ProtoBuf ( http . StatusCreated , data )
protoData , err := proto . Marshal ( data )
assert . NoError ( t , err )
assert . Equal ( t , http . StatusCreated , w . Code )
2018-09-12 16:21:26 +03:00
assert . Equal ( t , string ( protoData ) , w . Body . String ( ) )
2018-08-19 05:45:56 +03:00
assert . Equal ( t , "application/x-protobuf" , w . HeaderMap . Get ( "Content-Type" ) )
}
2015-05-18 16:45:24 +03:00
func TestContextHeaders ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-18 16:45:24 +03:00
c . Header ( "Content-Type" , "text/plain" )
c . Header ( "X-Custom" , "value" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "text/plain" , c . Writer . Header ( ) . Get ( "Content-Type" ) )
assert . Equal ( t , "value" , c . Writer . Header ( ) . Get ( "X-Custom" ) )
2015-05-18 16:45:24 +03:00
c . Header ( "Content-Type" , "text/html" )
c . Header ( "X-Custom" , "" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "text/html" , c . Writer . Header ( ) . Get ( "Content-Type" ) )
2015-05-18 16:45:24 +03:00
_ , exist := c . Writer . Header ( ) [ "X-Custom" ]
assert . False ( t , exist )
}
2015-04-08 03:58:35 +03:00
// TODO
func TestContextRenderRedirectWithRelativePath ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-04-08 03:58:35 +03:00
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , nil )
assert . Panics ( t , func ( ) { c . Redirect ( 299 , "/new_path" ) } )
assert . Panics ( t , func ( ) { c . Redirect ( 309 , "/new_path" ) } )
2018-08-14 04:51:56 +03:00
c . Redirect ( http . StatusMovedPermanently , "/path" )
2015-04-08 03:58:35 +03:00
c . Writer . WriteHeaderNow ( )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusMovedPermanently , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "/path" , w . Header ( ) . Get ( "Location" ) )
2014-08-08 17:31:01 +04:00
}
2015-04-08 03:58:35 +03:00
func TestContextRenderRedirectWithAbsolutePath ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-04-08 03:58:35 +03:00
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , nil )
2018-08-14 04:51:56 +03:00
c . Redirect ( http . StatusFound , "http://google.com" )
2015-04-08 03:58:35 +03:00
c . Writer . WriteHeaderNow ( )
2014-08-08 15:48:15 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusFound , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "http://google.com" , w . Header ( ) . Get ( "Location" ) )
2014-08-08 15:48:15 +04:00
}
2016-01-28 02:34:05 +03:00
func TestContextRenderRedirectWith201 ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2016-01-28 02:34:05 +03:00
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , nil )
2018-08-14 04:51:56 +03:00
c . Redirect ( http . StatusCreated , "/resource" )
2016-01-28 02:34:05 +03:00
c . Writer . WriteHeaderNow ( )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusCreated , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "/resource" , w . Header ( ) . Get ( "Location" ) )
2016-01-28 02:34:05 +03:00
}
func TestContextRenderRedirectAll ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2016-01-28 02:34:05 +03:00
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , nil )
2018-08-14 04:51:56 +03:00
assert . Panics ( t , func ( ) { c . Redirect ( http . StatusOK , "/resource" ) } )
assert . Panics ( t , func ( ) { c . Redirect ( http . StatusAccepted , "/resource" ) } )
2016-01-28 02:34:05 +03:00
assert . Panics ( t , func ( ) { c . Redirect ( 299 , "/resource" ) } )
assert . Panics ( t , func ( ) { c . Redirect ( 309 , "/resource" ) } )
2018-08-14 04:51:56 +03:00
assert . NotPanics ( t , func ( ) { c . Redirect ( http . StatusMultipleChoices , "/resource" ) } )
// todo(thinkerou): go1.6 not support StatusPermanentRedirect(308)
// when we upgrade go version we can use http.StatusPermanentRedirect
2016-01-28 02:34:05 +03:00
assert . NotPanics ( t , func ( ) { c . Redirect ( 308 , "/resource" ) } )
}
2017-05-29 09:28:38 +03:00
func TestContextNegotiationWithJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "" , nil )
2018-08-14 04:51:56 +03:00
c . Negotiate ( http . StatusOK , Negotiate {
2017-05-29 09:28:38 +03:00
Offered : [ ] string { MIMEJSON , MIMEXML } ,
Data : H { "foo" : "bar" } ,
} )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusOK , w . Code )
2017-05-29 09:28:38 +03:00
assert . Equal ( t , "{\"foo\":\"bar\"}" , w . Body . String ( ) )
assert . Equal ( t , "application/json; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
func TestContextNegotiationWithXML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "" , nil )
2018-08-14 04:51:56 +03:00
c . Negotiate ( http . StatusOK , Negotiate {
2017-05-29 09:28:38 +03:00
Offered : [ ] string { MIMEXML , MIMEJSON } ,
Data : H { "foo" : "bar" } ,
} )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusOK , w . Code )
2017-05-29 09:28:38 +03:00
assert . Equal ( t , "<map><foo>bar</foo></map>" , w . Body . String ( ) )
assert . Equal ( t , "application/xml; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
func TestContextNegotiationWithHTML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , router := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "" , nil )
templ := template . Must ( template . New ( "t" ) . Parse ( ` Hello {{ .name }} ` ) )
router . SetHTMLTemplate ( templ )
2018-08-14 04:51:56 +03:00
c . Negotiate ( http . StatusOK , Negotiate {
2017-05-29 09:28:38 +03:00
Offered : [ ] string { MIMEHTML } ,
Data : H { "name" : "gin" } ,
HTMLName : "t" ,
} )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusOK , w . Code )
2017-05-29 09:28:38 +03:00
assert . Equal ( t , "Hello gin" , w . Body . String ( ) )
assert . Equal ( t , "text/html; charset=utf-8" , w . HeaderMap . Get ( "Content-Type" ) )
}
func TestContextNegotiationNotSupport ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "" , nil )
2018-08-14 04:51:56 +03:00
c . Negotiate ( http . StatusOK , Negotiate {
2017-05-29 09:28:38 +03:00
Offered : [ ] string { MIMEPOSTForm } ,
} )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusNotAcceptable , w . Code )
2017-05-29 09:28:38 +03:00
assert . Equal ( t , c . index , abortIndex )
assert . True ( t , c . IsAborted ( ) )
}
2015-04-08 03:58:35 +03:00
func TestContextNegotiationFormat ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-04-08 03:58:35 +03:00
c . Request , _ = http . NewRequest ( "POST" , "" , nil )
2014-08-08 15:48:15 +04:00
2015-04-09 13:15:02 +03:00
assert . Panics ( t , func ( ) { c . NegotiateFormat ( ) } )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , MIMEJSON , c . NegotiateFormat ( MIMEJSON , MIMEXML ) )
assert . Equal ( t , MIMEHTML , c . NegotiateFormat ( MIMEHTML , MIMEJSON ) )
2014-08-08 15:48:15 +04:00
}
2015-04-08 03:58:35 +03:00
func TestContextNegotiationFormatWithAccept ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , nil )
2015-04-08 03:58:35 +03:00
c . Request . Header . Add ( "Accept" , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" )
2014-08-11 14:25:52 +04:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , MIMEXML , c . NegotiateFormat ( MIMEJSON , MIMEXML ) )
assert . Equal ( t , MIMEHTML , c . NegotiateFormat ( MIMEXML , MIMEHTML ) )
assert . Empty ( t , c . NegotiateFormat ( MIMEJSON ) )
2015-04-08 03:58:35 +03:00
}
2014-08-11 14:25:52 +04:00
2015-04-08 03:58:35 +03:00
func TestContextNegotiationFormatCustum ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , nil )
2015-04-08 03:58:35 +03:00
c . Request . Header . Add ( "Accept" , "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" )
2014-08-11 14:25:52 +04:00
2015-04-08 03:58:35 +03:00
c . Accepted = nil
c . SetAccepted ( MIMEJSON , MIMEXML )
2014-08-11 14:25:52 +04:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , MIMEJSON , c . NegotiateFormat ( MIMEJSON , MIMEXML ) )
assert . Equal ( t , MIMEXML , c . NegotiateFormat ( MIMEXML , MIMEHTML ) )
assert . Equal ( t , MIMEJSON , c . NegotiateFormat ( MIMEJSON ) )
2014-08-11 14:25:52 +04:00
}
2015-07-02 14:27:22 +03:00
func TestContextIsAborted ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-07-02 14:27:22 +03:00
assert . False ( t , c . IsAborted ( ) )
c . Abort ( )
assert . True ( t , c . IsAborted ( ) )
2015-07-02 17:37:35 +03:00
c . Next ( )
2015-07-02 19:45:09 +03:00
assert . True ( t , c . IsAborted ( ) )
2015-07-02 14:27:22 +03:00
2015-07-02 21:24:54 +03:00
c . index ++
2015-07-02 14:27:22 +03:00
assert . True ( t , c . IsAborted ( ) )
}
2015-04-08 03:58:35 +03:00
// TestContextData tests that the response can be written from `bytesting`
// with specified MIME type
func TestContextAbortWithStatus ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-04-08 03:58:35 +03:00
c . index = 4
2018-08-14 04:51:56 +03:00
c . AbortWithStatus ( http . StatusUnauthorized )
2015-04-08 03:58:35 +03:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , abortIndex , c . index )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusUnauthorized , c . Writer . Status ( ) )
assert . Equal ( t , http . StatusUnauthorized , w . Code )
2015-04-08 03:58:35 +03:00
assert . True ( t , c . IsAborted ( ) )
}
2014-08-11 14:25:52 +04:00
2017-02-14 04:11:01 +03:00
type testJSONAbortMsg struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
}
func TestContextAbortWithStatusJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . index = 4
in := new ( testJSONAbortMsg )
in . Bar = "barValue"
in . Foo = "fooValue"
2018-08-14 04:51:56 +03:00
c . AbortWithStatusJSON ( http . StatusUnsupportedMediaType , in )
2017-02-14 04:11:01 +03:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , abortIndex , c . index )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusUnsupportedMediaType , c . Writer . Status ( ) )
assert . Equal ( t , http . StatusUnsupportedMediaType , w . Code )
2017-02-14 04:11:01 +03:00
assert . True ( t , c . IsAborted ( ) )
contentType := w . Header ( ) . Get ( "Content-Type" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "application/json; charset=utf-8" , contentType )
2017-02-14 04:11:01 +03:00
buf := new ( bytes . Buffer )
buf . ReadFrom ( w . Body )
jsonStringBody := buf . String ( )
assert . Equal ( t , fmt . Sprint ( ` { "foo":"fooValue","bar":"barValue"} ` ) , jsonStringBody )
}
2015-04-08 03:58:35 +03:00
func TestContextError ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-22 17:39:15 +03:00
assert . Empty ( t , c . Errors )
2015-04-09 13:15:02 +03:00
2015-05-22 17:39:15 +03:00
c . Error ( errors . New ( "first error" ) )
2015-04-08 03:58:35 +03:00
assert . Len ( t , c . Errors , 1 )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "Error #01: first error\n" , c . Errors . String ( ) )
2014-08-11 14:25:52 +04:00
2015-05-22 17:39:15 +03:00
c . Error ( & Error {
Err : errors . New ( "second error" ) ,
Meta : "some data 2" ,
Type : ErrorTypePublic ,
} )
2015-04-08 03:58:35 +03:00
assert . Len ( t , c . Errors , 2 )
2014-08-11 14:25:52 +04:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , errors . New ( "first error" ) , c . Errors [ 0 ] . Err )
2015-05-22 17:39:15 +03:00
assert . Nil ( t , c . Errors [ 0 ] . Meta )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , ErrorTypePrivate , c . Errors [ 0 ] . Type )
2014-08-11 14:25:52 +04:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , errors . New ( "second error" ) , c . Errors [ 1 ] . Err )
assert . Equal ( t , "some data 2" , c . Errors [ 1 ] . Meta )
assert . Equal ( t , ErrorTypePublic , c . Errors [ 1 ] . Type )
2015-05-22 17:39:15 +03:00
assert . Equal ( t , c . Errors . Last ( ) , c . Errors [ 1 ] )
2017-05-09 03:04:22 +03:00
defer func ( ) {
if recover ( ) == nil {
t . Error ( "didn't panic" )
}
} ( )
c . Error ( nil )
2015-04-08 03:58:35 +03:00
}
2014-08-11 14:25:52 +04:00
2015-04-08 03:58:35 +03:00
func TestContextTypedError ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-22 17:39:15 +03:00
c . Error ( errors . New ( "externo 0" ) ) . SetType ( ErrorTypePublic )
c . Error ( errors . New ( "interno 0" ) ) . SetType ( ErrorTypePrivate )
2015-05-22 04:25:21 +03:00
for _ , err := range c . Errors . ByType ( ErrorTypePublic ) {
2017-11-21 16:18:45 +03:00
assert . Equal ( t , ErrorTypePublic , err . Type )
2014-08-11 14:25:52 +04:00
}
2015-05-22 04:25:21 +03:00
for _ , err := range c . Errors . ByType ( ErrorTypePrivate ) {
2017-11-21 16:18:45 +03:00
assert . Equal ( t , ErrorTypePrivate , err . Type )
2014-08-11 14:25:52 +04:00
}
2017-11-21 16:18:45 +03:00
assert . Equal ( t , [ ] string { "externo 0" , "interno 0" } , c . Errors . Errors ( ) )
2014-08-11 14:25:52 +04:00
}
2015-05-22 17:39:15 +03:00
func TestContextAbortWithError ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2018-08-14 04:51:56 +03:00
c . AbortWithError ( http . StatusUnauthorized , errors . New ( "bad input" ) ) . SetMeta ( "some input" )
2014-08-11 14:25:52 +04:00
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusUnauthorized , w . Code )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , abortIndex , c . index )
2015-04-08 03:58:35 +03:00
assert . True ( t , c . IsAborted ( ) )
}
2014-08-11 14:25:52 +04:00
2015-04-08 03:58:35 +03:00
func TestContextClientIP ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , nil )
2014-08-11 14:25:52 +04:00
2015-05-24 16:35:08 +03:00
c . Request . Header . Set ( "X-Real-IP" , " 10.10.10.10 " )
2015-06-04 14:15:22 +03:00
c . Request . Header . Set ( "X-Forwarded-For" , " 20.20.20.20, 30.30.30.30" )
2016-12-05 13:21:59 +03:00
c . Request . Header . Set ( "X-Appengine-Remote-Addr" , "50.50.50.50" )
2015-07-01 21:48:21 +03:00
c . Request . RemoteAddr = " 40.40.40.40:42123 "
2014-08-11 14:25:52 +04:00
2017-01-03 18:42:21 +03:00
assert . Equal ( t , "20.20.20.20" , c . ClientIP ( ) )
2015-05-24 16:35:08 +03:00
2017-01-03 18:42:21 +03:00
c . Request . Header . Del ( "X-Forwarded-For" )
assert . Equal ( t , "10.10.10.10" , c . ClientIP ( ) )
2015-05-24 16:35:08 +03:00
2015-06-04 14:15:22 +03:00
c . Request . Header . Set ( "X-Forwarded-For" , "30.30.30.30 " )
2017-01-03 18:42:21 +03:00
assert . Equal ( t , "30.30.30.30" , c . ClientIP ( ) )
2015-05-24 16:35:08 +03:00
2015-04-08 03:58:35 +03:00
c . Request . Header . Del ( "X-Forwarded-For" )
2017-01-03 18:42:21 +03:00
c . Request . Header . Del ( "X-Real-IP" )
2016-12-05 13:21:59 +03:00
c . engine . AppEngine = true
2017-01-03 18:42:21 +03:00
assert . Equal ( t , "50.50.50.50" , c . ClientIP ( ) )
2016-12-05 13:21:59 +03:00
c . Request . Header . Del ( "X-Appengine-Remote-Addr" )
2017-01-03 18:42:21 +03:00
assert . Equal ( t , "40.40.40.40" , c . ClientIP ( ) )
2016-12-05 13:21:59 +03:00
// no port
c . Request . RemoteAddr = "50.50.50.50"
2017-11-21 16:18:45 +03:00
assert . Empty ( t , c . ClientIP ( ) )
2015-02-10 02:13:05 +03:00
}
2015-04-08 03:58:35 +03:00
func TestContextContentType ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , nil )
2015-04-08 03:58:35 +03:00
c . Request . Header . Set ( "Content-Type" , "application/json; charset=utf-8" )
2015-02-10 02:13:05 +03:00
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "application/json" , c . ContentType ( ) )
2015-04-08 03:58:35 +03:00
}
2015-02-10 02:13:05 +03:00
2015-05-26 18:22:39 +03:00
func TestContextAutoBindJSON ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( "{\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
2015-04-08 03:58:35 +03:00
c . Request . Header . Add ( "Content-Type" , MIMEJSON )
2015-05-26 18:22:39 +03:00
2015-04-08 03:58:35 +03:00
var obj struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
}
2015-05-22 04:25:21 +03:00
assert . NoError ( t , c . Bind ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
2015-05-26 18:22:39 +03:00
assert . Empty ( t , c . Errors )
2015-04-08 03:58:35 +03:00
}
2015-02-10 02:13:05 +03:00
2015-05-26 18:22:39 +03:00
func TestContextBindWithJSON ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-05-26 18:22:39 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( "{\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
c . Request . Header . Add ( "Content-Type" , MIMEXML ) // set fake content-type
2015-05-26 15:21:35 +03:00
var obj struct {
2015-05-26 18:22:39 +03:00
Foo string ` json:"foo" `
Bar string ` json:"bar" `
2015-05-26 15:21:35 +03:00
}
2015-05-26 18:22:39 +03:00
assert . NoError ( t , c . BindJSON ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
assert . Equal ( t , 0 , w . Body . Len ( ) )
2015-05-26 15:21:35 +03:00
}
2018-08-17 04:12:15 +03:00
func TestContextBindWithXML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( ` < ? xml version = "1.0" encoding = "UTF-8" ? >
< root >
< foo > FOO < / foo >
< bar > BAR < / bar >
< / root > ` ) )
c . Request . Header . Add ( "Content-Type" , MIMEXML ) // set fake content-type
var obj struct {
Foo string ` xml:"foo" `
Bar string ` xml:"bar" `
}
assert . NoError ( t , c . BindXML ( & obj ) )
assert . Equal ( t , "FOO" , obj . Foo )
assert . Equal ( t , "BAR" , obj . Bar )
assert . Equal ( t , 0 , w . Body . Len ( ) )
}
2015-05-26 15:21:35 +03:00
2017-07-19 10:50:05 +03:00
func TestContextBindWithQuery ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "/?foo=bar&bar=foo" , bytes . NewBufferString ( "foo=unused" ) )
var obj struct {
Foo string ` form:"foo" `
Bar string ` form:"bar" `
}
assert . NoError ( t , c . BindQuery ( & obj ) )
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
assert . Equal ( t , 0 , w . Body . Len ( ) )
}
2015-04-08 03:58:35 +03:00
func TestContextBadAutoBind ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
2015-04-08 03:58:35 +03:00
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , bytes . NewBufferString ( "\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
c . Request . Header . Add ( "Content-Type" , MIMEJSON )
var obj struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
2015-02-10 02:13:05 +03:00
}
2015-04-08 03:58:35 +03:00
assert . False ( t , c . IsAborted ( ) )
2015-05-22 04:25:21 +03:00
assert . Error ( t , c . Bind ( & obj ) )
2015-04-08 03:58:35 +03:00
c . Writer . WriteHeaderNow ( )
2015-02-10 02:13:05 +03:00
2015-04-08 03:58:35 +03:00
assert . Empty ( t , obj . Bar )
assert . Empty ( t , obj . Foo )
2018-08-14 04:51:56 +03:00
assert . Equal ( t , http . StatusBadRequest , w . Code )
2015-04-08 03:58:35 +03:00
assert . True ( t , c . IsAborted ( ) )
2014-08-11 14:25:52 +04:00
}
2014-12-21 15:42:48 +03:00
2017-10-23 12:14:09 +03:00
func TestContextAutoShouldBindJSON ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( "{\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
c . Request . Header . Add ( "Content-Type" , MIMEJSON )
var obj struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
}
assert . NoError ( t , c . ShouldBind ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
2017-10-23 12:14:09 +03:00
assert . Empty ( t , c . Errors )
}
func TestContextShouldBindWithJSON ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( "{\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
c . Request . Header . Add ( "Content-Type" , MIMEXML ) // set fake content-type
var obj struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
}
assert . NoError ( t , c . ShouldBindJSON ( & obj ) )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
assert . Equal ( t , 0 , w . Body . Len ( ) )
2017-10-23 12:14:09 +03:00
}
2018-08-17 04:12:15 +03:00
func TestContextShouldBindWithXML ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( ` < ? xml version = "1.0" encoding = "UTF-8" ? >
< root >
< foo > FOO < / foo >
< bar > BAR < / bar >
< / root > ` ) )
c . Request . Header . Add ( "Content-Type" , MIMEXML ) // set fake content-type
var obj struct {
Foo string ` xml:"foo" `
Bar string ` xml:"bar" `
}
assert . NoError ( t , c . ShouldBindXML ( & obj ) )
assert . Equal ( t , "FOO" , obj . Foo )
assert . Equal ( t , "BAR" , obj . Bar )
assert . Equal ( t , 0 , w . Body . Len ( ) )
}
2017-10-23 12:14:09 +03:00
func TestContextShouldBindWithQuery ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "/?foo=bar&bar=foo" , bytes . NewBufferString ( "foo=unused" ) )
var obj struct {
Foo string ` form:"foo" `
Bar string ` form:"bar" `
}
assert . NoError ( t , c . ShouldBindQuery ( & obj ) )
assert . Equal ( t , "foo" , obj . Bar )
assert . Equal ( t , "bar" , obj . Foo )
assert . Equal ( t , 0 , w . Body . Len ( ) )
}
func TestContextBadAutoShouldBind ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest ( "POST" , "http://example.com" , bytes . NewBufferString ( "\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
c . Request . Header . Add ( "Content-Type" , MIMEJSON )
var obj struct {
Foo string ` json:"foo" `
Bar string ` json:"bar" `
}
assert . False ( t , c . IsAborted ( ) )
assert . Error ( t , c . ShouldBind ( & obj ) )
assert . Empty ( t , obj . Bar )
assert . Empty ( t , obj . Foo )
assert . False ( t , c . IsAborted ( ) )
}
2018-05-11 05:33:33 +03:00
func TestContextShouldBindBodyWith ( t * testing . T ) {
type typeA struct {
Foo string ` json:"foo" xml:"foo" binding:"required" `
}
type typeB struct {
Bar string ` json:"bar" xml:"bar" binding:"required" `
}
for _ , tt := range [ ] struct {
name string
bindingA , bindingB binding . BindingBody
bodyA , bodyB string
} {
{
name : "JSON & JSON" ,
bindingA : binding . JSON ,
bindingB : binding . JSON ,
bodyA : ` { "foo":"FOO"} ` ,
bodyB : ` { "bar":"BAR"} ` ,
} ,
{
name : "JSON & XML" ,
bindingA : binding . JSON ,
bindingB : binding . XML ,
bodyA : ` { "foo":"FOO"} ` ,
bodyB : ` < ? xml version = "1.0" encoding = "UTF-8" ? >
< root >
< bar > BAR < / bar >
< / root > ` ,
} ,
{
name : "XML & XML" ,
bindingA : binding . XML ,
bindingB : binding . XML ,
bodyA : ` < ? xml version = "1.0" encoding = "UTF-8" ? >
< root >
< foo > FOO < / foo >
< / root > ` ,
bodyB : ` < ? xml version = "1.0" encoding = "UTF-8" ? >
< root >
< bar > BAR < / bar >
< / root > ` ,
} ,
} {
t . Logf ( "testing: %s" , tt . name )
// bodyA to typeA and typeB
{
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest (
"POST" , "http://example.com" , bytes . NewBufferString ( tt . bodyA ) ,
)
// When it binds to typeA and typeB, it finds the body is
// not typeB but typeA.
objA := typeA { }
assert . NoError ( t , c . ShouldBindBodyWith ( & objA , tt . bindingA ) )
assert . Equal ( t , typeA { "FOO" } , objA )
objB := typeB { }
assert . Error ( t , c . ShouldBindBodyWith ( & objB , tt . bindingB ) )
assert . NotEqual ( t , typeB { "BAR" } , objB )
}
// bodyB to typeA and typeB
{
// When it binds to typeA and typeB, it finds the body is
// not typeA but typeB.
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
c . Request , _ = http . NewRequest (
"POST" , "http://example.com" , bytes . NewBufferString ( tt . bodyB ) ,
)
objA := typeA { }
assert . Error ( t , c . ShouldBindBodyWith ( & objA , tt . bindingA ) )
assert . NotEqual ( t , typeA { "FOO" } , objA )
objB := typeB { }
assert . NoError ( t , c . ShouldBindBodyWith ( & objB , tt . bindingB ) )
assert . Equal ( t , typeB { "BAR" } , objB )
}
}
}
2015-05-19 03:29:32 +03:00
func TestContextGolangContext ( t * testing . T ) {
2016-09-21 05:16:51 +03:00
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
2015-05-19 03:29:32 +03:00
c . Request , _ = http . NewRequest ( "POST" , "/" , bytes . NewBufferString ( "{\"foo\":\"bar\", \"bar\":\"foo\"}" ) )
assert . NoError ( t , c . Err ( ) )
assert . Nil ( t , c . Done ( ) )
ti , ok := c . Deadline ( )
assert . Equal ( t , ti , time . Time { } )
assert . False ( t , ok )
assert . Equal ( t , c . Value ( 0 ) , c . Request )
assert . Nil ( t , c . Value ( "foo" ) )
c . Set ( "foo" , "bar" )
2017-11-21 16:18:45 +03:00
assert . Equal ( t , "bar" , c . Value ( "foo" ) )
2015-05-19 03:29:32 +03:00
assert . Nil ( t , c . Value ( 1 ) )
}
2017-01-02 11:05:30 +03:00
func TestWebsocketsRequired ( t * testing . T ) {
// Example request from spec: https://tools.ietf.org/html/rfc6455#section-1.2
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "GET" , "/chat" , nil )
c . Request . Header . Set ( "Host" , "server.example.com" )
c . Request . Header . Set ( "Upgrade" , "websocket" )
c . Request . Header . Set ( "Connection" , "Upgrade" )
c . Request . Header . Set ( "Sec-WebSocket-Key" , "dGhlIHNhbXBsZSBub25jZQ==" )
c . Request . Header . Set ( "Origin" , "http://example.com" )
c . Request . Header . Set ( "Sec-WebSocket-Protocol" , "chat, superchat" )
c . Request . Header . Set ( "Sec-WebSocket-Version" , "13" )
assert . True ( t , c . IsWebsocket ( ) )
// Normal request, no websocket required.
c , _ = CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "GET" , "/chat" , nil )
c . Request . Header . Set ( "Host" , "server.example.com" )
assert . False ( t , c . IsWebsocket ( ) )
}
2017-03-24 15:43:23 +03:00
func TestGetRequestHeaderValue ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
c . Request , _ = http . NewRequest ( "GET" , "/chat" , nil )
c . Request . Header . Set ( "Gin-Version" , "1.0.0" )
assert . Equal ( t , "1.0.0" , c . GetHeader ( "Gin-Version" ) )
2017-11-21 16:18:45 +03:00
assert . Empty ( t , c . GetHeader ( "Connection" ) )
2017-03-24 15:43:23 +03:00
}
2017-03-31 03:45:56 +03:00
func TestContextGetRawData ( t * testing . T ) {
c , _ := CreateTestContext ( httptest . NewRecorder ( ) )
body := bytes . NewBufferString ( "Fetch binary post data" )
c . Request , _ = http . NewRequest ( "POST" , "/" , body )
c . Request . Header . Add ( "Content-Type" , MIMEPOSTForm )
data , err := c . GetRawData ( )
assert . Nil ( t , err )
assert . Equal ( t , "Fetch binary post data" , string ( data ) )
}
2018-05-12 06:00:42 +03:00
func TestContextRenderDataFromReader ( t * testing . T ) {
w := httptest . NewRecorder ( )
c , _ := CreateTestContext ( w )
body := "#!PNG some raw data"
reader := strings . NewReader ( body )
contentLength := int64 ( len ( body ) )
contentType := "image/png"
extraHeaders := map [ string ] string { "Content-Disposition" : ` attachment; filename="gopher.png" ` }
c . DataFromReader ( http . StatusOK , contentLength , contentType , reader , extraHeaders )
assert . Equal ( t , http . StatusOK , w . Code )
assert . Equal ( t , body , w . Body . String ( ) )
assert . Equal ( t , contentType , w . HeaderMap . Get ( "Content-Type" ) )
assert . Equal ( t , fmt . Sprintf ( "%d" , contentLength ) , w . HeaderMap . Get ( "Content-Length" ) )
assert . Equal ( t , extraHeaders [ "Content-Disposition" ] , w . HeaderMap . Get ( "Content-Disposition" ) )
}
2018-08-07 01:44:32 +03:00
2018-08-12 05:12:33 +03:00
type TestResponseRecorder struct {
* httptest . ResponseRecorder
closeChannel chan bool
}
func ( r * TestResponseRecorder ) CloseNotify ( ) <- chan bool {
return r . closeChannel
}
func ( r * TestResponseRecorder ) closeClient ( ) {
r . closeChannel <- true
}
func CreateTestResponseRecorder ( ) * TestResponseRecorder {
return & TestResponseRecorder {
httptest . NewRecorder ( ) ,
make ( chan bool , 1 ) ,
}
}
2018-08-07 01:44:32 +03:00
func TestContextStream ( t * testing . T ) {
w := CreateTestResponseRecorder ( )
c , _ := CreateTestContext ( w )
stopStream := true
c . Stream ( func ( w io . Writer ) bool {
defer func ( ) {
stopStream = false
} ( )
w . Write ( [ ] byte ( "test" ) )
return stopStream
} )
assert . Equal ( t , "testtest" , w . Body . String ( ) )
}
func TestContextStreamWithClientGone ( t * testing . T ) {
w := CreateTestResponseRecorder ( )
c , _ := CreateTestContext ( w )
c . Stream ( func ( writer io . Writer ) bool {
defer func ( ) {
w . closeClient ( )
} ( )
writer . Write ( [ ] byte ( "test" ) )
return true
} )
assert . Equal ( t , "test" , w . Body . String ( ) )
}