package service import ( "context" "os" "path/filepath" "strings" "testing" "time" "git.casaderoll.de/michael/urbm/internal/model" "git.casaderoll.de/michael/urbm/internal/queue" "git.casaderoll.de/michael/urbm/internal/rsync" ) func TestRsyncSummaryDistinguishesDryRun(t *testing.T) { for _, dry := range []bool{true, false} { run := model.Run{TaskType: "rsync", RsyncDryRun: dry} summary := rsync.Summary{Files: 1376, Deleted: 1214, Bytes: 1234567890} applyRsyncSummary(&run, summary) logRsyncSummary(&run, summary) message := notificationMessage("Mirror", "", run, time.Now()) for _, expected := range []string{"1376", "1214", "1.1 GiB"} { if !strings.Contains(message, expected) || !strings.Contains(strings.Join(run.LiveLog, "\n"), expected) { t.Fatalf("missing %s: %s %v", expected, message, run.LiveLog) } } if dry { if run.BytesAdded != 0 || !strings.Contains(message, "würden") || !strings.Contains(message, "keine Änderungen vorgenommen") || strings.Contains(message, "⚠️") { t.Fatal(message) } } else if run.BytesAdded != summary.Bytes || strings.Contains(message, "würden") { t.Fatal(message) } } } func TestExecuteRsyncLogsSetupSamplesAndErrors(t *testing.T) { for _, fail := range []bool{false, true} { dir := t.TempDir() source, target := filepath.Join(dir, "source"), filepath.Join(dir, "target") for _, path := range []string{source, target} { if err := os.Mkdir(path, 0700); err != nil { t.Fatal(err) } } binary := filepath.Join(dir, "rsync") script := "#!/bin/sh\ncase \" $* \" in *' --dry-run '*) ;; *) exit 99;; esac\n" if fail { script += "echo 'test failure' >&2\nexit 23\n" } else { script += "i=0; while [ $i -lt 25 ]; do printf 'CHANGE|>f+++++++++|source/file%s\\n' \"$i\"; i=$((i+1)); done\nprintf '%s\\n' 'Number of regular files transferred: 25' 'Number of deleted files: 3 (reg: 3)' 'Total transferred file size: 123456 bytes'\n" } if err := os.WriteFile(binary, []byte(script), 0700); err != nil { t.Fatal(err) } job := model.Job{ID: "mirror", Sources: []model.Source{{Path: source}}, Rsync: model.RsyncOptions{Target: target, DryRun: true, Overwrite: true, Delete: true, Checksum: true}} s := &Service{config: model.Config{Jobs: []model.Job{job}}, rsync: &rsync.Runner{Binary: binary}, queue: queue.New(nil, nil)} result := s.executeRsync(context.Background(), model.Run{ID: "run", JobID: job.ID, TaskType: "rsync"}) log := strings.Join(result.LiveLog, "\n") for _, expected := range []string{"Testlauf", "Quelle: " + source, "Ziel: " + target, "Löschen: an", "Prüfsumme"} { if !strings.Contains(log, expected) { t.Fatalf("missing %s: %s", expected, log) } } if fail { if result.Status != "failed" || !strings.Contains(log, "test failure") { t.Fatal(result) } } else { if result.Status != "success" || result.BytesAdded != 0 || result.BytesProcessed != 123456 || result.EntriesDeleted != 3 { t.Fatal(result) } if strings.Count(log, "Geplant: Neu") != 20 || !strings.Contains(log, "Weitere Einzeländerungen ausgeblendet") || !strings.Contains(log, "25 Dateien würden") { t.Fatal(log) } } } }