fix: move checksum to HTTP opts, fix mismatch retry, scope get_download_speed to aggregate-only

This commit is contained in:
ashish6298 committed 2026-09-25 12:15:50 +05:30
1 parent 929e2d2d7c
commit b5e8d61f01
16 files changed
+501 -655

No files matched your search

+147 -16
View File
@@ -10,6 +10,7 @@ import (
"strings"
"testing"
"github.com/GopeedLab/gopeed/internal/fetcher"
"github.com/GopeedLab/gopeed/internal/test"
"github.com/GopeedLab/gopeed/pkg/base"
"github.com/GopeedLab/gopeed/pkg/protocol/http"
@@ -44,10 +45,10 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
Name: "test_valid_md5.txt",
Extra: &http.OptsExtra{
Connections: 1,
},
Checksum: &base.ChecksumOption{
Algorithm: "md5",
Expected: correctMd5,
Checksum: &http.ChecksumOption{
Algorithm: "md5",
Expected: correctMd5,
},
},
}
@@ -71,10 +72,10 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
Name: "test_valid_sha256.txt",
Extra: &http.OptsExtra{
Connections: 1,
},
Checksum: &base.ChecksumOption{
Algorithm: "sha256",
Expected: correctSha256,
Checksum: &http.ChecksumOption{
Algorithm: "sha256",
Expected: correctSha256,
},
},
}
@@ -98,10 +99,10 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
Name: "test_wrong_md5.txt",
Extra: &http.OptsExtra{
Connections: 1,
},
Checksum: &base.ChecksumOption{
Algorithm: "md5",
Expected: wrongHash,
Checksum: &http.ChecksumOption{
Algorithm: "md5",
Expected: wrongHash,
},
},
}
@@ -129,10 +130,10 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
Name: "test_unsupported.txt",
Extra: &http.OptsExtra{
Connections: 1,
},
Checksum: &base.ChecksumOption{
Algorithm: "invalid-algo",
Expected: wrongHash,
Checksum: &http.ChecksumOption{
Algorithm: "invalid-algo",
Expected: wrongHash,
},
},
}
@@ -149,6 +150,106 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
if !strings.Contains(err.Error(), "unsupported checksum algorithm") {
t.Fatalf("expected 'unsupported checksum algorithm' in error, got %v", err)
}
if f.checksumFailed.Load() {
t.Fatal("checksumFailed flag should NOT be set on unsupported algorithm error")
}
})
t.Run("Case-Insensitive Hash Comparison", func(t *testing.T) {
f := buildFetcher()
defer f.Close()
opts := &base.Options{
Path: t.TempDir(),
Name: "test_case_insensitive.txt",
Extra: &http.OptsExtra{
Connections: 1,
Checksum: &http.ChecksumOption{
Algorithm: "sha256",
Expected: strings.ToUpper(correctSha256),
},
},
}
if err := f.Resolve(&base.Request{URL: server.URL + "/test.txt"}, opts); err != nil {
t.Fatalf("Resolve error: %v", err)
}
if err := f.Start(); err != nil {
t.Fatalf("Start error: %v", err)
}
if err := f.Wait(); err != nil {
t.Fatalf("Wait error (expected success with upper case hash): %v", err)
}
})
t.Run("Empty Expected Checksum (Skipped)", func(t *testing.T) {
f := buildFetcher()
defer f.Close()
opts := &base.Options{
Path: t.TempDir(),
Name: "test_empty_expected.txt",
Extra: &http.OptsExtra{
Connections: 1,
Checksum: &http.ChecksumOption{
Algorithm: "",
Expected: "",
},
},
}
if err := f.Resolve(&base.Request{URL: server.URL + "/test.txt"}, opts); err != nil {
t.Fatalf("Resolve error: %v", err)
}
if err := f.Start(); err != nil {
t.Fatalf("Start error: %v", err)
}
if err := f.Wait(); err != nil {
t.Fatalf("Wait error (expected skip and success): %v", err)
}
})
t.Run("Large File Multi-Chunk Streaming (>64KB)", func(t *testing.T) {
largeData := make([]byte, 128*1024)
for i := range largeData {
largeData[i] = byte(i % 256)
}
largeSha256Hasher := sha256.New()
largeSha256Hasher.Write(largeData)
largeSha256 := hex.EncodeToString(largeSha256Hasher.Sum(nil))
largeServer := httptest.NewServer(gohttp.HandlerFunc(func(w gohttp.ResponseWriter, r *gohttp.Request) {
w.Header().Set(base.HttpHeaderContentLength, fmt.Sprintf("%d", len(largeData)))
w.Header().Set(base.HttpHeaderAcceptRanges, base.HttpHeaderBytes)
w.WriteHeader(gohttp.StatusOK)
_, _ = w.Write(largeData)
}))
defer largeServer.Close()
f := buildFetcher()
defer f.Close()
opts := &base.Options{
Path: t.TempDir(),
Name: "test_large_file.bin",
Extra: &http.OptsExtra{
Connections: 1,
Checksum: &http.ChecksumOption{
Algorithm: "sha256",
Expected: largeSha256,
},
},
}
if err := f.Resolve(&base.Request{URL: largeServer.URL + "/large.bin"}, opts); err != nil {
t.Fatalf("Resolve error: %v", err)
}
if err := f.Start(); err != nil {
t.Fatalf("Start error: %v", err)
}
if err := f.Wait(); err != nil {
t.Fatalf("Wait error (expected large file checksum success): %v", err)
}
})
t.Run("No Checksum (Opt-in backward compatibility)", func(t *testing.T) {
@@ -174,3 +275,33 @@ func TestFetcher_ChecksumVerification(t *testing.T) {
}
})
}
func TestResetConnectionForRestart_ForceOnRangeDownload(t *testing.T) {
f := buildFetcher()
f.meta = &fetcher.FetcherMeta{
Res: &base.Resource{
Range: true,
},
}
conn := &connection{
Chunk: newChunk(0, 1024),
Downloaded: 512,
Completed: true,
}
conn.Chunk.Downloaded = 512
// Non-forced reset on range-supported download does not reset Chunk.Downloaded
f.resetConnectionForRestart(conn, false)
if conn.Chunk.Downloaded != 512 {
t.Fatalf("expected Chunk.Downloaded to remain 512 when force is false, got %d", conn.Chunk.Downloaded)
}
// Forced reset on range-supported download resets Chunk.Downloaded to 0
f.resetConnectionForRestart(conn, true)
if conn.Chunk.Downloaded != 0 {
t.Fatalf("expected Chunk.Downloaded to be reset to 0 when force is true, got %d", conn.Chunk.Downloaded)
}
if conn.Completed {
t.Fatal("expected Completed to be false after reset")
}
}