mirror of
https://github.com/go-gitea/gitea.git
synced 2026-09-26 00:56:33 +02:00
161 lines
4.3 KiB
Go
161 lines
4.3 KiB
Go
// Copyright 2026 The Gitea Authors. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package session
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
func TestVirtualStore_BasicOperations(t *testing.T) {
|
|
p := &VirtualSessionProvider{provider: &mockProvider{}}
|
|
store := NewVirtualStore(p, "test-sid", make(map[any]any))
|
|
|
|
assert.Equal(t, "test-sid", store.ID())
|
|
|
|
require.NoError(t, store.Set("uid", int64(42)))
|
|
assert.Equal(t, int64(42), store.Get("uid"))
|
|
|
|
require.NoError(t, store.Delete("uid"))
|
|
assert.Nil(t, store.Get("uid"))
|
|
}
|
|
|
|
func TestInertVirtualStore_IgnoresWrites(t *testing.T) {
|
|
store := NewInertVirtualStore("dead-sid")
|
|
|
|
assert.Equal(t, "dead-sid", store.ID())
|
|
|
|
// Set should be silently ignored
|
|
require.NoError(t, store.Set("uid", int64(42)))
|
|
assert.Nil(t, store.Get("uid"))
|
|
|
|
// Release should be a no-op
|
|
require.NoError(t, store.Release())
|
|
}
|
|
|
|
func TestVirtualSessionProvider_DestroyTombstone(t *testing.T) {
|
|
mp := &mockProvider{sessions: map[string]map[any]any{
|
|
"sid-1": {"uid": int64(1)},
|
|
}}
|
|
vsp := &VirtualSessionProvider{provider: mp}
|
|
|
|
// Before destroy, Read returns data from the mock provider
|
|
store, err := vsp.Read("sid-1")
|
|
require.NoError(t, err)
|
|
assert.Equal(t, int64(1), store.Get("uid"))
|
|
|
|
// Destroy the session
|
|
require.NoError(t, vsp.Destroy("sid-1"))
|
|
|
|
// Simulate concurrent request recreating the session file:
|
|
// the mock provider now has the session again
|
|
mp.sessions["sid-1"] = map[any]any{"uid": int64(1)}
|
|
|
|
// Read after destroy should return inert store due to tombstone
|
|
store, err = vsp.Read("sid-1")
|
|
require.NoError(t, err)
|
|
assert.Nil(t, store.Get("uid"), "tombstoned session should return empty store")
|
|
|
|
// The inert store should ignore writes and releases
|
|
require.NoError(t, store.Set("uid", int64(99)))
|
|
assert.Nil(t, store.Get("uid"))
|
|
require.NoError(t, store.Release())
|
|
}
|
|
|
|
func TestVirtualSessionProvider_ReadNonExistent(t *testing.T) {
|
|
mp := &mockProvider{sessions: map[string]map[any]any{}}
|
|
vsp := &VirtualSessionProvider{provider: mp}
|
|
|
|
// Read for a session that doesn't exist returns a VirtualStore
|
|
store, err := vsp.Read("no-such-sid")
|
|
require.NoError(t, err)
|
|
assert.Nil(t, store.Get("uid"))
|
|
assert.Equal(t, "no-such-sid", store.ID())
|
|
}
|
|
|
|
func TestVirtualSessionProvider_ExistAlwaysTrue(t *testing.T) {
|
|
vsp := &VirtualSessionProvider{provider: &mockProvider{}}
|
|
|
|
exists, err := vsp.Exist("anything")
|
|
require.NoError(t, err)
|
|
assert.True(t, exists)
|
|
}
|
|
|
|
func TestDestroySessionByID_NilProvider(t *testing.T) {
|
|
// Ensure DestroySessionByID doesn't panic when globalProvider is nil
|
|
old := globalProvider
|
|
globalProvider = nil
|
|
defer func() { globalProvider = old }()
|
|
|
|
assert.NoError(t, DestroySessionByID("anything"))
|
|
}
|
|
|
|
// mockProvider is a minimal in-memory session.Provider for testing
|
|
type mockProvider struct {
|
|
sessions map[string]map[any]any
|
|
}
|
|
|
|
func (m *mockProvider) Init(_ int64, _ string) error { return nil }
|
|
|
|
func (m *mockProvider) Read(sid string) (RawStore, error) {
|
|
if m.sessions == nil {
|
|
m.sessions = make(map[string]map[any]any)
|
|
}
|
|
data, ok := m.sessions[sid]
|
|
if !ok {
|
|
data = make(map[any]any)
|
|
m.sessions[sid] = data
|
|
}
|
|
return &mockStore{sid: sid, data: data}, nil
|
|
}
|
|
|
|
func (m *mockProvider) Exist(sid string) (bool, error) {
|
|
if m.sessions == nil {
|
|
return false, nil
|
|
}
|
|
_, ok := m.sessions[sid]
|
|
return ok, nil
|
|
}
|
|
|
|
func (m *mockProvider) Destroy(sid string) error {
|
|
delete(m.sessions, sid)
|
|
return nil
|
|
}
|
|
|
|
func (m *mockProvider) Regenerate(oldsid, sid string) (RawStore, error) {
|
|
data := m.sessions[oldsid]
|
|
delete(m.sessions, oldsid)
|
|
if data == nil {
|
|
data = make(map[any]any)
|
|
}
|
|
m.sessions[sid] = data
|
|
return &mockStore{sid: sid, data: data}, nil
|
|
}
|
|
|
|
func (m *mockProvider) Count() (int, error) {
|
|
return len(m.sessions), nil
|
|
}
|
|
|
|
func (m *mockProvider) GC() {}
|
|
|
|
// mockStore is a minimal in-memory RawStore for testing
|
|
type mockStore struct {
|
|
sid string
|
|
data map[any]any
|
|
}
|
|
|
|
func (s *mockStore) Set(key, val any) error { s.data[key] = val; return nil }
|
|
func (s *mockStore) Get(key any) any { return s.data[key] }
|
|
func (s *mockStore) Delete(key any) error { delete(s.data, key); return nil }
|
|
func (s *mockStore) ID() string { return s.sid }
|
|
func (s *mockStore) Release() error { return nil }
|
|
func (s *mockStore) Flush() error {
|
|
for k := range s.data {
|
|
delete(s.data, k)
|
|
}
|
|
return nil
|
|
}
|