388 lines
11 KiB
Go
388 lines
11 KiB
Go
// Copyright 2014 The Macaron Authors
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
|
// not use this file except in compliance with the License. You may obtain
|
|
// a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
// License for the specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
package macaron
|
|
|
|
import (
|
|
"bytes"
|
|
"io/ioutil"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"net/url"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/unknwon/com"
|
|
|
|
. "github.com/smartystreets/goconvey/convey"
|
|
)
|
|
|
|
func Test_Context(t *testing.T) {
|
|
Convey("Do advanced encapsulation operations", t, func() {
|
|
m := Classic()
|
|
m.Use(Renderers(RenderOptions{
|
|
Directory: "fixtures/basic",
|
|
}, "fixtures/basic2"))
|
|
|
|
Convey("Get request body", func() {
|
|
m.Get("/body1", func(ctx *Context) {
|
|
data, err := ioutil.ReadAll(ctx.Req.Body().ReadCloser())
|
|
So(err, ShouldBeNil)
|
|
So(string(data), ShouldEqual, "This is my request body")
|
|
})
|
|
m.Get("/body2", func(ctx *Context) {
|
|
data, err := ctx.Req.Body().Bytes()
|
|
So(err, ShouldBeNil)
|
|
So(string(data), ShouldEqual, "This is my request body")
|
|
})
|
|
m.Get("/body3", func(ctx *Context) {
|
|
data, err := ctx.Req.Body().String()
|
|
So(err, ShouldBeNil)
|
|
So(data, ShouldEqual, "This is my request body")
|
|
})
|
|
m.Get("/body4", ContextInvoker(func(ctx *Context) {
|
|
data, err := ctx.Req.Body().String()
|
|
So(err, ShouldBeNil)
|
|
So(data, ShouldEqual, "This is my request body")
|
|
}))
|
|
|
|
for i := 1; i <= 4; i++ {
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/body"+com.ToStr(i), nil)
|
|
req.Body = ioutil.NopCloser(bytes.NewBufferString("This is my request body"))
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
}
|
|
})
|
|
|
|
Convey("Get remote IP address", func() {
|
|
m.Get("/remoteaddr", func(ctx *Context) string {
|
|
return ctx.RemoteAddr()
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/remoteaddr", nil)
|
|
req.RemoteAddr = "127.0.0.1:3333"
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "127.0.0.1")
|
|
})
|
|
|
|
Convey("Render HTML", func() {
|
|
|
|
Convey("Normal HTML", func() {
|
|
m.Get("/html", func(ctx *Context) {
|
|
ctx.HTML(304, "hello", "Unknwon") // 304 for logger test.
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/html", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "<h1>Hello Unknwon</h1>")
|
|
})
|
|
|
|
Convey("HTML template set", func() {
|
|
m.Get("/html2", func(ctx *Context) {
|
|
ctx.Data["Name"] = "Unknwon"
|
|
ctx.HTMLSet(200, "basic2", "hello2")
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/html2", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "<h1>Hello Unknwon</h1>")
|
|
})
|
|
|
|
Convey("With layout", func() {
|
|
m.Get("/layout", func(ctx *Context) {
|
|
ctx.HTML(200, "hello", "Unknwon", HTMLOptions{"layout"})
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/layout", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "head<h1>Hello Unknwon</h1>foot")
|
|
})
|
|
})
|
|
|
|
Convey("Parse from and query", func() {
|
|
m.Get("/query", func(ctx *Context) string {
|
|
var buf bytes.Buffer
|
|
buf.WriteString(ctx.QueryTrim("name") + " ")
|
|
buf.WriteString(ctx.QueryEscape("name") + " ")
|
|
buf.WriteString(com.ToStr(ctx.QueryBool("bool")) + " ")
|
|
buf.WriteString(com.ToStr(ctx.QueryInt("int")) + " ")
|
|
buf.WriteString(com.ToStr(ctx.QueryInt64("int64")) + " ")
|
|
buf.WriteString(com.ToStr(ctx.QueryFloat64("float64")) + " ")
|
|
return buf.String()
|
|
})
|
|
m.Get("/query2", func(ctx *Context) string {
|
|
var buf bytes.Buffer
|
|
buf.WriteString(strings.Join(ctx.QueryStrings("list"), ",") + " ")
|
|
buf.WriteString(strings.Join(ctx.QueryStrings("404"), ",") + " ")
|
|
return buf.String()
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/query?name=Unknwon&bool=t&int=12&int64=123&float64=1.25", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "Unknwon Unknwon true 12 123 1.25 ")
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/query2?list=item1&list=item2", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "item1,item2 ")
|
|
})
|
|
|
|
Convey("URL parameter", func() {
|
|
m.Get("/:name/:int/:int64/:float64", func(ctx *Context) string {
|
|
var buf bytes.Buffer
|
|
ctx.SetParams("name", ctx.Params("name"))
|
|
buf.WriteString(ctx.Params(""))
|
|
buf.WriteString(ctx.Params(":name") + " ")
|
|
buf.WriteString(ctx.ParamsEscape(":name") + " ")
|
|
buf.WriteString(com.ToStr(ctx.ParamsInt(":int")) + " ")
|
|
buf.WriteString(com.ToStr(ctx.ParamsInt64(":int64")) + " ")
|
|
buf.WriteString(com.ToStr(ctx.ParamsFloat64(":float64")) + " ")
|
|
return buf.String()
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/user/1/13/1.24", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "user user 1 13 1.24 ")
|
|
})
|
|
|
|
Convey("Get file", func() {
|
|
m.Post("/getfile", func(ctx *Context) {
|
|
ctx.Query("")
|
|
ctx.GetFile("hi")
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("POST", "/getfile", nil)
|
|
So(err, ShouldBeNil)
|
|
req.Header.Set("Content-Type", "multipart/form-data")
|
|
m.ServeHTTP(resp, req)
|
|
})
|
|
|
|
Convey("Set and get cookie", func() {
|
|
m.Get("/set", func(ctx *Context) {
|
|
t, err := time.Parse(time.RFC1123, "Sun, 13 Mar 2016 01:29:26 UTC")
|
|
So(err, ShouldBeNil)
|
|
ctx.SetCookie("user", "Unknwon", 1, "/", "localhost", true, true, t)
|
|
ctx.SetCookie("user", "Unknwon", int32(1), "/", "localhost", 1)
|
|
ctx.SetCookie("user", "Unknwon", int64(1))
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/set", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Header().Get("Set-Cookie"), ShouldEqual, "user=Unknwon; Path=/; Domain=localhost; Expires=Sun, 13 Mar 2016 01:29:26 GMT; Max-Age=1; HttpOnly; Secure")
|
|
|
|
m.Get("/get", func(ctx *Context) string {
|
|
ctx.GetCookie("404")
|
|
So(ctx.GetCookieInt("uid"), ShouldEqual, 1)
|
|
So(ctx.GetCookieInt64("uid"), ShouldEqual, 1)
|
|
So(ctx.GetCookieFloat64("balance"), ShouldEqual, 1.25)
|
|
return ctx.GetCookie("user")
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/get", nil)
|
|
So(err, ShouldBeNil)
|
|
req.Header.Set("Cookie", "user=Unknwon; uid=1; balance=1.25")
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "Unknwon")
|
|
})
|
|
|
|
Convey("Set and get secure cookie", func() {
|
|
m.SetDefaultCookieSecret("macaron")
|
|
m.Get("/set", func(ctx *Context) {
|
|
ctx.SetSecureCookie("user", "Unknwon", 1)
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/set", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
|
|
cookie := resp.Header().Get("Set-Cookie")
|
|
|
|
m.Get("/get", func(ctx *Context) string {
|
|
name, ok := ctx.GetSecureCookie("user")
|
|
So(ok, ShouldBeTrue)
|
|
return name
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/get", nil)
|
|
So(err, ShouldBeNil)
|
|
req.Header.Set("Cookie", cookie)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "Unknwon")
|
|
})
|
|
|
|
Convey("Serve files", func() {
|
|
m.Get("/file", func(ctx *Context) {
|
|
ctx.ServeFile("fixtures/custom_funcs/index.tmpl")
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/file", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "{{ myCustomFunc }}")
|
|
|
|
m.Get("/file2", func(ctx *Context) {
|
|
ctx.ServeFile("fixtures/custom_funcs/index.tmpl", "ok.tmpl")
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/file2", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "{{ myCustomFunc }}")
|
|
})
|
|
|
|
Convey("Serve file content", func() {
|
|
m.Get("/file", func(ctx *Context) {
|
|
ctx.ServeFileContent("fixtures/custom_funcs/index.tmpl")
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/file", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "{{ myCustomFunc }}")
|
|
|
|
m.Get("/file2", func(ctx *Context) {
|
|
ctx.ServeFileContent("fixtures/custom_funcs/index.tmpl", "ok.tmpl")
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/file2", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "{{ myCustomFunc }}")
|
|
|
|
m.Get("/file3", func(ctx *Context) {
|
|
ctx.ServeFileContent("404.tmpl")
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/file3", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "open 404.tmpl: no such file or directory\n")
|
|
So(resp.Code, ShouldEqual, 500)
|
|
})
|
|
|
|
Convey("Serve content", func() {
|
|
m.Get("/content", func(ctx *Context) {
|
|
ctx.ServeContent("content1", bytes.NewReader([]byte("Hello world!")))
|
|
})
|
|
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/content", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "Hello world!")
|
|
|
|
m.Get("/content2", func(ctx *Context) {
|
|
ctx.ServeContent("content1", bytes.NewReader([]byte("Hello world!")), time.Now())
|
|
})
|
|
|
|
resp = httptest.NewRecorder()
|
|
req, err = http.NewRequest("GET", "/content2", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
So(resp.Body.String(), ShouldEqual, "Hello world!")
|
|
})
|
|
})
|
|
}
|
|
|
|
func Test_Context_Render(t *testing.T) {
|
|
Convey("Invalid render", t, func() {
|
|
defer func() {
|
|
So(recover(), ShouldNotBeNil)
|
|
}()
|
|
|
|
m := New()
|
|
|
|
m.Get("/", func(ctx *Context) {
|
|
ctx.HTML(200, "hey")
|
|
})
|
|
resp := httptest.NewRecorder()
|
|
req, err := http.NewRequest("GET", "/", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
|
|
m.Get("/f", ContextInvoker(func(ctx *Context) {
|
|
ctx.HTML(200, "hey")
|
|
}))
|
|
req, err = http.NewRequest("GET", "/f", nil)
|
|
So(err, ShouldBeNil)
|
|
m.ServeHTTP(resp, req)
|
|
})
|
|
}
|
|
|
|
func Test_Context_Redirect(t *testing.T) {
|
|
Convey("Context with default redirect", t, func() {
|
|
url, err := url.Parse("http://localhost/path/one")
|
|
So(err, ShouldBeNil)
|
|
resp := httptest.NewRecorder()
|
|
req := http.Request{
|
|
Method: "GET",
|
|
URL: url,
|
|
}
|
|
ctx := &Context{
|
|
Req: Request{&req},
|
|
Resp: NewResponseWriter(req.Method, resp),
|
|
Data: make(map[string]interface{}),
|
|
}
|
|
ctx.Redirect("two")
|
|
|
|
So(resp.Code, ShouldEqual, http.StatusFound)
|
|
So(resp.HeaderMap["Location"][0], ShouldEqual, "/path/two")
|
|
})
|
|
|
|
Convey("Context with custom redirect", t, func() {
|
|
url, err := url.Parse("http://localhost/path/one")
|
|
So(err, ShouldBeNil)
|
|
resp := httptest.NewRecorder()
|
|
req := http.Request{
|
|
Method: "GET",
|
|
URL: url,
|
|
}
|
|
ctx := &Context{
|
|
Req: Request{&req},
|
|
Resp: NewResponseWriter(req.Method, resp),
|
|
Data: make(map[string]interface{}),
|
|
}
|
|
ctx.Redirect("two", 307)
|
|
|
|
So(resp.Code, ShouldEqual, http.StatusTemporaryRedirect)
|
|
So(resp.HeaderMap["Location"][0], ShouldEqual, "/path/two")
|
|
})
|
|
}
|