Skip to content

Commit d75f52a

Browse files
committed
test(fscache): add filesystem limits tests and benchmarks
Add comprehensive testing for long URL handling to validate fragmentation behavior discussed in PR #17. - Test URL lengths up to 100KB - Benchmark performance scaling - Verify directory depth handling Related to #16, addresses concerns from PR #17
1 parent f14f6a8 commit d75f52a

1 file changed

Lines changed: 121 additions & 0 deletions

File tree

store/fscache/issue16_test.go

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright (c) 2025 Bart Venter <bartventer@proton.me>
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package fscache
16+
17+
import (
18+
"fmt"
19+
"os"
20+
"runtime"
21+
"strconv"
22+
"strings"
23+
"testing"
24+
25+
"github.com/bartventer/httpcache/internal/testutil"
26+
)
27+
28+
func Test_Issue16_LongURLFragmentation(t *testing.T) {
29+
t.Attr("GOOS", runtime.GOOS)
30+
t.Attr("GOARCH", runtime.GOARCH)
31+
t.Attr("GOVERSION", runtime.Version())
32+
33+
tempDir := t.TempDir()
34+
cache, err := Open("test-fragmentation", WithBaseDir(tempDir))
35+
testutil.RequireNoError(t, err)
36+
37+
tests := []struct {
38+
name string
39+
urlLen int
40+
expectOK bool
41+
}{
42+
{"normal URL", 100, true},
43+
{"long URL (1KB)", 1024, true},
44+
{"very long URL (4KB)", 4096, true},
45+
{"extremely long URL (10KB)", 10240, true},
46+
{"massive URL (100KB)", 102400, true},
47+
}
48+
49+
for _, tt := range tests {
50+
t.Run(tt.name, func(t *testing.T) {
51+
// Generate URL of specified length
52+
url := "https://example.com/" + strings.Repeat(
53+
"x",
54+
tt.urlLen-len("https://example.com/"),
55+
)
56+
57+
// Get fragmentation details
58+
filename := cache.fn.FileName(url)
59+
depth := strings.Count(filename, string(os.PathSeparator))
60+
t.Attr("URLLength", strconv.Itoa(len(url)))
61+
t.Attr("PathLength", strconv.Itoa(len(filename)))
62+
t.Attr("DirectoryDepth", strconv.Itoa(depth))
63+
64+
// Test round-trip: Set -> Get -> Delete
65+
data := []byte("test data")
66+
err := cache.Set(url, data)
67+
68+
if tt.expectOK {
69+
testutil.RequireNoError(t, err)
70+
71+
retrieved, getErr := cache.Get(url)
72+
testutil.RequireNoError(t, getErr)
73+
testutil.AssertEqual(t, string(data), string(retrieved))
74+
75+
setErr := cache.Delete(url)
76+
testutil.RequireNoError(t, setErr)
77+
78+
t.Logf("Successfully handled %d byte URL", len(url))
79+
} else if err == nil {
80+
t.Errorf("Expected error for %d byte URL, but got none", len(url))
81+
}
82+
})
83+
}
84+
}
85+
86+
func Benchmark_Issue16_LongURLs(b *testing.B) {
87+
tempDir := b.TempDir()
88+
cache, err := Open("bench-long-urls", WithBaseDir(tempDir))
89+
if err != nil {
90+
b.Fatal(err)
91+
}
92+
93+
urlLengths := []int{100, 1000, 10000, 50000}
94+
95+
for _, length := range urlLengths {
96+
b.Run(fmt.Sprintf("url_length_%d", length), func(b *testing.B) {
97+
url := "https://example.com/" + strings.Repeat("x", length-len("https://example.com/"))
98+
data := []byte("benchmark data")
99+
100+
b.ResetTimer()
101+
for i := 0; b.Loop(); i++ {
102+
key := fmt.Sprintf("%s-%d", url, i)
103+
104+
err := cache.Set(key, data)
105+
if err != nil {
106+
b.Fatal(err)
107+
}
108+
109+
_, err = cache.Get(key)
110+
if err != nil {
111+
b.Fatal(err)
112+
}
113+
114+
err = cache.Delete(key)
115+
if err != nil {
116+
b.Fatal(err)
117+
}
118+
}
119+
})
120+
}
121+
}

0 commit comments

Comments
 (0)