Files
vdm/core/tests/task/api_compiles_test.cpp
T
samiandClaude Sonnet 5 d6cf1fe7dc core: post the engine API for DAEMON review (pre-stage-7)
The download entry point the AGENT-CORE brief asked for on day one and
that slipped. DAEMON has an RPC surface and a store and, until this is
agreed, nothing in velox::core to call.

vdm/task/download.hpp — DownloadSpec (the resolved subset DAEMON hands in:
absolute save_path, verbatim browser headers, requested segments/buffer,
optional probe_hint / checksum / auth, allow_resume), EngineState (the
CORE-owned subset of the wire TaskState), Progress / SegmentProgress,
DownloadCallbacks (on_progress <=4 Hz, on_state for every transition
incl. auto-pauses, on_auth_required, on_decision_needed, on_finished
last), DownloadHandle (pause/resume/cancel — idempotent per the ADR 0013
signature — plus provide_auth / decide / refresh_url, and synchronous
state()/progress() snapshots).

vdm/engine.hpp — Engine: start(spec, callbacks) -> handle, segment_budget()
(DAEMON's sched/ admission surface, ADR 0011), live connection.* setters,
a standalone probe() on the pool outside the segment budget.

core/docs/engine-api-m1.md — the review doc: field semantics, the state
machine, threading/lifetime rules (which thread callbacks arrive on, what
is legal from inside one, handle/engine lifetime), the shared-`paused`
idempotency contract as a signature, and five open questions for DAEMON.

Value types compile and are covered by api_compiles_test; Engine /
DownloadHandle bodies land in stage 8, built against whatever DAEMON
signs off here.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01HPPSGhiArbvQgwC2DNiURS
2026-09-10 15:39:25 +04:00

85 lines
2.6 KiB
C++

// The engine API sketch must compile and its value types must behave. Engine /
// DownloadHandle bodies land in stage 8; this only exercises the data shapes DAEMON
// builds against.
#include "vdm/engine.hpp"
#include "vdm/task/download.hpp"
#include <type_traits>
#include "vtest.hpp"
using namespace vdm;
using namespace vdm::task;
VT_TEST(api_download_spec_defaults) {
DownloadSpec s;
s.url = "https://example.com/big.iso";
s.save_path = "/home/u/Downloads/big.iso";
VT_CHECK(s.mirrors.empty());
VT_CHECK(!s.segments.has_value());
VT_CHECK(!s.buffer_bytes.has_value());
VT_CHECK(!s.checksum.has_value());
VT_CHECK(!s.probe_hint.has_value());
VT_CHECK(s.allow_resume);
VT_CHECK(s.proxy.kind == net::ProxyKind::none);
VT_CHECK(s.auth.scheme == net::AuthScheme::none);
}
VT_TEST(api_state_helpers) {
VT_CHECK(is_terminal(EngineState::complete));
VT_CHECK(is_terminal(EngineState::failed));
VT_CHECK(is_terminal(EngineState::cancelled));
VT_CHECK(!is_terminal(EngineState::paused));
VT_CHECK(!is_terminal(EngineState::downloading));
}
VT_TEST(api_callbacks_are_all_optional) {
DownloadCallbacks cb; // every std::function default-constructs empty
VT_CHECK(!cb.on_progress);
VT_CHECK(!cb.on_state);
VT_CHECK(!cb.on_auth_required);
VT_CHECK(!cb.on_decision_needed);
VT_CHECK(!cb.on_finished);
cb.on_state = [](EngineState, EngineState, const std::optional<vdm::ErrorInfo> &) {};
cb.on_finished = [](Result<DownloadOutcome>) {};
VT_CHECK(cb.on_state && cb.on_finished);
}
VT_TEST(api_value_types_roundtrip) {
Progress p;
p.downloaded = 1234;
p.total = 5000;
p.effective_segments = 4;
SegmentProgress sp;
sp.index = 0;
sp.end = 1249;
sp.completed = 1234;
p.segments.push_back(sp);
VT_CHECK_EQ(p.segments.size(), 1u);
VT_CHECK_EQ(p.segments[0].end, 1249u);
DownloadOutcome o;
o.final_path = "/x";
o.bytes = 5000;
VT_CHECK_EQ(o.bytes, 5000u);
AuthChallenge a;
a.host = "h";
a.scheme = AuthChallenge::Scheme::digest;
VT_CHECK(a.scheme == AuthChallenge::Scheme::digest);
DecisionRequest d;
d.kind = DecisionRequest::Kind::server_file_changed;
d.detail = "changed";
VT_CHECK(d.kind == DecisionRequest::Kind::server_file_changed);
}
VT_TEST(api_handle_and_engine_are_move_only_shaped) {
static_assert(!std::is_copy_constructible_v<Engine>, "Engine is non-copyable");
static_assert(std::is_copy_constructible_v<DownloadHandle>, "handle is a shared handle");
DownloadHandle h; // default handle is invalid until Engine::start() fills it
VT_CHECK(!h.valid());
}