iris/sessions/sessions_test.go

312 lines
8.7 KiB
Go
Raw Normal View History

package sessions_test
import (
"sync"
"testing"
"time"
"github.com/kataras/iris/v12"
"github.com/kataras/iris/v12/context"
"github.com/kataras/iris/v12/httptest"
"github.com/kataras/iris/v12/sessions"
)
func TestSessions(t *testing.T) {
app := iris.New()
sess := sessions.New(sessions.Config{Cookie: "mycustomsessionid"})
testSessions(t, sess, app)
}
const (
testEnableSubdomain = true
)
func testSessions(t *testing.T, sess *sessions.Sessions, app *iris.Application) {
values := map[string]interface{}{
"Name": "iris",
"Months": "4",
"Secret": "dsads£2132215£%%Ssdsa",
}
writeValues := func(ctx context.Context) {
s := sess.Start(ctx)
sessValues := s.GetAll()
_, err := ctx.JSON(sessValues)
if err != nil {
t.Fatal(err)
}
}
if testEnableSubdomain {
app.Party("subdomain.").Get("/get", writeValues)
}
app.Post("/set", func(ctx context.Context) {
s := sess.Start(ctx)
vals := make(map[string]interface{})
if err := ctx.ReadJSON(&vals); err != nil {
t.Fatalf("Cannot read JSON. Trace %s", err.Error())
}
for k, v := range vals {
s.Set(k, v)
}
})
app.Get("/get", func(ctx context.Context) {
writeValues(ctx)
})
app.Get("/clear", func(ctx context.Context) {
sess.Start(ctx).Clear()
writeValues(ctx)
})
app.Get("/destroy", func(ctx context.Context) {
sess.Destroy(ctx)
writeValues(ctx)
// the cookie and all values should be empty
})
// request cookie should be empty
app.Get("/after_destroy", func(ctx context.Context) {
})
app.Get("/multi_start_set_get", func(ctx context.Context) {
s := sess.Start(ctx)
s.Set("key", "value")
ctx.Next()
}, func(ctx context.Context) {
s := sess.Start(ctx)
_, err := ctx.Writef(s.GetString("key"))
if err != nil {
t.Fatal(err)
}
})
e := httptest.New(t, app, httptest.URL("http://example.com"))
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 := e.Builder(func(req *httptest.Request) {
req.WithURL("http://subdomain.example.com")
})
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 set 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()
// test start on the same request but more than one times
e.GET("/multi_start_set_get").Expect().Status(iris.StatusOK).Body().Equal("value")
}
func TestFlashMessages(t *testing.T) {
app := iris.New()
sess := 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 context.Context, values map[string]interface{}) error {
_, err := ctx.JSON(values)
return err
}
app.Post("/set", func(ctx context.Context) {
vals := make(map[string]interface{})
if err := ctx.ReadJSON(&vals); err != nil {
t.Fatalf("Cannot readjson. Trace %s", err.Error())
}
s := sess.Start(ctx)
for k, v := range vals {
s.SetFlash(k, v)
}
ctx.StatusCode(iris.StatusOK)
})
writeFlashValues := func(ctx context.Context) {
s := sess.Start(ctx)
flashes := s.GetFlashes()
if err := writeValues(ctx, flashes); err != nil {
t.Fatalf("While serialize the flash values: %s", err.Error())
}
}
app.Get("/get_single", func(ctx context.Context) {
s := sess.Start(ctx)
flashMsgString := s.GetFlashString(valueSingleKey)
ctx.WriteString(flashMsgString)
})
app.Get("/get", func(ctx context.Context) {
writeFlashValues(ctx)
})
app.Get("/clear", func(ctx context.Context) {
s := sess.Start(ctx)
s.ClearFlashes()
writeFlashValues(ctx)
})
app.Get("/destroy", func(ctx context.Context) {
sess.Destroy(ctx)
writeFlashValues(ctx)
ctx.StatusCode(iris.StatusOK)
// the cookie and all values should be empty
})
// request cookie should be empty
app.Get("/after_destroy", func(ctx context.Context) {
ctx.StatusCode(iris.StatusOK)
})
e := httptest.New(t, app, httptest.URL("http://example.com"))
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 destroy 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_single").Expect().Status(iris.StatusOK).Body().Equal(valueSingleValue)
}
func TestSessionsUpdateExpiration(t *testing.T) {
app := iris.New()
cookieName := "mycustomsessionid"
sess := sessions.New(sessions.Config{
Cookie: cookieName,
Expires: 30 * time.Minute,
AllowReclaim: true,
})
app.Use(sess.Handler())
type response struct {
SessionID string `json:"sessionID"`
Logged bool `json:"logged"`
}
var writeResponse = func(ctx context.Context) {
session := sessions.Get(ctx)
ctx.JSON(response{
SessionID: session.ID(),
Logged: session.GetBooleanDefault("logged", false),
})
}
app.Get("/get", func(ctx context.Context) {
writeResponse(ctx)
})
app.Get("/set", func(ctx iris.Context) {
sessions.Get(ctx).Set("logged", true)
writeResponse(ctx)
})
app.Post("/remember_me", func(ctx iris.Context) {
// re-sends the cookie with the new Expires and MaxAge fields,
// test checks that on same session id too.
sessions.Get(ctx).Man.UpdateExpiration(ctx, 24*time.Hour)
writeResponse(ctx)
})
app.Get("/destroy", func(ctx iris.Context) {
sessions.Get(ctx).Man.Destroy(ctx) // this will delete the cookie too.
})
e := httptest.New(t, app, httptest.URL("http://example.com"))
tt := e.GET("/set").Expect().Status(httptest.StatusOK)
tt.Cookie(cookieName).MaxAge().InRange(29*time.Minute, 30*time.Minute)
sessionID := tt.JSON().Object().Raw()["sessionID"].(string)
expectedResponse := response{SessionID: sessionID, Logged: true}
e.GET("/get").Expect().Status(httptest.StatusOK).
JSON().Equal(expectedResponse)
tt = e.POST("/remember_me").Expect().Status(httptest.StatusOK)
tt.Cookie(cookieName).MaxAge().InRange(23*time.Hour, 24*time.Hour)
tt.JSON().Equal(expectedResponse)
// Test call `UpdateExpiration` when cookie is firstly created.
e.GET("/destroy").Expect().Status(httptest.StatusOK)
e.POST("/remember_me").Expect().Status(httptest.StatusOK).
Cookie(cookieName).MaxAge().InRange(23*time.Hour, 24*time.Hour)
}
// go test -v -count=100 -run=TestSessionsUpdateExpirationConcurrently$
// #1488
func TestSessionsUpdateExpirationConcurrently(t *testing.T) {
cookieName := "mycustomsessionid"
sess := sessions.New(sessions.Config{
Cookie: cookieName,
Expires: 30 * time.Minute,
AllowReclaim: true,
})
app := iris.New()
app.Use(sess.Handler())
app.Use(func(ctx iris.Context) {
// session will expire after 30 minute at the last visit
sess.UpdateExpiration(ctx, 30*time.Minute)
ctx.Next()
})
app.Get("/get", func(ctx iris.Context) {
ctx.WriteString(sessions.Get(ctx).ID())
})
e := httptest.New(t, app, httptest.URL("http://example.com"))
id := e.GET("/get").Expect().Status(httptest.StatusOK).Body().Raw()
i := 0
wg := sync.WaitGroup{}
wg.Add(1000)
for i < 1000 {
go func() {
tt := e.GET("/get").Expect().Status(httptest.StatusOK)
tt.Body().Equal(id)
tt.Cookie(cookieName).MaxAge().InRange(29*time.Minute, 30*time.Minute)
wg.Done()
}()
i++
}
wg.Wait()
tt := e.GET("/get").Expect()
tt.Status(httptest.StatusOK).Body().Equal(id)
tt.Cookie(cookieName).MaxAge().InRange(29*time.Minute, 30*time.Minute)
}