package server import ( "context" "os" "path/filepath" "syscall" "testing" "time" ) func TestQueueEnqueueNextMarkDone(t *testing.T) { q, err := NewQueue("") if err != nil { t.Fatalf("new queue: %v", err) } req := VideoRequest{URL: "https://example.com/watch?v=1", OutDir: "/tmp/videos", MetadataOnly: false} id, err := q.Enqueue(req) if err != nil { t.Fatalf("enqueue: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() item, err := q.Next(ctx) if err != nil { t.Fatalf("next: %v", err) } if item.ID != id { t.Fatalf("expected id %s, got %s", id, item.ID) } if item.Request.URL != req.URL { t.Fatalf("unexpected url: %s", item.Request.URL) } if err := q.MarkDone(item.ID); err != nil { t.Fatalf("mark done: %v", err) } select { case <-time.After(20 * time.Millisecond): default: } } func TestQueuePersistence(t *testing.T) { tmpDir := t.TempDir() queuePath := filepath.Join(tmpDir, "queue.json") q, err := NewQueue(queuePath) if err != nil { t.Fatalf("new queue: %v", err) } req := VideoRequest{URL: "https://example.com/watch?v=2", OutDir: "/data", MetadataOnly: true} id, err := q.Enqueue(req) if err != nil { t.Fatalf("enqueue: %v", err) } if _, err := os.Stat(queuePath); err != nil { t.Fatalf("queue file missing: %v", err) } q2, err := NewQueue(queuePath) if err != nil { t.Fatalf("reload queue: %v", err) } ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() item, err := q2.Next(ctx) if err != nil { t.Fatalf("next: %v", err) } if item.ID != id { t.Fatalf("expected persisted id %s, got %s", id, item.ID) } if err := q2.MarkDone(item.ID); err != nil { t.Fatalf("mark done: %v", err) } if _, err := os.Stat(queuePath); !os.IsNotExist(err) { t.Fatalf("expected queue file removed after draining, got %v", err) } } func TestWriteFileAtomicFallback(t *testing.T) { // Simulate EBUSY by replacing os.Rename temporarily. origRename := osRename origWriteFile := osWriteFile defer func() { osRename = origRename osWriteFile = origWriteFile }() tmpDir := t.TempDir() path := filepath.Join(tmpDir, "queue.json") odyssey := filepath.Join(tmpDir, "queue.json.tmp") osWriteFile = func(name string, data []byte, perm os.FileMode) error { if name == path { if err := os.WriteFile(name, data, perm); err != nil { return err } return nil } return os.WriteFile(name, data, perm) } osRename = func(oldpath, newpath string) error { return syscall.EBUSY } if err := writeFileAtomic(path, []byte("{}")); err != nil { t.Fatalf("writeFileAtomic: %v", err) } data, err := os.ReadFile(path) if err != nil { t.Fatalf("read path: %v", err) } if string(data) != "{}" { t.Fatalf("expected file contents '{}', got %q", data) } if _, err := os.Stat(odyssey); !os.IsNotExist(err) { t.Fatalf("expected tmp removed, got %v", err) } }