113 lines
3.3 KiB
Go
113 lines
3.3 KiB
Go
package appstate
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestEnsureRotatingLocalBackupCreatesAndRotates(t *testing.T) {
|
|
temp := t.TempDir()
|
|
dbPath := filepath.Join(temp, "qfs.db")
|
|
cfgPath := filepath.Join(temp, "config.yaml")
|
|
|
|
if err := os.WriteFile(dbPath, []byte("db"), 0644); err != nil {
|
|
t.Fatalf("write db: %v", err)
|
|
}
|
|
if err := os.WriteFile(cfgPath, []byte("cfg"), 0644); err != nil {
|
|
t.Fatalf("write config: %v", err)
|
|
}
|
|
|
|
prevNow := backupNow
|
|
defer func() { backupNow = prevNow }()
|
|
backupNow = func() time.Time { return time.Date(2026, 2, 11, 10, 0, 0, 0, time.UTC) }
|
|
|
|
created, err := EnsureRotatingLocalBackup(dbPath, cfgPath)
|
|
if err != nil {
|
|
t.Fatalf("backup: %v", err)
|
|
}
|
|
if len(created) == 0 {
|
|
t.Fatalf("expected backup to be created")
|
|
}
|
|
|
|
dailyArchive := filepath.Join(temp, "backups", "daily", "qfs-backp-2026-02-11.zip")
|
|
if _, err := os.Stat(dailyArchive); err != nil {
|
|
t.Fatalf("daily archive missing: %v", err)
|
|
}
|
|
|
|
backupNow = func() time.Time { return time.Date(2026, 2, 12, 10, 0, 0, 0, time.UTC) }
|
|
created, err = EnsureRotatingLocalBackup(dbPath, cfgPath)
|
|
if err != nil {
|
|
t.Fatalf("backup rotate: %v", err)
|
|
}
|
|
if len(created) == 0 {
|
|
t.Fatalf("expected backup to be created for new day")
|
|
}
|
|
|
|
dailyArchive = filepath.Join(temp, "backups", "daily", "qfs-backp-2026-02-12.zip")
|
|
if _, err := os.Stat(dailyArchive); err != nil {
|
|
t.Fatalf("daily archive missing after rotate: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestEnsureRotatingLocalBackupEnvControls(t *testing.T) {
|
|
temp := t.TempDir()
|
|
dbPath := filepath.Join(temp, "qfs.db")
|
|
cfgPath := filepath.Join(temp, "config.yaml")
|
|
|
|
if err := os.WriteFile(dbPath, []byte("db"), 0644); err != nil {
|
|
t.Fatalf("write db: %v", err)
|
|
}
|
|
if err := os.WriteFile(cfgPath, []byte("cfg"), 0644); err != nil {
|
|
t.Fatalf("write config: %v", err)
|
|
}
|
|
|
|
backupRoot := filepath.Join(temp, "custom_backups")
|
|
t.Setenv(envBackupDir, backupRoot)
|
|
|
|
if _, err := EnsureRotatingLocalBackup(dbPath, cfgPath); err != nil {
|
|
t.Fatalf("backup with env: %v", err)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(backupRoot, "daily", ".period.json")); err != nil {
|
|
t.Fatalf("expected backup in custom dir: %v", err)
|
|
}
|
|
|
|
t.Setenv(envBackupDisable, "1")
|
|
if _, err := EnsureRotatingLocalBackup(dbPath, cfgPath); err != nil {
|
|
t.Fatalf("backup disabled: %v", err)
|
|
}
|
|
if _, err := os.Stat(filepath.Join(backupRoot, "daily", ".period.json")); err != nil {
|
|
t.Fatalf("backup should remain from previous run: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestEnsureRotatingLocalBackupRejectsGitWorktree(t *testing.T) {
|
|
temp := t.TempDir()
|
|
repoRoot := filepath.Join(temp, "repo")
|
|
if err := os.MkdirAll(filepath.Join(repoRoot, ".git"), 0755); err != nil {
|
|
t.Fatalf("mkdir git dir: %v", err)
|
|
}
|
|
|
|
dbPath := filepath.Join(repoRoot, "data", "qfs.db")
|
|
cfgPath := filepath.Join(repoRoot, "data", "config.yaml")
|
|
if err := os.MkdirAll(filepath.Dir(dbPath), 0755); err != nil {
|
|
t.Fatalf("mkdir data dir: %v", err)
|
|
}
|
|
if err := os.WriteFile(dbPath, []byte("db"), 0644); err != nil {
|
|
t.Fatalf("write db: %v", err)
|
|
}
|
|
if err := os.WriteFile(cfgPath, []byte("cfg"), 0644); err != nil {
|
|
t.Fatalf("write cfg: %v", err)
|
|
}
|
|
|
|
_, err := EnsureRotatingLocalBackup(dbPath, cfgPath)
|
|
if err == nil {
|
|
t.Fatal("expected git worktree backup root to be rejected")
|
|
}
|
|
if !strings.Contains(err.Error(), "outside git worktree") {
|
|
t.Fatalf("unexpected error: %v", err)
|
|
}
|
|
}
|