Enhance DiskFS initialization and error handling
- Updated `disk.New` to support asynchronous initialization for large caches, improving responsiveness during startup. - Introduced an eviction function parameter to `disk.New`, ensuring proper handling of over-capacity scenarios. - Enhanced error handling in various components, including memory and disk tests, to ensure robustness and clarity. - Refactored tests to validate new behaviors, including checks for delayed attachment and proper error propagation. - Removed obsolete error handling code and tests related to the now-deleted errors package, streamlining the codebase.
This commit is contained in:
+71
-14
@@ -3,6 +3,7 @@ package memory
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
@@ -11,7 +12,10 @@ import (
|
||||
|
||||
func TestMemoryFS_Basic(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(1024 * 1024)
|
||||
m, err := New(1024 * 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if m.Name() != "MemoryFS" {
|
||||
t.Error("bad name")
|
||||
}
|
||||
@@ -52,7 +56,10 @@ func TestMemoryFS_Basic(t *testing.T) {
|
||||
|
||||
func TestMemoryFS_EvictUnderPressure(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(500)
|
||||
m, err := New(500)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// create 3x200 = 600 >500, should trigger internal? but direct evict call
|
||||
for i := 0; i < 3; i++ {
|
||||
w, _ := m.Create("f"+string(rune('0'+i)), 200)
|
||||
@@ -69,7 +76,10 @@ func TestMemoryFS_EvictUnderPressure(t *testing.T) {
|
||||
func TestMemoryFS_SizeNeverExceedsAfterEvict(t *testing.T) {
|
||||
t.Parallel()
|
||||
cap := int64(1000)
|
||||
m := New(cap)
|
||||
m, err := New(cap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// Cycle through strategies (randomized feel via mod), use testKey, stricter post-evict with documented epsilon.
|
||||
strats := []func(uint) uint{m.EvictLRU, func(n uint) uint { return m.EvictBySize(n, true) }, m.EvictFIFO, m.EvictLFU, m.EvictHybrid}
|
||||
for i := 0; i < 50; i++ { // more cycles
|
||||
@@ -97,7 +107,10 @@ func TestMemoryFS_ConcurrentCreateOpenDelete(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
m := New(10 * 1024 * 1024)
|
||||
m, err := New(10 * 1024 * 1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
const N = 50
|
||||
var ops int64
|
||||
@@ -137,7 +150,10 @@ func TestMemoryFS_ConcurrentCreateOpenDelete(t *testing.T) {
|
||||
}
|
||||
|
||||
func BenchmarkMemoryFS_CreateOpen(b *testing.B) {
|
||||
m := New(64 * 1024 * 1024)
|
||||
m, err := New(64 * 1024 * 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
data := make([]byte, 4096)
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
@@ -162,7 +178,10 @@ func BenchmarkMemoryFS_CreateOpen(b *testing.B) {
|
||||
// BenchmarkMemoryFS_EvictionUnderPressure exercises memory eviction under synthetic pressure (parallels BenchmarkDiskFS_EvictionUnderPressure).
|
||||
// Uses cycling keys via testKey for stable behavior; exercises LRU path (other strategies lightly covered via existing tests + EvictHybrid uses DecayedScore).
|
||||
func BenchmarkMemoryFS_EvictionUnderPressure(b *testing.B) {
|
||||
m := New(1 * 1024 * 1024)
|
||||
m, err := New(1 * 1024 * 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -183,7 +202,10 @@ func BenchmarkMemoryFS_EvictionUnderPressure(b *testing.B) {
|
||||
// BenchmarkMemoryFS_EvictBySizeUnderPressure parallels the disk eviction strategy testing.
|
||||
// Exercises EvictBySize under repeated pressure.
|
||||
func BenchmarkMemoryFS_EvictBySizeUnderPressure(b *testing.B) {
|
||||
m := New(1 * 1024 * 1024)
|
||||
m, err := New(1 * 1024 * 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -195,7 +217,7 @@ func BenchmarkMemoryFS_EvictBySizeUnderPressure(b *testing.B) {
|
||||
w.Write(make([]byte, 64*1024))
|
||||
w.Close()
|
||||
}
|
||||
m.EvictBySize(512 * 1024, true) // ascending = evict smallest first
|
||||
m.EvictBySize(512*1024, true) // ascending = evict smallest first
|
||||
}
|
||||
_ = m // keep
|
||||
}
|
||||
@@ -203,7 +225,10 @@ func BenchmarkMemoryFS_EvictBySizeUnderPressure(b *testing.B) {
|
||||
// BenchmarkMemoryFS_EvictHybridUnderPressure exercises the hybrid strategy (which uses
|
||||
// the centralized DecayedScore) under pressure. Provides coverage for the time-decayed scoring.
|
||||
func BenchmarkMemoryFS_EvictHybridUnderPressure(b *testing.B) {
|
||||
m := New(1 * 1024 * 1024)
|
||||
m, err := New(1 * 1024 * 1024)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
@@ -222,7 +247,10 @@ func BenchmarkMemoryFS_EvictHybridUnderPressure(b *testing.B) {
|
||||
|
||||
func TestMemoryFS_Stats(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(1024)
|
||||
m, err := New(1024)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
stats := m.GetFragmentationStats()
|
||||
if stats["buffer_count"] != 0 {
|
||||
t.Error("initial buffers >0?")
|
||||
@@ -242,7 +270,10 @@ func TestMemoryFS_ConcurrentCloseAndEvict_RaceFree(t *testing.T) {
|
||||
t.Skip()
|
||||
}
|
||||
t.Parallel()
|
||||
m := New(2 * 1024 * 1024) // 2MB
|
||||
m, err := New(2 * 1024 * 1024) // 2MB
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var wg sync.WaitGroup
|
||||
stopCh := make(chan struct{})
|
||||
const writers = 3
|
||||
@@ -317,7 +348,10 @@ func TestMemoryFS_ConcurrentCloseAndEvict_RaceFree(t *testing.T) {
|
||||
|
||||
func TestMemoryFS_EvictVariantsAndErrors(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(800)
|
||||
m, err := New(800)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// populate
|
||||
for i := 0; i < 4; i++ {
|
||||
w, _ := m.Create("ev"+string(rune('0'+i)), 150)
|
||||
@@ -361,7 +395,10 @@ func TestMemoryFS_EvictVariantsAndErrors(t *testing.T) {
|
||||
|
||||
func TestMemoryFS_AllEvictStrategies(t *testing.T) {
|
||||
t.Parallel()
|
||||
m := New(300)
|
||||
m, err := New(300)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for i := 0; i < 3; i++ {
|
||||
w, _ := m.Create("s"+string(rune(i)), 120)
|
||||
w.Write(make([]byte, 120))
|
||||
@@ -387,7 +424,10 @@ func TestMemoryFS_EvictBoundedLargeN(t *testing.T) {
|
||||
}
|
||||
t.Parallel()
|
||||
cap := int64(128 * 1024)
|
||||
m := New(cap)
|
||||
m, err := New(cap)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
const nFiles = 3000 // >> maxEvictBatch
|
||||
const fSize = 128
|
||||
for i := 0; i < nFiles; i++ {
|
||||
@@ -417,3 +457,20 @@ func TestMemoryFS_EvictBoundedLargeN(t *testing.T) {
|
||||
}
|
||||
_ = totalEvicted
|
||||
}
|
||||
|
||||
// TestMemoryFS_NewInvalidCapacity exercises the new error return (was panic) for ctor hygiene (Item 3 coverage).
|
||||
func TestMemoryFS_NewInvalidCapacity(t *testing.T) {
|
||||
t.Parallel()
|
||||
_, err := New(0)
|
||||
if err == nil {
|
||||
t.Fatal("expected error for capacity=0")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "must be greater than 0") {
|
||||
t.Errorf("err %q missing 'must be greater than 0'", err)
|
||||
}
|
||||
|
||||
_, err = New(-1)
|
||||
if err == nil || !strings.Contains(err.Error(), "must be greater than 0") {
|
||||
t.Errorf("negative capacity should return error containing phrase, got %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user