package services import ( "archive/zip" "bytes" "os" "path/filepath" "testing" "github.com/stretchr/testify/require" ) func writeLargeZipEntry(t *testing.T, writer *zip.Writer, name string, sizeBytes int64) { t.Helper() entry, err := writer.Create(name) require.NoError(t, err) chunk := bytes.Repeat([]byte{0}, 1024*1024) remaining := sizeBytes for remaining > 0 { toWrite := int64(len(chunk)) if remaining < toWrite { toWrite = remaining } _, err := entry.Write(chunk[:toWrite]) require.NoError(t, err) remaining -= toWrite } } func TestBackupServiceWave7_CreateBackup_SnapshotFailureForNonSQLiteDB(t *testing.T) { tmpDir := t.TempDir() backupDir := filepath.Join(tmpDir, "backups") require.NoError(t, os.MkdirAll(backupDir, 0o700)) dbPath := filepath.Join(tmpDir, "charon.db") require.NoError(t, os.WriteFile(dbPath, []byte("not-a-sqlite-db"), 0o600)) svc := &BackupService{ DataDir: tmpDir, BackupDir: backupDir, DatabaseName: "charon.db", } _, err := svc.CreateBackup() require.Error(t, err) require.Contains(t, err.Error(), "create sqlite snapshot before backup") } func TestBackupServiceWave7_ExtractDatabaseFromBackup_DBEntryOverLimit(t *testing.T) { tmpDir := t.TempDir() zipPath := filepath.Join(tmpDir, "db-over-limit.zip") zipFile, err := os.Create(zipPath) // #nosec G304 -- path is derived from t.TempDir() require.NoError(t, err) writer := zip.NewWriter(zipFile) writeLargeZipEntry(t, writer, "charon.db", int64(101*1024*1024)) require.NoError(t, writer.Close()) require.NoError(t, zipFile.Close()) svc := &BackupService{DatabaseName: "charon.db"} _, err = svc.extractDatabaseFromBackup(zipPath) require.Error(t, err) require.Contains(t, err.Error(), "extract database entry from backup archive") require.Contains(t, err.Error(), "decompression limit") } func TestBackupServiceWave7_ExtractDatabaseFromBackup_WALEntryOverLimit(t *testing.T) { tmpDir := t.TempDir() dbPath := filepath.Join(tmpDir, "charon.db") createSQLiteTestDB(t, dbPath) zipPath := filepath.Join(tmpDir, "wal-over-limit.zip") zipFile, err := os.Create(zipPath) // #nosec G304 -- path is derived from t.TempDir() require.NoError(t, err) writer := zip.NewWriter(zipFile) dbBytes, err := os.ReadFile(dbPath) // #nosec G304 -- path is derived from t.TempDir() require.NoError(t, err) dbEntry, err := writer.Create("charon.db") require.NoError(t, err) _, err = dbEntry.Write(dbBytes) require.NoError(t, err) writeLargeZipEntry(t, writer, "charon.db-wal", int64(101*1024*1024)) require.NoError(t, writer.Close()) require.NoError(t, zipFile.Close()) svc := &BackupService{DatabaseName: "charon.db"} _, err = svc.extractDatabaseFromBackup(zipPath) require.Error(t, err) require.Contains(t, err.Error(), "extract wal entry from backup archive") require.Contains(t, err.Error(), "decompression limit") }