Implement a native chunked resumable upload API and frontend integration to support reliable large file uploads. Changes include: - Added a 3-step resumable upload API flow (create session, upload chunks, complete session). - Introduced configuration options for chunk size, retention hours, and toggling the feature. - Updated the frontend to utilize resumable uploads with progress tracking. - Configured temporary chunk storage under `data/tmp/uploads` with automatic cleanup. - Documented the API flow and configuration in the README.
81 lines
2.1 KiB
Go
81 lines
2.1 KiB
Go
package config
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestParseMegabytes(t *testing.T) {
|
|
tests := map[string]int64{
|
|
"0.5": 512 * 1024,
|
|
"0.5Mb": 512 * 1024,
|
|
"1mb": 1024 * 1024,
|
|
"1MB": 1024 * 1024,
|
|
"1.5Mb": 1536 * 1024,
|
|
" 2 ": 2 * 1024 * 1024,
|
|
}
|
|
|
|
for input, want := range tests {
|
|
got, err := parseMegabytes(input)
|
|
if err != nil {
|
|
t.Fatalf("parseMegabytes(%q) returned error: %v", input, err)
|
|
}
|
|
if got != want {
|
|
t.Fatalf("parseMegabytes(%q) = %d, want %d", input, got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestParseMegabytesRejectsInvalidValues(t *testing.T) {
|
|
tests := []string{"", "0", "-1", "abc"}
|
|
|
|
for _, input := range tests {
|
|
if _, err := parseMegabytes(input); err == nil {
|
|
t.Fatalf("parseMegabytes(%q) returned nil error", input)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestEnvBool(t *testing.T) {
|
|
t.Setenv("WARPBOX_TEST_BOOL", "false")
|
|
if got := envBool("WARPBOX_TEST_BOOL", true); got {
|
|
t.Fatalf("envBool() = true, want false")
|
|
}
|
|
|
|
t.Setenv("WARPBOX_TEST_BOOL", "1")
|
|
if got := envBool("WARPBOX_TEST_BOOL", false); !got {
|
|
t.Fatalf("envBool() = false, want true")
|
|
}
|
|
|
|
t.Setenv("WARPBOX_TEST_BOOL", "not-a-bool")
|
|
if got := envBool("WARPBOX_TEST_BOOL", true); !got {
|
|
t.Fatalf("envBool() did not fall back to true")
|
|
}
|
|
}
|
|
|
|
func TestLoadDefaultsUseLargeUploadFriendlyTimeouts(t *testing.T) {
|
|
t.Setenv("WARPBOX_BASE_URL", "http://example.test")
|
|
cfg, err := Load()
|
|
if err != nil {
|
|
t.Fatalf("Load returned error: %v", err)
|
|
}
|
|
if cfg.ReadHeaderTimeout != 15*time.Second {
|
|
t.Fatalf("ReadHeaderTimeout = %s, want 15s", cfg.ReadHeaderTimeout)
|
|
}
|
|
if cfg.ReadTimeout != 0 {
|
|
t.Fatalf("ReadTimeout = %s, want 0 for long uploads", cfg.ReadTimeout)
|
|
}
|
|
if cfg.WriteTimeout != 0 {
|
|
t.Fatalf("WriteTimeout = %s, want 0 for long uploads", cfg.WriteTimeout)
|
|
}
|
|
if !cfg.ResumableUploadsEnabled {
|
|
t.Fatalf("ResumableUploadsEnabled = false, want true")
|
|
}
|
|
if cfg.ResumableChunkSize != 8*1024*1024 {
|
|
t.Fatalf("ResumableChunkSize = %d, want 8 MiB", cfg.ResumableChunkSize)
|
|
}
|
|
if cfg.ResumableRetention != 24*time.Hour {
|
|
t.Fatalf("ResumableRetention = %s, want 24h", cfg.ResumableRetention)
|
|
}
|
|
}
|