#pragma once // A recording EnginePort for Scheduler tests. Every call is logged; start() hands back a // sequential TaskId. No threads, no real work. #include #include #include #include #include "sched/engine_port.hpp" namespace velox::daemon::sched { class FakeEnginePort final : public EnginePort { public: struct StartCall { vdm::TaskId id; std::string url; std::string save_path; vdm::task::DownloadCallbacks callbacks; }; std::vector starts; std::vector paused; std::vector resumed; std::vector> cancelled; std::vector released; std::vector> orders; std::vector max_active_segments; std::vector> host_caps; // probe(): synchronous by default (a default-constructed ProbeResult — success, // resumable=false, no known size) so a test that doesn't care about probe details // still sees start() happen within the same tick(). Set auto_probe_result to nullopt // to switch to manual mode: probe() then just records the request and stashes `done` // in pending_probes for the test to resolve explicitly, in order. std::optional> auto_probe_result = vdm::Result{vdm::net::ProbeResult{}}; std::vector probe_requests; std::vector)>> pending_probes; void probe(const vdm::net::ProbeRequest& req, std::function)> done) override { probe_requests.push_back(req); if (auto_probe_result) { done(*auto_probe_result); } else { pending_probes.push_back(std::move(done)); } } vdm::TaskId start(const vdm::task::DownloadSpec& spec, vdm::task::DownloadCallbacks callbacks) override { const vdm::TaskId id{next_++}; starts.push_back({id, spec.url, spec.save_path, std::move(callbacks)}); return id; } void pause(vdm::TaskId id) override { paused.push_back(id); } void resume(vdm::TaskId id) override { resumed.push_back(id); } void cancel(vdm::TaskId id, bool discard) override { cancelled.emplace_back(id, discard); } void provide_auth(vdm::TaskId, const std::string&, const std::string&, bool) override {} void decide(vdm::TaskId, vdm::task::Decision) override {} void refresh_url(vdm::TaskId id, const std::string& url, const std::vector& headers) override { refreshed_urls.emplace_back(id, url, headers); } struct RefreshCall { vdm::TaskId id; std::string url; std::vector headers; }; std::vector refreshed_urls; void release(vdm::TaskId id) override { released.push_back(id); } std::optional progress(vdm::TaskId id) const override { auto it = fake_progress.find(id.value); return it == fake_progress.end() ? std::nullopt : std::optional(it->second); } // Tests set this to control what progress(id) returns. std::unordered_map fake_progress; void set_task_order(const std::vector& order) override { orders.push_back(order); } void set_max_active_segments(std::uint32_t n) override { max_active_segments.push_back(n); } void set_host_segment_cap(const std::string& h, std::uint32_t c) override { host_caps.emplace_back(h, c); } void set_global_speed_limit(std::uint64_t bps) override { global_speed_limits.push_back(bps); } std::vector global_speed_limits; const std::vector& last_order() const { return orders.back(); } private: std::uint64_t next_ = 1; }; } // namespace velox::daemon::sched