transfer.sh/vendor/github.com/PuerkitoBio/ghost/handlers/session_test.go

259 lines
7.1 KiB
Go
Raw Normal View History

package handlers
import (
"fmt"
"io/ioutil"
"net/http"
"net/http/cookiejar"
"net/http/httptest"
"testing"
"time"
)
var (
store SessionStore
secret = "butchered at birth"
)
func TestSession(t *testing.T) {
stores := map[string]SessionStore{
"memory": NewMemoryStore(1),
"redis": NewRedisStore(&RedisStoreOptions{
Network: "tcp",
Address: ":6379",
Database: 1,
KeyPrefix: "sess",
}),
}
for k, v := range stores {
t.Logf("testing session with %s store\n", k)
store = v
t.Log("SessionExists")
testSessionExists(t)
t.Log("SessionPersists")
testSessionPersists(t)
t.Log("SessionExpires")
testSessionExpires(t)
t.Log("SessionBeforeExpires")
testSessionBeforeExpires(t)
t.Log("PanicIfNoSecret")
testPanicIfNoSecret(t)
t.Log("InvalidPath")
testInvalidPath(t)
t.Log("ValidSubPath")
testValidSubPath(t)
t.Log("SecureOverHttp")
testSecureOverHttp(t)
}
}
func setupTest(f func(w http.ResponseWriter, r *http.Request), ckPath string, secure bool, maxAge int) *httptest.Server {
opts := NewSessionOptions(store, secret)
if ckPath != "" {
opts.CookieTemplate.Path = ckPath
}
opts.CookieTemplate.Secure = secure
opts.CookieTemplate.MaxAge = maxAge
h := SessionHandler(http.HandlerFunc(f), opts)
return httptest.NewServer(h)
}
func doRequest(u string, newJar bool) *http.Response {
var err error
if newJar {
http.DefaultClient.Jar, err = cookiejar.New(new(cookiejar.Options))
if err != nil {
panic(err)
}
}
res, err := http.Get(u)
if err != nil {
panic(err)
}
return res
}
func testSessionExists(t *testing.T) {
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
ssn, ok := GetSession(w)
if assertTrue(ok, "expected session to be non-nil, got nil", t) {
ssn.Data["foo"] = "bar"
assertTrue(ssn.Data["foo"] == "bar", fmt.Sprintf("expected ssn[foo] to be 'bar', got %v", ssn.Data["foo"]), t)
}
w.Write([]byte("ok"))
}, "", false, 0)
defer s.Close()
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
}
func testSessionPersists(t *testing.T) {
cnt := 0
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
ssn, ok := GetSession(w)
if !ok {
panic("session not found!")
}
if cnt == 0 {
ssn.Data["foo"] = "bar"
w.Write([]byte("ok"))
cnt++
} else {
w.Write([]byte(ssn.Data["foo"].(string)))
}
}, "", false, 0)
defer s.Close()
// 1st call, set the session value
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
// 2nd call, get the session value
res = doRequest(s.URL, false)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("bar"), res, t)
assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected 2nd response to have 0 cookie, got %d", len(res.Cookies())), t)
}
func testSessionExpires(t *testing.T) {
cnt := 0
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
ssn, ok := GetSession(w)
if !ok {
panic("session not found!")
}
if cnt == 0 {
w.Write([]byte(ssn.ID()))
cnt++
} else {
w.Write([]byte(ssn.ID()))
}
}, "", false, 1) // Expire in 1 second
defer s.Close()
// 1st call, set the session value
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
id1, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
res.Body.Close()
time.Sleep(1001 * time.Millisecond)
// 2nd call, get the session value
res = doRequest(s.URL, false)
assertStatus(http.StatusOK, res.StatusCode, t)
id2, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
res.Body.Close()
sid1, sid2 := string(id1), string(id2)
assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected 2nd response to have 1 cookie, got %d", len(res.Cookies())), t)
assertTrue(sid1 != sid2, "expected session IDs to be different, got same", t)
}
func testSessionBeforeExpires(t *testing.T) {
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
ssn, ok := GetSession(w)
if !ok {
panic("session not found!")
}
w.Write([]byte(ssn.ID()))
}, "", false, 1) // Expire in 1 second
defer s.Close()
// 1st call, set the session value
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
id1, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
res.Body.Close()
time.Sleep(500 * time.Millisecond)
// 2nd call, get the session value
res = doRequest(s.URL, false)
assertStatus(http.StatusOK, res.StatusCode, t)
id2, err := ioutil.ReadAll(res.Body)
if err != nil {
panic(err)
}
res.Body.Close()
sid1, sid2 := string(id1), string(id2)
assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected 2nd response to have no cookie, got %d", len(res.Cookies())), t)
assertTrue(sid1 == sid2, "expected session IDs to be the same, got different", t)
}
func testPanicIfNoSecret(t *testing.T) {
defer assertPanic(t)
SessionHandler(http.NotFoundHandler(), NewSessionOptions(nil, ""))
}
func testInvalidPath(t *testing.T) {
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
_, ok := GetSession(w)
assertTrue(!ok, "expected session to be nil, got non-nil", t)
w.Write([]byte("ok"))
}, "/foo", false, 0)
defer s.Close()
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected response to have no cookie, got %d", len(res.Cookies())), t)
}
func testValidSubPath(t *testing.T) {
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
_, ok := GetSession(w)
assertTrue(ok, "expected session to be non-nil, got nil", t)
w.Write([]byte("ok"))
}, "/foo", false, 0)
defer s.Close()
res := doRequest(s.URL+"/foo/bar", true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
}
func testSecureOverHttp(t *testing.T) {
s := setupTest(func(w http.ResponseWriter, r *http.Request) {
_, ok := GetSession(w)
assertTrue(ok, "expected session to be non-nil, got nil", t)
w.Write([]byte("ok"))
}, "", true, 0)
defer s.Close()
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
assertTrue(len(res.Cookies()) == 0, fmt.Sprintf("expected response to have no cookie, got %d", len(res.Cookies())), t)
}
// TODO : commented, certificate problem
func xtestSecureOverHttps(t *testing.T) {
opts := NewSessionOptions(store, secret)
opts.CookieTemplate.Secure = true
h := SessionHandler(http.HandlerFunc(
func(w http.ResponseWriter, r *http.Request) {
_, ok := GetSession(w)
assertTrue(ok, "expected session to be non-nil, got nil", t)
w.Write([]byte("ok"))
}), opts)
s := httptest.NewTLSServer(h)
defer s.Close()
res := doRequest(s.URL, true)
assertStatus(http.StatusOK, res.StatusCode, t)
assertBody([]byte("ok"), res, t)
assertTrue(len(res.Cookies()) == 1, fmt.Sprintf("expected response to have 1 cookie, got %d", len(res.Cookies())), t)
}