Files
3x-ui-web-src/internal/web/service/backup_filename_test.go
T
Sanaei f727d04f65
CI / go-test (push) Canceled after 0s
CI / postgres-durable-first (push) Canceled after 0s
CI / codegen (push) Canceled after 0s
CI / govulncheck (push) Canceled after 0s
CI / race (push) Canceled after 0s
CI / fuzz-smoke (push) Canceled after 0s
CI / golangci (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CodeQL Advanced / Analyze (go) (push) Canceled after 0s
CodeQL Advanced / Analyze (actions) (push) Canceled after 0s
CodeQL Advanced / Analyze (javascript-typescript) (push) Canceled after 0s
Docs CI / build (push) Canceled after 0s
Docs Deploy (GitHub Pages) / build (push) Canceled after 0s
Release 3X-UI / build (386) (push) Canceled after 0s
Release 3X-UI / build (amd64) (push) Canceled after 0s
Release 3X-UI / build (arm64) (push) Canceled after 0s
Release 3X-UI / build (armv5) (push) Canceled after 0s
Release 3X-UI / build (armv6) (push) Canceled after 0s
Release 3X-UI / build (armv7) (push) Canceled after 0s
Release 3X-UI / build (s390x) (push) Canceled after 0s
Release 3X-UI / Build for Windows (amd64) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / noninteractive-install (ubuntu-latest) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-24.04-arm) (push) Canceled after 0s
Deploy Smoke Tests / release-tag-install (ubuntu-latest) (push) Canceled after 0s
Docs Deploy (GitHub Pages) / deploy (push) Canceled after 0s
Release 3X-UI / Publish rolling dev release (push) Canceled after 0s
v3.7.0
2026-08-24 15:07:15 +02:00

69 lines
2.1 KiB
Go

package service
import (
"regexp"
"testing"
"time"
)
// getDb (controller) only accepts a Content-Disposition filename matching this
// pattern, so every sanitizeBackupHost output must satisfy it.
var backupFilenameRegex = regexp.MustCompile(`^[a-zA-Z0-9_\-.]+$`)
func TestSanitizeBackupHost(t *testing.T) {
cases := []struct {
name string
in string
want string
}{
{"domain", "panel.example.com", "panel.example.com"},
{"ipv4", "203.0.113.5", "203.0.113.5"},
{"ipv6", "2001:db8::1", "2001-db8--1"},
{"ipv6 bracketed", "[fe80::1]", "fe80--1"},
{"domain with port", "example.com:8443", "example.com-8443"},
{"trims edge dots and dashes", "-.example.com.-", "example.com"},
{"empty falls back", "", "x-ui"},
{"all invalid falls back", ":::", "x-ui"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := sanitizeBackupHost(tc.in)
if got != tc.want {
t.Errorf("sanitizeBackupHost(%q) = %q, want %q", tc.in, got, tc.want)
}
if !backupFilenameRegex.MatchString(got) {
t.Errorf("sanitizeBackupHost(%q) = %q, not a valid download filename", tc.in, got)
}
})
}
}
// dateSuffixRegex narrows backupFilenameRegex to the exact _YYYY-MM-DD_HHMMSS shape.
var dateSuffixRegex = regexp.MustCompile(`^_\d{4}-\d{2}-\d{2}_\d{6}$`)
func TestBackupDateSuffix(t *testing.T) {
cases := []struct {
name string
now time.Time
want string
}{
{"utc midnight", time.Date(2026, 6, 27, 0, 0, 0, 0, time.UTC), "_2026-06-27_000000"},
{"end of year", time.Date(2025, 12, 31, 23, 59, 59, 0, time.UTC), "_2025-12-31_235959"},
{"single digit month/day padded", time.Date(2026, 1, 5, 9, 4, 0, 0, time.UTC), "_2026-01-05_090400"},
}
for _, tc := range cases {
t.Run(tc.name, func(t *testing.T) {
got := backupDateSuffix(tc.now)
if got != tc.want {
t.Errorf("backupDateSuffix(%v) = %q, want %q", tc.now, got, tc.want)
}
if !dateSuffixRegex.MatchString(got) {
t.Errorf("backupDateSuffix(%v) = %q, not a valid date suffix", tc.now, got)
}
if !backupFilenameRegex.MatchString(got) {
t.Errorf("backupDateSuffix(%v) = %q, not a valid download filename char", tc.now, got)
}
})
}
}