github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/gin/render/render_test.go (about)

     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 render
     6  
     7  import (
     8  	"encoding/xml"
     9  	"errors"
    10  	"github.com/hellobchain/newcryptosm/http"
    11  	"github.com/hellobchain/newcryptosm/http/httptest"
    12  	"html/template"
    13  	"strconv"
    14  	"strings"
    15  	"testing"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/stretchr/testify/assert"
    19  
    20  	testdata "github.com/hellobchain/third_party/gin/testdata/protoexample"
    21  )
    22  
    23  // TODO unit tests
    24  // test errors
    25  
    26  func TestRenderJSON(t *testing.T) {
    27  	w := httptest.NewRecorder()
    28  	data := map[string]interface{}{
    29  		"foo":  "bar",
    30  		"html": "<b>",
    31  	}
    32  
    33  	(JSON{data}).WriteContentType(w)
    34  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
    35  
    36  	err := (JSON{data}).Render(w)
    37  
    38  	assert.NoError(t, err)
    39  	assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"\\u003cb\\u003e\"}", w.Body.String())
    40  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
    41  }
    42  
    43  func TestRenderJSONPanics(t *testing.T) {
    44  	w := httptest.NewRecorder()
    45  	data := make(chan int)
    46  
    47  	// json: unsupported type: chan int
    48  	assert.Panics(t, func() { assert.NoError(t, (JSON{data}).Render(w)) })
    49  }
    50  
    51  func TestRenderIndentedJSON(t *testing.T) {
    52  	w := httptest.NewRecorder()
    53  	data := map[string]interface{}{
    54  		"foo": "bar",
    55  		"bar": "foo",
    56  	}
    57  
    58  	err := (IndentedJSON{data}).Render(w)
    59  
    60  	assert.NoError(t, err)
    61  	assert.Equal(t, "{\n    \"bar\": \"foo\",\n    \"foo\": \"bar\"\n}", w.Body.String())
    62  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
    63  }
    64  
    65  func TestRenderIndentedJSONPanics(t *testing.T) {
    66  	w := httptest.NewRecorder()
    67  	data := make(chan int)
    68  
    69  	// json: unsupported type: chan int
    70  	err := (IndentedJSON{data}).Render(w)
    71  	assert.Error(t, err)
    72  }
    73  
    74  func TestRenderSecureJSON(t *testing.T) {
    75  	w1 := httptest.NewRecorder()
    76  	data := map[string]interface{}{
    77  		"foo": "bar",
    78  	}
    79  
    80  	(SecureJSON{"while(1);", data}).WriteContentType(w1)
    81  	assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
    82  
    83  	err1 := (SecureJSON{"while(1);", data}).Render(w1)
    84  
    85  	assert.NoError(t, err1)
    86  	assert.Equal(t, "{\"foo\":\"bar\"}", w1.Body.String())
    87  	assert.Equal(t, "application/json; charset=utf-8", w1.Header().Get("Content-Type"))
    88  
    89  	w2 := httptest.NewRecorder()
    90  	datas := []map[string]interface{}{{
    91  		"foo": "bar",
    92  	}, {
    93  		"bar": "foo",
    94  	}}
    95  
    96  	err2 := (SecureJSON{"while(1);", datas}).Render(w2)
    97  	assert.NoError(t, err2)
    98  	assert.Equal(t, "while(1);[{\"foo\":\"bar\"},{\"bar\":\"foo\"}]", w2.Body.String())
    99  	assert.Equal(t, "application/json; charset=utf-8", w2.Header().Get("Content-Type"))
   100  }
   101  
   102  func TestRenderSecureJSONFail(t *testing.T) {
   103  	w := httptest.NewRecorder()
   104  	data := make(chan int)
   105  
   106  	// json: unsupported type: chan int
   107  	err := (SecureJSON{"while(1);", data}).Render(w)
   108  	assert.Error(t, err)
   109  }
   110  
   111  func TestRenderJsonpJSON(t *testing.T) {
   112  	w1 := httptest.NewRecorder()
   113  	data := map[string]interface{}{
   114  		"foo": "bar",
   115  	}
   116  
   117  	(JsonpJSON{"x", data}).WriteContentType(w1)
   118  	assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
   119  
   120  	err1 := (JsonpJSON{"x", data}).Render(w1)
   121  
   122  	assert.NoError(t, err1)
   123  	assert.Equal(t, "x({\"foo\":\"bar\"});", w1.Body.String())
   124  	assert.Equal(t, "application/javascript; charset=utf-8", w1.Header().Get("Content-Type"))
   125  
   126  	w2 := httptest.NewRecorder()
   127  	datas := []map[string]interface{}{{
   128  		"foo": "bar",
   129  	}, {
   130  		"bar": "foo",
   131  	}}
   132  
   133  	err2 := (JsonpJSON{"x", datas}).Render(w2)
   134  	assert.NoError(t, err2)
   135  	assert.Equal(t, "x([{\"foo\":\"bar\"},{\"bar\":\"foo\"}]);", w2.Body.String())
   136  	assert.Equal(t, "application/javascript; charset=utf-8", w2.Header().Get("Content-Type"))
   137  }
   138  
   139  func TestRenderJsonpJSONError2(t *testing.T) {
   140  	w := httptest.NewRecorder()
   141  	data := map[string]interface{}{
   142  		"foo": "bar",
   143  	}
   144  	(JsonpJSON{"", data}).WriteContentType(w)
   145  	assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
   146  
   147  	e := (JsonpJSON{"", data}).Render(w)
   148  	assert.NoError(t, e)
   149  
   150  	assert.Equal(t, "{\"foo\":\"bar\"}", w.Body.String())
   151  	assert.Equal(t, "application/javascript; charset=utf-8", w.Header().Get("Content-Type"))
   152  }
   153  
   154  func TestRenderJsonpJSONFail(t *testing.T) {
   155  	w := httptest.NewRecorder()
   156  	data := make(chan int)
   157  
   158  	// json: unsupported type: chan int
   159  	err := (JsonpJSON{"x", data}).Render(w)
   160  	assert.Error(t, err)
   161  }
   162  
   163  func TestRenderAsciiJSON(t *testing.T) {
   164  	w1 := httptest.NewRecorder()
   165  	data1 := map[string]interface{}{
   166  		"lang": "GO语言",
   167  		"tag":  "<br>",
   168  	}
   169  
   170  	err := (AsciiJSON{data1}).Render(w1)
   171  
   172  	assert.NoError(t, err)
   173  	assert.Equal(t, "{\"lang\":\"GO\\u8bed\\u8a00\",\"tag\":\"\\u003cbr\\u003e\"}", w1.Body.String())
   174  	assert.Equal(t, "application/json", w1.Header().Get("Content-Type"))
   175  
   176  	w2 := httptest.NewRecorder()
   177  	data2 := float64(3.1415926)
   178  
   179  	err = (AsciiJSON{data2}).Render(w2)
   180  	assert.NoError(t, err)
   181  	assert.Equal(t, "3.1415926", w2.Body.String())
   182  }
   183  
   184  func TestRenderAsciiJSONFail(t *testing.T) {
   185  	w := httptest.NewRecorder()
   186  	data := make(chan int)
   187  
   188  	// json: unsupported type: chan int
   189  	assert.Error(t, (AsciiJSON{data}).Render(w))
   190  }
   191  
   192  func TestRenderPureJSON(t *testing.T) {
   193  	w := httptest.NewRecorder()
   194  	data := map[string]interface{}{
   195  		"foo":  "bar",
   196  		"html": "<b>",
   197  	}
   198  	err := (PureJSON{data}).Render(w)
   199  	assert.NoError(t, err)
   200  	assert.Equal(t, "{\"foo\":\"bar\",\"html\":\"<b>\"}\n", w.Body.String())
   201  	assert.Equal(t, "application/json; charset=utf-8", w.Header().Get("Content-Type"))
   202  }
   203  
   204  type xmlmap map[string]interface{}
   205  
   206  // Allows type H to be used with xml.Marshal
   207  func (h xmlmap) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
   208  	start.Name = xml.Name{
   209  		Space: "",
   210  		Local: "map",
   211  	}
   212  	if err := e.EncodeToken(start); err != nil {
   213  		return err
   214  	}
   215  	for key, value := range h {
   216  		elem := xml.StartElement{
   217  			Name: xml.Name{Space: "", Local: key},
   218  			Attr: []xml.Attr{},
   219  		}
   220  		if err := e.EncodeElement(value, elem); err != nil {
   221  			return err
   222  		}
   223  	}
   224  
   225  	return e.EncodeToken(xml.EndElement{Name: start.Name})
   226  }
   227  
   228  func TestRenderYAML(t *testing.T) {
   229  	w := httptest.NewRecorder()
   230  	data := `
   231  a : Easy!
   232  b:
   233  	c: 2
   234  	d: [3, 4]
   235  	`
   236  	(YAML{data}).WriteContentType(w)
   237  	assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
   238  
   239  	err := (YAML{data}).Render(w)
   240  	assert.NoError(t, err)
   241  	assert.Equal(t, "\"\\na : Easy!\\nb:\\n\\tc: 2\\n\\td: [3, 4]\\n\\t\"\n", w.Body.String())
   242  	assert.Equal(t, "application/x-yaml; charset=utf-8", w.Header().Get("Content-Type"))
   243  }
   244  
   245  type fail struct{}
   246  
   247  // Hook MarshalYAML
   248  func (ft *fail) MarshalYAML() (interface{}, error) {
   249  	return nil, errors.New("fail")
   250  }
   251  
   252  func TestRenderYAMLFail(t *testing.T) {
   253  	w := httptest.NewRecorder()
   254  	err := (YAML{&fail{}}).Render(w)
   255  	assert.Error(t, err)
   256  }
   257  
   258  // test Protobuf rendering
   259  func TestRenderProtoBuf(t *testing.T) {
   260  	w := httptest.NewRecorder()
   261  	reps := []int64{int64(1), int64(2)}
   262  	label := "test"
   263  	data := &testdata.Test{
   264  		Label: &label,
   265  		Reps:  reps,
   266  	}
   267  
   268  	(ProtoBuf{data}).WriteContentType(w)
   269  	protoData, err := proto.Marshal(data)
   270  	assert.NoError(t, err)
   271  	assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
   272  
   273  	err = (ProtoBuf{data}).Render(w)
   274  
   275  	assert.NoError(t, err)
   276  	assert.Equal(t, string(protoData), w.Body.String())
   277  	assert.Equal(t, "application/x-protobuf", w.Header().Get("Content-Type"))
   278  }
   279  
   280  func TestRenderProtoBufFail(t *testing.T) {
   281  	w := httptest.NewRecorder()
   282  	data := &testdata.Test{}
   283  	err := (ProtoBuf{data}).Render(w)
   284  	assert.Error(t, err)
   285  }
   286  
   287  func TestRenderXML(t *testing.T) {
   288  	w := httptest.NewRecorder()
   289  	data := xmlmap{
   290  		"foo": "bar",
   291  	}
   292  
   293  	(XML{data}).WriteContentType(w)
   294  	assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
   295  
   296  	err := (XML{data}).Render(w)
   297  
   298  	assert.NoError(t, err)
   299  	assert.Equal(t, "<map><foo>bar</foo></map>", w.Body.String())
   300  	assert.Equal(t, "application/xml; charset=utf-8", w.Header().Get("Content-Type"))
   301  }
   302  
   303  func TestRenderRedirect(t *testing.T) {
   304  	req, err := http.NewRequest("GET", "/test-redirect", nil)
   305  	assert.NoError(t, err)
   306  
   307  	data1 := Redirect{
   308  		Code:     http.StatusMovedPermanently,
   309  		Request:  req,
   310  		Location: "/new/location",
   311  	}
   312  
   313  	w := httptest.NewRecorder()
   314  	err = data1.Render(w)
   315  	assert.NoError(t, err)
   316  
   317  	data2 := Redirect{
   318  		Code:     http.StatusOK,
   319  		Request:  req,
   320  		Location: "/new/location",
   321  	}
   322  
   323  	w = httptest.NewRecorder()
   324  	assert.PanicsWithValue(t, "Cannot redirect with status code 200", func() {
   325  		err := data2.Render(w)
   326  		assert.NoError(t, err)
   327  	})
   328  
   329  	data3 := Redirect{
   330  		Code:     http.StatusCreated,
   331  		Request:  req,
   332  		Location: "/new/location",
   333  	}
   334  
   335  	w = httptest.NewRecorder()
   336  	err = data3.Render(w)
   337  	assert.NoError(t, err)
   338  
   339  	// only improve coverage
   340  	data2.WriteContentType(w)
   341  }
   342  
   343  func TestRenderData(t *testing.T) {
   344  	w := httptest.NewRecorder()
   345  	data := []byte("#!PNG some raw data")
   346  
   347  	err := (Data{
   348  		ContentType: "image/png",
   349  		Data:        data,
   350  	}).Render(w)
   351  
   352  	assert.NoError(t, err)
   353  	assert.Equal(t, "#!PNG some raw data", w.Body.String())
   354  	assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
   355  }
   356  
   357  func TestRenderString(t *testing.T) {
   358  	w := httptest.NewRecorder()
   359  
   360  	(String{
   361  		Format: "hello %s %d",
   362  		Data:   []interface{}{},
   363  	}).WriteContentType(w)
   364  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
   365  
   366  	err := (String{
   367  		Format: "hola %s %d",
   368  		Data:   []interface{}{"manu", 2},
   369  	}).Render(w)
   370  
   371  	assert.NoError(t, err)
   372  	assert.Equal(t, "hola manu 2", w.Body.String())
   373  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
   374  }
   375  
   376  func TestRenderStringLenZero(t *testing.T) {
   377  	w := httptest.NewRecorder()
   378  
   379  	err := (String{
   380  		Format: "hola %s %d",
   381  		Data:   []interface{}{},
   382  	}).Render(w)
   383  
   384  	assert.NoError(t, err)
   385  	assert.Equal(t, "hola %s %d", w.Body.String())
   386  	assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
   387  }
   388  
   389  func TestRenderHTMLTemplate(t *testing.T) {
   390  	w := httptest.NewRecorder()
   391  	templ := template.Must(template.New("t").Parse(`Hello {{.name}}`))
   392  
   393  	htmlRender := HTMLProduction{Template: templ}
   394  	instance := htmlRender.Instance("t", map[string]interface{}{
   395  		"name": "alexandernyquist",
   396  	})
   397  
   398  	err := instance.Render(w)
   399  
   400  	assert.NoError(t, err)
   401  	assert.Equal(t, "Hello alexandernyquist", w.Body.String())
   402  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   403  }
   404  
   405  func TestRenderHTMLTemplateEmptyName(t *testing.T) {
   406  	w := httptest.NewRecorder()
   407  	templ := template.Must(template.New("").Parse(`Hello {{.name}}`))
   408  
   409  	htmlRender := HTMLProduction{Template: templ}
   410  	instance := htmlRender.Instance("", map[string]interface{}{
   411  		"name": "alexandernyquist",
   412  	})
   413  
   414  	err := instance.Render(w)
   415  
   416  	assert.NoError(t, err)
   417  	assert.Equal(t, "Hello alexandernyquist", w.Body.String())
   418  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   419  }
   420  
   421  func TestRenderHTMLDebugFiles(t *testing.T) {
   422  	w := httptest.NewRecorder()
   423  	htmlRender := HTMLDebug{Files: []string{"../testdata/template/hello.tmpl"},
   424  		Glob:    "",
   425  		Delims:  Delims{Left: "{[{", Right: "}]}"},
   426  		FuncMap: nil,
   427  	}
   428  	instance := htmlRender.Instance("hello.tmpl", map[string]interface{}{
   429  		"name": "thinkerou",
   430  	})
   431  
   432  	err := instance.Render(w)
   433  
   434  	assert.NoError(t, err)
   435  	assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String())
   436  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   437  }
   438  
   439  func TestRenderHTMLDebugGlob(t *testing.T) {
   440  	w := httptest.NewRecorder()
   441  	htmlRender := HTMLDebug{Files: nil,
   442  		Glob:    "../testdata/template/hello*",
   443  		Delims:  Delims{Left: "{[{", Right: "}]}"},
   444  		FuncMap: nil,
   445  	}
   446  	instance := htmlRender.Instance("hello.tmpl", map[string]interface{}{
   447  		"name": "thinkerou",
   448  	})
   449  
   450  	err := instance.Render(w)
   451  
   452  	assert.NoError(t, err)
   453  	assert.Equal(t, "<h1>Hello thinkerou</h1>", w.Body.String())
   454  	assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
   455  }
   456  
   457  func TestRenderHTMLDebugPanics(t *testing.T) {
   458  	htmlRender := HTMLDebug{Files: nil,
   459  		Glob:    "",
   460  		Delims:  Delims{"{{", "}}"},
   461  		FuncMap: nil,
   462  	}
   463  	assert.Panics(t, func() { htmlRender.Instance("", nil) })
   464  }
   465  
   466  func TestRenderReader(t *testing.T) {
   467  	w := httptest.NewRecorder()
   468  
   469  	body := "#!PNG some raw data"
   470  	headers := make(map[string]string)
   471  	headers["Content-Disposition"] = `attachment; filename="filename.png"`
   472  	headers["x-request-id"] = "requestId"
   473  
   474  	err := (Reader{
   475  		ContentLength: int64(len(body)),
   476  		ContentType:   "image/png",
   477  		Reader:        strings.NewReader(body),
   478  		Headers:       headers,
   479  	}).Render(w)
   480  
   481  	assert.NoError(t, err)
   482  	assert.Equal(t, body, w.Body.String())
   483  	assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
   484  	assert.Equal(t, strconv.Itoa(len(body)), w.Header().Get("Content-Length"))
   485  	assert.Equal(t, headers["Content-Disposition"], w.Header().Get("Content-Disposition"))
   486  	assert.Equal(t, headers["x-request-id"], w.Header().Get("x-request-id"))
   487  }
   488  
   489  func TestRenderReaderNoContentLength(t *testing.T) {
   490  	w := httptest.NewRecorder()
   491  
   492  	body := "#!PNG some raw data"
   493  	headers := make(map[string]string)
   494  	headers["Content-Disposition"] = `attachment; filename="filename.png"`
   495  	headers["x-request-id"] = "requestId"
   496  
   497  	err := (Reader{
   498  		ContentLength: -1,
   499  		ContentType:   "image/png",
   500  		Reader:        strings.NewReader(body),
   501  		Headers:       headers,
   502  	}).Render(w)
   503  
   504  	assert.NoError(t, err)
   505  	assert.Equal(t, body, w.Body.String())
   506  	assert.Equal(t, "image/png", w.Header().Get("Content-Type"))
   507  	assert.NotContains(t, "Content-Length", w.Header())
   508  	assert.Equal(t, headers["Content-Disposition"], w.Header().Get("Content-Disposition"))
   509  	assert.Equal(t, headers["x-request-id"], w.Header().Get("x-request-id"))
   510  }