package api import ( "encoding/json" "testing" ) func TestParseBlenderFrame(t *testing.T) { frame, ok := parseBlenderFrame("Info Fra:2470 Mem:12.00M") if !ok || frame != 2470 { t.Fatalf("parseBlenderFrame() = (%d,%v), want (2470,true)", frame, ok) } if _, ok := parseBlenderFrame("no frame here"); ok { t.Fatal("expected parse to fail for non-frame text") } } func TestJobTaskCounts_Progress(t *testing.T) { c := &jobTaskCounts{total: 10, completed: 4} if got := c.progress(); got != 40 { t.Fatalf("progress() = %v, want 40", got) } } func TestParseWSTaskUpdate_LegacyErrorObject(t *testing.T) { // Simulates older runners that JSON-marshaled an error interface as {} raw := json.RawMessage(`{"task_id":99,"success":false,"error":{}}`) update, err := parseWSTaskUpdate(raw) if err != nil { t.Fatalf("parseWSTaskUpdate: %v", err) } if update.TaskID != 99 { t.Fatalf("TaskID = %d, want 99", update.TaskID) } if update.Success { t.Fatal("Success = true, want false") } if update.Error != "" { t.Fatalf("Error = %q, want empty (legacy object)", update.Error) } } func TestParseWSTaskUpdate_StringError(t *testing.T) { raw := json.RawMessage(`{"task_id":7,"success":false,"error":"blender failed: signal: segmentation fault (core dumped)","free_requeue":true}`) update, err := parseWSTaskUpdate(raw) if err != nil { t.Fatalf("parseWSTaskUpdate: %v", err) } if update.TaskID != 7 || update.Success { t.Fatalf("unexpected update: %+v", update) } if update.Error != "blender failed: signal: segmentation fault (core dumped)" { t.Fatalf("Error = %q", update.Error) } if !update.FreeRequeue { t.Fatal("expected FreeRequeue true") } } func TestFormatInferredTaskFailure(t *testing.T) { tests := []struct { name string in string want string }{ { name: "task failed segfault prefix", in: "Task failed: blender failed: signal: segmentation fault (core dumped)", want: "blender failed: signal: segmentation fault (core dumped)", }, { name: "blender render failed prefix", in: "Blender render failed: blender failed: signal: segmentation fault (core dumped)", want: "blender failed: signal: segmentation fault (core dumped)", }, { name: "double prefix", in: "Task failed: Blender render failed: blender failed: signal: segmentation fault (core dumped)", want: "blender failed: signal: segmentation fault (core dumped)", }, { name: "plain message", in: "blender failed: exit status 1", want: "blender failed: exit status 1", }, { name: "empty falls back", in: " ", want: defaultUnexpectedDisconnectError, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := formatInferredTaskFailure(tt.in); got != tt.want { t.Fatalf("formatInferredTaskFailure(%q) = %q, want %q", tt.in, got, tt.want) } }) } }