mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-05 09:03:54 -04:00
200 lines
5.6 KiB
Go
200 lines
5.6 KiB
Go
package downloader
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"path/filepath"
|
|
"sync/atomic"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
const (
|
|
retryDelay = 100 * time.Millisecond
|
|
)
|
|
|
|
func TestDownloadToFile_Success(t *testing.T) {
|
|
// Create a test server that responds successfully
|
|
content := "test file content"
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte(content))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Create a temporary file for download
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
// Download the file
|
|
err := DownloadToFile(context.Background(), retryDelay, server.URL, dstFile)
|
|
if err != nil {
|
|
t.Fatalf("expected no error, got: %v", err)
|
|
}
|
|
|
|
// Verify the file content
|
|
data, err := os.ReadFile(dstFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read downloaded file: %v", err)
|
|
}
|
|
|
|
if string(data) != content {
|
|
t.Errorf("expected content %q, got %q", content, string(data))
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_SuccessAfterRetry(t *testing.T) {
|
|
content := "test file content after retry"
|
|
var attemptCount atomic.Int32
|
|
|
|
// Create a test server that fails on first attempt, succeeds on second
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
attempt := attemptCount.Add(1)
|
|
if attempt == 1 {
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
_, _ = w.Write([]byte("error"))
|
|
return
|
|
}
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte(content))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Create a temporary file for download
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
// Download the file (should succeed after retry)
|
|
if err := DownloadToFile(context.Background(), 10*time.Millisecond, server.URL, dstFile); err != nil {
|
|
t.Fatalf("expected no error after retry, got: %v", err)
|
|
}
|
|
|
|
// Verify the file content
|
|
data, err := os.ReadFile(dstFile)
|
|
if err != nil {
|
|
t.Fatalf("failed to read downloaded file: %v", err)
|
|
}
|
|
|
|
if string(data) != content {
|
|
t.Errorf("expected content %q, got %q", content, string(data))
|
|
}
|
|
|
|
// Verify it took 2 attempts
|
|
if attemptCount.Load() != 2 {
|
|
t.Errorf("expected 2 attempts, got %d", attemptCount.Load())
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_FailsAfterRetry(t *testing.T) {
|
|
var attemptCount atomic.Int32
|
|
|
|
// Create a test server that always fails
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
attemptCount.Add(1)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
_, _ = w.Write([]byte("error"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Create a temporary file for download
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
// Download the file (should fail after retry)
|
|
if err := DownloadToFile(context.Background(), 10*time.Millisecond, server.URL, dstFile); err == nil {
|
|
t.Fatal("expected error after retry, got nil")
|
|
}
|
|
|
|
// Verify it tried 2 times
|
|
if attemptCount.Load() != 2 {
|
|
t.Errorf("expected 2 attempts, got %d", attemptCount.Load())
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_ContextCancellationDuringRetry(t *testing.T) {
|
|
var attemptCount atomic.Int32
|
|
|
|
// Create a test server that always fails
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
attemptCount.Add(1)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Create a temporary file for download
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
// Create a context that will be cancelled during retry delay
|
|
ctx, cancel := context.WithCancel(context.Background())
|
|
|
|
// Cancel after a short delay (during the retry sleep)
|
|
go func() {
|
|
time.Sleep(100 * time.Millisecond)
|
|
cancel()
|
|
}()
|
|
|
|
// Download the file (should fail due to context cancellation during retry)
|
|
err := DownloadToFile(ctx, 1*time.Second, server.URL, dstFile)
|
|
if err == nil {
|
|
t.Fatal("expected error due to context cancellation, got nil")
|
|
}
|
|
|
|
// Should have only made 1 attempt (cancelled during retry delay)
|
|
if attemptCount.Load() != 1 {
|
|
t.Errorf("expected 1 attempt, got %d", attemptCount.Load())
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_InvalidURL(t *testing.T) {
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
err := DownloadToFile(context.Background(), retryDelay, "://invalid-url", dstFile)
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid URL, got nil")
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_InvalidDestination(t *testing.T) {
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
w.WriteHeader(http.StatusOK)
|
|
_, _ = w.Write([]byte("test"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Use an invalid destination path
|
|
err := DownloadToFile(context.Background(), retryDelay, server.URL, "/invalid/path/that/does/not/exist/file.txt")
|
|
if err == nil {
|
|
t.Fatal("expected error for invalid destination, got nil")
|
|
}
|
|
}
|
|
|
|
func TestDownloadToFile_NoRetry(t *testing.T) {
|
|
var attemptCount atomic.Int32
|
|
|
|
// Create a test server that always fails
|
|
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
attemptCount.Add(1)
|
|
w.WriteHeader(http.StatusInternalServerError)
|
|
_, _ = w.Write([]byte("error"))
|
|
}))
|
|
defer server.Close()
|
|
|
|
// Create a temporary file for download
|
|
tempDir := t.TempDir()
|
|
dstFile := filepath.Join(tempDir, "downloaded.txt")
|
|
|
|
// Download the file with retryDelay = 0 (should not retry)
|
|
if err := DownloadToFile(context.Background(), 0, server.URL, dstFile); err == nil {
|
|
t.Fatal("expected error, got nil")
|
|
}
|
|
|
|
// Verify it only made 1 attempt (no retry)
|
|
if attemptCount.Load() != 1 {
|
|
t.Errorf("expected 1 attempt, got %d", attemptCount.Load())
|
|
}
|
|
}
|