//go:build linux || freebsd // +build linux freebsd package ftp import ( "os" "path/filepath" "testing" "codeberg.org/petrbalvin/goget/internal/output" ) // TestSaveFTPResume verifies the helper persists partial FTP progress // to a .goget.meta sidecar and that the sidecar is suitable for a // subsequent goget --resume invocation. The function is called from // Client.DownloadFile when ctx is cancelled mid-transfer; without a // working sidecar the user's interrupted download cannot be continued. func TestSaveFTPResume(t *testing.T) { tmp := t.TempDir() out := filepath.Join(tmp, "file.bin") // 1. First call records partial progress. if err := saveFTPResume("ftp://example.com/file.bin", out, 4096, 1<<20); err != nil { t.Fatalf("saveFTPResume: %v", err) } meta, err := output.LoadResumeMetadata(out) if err != nil { t.Fatalf("LoadResumeMetadata: %v", err) } if meta == nil { t.Fatal("expected resume metadata, got nil") } if meta.URL != "ftp://example.com/file.bin" { t.Errorf("URL = %q, want ftp://example.com/file.bin", meta.URL) } if meta.Downloaded != 4096 { t.Errorf("Downloaded = %d, want 4096", meta.Downloaded) } if meta.Total != 1<<20 { t.Errorf("Total = %d, want %d", meta.Total, 1<<20) } // 2. Second call overwrites the sidecar with a later snapshot. if err := saveFTPResume("ftp://example.com/file.bin", out, 8192, 1<<20); err != nil { t.Fatalf("saveFTPResume (2): %v", err) } meta2, _ := output.LoadResumeMetadata(out) if meta2 == nil || meta2.Downloaded != 8192 { t.Errorf("second call did not update sidecar: %+v", meta2) } // 3. Zero-byte save is a no-op (no point persisting a sidecar // for an empty transfer). out2 := filepath.Join(tmp, "empty.bin") if err := saveFTPResume("ftp://x", out2, 0, 100); err != nil { t.Errorf("zero-byte save returned error: %v", err) } if _, err := os.Stat(out2 + output.ResumeMetaFileSuffix); !os.IsNotExist(err) { t.Errorf("expected no sidecar for zero-byte save, got one") } }