Initial commit: Open sourcing all of the Maple Open Technologies code.
This commit is contained in:
commit
755d54a99d
2010 changed files with 448675 additions and 0 deletions
207
cloud/maplefile-backend/test/integration/memory_leak_test.go
Normal file
207
cloud/maplefile-backend/test/integration/memory_leak_test.go
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
// Package integration provides integration tests for memory leak detection.
|
||||
//
|
||||
//go:build integration
|
||||
// +build integration
|
||||
|
||||
package integration
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/awnumar/memguard"
|
||||
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/security/securebytes"
|
||||
"codeberg.org/mapleopentech/monorepo/cloud/maplefile-backend/pkg/security/securestring"
|
||||
)
|
||||
|
||||
// TestSecureStringMemoryLeak verifies SecureString doesn't leak memory.
|
||||
func TestSecureStringMemoryLeak(t *testing.T) {
|
||||
// Force GC before measurement
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memBefore runtime.MemStats
|
||||
runtime.ReadMemStats(&memBefore)
|
||||
|
||||
// Perform 10000 SecureString operations
|
||||
for i := 0; i < 10000; i++ {
|
||||
s, err := securestring.NewSecureString("test data that should be cleaned up properly")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create SecureString: %v", err)
|
||||
}
|
||||
_ = s.String() // Access the string
|
||||
s.Wipe()
|
||||
}
|
||||
|
||||
// Force GC after operations
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memAfter runtime.MemStats
|
||||
runtime.ReadMemStats(&memAfter)
|
||||
|
||||
// Check for memory leak - allow up to 5MB growth for test overhead
|
||||
heapGrowth := int64(memAfter.HeapAlloc) - int64(memBefore.HeapAlloc)
|
||||
if heapGrowth > 5*1024*1024 {
|
||||
t.Errorf("Possible memory leak in SecureString: heap grew by %d bytes", heapGrowth)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSecureBytesMemoryLeak verifies SecureBytes doesn't leak memory.
|
||||
func TestSecureBytesMemoryLeak(t *testing.T) {
|
||||
// Force GC before measurement
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memBefore runtime.MemStats
|
||||
runtime.ReadMemStats(&memBefore)
|
||||
|
||||
// Perform 10000 SecureBytes operations
|
||||
for i := 0; i < 10000; i++ {
|
||||
data := make([]byte, 64)
|
||||
for j := range data {
|
||||
data[j] = byte(i % 256)
|
||||
}
|
||||
|
||||
sb, err := securebytes.NewSecureBytes(data)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create SecureBytes: %v", err)
|
||||
}
|
||||
_ = sb.Bytes() // Access the bytes
|
||||
sb.Wipe()
|
||||
}
|
||||
|
||||
// Force GC after operations
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memAfter runtime.MemStats
|
||||
runtime.ReadMemStats(&memAfter)
|
||||
|
||||
// Check for memory leak
|
||||
heapGrowth := int64(memAfter.HeapAlloc) - int64(memBefore.HeapAlloc)
|
||||
if heapGrowth > 5*1024*1024 {
|
||||
t.Errorf("Possible memory leak in SecureBytes: heap grew by %d bytes", heapGrowth)
|
||||
}
|
||||
}
|
||||
|
||||
// TestMemguardWipeBytesEffectiveness verifies memguard.WipeBytes actually zeros memory.
|
||||
func TestMemguardWipeBytesEffectiveness(t *testing.T) {
|
||||
// Create sensitive data
|
||||
sensitiveData := []byte("super-secret-password-12345")
|
||||
originalLen := len(sensitiveData)
|
||||
|
||||
// Wipe the data
|
||||
memguard.WipeBytes(sensitiveData)
|
||||
|
||||
// Verify all bytes are zero
|
||||
for i, b := range sensitiveData {
|
||||
if b != 0 {
|
||||
t.Errorf("Byte at position %d not wiped: got %d, expected 0", i, b)
|
||||
}
|
||||
}
|
||||
|
||||
// Verify length unchanged
|
||||
if len(sensitiveData) != originalLen {
|
||||
t.Errorf("Length changed after wipe: got %d, expected %d", len(sensitiveData), originalLen)
|
||||
}
|
||||
}
|
||||
|
||||
// TestSecureStringWipeEffectiveness verifies SecureString.Wipe() actually cleans up.
|
||||
func TestSecureStringWipeEffectiveness(t *testing.T) {
|
||||
secret := "my-super-secret-token"
|
||||
ss, err := securestring.NewSecureString(secret)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create SecureString: %v", err)
|
||||
}
|
||||
|
||||
// Verify we can access the string before wiping
|
||||
if ss.String() != secret {
|
||||
t.Error("SecureString didn't store the original value correctly")
|
||||
}
|
||||
|
||||
// Wipe the secure string
|
||||
ss.Wipe()
|
||||
|
||||
// After wiping, String() should return empty
|
||||
if ss.String() != "" {
|
||||
t.Error("SecureString.String() should return empty after Wipe()")
|
||||
}
|
||||
}
|
||||
|
||||
// TestLockedBufferMemoryLeak verifies LockedBuffer doesn't leak memory.
|
||||
func TestLockedBufferMemoryLeak(t *testing.T) {
|
||||
// Force GC before measurement
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memBefore runtime.MemStats
|
||||
runtime.ReadMemStats(&memBefore)
|
||||
|
||||
// Perform 10000 LockedBuffer operations
|
||||
for i := 0; i < 10000; i++ {
|
||||
buf := memguard.NewBuffer(64)
|
||||
copy(buf.Bytes(), []byte("test-data-for-locked-buffer"))
|
||||
buf.Destroy()
|
||||
}
|
||||
|
||||
// Force GC after operations
|
||||
runtime.GC()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
var memAfter runtime.MemStats
|
||||
runtime.ReadMemStats(&memAfter)
|
||||
|
||||
// Check for memory leak
|
||||
heapGrowth := int64(memAfter.HeapAlloc) - int64(memBefore.HeapAlloc)
|
||||
if heapGrowth > 5*1024*1024 {
|
||||
t.Errorf("Possible memory leak in LockedBuffer: heap grew by %d bytes", heapGrowth)
|
||||
}
|
||||
}
|
||||
|
||||
// TestConcurrentSecureStringOperations tests thread safety.
|
||||
func TestConcurrentSecureStringOperations(t *testing.T) {
|
||||
done := make(chan bool, 10)
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
go func(id int) {
|
||||
defer func() { done <- true }()
|
||||
|
||||
for j := 0; j < 1000; j++ {
|
||||
ss, err := securestring.NewSecureString("concurrent-test-data")
|
||||
if err != nil {
|
||||
t.Errorf("Goroutine %d: Failed to create SecureString: %v", id, err)
|
||||
return
|
||||
}
|
||||
_ = ss.String()
|
||||
ss.Wipe()
|
||||
}
|
||||
}(i)
|
||||
}
|
||||
|
||||
// Wait for all goroutines
|
||||
for i := 0; i < 10; i++ {
|
||||
<-done
|
||||
}
|
||||
}
|
||||
|
||||
// TestRepeatedWipeCalls verifies multiple Wipe() calls don't panic.
|
||||
func TestRepeatedWipeCalls(t *testing.T) {
|
||||
ss, err := securestring.NewSecureString("test-data")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create SecureString: %v", err)
|
||||
}
|
||||
|
||||
// Multiple wipe calls should be safe
|
||||
for i := 0; i < 10; i++ {
|
||||
err := ss.Wipe()
|
||||
if err != nil {
|
||||
t.Errorf("Wipe() call %d returned error: %v", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Run integration tests with:
|
||||
// go test -tags=integration -v ./test/integration/
|
||||
Loading…
Add table
Add a link
Reference in a new issue