package status import ( "strings" "testing" ) func TestScanProgress(t *testing.T) { tests := []struct { name string input string wantOutSec, wantFPS, wantSpd float64 wantDone bool }{ { name: "out_time_us preferred over ms and string", input: "frame=120\nfps=24.00\nout_time_us=5000000\nout_time_ms=9999999\nout_time=00:00:09.000000\nspeed=1.02x\nprogress=continue\n", wantOutSec: 5, wantFPS: 24, wantSpd: 1.02, wantDone: false, }, { name: "out_time string fallback when no us field", input: "fps=12\nout_time=00:01:30.500000\nspeed=0.09x\nprogress=continue\n", wantOutSec: 90.5, wantFPS: 12, wantSpd: 0.09, wantDone: false, }, { name: "end block", input: "out_time_us=7200000000\nspeed=2x\nprogress=end\n", wantOutSec: 7200, wantFPS: 0, wantSpd: 2, wantDone: true, }, { name: "speed N/A leaves zero", input: "out_time_us=1000000\nspeed=N/A\nprogress=continue\n", wantOutSec: 1, wantFPS: 0, wantSpd: 0, wantDone: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { var last ProgressSample n := 0 if err := ScanProgress(strings.NewReader(tt.input), func(s ProgressSample) { last = s; n++ }); err != nil { t.Fatalf("ScanProgress: %v", err) } if n != 1 { t.Fatalf("got %d samples, want 1", n) } if last.OutTimeSec != tt.wantOutSec || last.FPS != tt.wantFPS || last.Speed != tt.wantSpd || last.Done != tt.wantDone { t.Errorf("got %+v, want out=%v fps=%v spd=%v done=%v", last, tt.wantOutSec, tt.wantFPS, tt.wantSpd, tt.wantDone) } }) } } func TestScanProgressMultipleBlocks(t *testing.T) { in := "out_time_us=1000000\nspeed=1x\nprogress=continue\nout_time_us=2000000\nspeed=1x\nprogress=end\n" var got []ProgressSample if err := ScanProgress(strings.NewReader(in), func(s ProgressSample) { got = append(got, s) }); err != nil { t.Fatal(err) } if len(got) != 2 { t.Fatalf("got %d blocks, want 2", len(got)) } if got[0].OutTimeSec != 1 || got[1].OutTimeSec != 2 || got[0].Done || !got[1].Done { t.Errorf("blocks = %+v", got) } } func TestSnapshotPercentAndETA(t *testing.T) { tr := New() tr.Begin("episode.mkv") tr.SetTotal(100) tr.Update(25, 10, 0.5) // 25% done, 75s left at 0.5x -> 150s ETA s := tr.Snapshot() if s.Percent != 25 { t.Errorf("Percent = %v, want 25", s.Percent) } if s.ETASec != 150 { t.Errorf("ETASec = %v, want 150", s.ETASec) } if s.File != "episode.mkv" || s.Phase != PhaseProbing { t.Errorf("File/Phase = %q/%q", s.File, s.Phase) } } func TestSetPausedFlag(t *testing.T) { tr := New() tr.Begin("x.mkv") if tr.Snapshot().Paused { t.Fatal("should not start paused") } tr.SetPaused(true) if !tr.Snapshot().Paused { t.Error("expected paused after SetPaused(true)") } tr.SetPaused(true) // idempotent — must not double-count tr.SetPaused(false) if tr.Snapshot().Paused { t.Error("expected not paused after SetPaused(false)") } tr.Idle() if tr.Snapshot().Paused { t.Error("Idle should clear paused") } } func TestSnapshotIdleNoDivByZero(t *testing.T) { s := New().Snapshot() // no Begin, totalSec 0 if s.Percent != 0 || s.ETASec != 0 || s.Phase != PhaseIdle { t.Errorf("idle snapshot = %+v", s) } }