// steamcache/steamcache_test.go package steamcache import ( "io" "net/http" "os" "path/filepath" "testing" ) func TestCaching(t *testing.T) { td := t.TempDir() os.WriteFile(filepath.Join(td, "key2"), []byte("value2"), 0644) sc := New("localhost:8080", "1G", "1G", td, "", "lru", "lru") w, err := sc.vfs.Create("key", 5) if err != nil { t.Errorf("Create failed: %v", err) } w.Write([]byte("value")) w.Close() w, err = sc.vfs.Create("key1", 6) if err != nil { t.Errorf("Create failed: %v", err) } w.Write([]byte("value1")) w.Close() if sc.diskgc.Size() != 17 { t.Errorf("Size failed: got %d, want %d", sc.diskgc.Size(), 17) } if sc.vfs.Size() != 17 { t.Errorf("Size failed: got %d, want %d", sc.vfs.Size(), 17) } rc, err := sc.vfs.Open("key") if err != nil { t.Errorf("Open failed: %v", err) } d, _ := io.ReadAll(rc) rc.Close() if string(d) != "value" { t.Errorf("Get failed: got %s, want %s", d, "value") } rc, err = sc.vfs.Open("key1") if err != nil { t.Errorf("Open failed: %v", err) } d, _ = io.ReadAll(rc) rc.Close() if string(d) != "value1" { t.Errorf("Get failed: got %s, want %s", d, "value1") } rc, err = sc.vfs.Open("key2") if err != nil { t.Errorf("Open failed: %v", err) } d, _ = io.ReadAll(rc) rc.Close() if string(d) != "value2" { t.Errorf("Get failed: got %s, want %s", d, "value2") } if sc.diskgc.Size() != 17 { t.Errorf("Size failed: got %d, want %d", sc.diskgc.Size(), 17) } if sc.vfs.Size() != 17 { t.Errorf("Size failed: got %d, want %d", sc.vfs.Size(), 17) } sc.memory.Delete("key2") os.Remove(filepath.Join(td, "key2")) if _, err := sc.vfs.Open("key2"); err == nil { t.Errorf("Open failed: got nil, want error") } } func TestCacheMissAndHit(t *testing.T) { sc := New("localhost:8080", "0", "1G", t.TempDir(), "", "lru", "lru") key := "testkey" value := []byte("testvalue") // Simulate miss: but since no upstream, skip full ServeHTTP, test VFS w, err := sc.vfs.Create(key, int64(len(value))) if err != nil { t.Fatal(err) } w.Write(value) w.Close() rc, err := sc.vfs.Open(key) if err != nil { t.Fatal(err) } got, _ := io.ReadAll(rc) rc.Close() if string(got) != string(value) { t.Errorf("expected %s, got %s", value, got) } } func TestHashExtraction(t *testing.T) { // Test the specific key from the user's issue testCases := []struct { filename string expectedHash string shouldHaveHash bool }{ { filename: "e89c81a1a926eb4732e146bc806491da8a7d89ca", expectedHash: "e89c81a1a926eb4732e146bc806491da8a7d89ca", shouldHaveHash: true, // Now it should work with the new standalone hash pattern }, { filename: "chunk_e89c81a1a926eb4732e146bc806491da8a7d89ca", expectedHash: "", shouldHaveHash: false, // No longer supported with simplified patterns }, { filename: "file.e89c81a1a926eb4732e146bc806491da8a7d89ca.chunk", expectedHash: "", shouldHaveHash: false, // No longer supported with simplified patterns }, { filename: "chunk_abc123def456", expectedHash: "", shouldHaveHash: false, // Not 40 chars }, } for _, tc := range testCases { hash, hasHash := extractHashFromFilename(tc.filename) if hasHash != tc.shouldHaveHash { t.Errorf("filename: %s, expected hasHash: %v, got: %v", tc.filename, tc.shouldHaveHash, hasHash) } if hasHash && hash != tc.expectedHash { t.Errorf("filename: %s, expected hash: %s, got: %s", tc.filename, tc.expectedHash, hash) } } } func TestHashCalculation(t *testing.T) { // Test data testData := []byte("Hello, World!") // Calculate hash hash := calculateFileHash(testData) // Expected SHA1 hash of "Hello, World!" expectedHash := "0a0a9f2a6772942557ab5355d76af442f8f65e01" if hash != expectedHash { t.Errorf("Hash calculation failed: expected %s, got %s", expectedHash, hash) } // Test verification if !verifyFileHash(testData, expectedHash) { t.Error("Hash verification failed for correct hash") } if verifyFileHash(testData, "wronghash") { t.Error("Hash verification passed for wrong hash") } } func TestHashVerificationWithRealData(t *testing.T) { // Test with some real data to ensure our hash calculation is correct testCases := []struct { data string expected string }{ {"", "da39a3ee5e6b4b0d3255bfef95601890afd80709"}, // SHA1 of empty string {"test", "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"}, // SHA1 of "test" {"Hello, World!", "0a0a9f2a6772942557ab5355d76af442f8f65e01"}, // SHA1 of "Hello, World!" } for _, tc := range testCases { data := []byte(tc.data) hash := calculateFileHash(data) if hash != tc.expected { t.Errorf("Hash calculation failed for '%s': expected %s, got %s", tc.data, tc.expected, hash) } if !verifyFileHash(data, tc.expected) { t.Errorf("Hash verification failed for '%s'", tc.data) } } } func TestResponseHashCalculation(t *testing.T) { // Create a mock HTTP response resp := &http.Response{ StatusCode: 200, Status: "200 OK", Header: http.Header{ "Content-Type": []string{"application/octet-stream"}, "Content-Length": []string{"13"}, "Cache-Control": []string{"public, max-age=3600"}, }, } bodyData := []byte("Hello, World!") // Calculate response hash responseHash := calculateResponseHash(resp, bodyData) // The hash should be different from just the body hash bodyHash := calculateFileHash(bodyData) if responseHash == bodyHash { t.Error("Response hash should be different from body hash when headers are present") } // Test that the same response produces the same hash responseHash2 := calculateResponseHash(resp, bodyData) if responseHash != responseHash2 { t.Error("Response hash should be consistent for the same response") } // Test with different headers resp2 := &http.Response{ StatusCode: 200, Status: "200 OK", Header: http.Header{ "Content-Type": []string{"text/plain"}, "Content-Length": []string{"13"}, }, } responseHash3 := calculateResponseHash(resp2, bodyData) if responseHash == responseHash3 { t.Error("Response hash should be different for different headers") } }