From 5872eb1b126967162fe49f1c39075cc04f2c2816 Mon Sep 17 00:00:00 2001 From: "Gerasimos (Makis) Maropoulos" Date: Sun, 19 Feb 2017 10:23:01 +0200 Subject: [PATCH] Add tests for RedirectTo, Sessions, Flash messages and for Cookies. Former-commit-id: 5a631c366c4caf1d45c532dc5363459cb595f067 --- .gitignore | 1 + addr_test.go | 33 +++- context_test.go | 119 ++++++++++++ ...lamux_test.go => policy_gorillamux_test.go | 73 ++------ ...outer_test.go => policy_httprouter_test.go | 56 ++---- policy_test.go => policy_nativerouter_test.go | 2 +- policy_sessions_test.go | 169 ++++++++++++++++++ 7 files changed, 344 insertions(+), 109 deletions(-) rename adaptors/gorillamux/gorillamux_test.go => policy_gorillamux_test.go (88%) rename adaptors/httprouter/httprouter_test.go => policy_httprouter_test.go (90%) rename policy_test.go => policy_nativerouter_test.go (99%) create mode 100644 policy_sessions_test.go diff --git a/.gitignore b/.gitignore index 06c382d0..c101ac2e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .project 2M_donation_timeline.cpd performance_tips.txt +notes.txt diff --git a/addr_test.go b/addr_test.go index e1884556..6938367f 100644 --- a/addr_test.go +++ b/addr_test.go @@ -11,10 +11,38 @@ import ( "testing" "time" + "github.com/iris-contrib/httpexpect" "gopkg.in/kataras/iris.v6" "gopkg.in/kataras/iris.v6/httptest" ) +func getRandomNumber(min int, max int) int { + rand.Seed(time.Now().Unix()) + return rand.Intn(max-min) + min +} + +const ( + testEnableSubdomain = true + testSubdomain = "mysubdomain" +) + +func testSubdomainHost(host string) string { + s := testSubdomain + "." + host + return s +} + +func testSubdomainURL(scheme string, host string) string { + subdomainHost := testSubdomainHost(host) + return scheme + subdomainHost +} + +func subdomainTester(e *httpexpect.Expect, app *iris.Framework) *httpexpect.Expect { + es := e.Builder(func(req *httpexpect.Request) { + req.WithURL(testSubdomainURL(app.Config.VScheme, app.Config.VHost)) + }) + return es +} + func TestParseAddr(t *testing.T) { // test hosts @@ -145,11 +173,6 @@ k9X9TwWyZtp5IL1CAEd/Il9ZTXFzr3lNaN8LCFnU+EIsz1YgUW8LTg== ` ) -func getRandomNumber(min int, max int) int { - rand.Seed(time.Now().Unix()) - return rand.Intn(max-min) + min -} - // works as // defer listenTLS(iris.Default, hostTLS)() func listenTLS(app *iris.Framework, hostTLS string) func() { diff --git a/context_test.go b/context_test.go index f8c1881f..2264ee83 100644 --- a/context_test.go +++ b/context_test.go @@ -2,8 +2,11 @@ package iris_test import ( "io/ioutil" + "net/http" "strconv" + "strings" "testing" + "time" "gopkg.in/kataras/iris.v6" "gopkg.in/kataras/iris.v6/adaptors/httprouter" @@ -268,3 +271,119 @@ func TestRedirectHTTPS(t *testing.T) { e := httptest.New(app, t) e.GET("/redirect").Expect().Status(iris.StatusOK).Body().Equal(expectedBody) } + +// TestContextRedirectTo tests the named route redirect action +func TestContextRedirectTo(t *testing.T) { + app := iris.New() + app.Adapt(httprouter.New()) + h := func(ctx *iris.Context) { ctx.WriteString(ctx.Path()) } + app.Get("/mypath", h).ChangeName("my-path") + app.Get("/mypostpath", h).ChangeName("my-post-path") + app.Get("mypath/with/params/:param1/:param2", func(ctx *iris.Context) { + if l := ctx.ParamsLen(); l != 2 { + t.Fatalf("Strange error, expecting parameters to be two but we got: %d", l) + } + ctx.WriteString(ctx.Path()) + }).ChangeName("my-path-with-params") + + app.Get("/redirect/to/:routeName/*anyparams", func(ctx *iris.Context) { + routeName := ctx.Param("routeName") + var args []interface{} + anyparams := ctx.Param("anyparams") + if anyparams != "" && anyparams != "/" { + params := strings.Split(anyparams[1:], "/") // firstparam/secondparam + for _, s := range params { + args = append(args, s) + } + } + ctx.RedirectTo(routeName, args...) + }) + + e := httptest.New(app, t) + + e.GET("/redirect/to/my-path/").Expect().Status(iris.StatusOK).Body().Equal("/mypath") + e.GET("/redirect/to/my-post-path/").Expect().Status(iris.StatusOK).Body().Equal("/mypostpath") + e.GET("/redirect/to/my-path-with-params/firstparam/secondparam").Expect().Status(iris.StatusOK).Body().Equal("/mypath/with/params/firstparam/secondparam") +} + +func TestContextUserValues(t *testing.T) { + app := iris.New() + app.Adapt(httprouter.New()) + testCustomObjUserValue := struct{ Name string }{Name: "a name"} + values := map[string]interface{}{"key1": "value1", "key2": "value2", "key3": 3, "key4": testCustomObjUserValue, "key5": map[string]string{"key": "value"}} + + app.Get("/test", func(ctx *iris.Context) { + + for k, v := range values { + ctx.Set(k, v) + } + + }, func(ctx *iris.Context) { + for k, v := range values { + userValue := ctx.Get(k) + if userValue != v { + t.Fatalf("Expecting user value: %s to be equal with: %#v but got: %#v", k, v, userValue) + } + + if m, isMap := userValue.(map[string]string); isMap { + if m["key"] != v.(map[string]string)["key"] { + t.Fatalf("Expecting user value: %s to be equal with: %#v but got: %#v", k, v.(map[string]string)["key"], m["key"]) + } + } else { + if userValue != v { + t.Fatalf("Expecting user value: %s to be equal with: %#v but got: %#v", k, v, userValue) + } + } + + } + }) + + e := httptest.New(app, t) + + e.GET("/test").Expect().Status(iris.StatusOK) + +} + +func TestContextCookieSetGetRemove(t *testing.T) { + app := iris.New() + app.Adapt(httprouter.New()) + key := "mykey" + value := "myvalue" + app.Get("/set", func(ctx *iris.Context) { + ctx.SetCookieKV(key, value) // should return non empty cookies + }) + + app.Get("/set_advanced", func(ctx *iris.Context) { + c := &http.Cookie{} + c.Name = key + c.Value = value + c.HttpOnly = true + c.Expires = time.Now().Add(time.Duration((60 * 60 * 24 * 7 * 4)) * time.Second) + ctx.SetCookie(c) + }) + + app.Get("/get", func(ctx *iris.Context) { + ctx.WriteString(ctx.GetCookie(key)) // should return my value + }) + + app.Get("/remove", func(ctx *iris.Context) { + ctx.RemoveCookie(key) + cookieFound := false + ctx.VisitAllCookies(func(k, v string) { + cookieFound = true + }) + if cookieFound { + t.Fatalf("Cookie has been found, when it shouldn't!") + } + ctx.WriteString(ctx.GetCookie(key)) // should return "" + }) + + e := httptest.New(app, t) + e.GET("/set").Expect().Status(iris.StatusOK).Cookies().NotEmpty() + e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal(value) + e.GET("/remove").Expect().Status(iris.StatusOK).Body().Equal("") + // test again with advanced set + e.GET("/set_advanced").Expect().Status(iris.StatusOK).Cookies().NotEmpty() + e.GET("/get").Expect().Status(iris.StatusOK).Body().Equal(value) + e.GET("/remove").Expect().Status(iris.StatusOK).Body().Equal("") +} diff --git a/adaptors/gorillamux/gorillamux_test.go b/policy_gorillamux_test.go similarity index 88% rename from adaptors/gorillamux/gorillamux_test.go rename to policy_gorillamux_test.go index af9692f9..55b97a2d 100644 --- a/adaptors/gorillamux/gorillamux_test.go +++ b/policy_gorillamux_test.go @@ -1,70 +1,23 @@ -package gorillamux_test +package iris_test import ( - "math/rand" "strconv" "testing" - "time" - "github.com/iris-contrib/httpexpect" "gopkg.in/kataras/iris.v6" "gopkg.in/kataras/iris.v6/adaptors/gorillamux" "gopkg.in/kataras/iris.v6/httptest" ) -func getRandomNumber(min int, max int) int { - rand.Seed(time.Now().Unix()) - return rand.Intn(max-min) + min -} - -const ( - testEnableSubdomain = true - testSubdomain = "mysubdomain" -) - -func testSubdomainHost(host string) string { - s := testSubdomain + "." + host - return s -} - -func testSubdomainURL(scheme string, host string) string { - subdomainHost := testSubdomainHost(host) - return scheme + subdomainHost -} - -func subdomainTester(e *httpexpect.Expect, app *iris.Framework) *httpexpect.Expect { - es := e.Builder(func(req *httpexpect.Request) { - req.WithURL(testSubdomainURL(app.Config.VScheme, app.Config.VHost)) - }) - return es -} - -type param struct { - Key string - Value string -} - -type testRoute struct { - Method string - Path string - RequestPath string - RequestQuery string - Body string - Status int - Register bool - Params []param - URLParams []param -} - -func newApp() *iris.Framework { +func newGorillaMuxAPP() *iris.Framework { app := iris.New() app.Adapt(gorillamux.New()) return app } -func TestMuxSimple(t *testing.T) { - app := newApp() +func TestGorillaMuxSimple(t *testing.T) { + app := newGorillaMuxAPP() testRoutes := []testRoute{ // FOUND - registered @@ -141,8 +94,8 @@ func TestMuxSimple(t *testing.T) { } -func TestMuxSimpleParty(t *testing.T) { - app := newApp() +func TestGorillaMuxSimpleParty(t *testing.T) { + app := newGorillaMuxAPP() h := func(ctx *iris.Context) { ctx.WriteString(ctx.Host() + ctx.Path()) } @@ -202,8 +155,8 @@ func TestMuxSimpleParty(t *testing.T) { } } -func TestMuxPathEscape(t *testing.T) { - app := newApp() +func TestGorillaMuxPathEscape(t *testing.T) { + app := newGorillaMuxAPP() app.Get("/details/{name}", func(ctx *iris.Context) { name := ctx.Param("name") @@ -218,8 +171,8 @@ func TestMuxPathEscape(t *testing.T) { Expect().Status(iris.StatusOK).Body().Equal("name=Sakamoto desu ga,highlight=text") } -func TestMuxParamDecodedDecodeURL(t *testing.T) { - app := newApp() +func TestGorillaMuxParamDecodedDecodeURL(t *testing.T) { + app := newGorillaMuxAPP() app.Get("/encoding/{url}", func(ctx *iris.Context) { url := iris.DecodeURL(ctx.ParamDecoded("url")) @@ -232,7 +185,7 @@ func TestMuxParamDecodedDecodeURL(t *testing.T) { e.GET("/encoding/http%3A%2F%2Fsome-url.com").Expect().Status(iris.StatusOK).Body().Equal("http://some-url.com") } -func TestMuxCustomErrors(t *testing.T) { +func TestGorillaMuxCustomErrors(t *testing.T) { var ( notFoundMessage = "Iris custom message for 404 not found" internalServerMessage = "Iris custom message for 500 internal server error" @@ -259,7 +212,7 @@ func TestMuxCustomErrors(t *testing.T) { {"TRACE", "/test_trace_panic_custom", "/test_trace_panic_custom", "", internalServerMessage, 500, true, nil, nil}, } ) - app := newApp() + app := newGorillaMuxAPP() // first register the testRoutes needed for _, r := range testRoutesCustomErrors { if r.Register { @@ -289,7 +242,7 @@ func TestMuxCustomErrors(t *testing.T) { } } -func TestRouteURLPath(t *testing.T) { +func TestGorillaMuxRouteURLPath(t *testing.T) { app := iris.New() app.Adapt(gorillamux.New()) diff --git a/adaptors/httprouter/httprouter_test.go b/policy_httprouter_test.go similarity index 90% rename from adaptors/httprouter/httprouter_test.go rename to policy_httprouter_test.go index e9e403f5..87b4d718 100644 --- a/adaptors/httprouter/httprouter_test.go +++ b/policy_httprouter_test.go @@ -1,44 +1,14 @@ -package httprouter_test +package iris_test import ( - "math/rand" "strconv" "testing" - "time" - "github.com/iris-contrib/httpexpect" "gopkg.in/kataras/iris.v6" "gopkg.in/kataras/iris.v6/adaptors/httprouter" "gopkg.in/kataras/iris.v6/httptest" ) -func getRandomNumber(min int, max int) int { - rand.Seed(time.Now().Unix()) - return rand.Intn(max-min) + min -} - -const ( - testEnableSubdomain = true - testSubdomain = "mysubdomain" -) - -func testSubdomainHost(host string) string { - s := testSubdomain + "." + host - return s -} - -func testSubdomainURL(scheme string, host string) string { - subdomainHost := testSubdomainHost(host) - return scheme + subdomainHost -} - -func subdomainTester(e *httpexpect.Expect, app *iris.Framework) *httpexpect.Expect { - es := e.Builder(func(req *httpexpect.Request) { - req.WithURL(testSubdomainURL(app.Config.VScheme, app.Config.VHost)) - }) - return es -} - type param struct { Key string Value string @@ -56,15 +26,15 @@ type testRoute struct { URLParams []param } -func newApp() *iris.Framework { +func newHTTPRouterApp() *iris.Framework { app := iris.New() app.Adapt(httprouter.New()) return app } -func TestMuxSimple(t *testing.T) { - app := newApp() +func TestHTTPRouterSimple(t *testing.T) { + app := newHTTPRouterApp() testRoutes := []testRoute{ // FOUND - registered @@ -137,8 +107,8 @@ func TestMuxSimple(t *testing.T) { } -func TestMuxSimpleParty(t *testing.T) { - app := newApp() +func TestHTTPRouterSimpleParty(t *testing.T) { + app := newHTTPRouterApp() h := func(ctx *iris.Context) { ctx.WriteString(ctx.Host() + ctx.Path()) } @@ -198,8 +168,8 @@ func TestMuxSimpleParty(t *testing.T) { } } -func TestMuxPathEscape(t *testing.T) { - app := newApp() +func TestHTTPRouterPathEscape(t *testing.T) { + app := newHTTPRouterApp() app.Get("/details/:name", func(ctx *iris.Context) { name := ctx.Param("name") @@ -214,8 +184,8 @@ func TestMuxPathEscape(t *testing.T) { Expect().Status(iris.StatusOK).Body().Equal("name=Sakamoto desu ga,highlight=text") } -func TestMuxParamDecodedDecodeURL(t *testing.T) { - app := newApp() +func TestHTTPRouterParamDecodedDecodeURL(t *testing.T) { + app := newHTTPRouterApp() app.Get("/encoding/:url", func(ctx *iris.Context) { url := iris.DecodeURL(ctx.ParamDecoded("url")) @@ -228,7 +198,7 @@ func TestMuxParamDecodedDecodeURL(t *testing.T) { e.GET("/encoding/http%3A%2F%2Fsome-url.com").Expect().Status(iris.StatusOK).Body().Equal("http://some-url.com") } -func TestMuxCustomErrors(t *testing.T) { +func TestHTTPRouterCustomErrors(t *testing.T) { var ( notFoundMessage = "Iris custom message for 404 not found" internalServerMessage = "Iris custom message for 500 internal server error" @@ -255,7 +225,7 @@ func TestMuxCustomErrors(t *testing.T) { {"TRACE", "/test_trace_panic_custom", "/test_trace_panic_custom", "", internalServerMessage, 500, true, nil, nil}, } ) - app := newApp() + app := newHTTPRouterApp() // first register the testRoutes needed for _, r := range testRoutesCustomErrors { if r.Register { @@ -285,7 +255,7 @@ func TestMuxCustomErrors(t *testing.T) { } } -func TestRouteURLPath(t *testing.T) { +func TestHTTPRouterRouteURLPath(t *testing.T) { app := iris.New() app.Adapt(httprouter.New()) diff --git a/policy_test.go b/policy_nativerouter_test.go similarity index 99% rename from policy_test.go rename to policy_nativerouter_test.go index b52b94b8..619bf7a0 100644 --- a/policy_test.go +++ b/policy_nativerouter_test.go @@ -121,7 +121,7 @@ type testNativeRoute struct { status int } -func TestNativeRouterPolicyAdaptor(t *testing.T) { +func TestNativeRouter(t *testing.T) { expectedWrongMethodStatus := StatusNotFound app := New(Configuration{FireMethodNotAllowed: true}) app.Adapt(newTestNativeRouter()) diff --git a/policy_sessions_test.go b/policy_sessions_test.go new file mode 100644 index 00000000..545270c4 --- /dev/null +++ b/policy_sessions_test.go @@ -0,0 +1,169 @@ +package iris_test + +import ( + "testing" + + "gopkg.in/kataras/iris.v6" + "gopkg.in/kataras/iris.v6/adaptors/httprouter" + "gopkg.in/kataras/iris.v6/adaptors/sessions" + "gopkg.in/kataras/iris.v6/httptest" +) + +func TestSessions(t *testing.T) { + values := map[string]interface{}{ + "Name": "iris", + "Months": "4", + "Secret": "dsads£2132215£%%Ssdsa", + } + app := iris.New() + app.Adapt(httprouter.New()) + app.Adapt(sessions.New(sessions.Config{Cookie: "mycustomsessionid"})) + + writeValues := func(ctx *iris.Context) { + sessValues := ctx.Session().GetAll() + ctx.JSON(iris.StatusOK, sessValues) + } + + if testEnableSubdomain { + app.Party(testSubdomain+".").Get("/get", func(ctx *iris.Context) { + writeValues(ctx) + }) + } + + app.Post("set", func(ctx *iris.Context) { + vals := make(map[string]interface{}, 0) + if err := ctx.ReadJSON(&vals); err != nil { + t.Fatalf("Cannot readjson. Trace %s", err.Error()) + } + for k, v := range vals { + ctx.Session().Set(k, v) + } + }) + + app.Get("/get", func(ctx *iris.Context) { + writeValues(ctx) + }) + + app.Get("/clear", func(ctx *iris.Context) { + ctx.Session().Clear() + writeValues(ctx) + }) + + app.Get("/destroy", func(ctx *iris.Context) { + ctx.SessionDestroy() + writeValues(ctx) + // the cookie and all values should be empty + }) + + // request cookie should be empty + app.Get("/after_destroy", func(ctx *iris.Context) { + }) + app.Config.VHost = "mydomain.com" + e := httptest.New(app, t) + + e.POST("/set").WithJSON(values).Expect().Status(iris.StatusOK).Cookies().NotEmpty() + e.GET("/get").Expect().Status(iris.StatusOK).JSON().Object().Equal(values) + if testEnableSubdomain { + es := subdomainTester(e, app) + es.Request("GET", "/get").Expect().Status(iris.StatusOK).JSON().Object().Equal(values) + } + + // test destroy which also clears first + d := e.GET("/destroy").Expect().Status(iris.StatusOK) + d.JSON().Object().Empty() + // This removed: d.Cookies().Empty(). Reason: + // httpexpect counts the cookies setted or deleted at the response time, but cookie is not removed, to be really removed needs to SetExpire(now-1second) so, + // test if the cookies removed on the next request, like the browser's behavior. + e.GET("/after_destroy").Expect().Status(iris.StatusOK).Cookies().Empty() + // set and clear again + e.POST("/set").WithJSON(values).Expect().Status(iris.StatusOK).Cookies().NotEmpty() + e.GET("/clear").Expect().Status(iris.StatusOK).JSON().Object().Empty() +} + +func TestFlashMessages(t *testing.T) { + app := iris.New() + app.Adapt(httprouter.New()) + app.Adapt(sessions.New(sessions.Config{Cookie: "mycustomsessionid"})) + + valueSingleKey := "Name" + valueSingleValue := "iris-sessions" + + values := map[string]interface{}{ + valueSingleKey: valueSingleValue, + "Days": "1", + "Secret": "dsads£2132215£%%Ssdsa", + } + + writeValues := func(ctx *iris.Context, values map[string]interface{}) error { + return ctx.JSON(iris.StatusOK, values) + } + + app.Post("/set", func(ctx *iris.Context) { + vals := make(map[string]interface{}, 0) + if err := ctx.ReadJSON(&vals); err != nil { + t.Fatalf("Cannot readjson. Trace %s", err.Error()) + } + sess := ctx.Session() + for k, v := range vals { + sess.SetFlash(k, v) + } + + ctx.SetStatusCode(iris.StatusOK) + }) + + writeFlashValues := func(ctx *iris.Context) { + sess := ctx.Session() + flashes := sess.GetFlashes() + if err := writeValues(ctx, flashes); err != nil { + t.Fatalf("While serialize the flash values: %s", err.Error()) + } + } + + app.Get("/get_single", func(ctx *iris.Context) { + sess := ctx.Session() + flashMsgString := sess.GetFlashString(valueSingleKey) + ctx.WriteString(flashMsgString) + }) + + app.Get("/get", func(ctx *iris.Context) { + writeFlashValues(ctx) + }) + + app.Get("/clear", func(ctx *iris.Context) { + sess := ctx.Session() + sess.ClearFlashes() + writeFlashValues(ctx) + }) + + app.Get("/destroy", func(ctx *iris.Context) { + ctx.SessionDestroy() + writeFlashValues(ctx) + ctx.SetStatusCode(iris.StatusOK) + // the cookie and all values should be empty + }) + + // request cookie should be empty + app.Get("/after_destroy", func(ctx *iris.Context) { + ctx.SetStatusCode(iris.StatusOK) + }) + + e := httptest.New(app, t) + + e.POST("/set").WithJSON(values).Expect().Status(iris.StatusOK).Cookies().NotEmpty() + // get all + e.GET("/get").Expect().Status(iris.StatusOK).JSON().Object().Equal(values) + // get the same flash on other request should return nothing because the flash message is removed after fetch once + e.GET("/get").Expect().Status(iris.StatusOK).JSON().Object().Empty() + // test destory which also clears first + d := e.GET("/destroy").Expect().Status(iris.StatusOK) + d.JSON().Object().Empty() + e.GET("/after_destroy").Expect().Status(iris.StatusOK).Cookies().Empty() + // set and clear again + e.POST("/set").WithJSON(values).Expect().Status(iris.StatusOK).Cookies().NotEmpty() + e.GET("/clear").Expect().Status(iris.StatusOK).JSON().Object().Empty() + + // set again in order to take the single one ( we don't test Cookies.NotEmpty because httpexpect default conf reads that from the request-only) + e.POST("/set").WithJSON(values).Expect().Status(iris.StatusOK) + // e.GET("/get/").Expect().Status(http.StatusOK).JSON().Object().Equal(values) + e.GET("/get_single").Expect().Status(iris.StatusOK).Body().Equal(valueSingleValue) +}