Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion middleware/session/data.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func acquireData() *data {
func (d *data) Reset() {
d.Lock()
defer d.Unlock()
d.Data = make(map[any]any)
clear(d.Data)
}

// Get retrieves a value from the data map by key.
Expand Down
76 changes: 76 additions & 0 deletions middleware/session/data_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package session

import (
"reflect"
"testing"

"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -177,6 +178,81 @@
})
}

func mapPointer(m map[any]any) uintptr {
return reflect.ValueOf(m).Pointer()
}

func TestData_ResetPreservesAllocation(t *testing.T) {
t.Parallel()

d := acquireData()
t.Cleanup(func() {
d.Reset()
dataPool.Put(d)
})

originalPtr := mapPointer(d.Data)

d.Set("key1", "value1")
d.Set("key2", "value2")
require.Equal(t, originalPtr, mapPointer(d.Data), "Expected map pointer to stay constant after writes")

d.Reset()
require.Empty(t, d.Data, "Expected data map to be empty after reset")
require.Equal(t, originalPtr, mapPointer(d.Data), "Expected reset to preserve underlying map")

d.Set("key3", "value3")
require.Nil(t, d.Get("key1"), "Expected cleared key not to leak after reset")
require.Equal(t, originalPtr, mapPointer(d.Data), "Expected map pointer to remain stable after further writes")
}

func TestData_PoolReuseDoesNotLeakEntries(t *testing.T) {
t.Parallel()

acquired := make([]*data, 0, 6)
t.Cleanup(func() {
for _, item := range acquired {
item.Reset()
dataPool.Put(item)
}
})

acquireWithCleanup := func() *data {
d := acquireData()
acquired = append(acquired, d)
return d
}

first := acquireWithCleanup()
first.Set("key1", "value1")
first.Set("key2", "value2")
first.Reset()

originalPtr := mapPointer(first.Data)

var reused *data
for i := 0; i < 5; i++ {
candidate := acquireWithCleanup()
if mapPointer(candidate.Data) == originalPtr {
reused = candidate
break
}
require.Empty(t, candidate.Data, "Expected pooled data to be empty when new instance is returned")
require.Nil(t, candidate.Get("key2"), "Expected no leakage of prior entries on alternate pooled instance")
}

if reused == nil {

Check failure on line 244 in middleware/session/data_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011(related information): this check suggests that the pointer can be nil (staticcheck)
t.Skip("sync.Pool returned a different instance; reuse cannot be asserted")
}

require.Equal(t, originalPtr, mapPointer(reused.Data), "Expected pooled data to reuse cleared map")

Check failure on line 248 in middleware/session/data_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011: possible nil pointer dereference (staticcheck)
require.Empty(t, reused.Data, "Expected pooled data to be empty after reuse")

Check failure on line 249 in middleware/session/data_test.go

View workflow job for this annotation

GitHub Actions / lint

SA5011: possible nil pointer dereference (staticcheck)
require.Nil(t, reused.Get("key2"), "Expected no leakage of prior entries on reuse")

reused.Set("key4", "value4")
require.Equal(t, "value4", reused.Get("key4"), "Expected pooled map to accept new values")
}

func TestData_Delete(t *testing.T) {
t.Parallel()

Expand Down
Loading