lardon3d/tests/test_acquisition_campaign_task.cpp
fy59 b84f860d86 refactor(core): freeze global maintenance baseline
Complete the A-to-Z Lardon3D maintenance and coherence pass.

Generalize host resource policy, remove the global CPU12 ceiling, preserve
host CPU/RAM reserves, scale Task capabilities through the Resource Governor,
and validate deterministic parallel GV execution.

Migrate Project DB to v23 with data-driven camera, lens, optical configuration
and calibration profiles, including manual lenses without EXIF.

Integrate safe optional LARDON SSD swap/scratch control with Governor and F10
drain/safe-to-unplug semantics.

Refactor the ncurses TUI into a runtime observatory with durable progress,
elapsed time, smoothed ETA, throughput, resource telemetry, Governor state,
optics workflow, colors and compact/no-color fallbacks.

Reconcile Queue lifetime, persistence, concurrency, comments, tests,
README, AGENTS and canonical documentation.

GLOBAL_MAINTENANCE_AUDIT=PASS/FROZEN
2026-09-01 08:00:47 +02:00

862 lines
40 KiB
C++

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <filesystem>
#include <string>
#include <unistd.h>
#include <vector>
#include <sqlite3.h>
#include <opencv2/core.hpp>
extern "C" {
#include <lardon3d/acquisition_campaign_task.h>
#include <lardon3d/project_db.h>
#include <lardon3d/task_queue.h>
#include "../src/task_internal.h"
}
extern "C" bool
lardon3d_acquisition_campaign_task_internal_configure_restored(
Lardon3DTask *, void *);
extern "C" bool lardon3d_acquisition_campaign_task_test_configure_execution(
void *, const uint64_t *, size_t, uint32_t, unsigned int);
extern "C" bool lardon3d_acquisition_campaign_task_test_observed_threads(
void *, unsigned int *, size_t, size_t *);
#define CHECK(x) \
do { \
if (!(x)) { \
std::fprintf(stderr, "failure line %d: %s\n", __LINE__, #x); \
return 1; \
} \
} while (0)
extern "C" const Lardon3DTaskKindRegistry *
lardon3d_task_kind_registry_production(void) {
return nullptr;
}
static bool completed_task_callback(Lardon3DTask *, void *) { return true; }
static bool query_int64(sqlite3 *database, const std::string &sql,
sqlite3_int64 *value) {
sqlite3_stmt *statement = nullptr;
if (!database || !value ||
sqlite3_prepare_v2(database, sql.c_str(), -1, &statement, nullptr) !=
SQLITE_OK)
return false;
const int code = sqlite3_step(statement);
const bool valid = code == SQLITE_ROW &&
sqlite3_column_type(statement, 0) == SQLITE_INTEGER;
if (valid)
*value = sqlite3_column_int64(statement, 0);
return sqlite3_finalize(statement) == SQLITE_OK && valid;
}
static bool query_text(sqlite3 *database, const std::string &sql,
std::string *value) {
sqlite3_stmt *statement = nullptr;
if (!database || !value ||
sqlite3_prepare_v2(database, sql.c_str(), -1, &statement, nullptr) !=
SQLITE_OK)
return false;
const int code = sqlite3_step(statement);
const unsigned char *text = code == SQLITE_ROW
? sqlite3_column_text(statement, 0)
: nullptr;
const int bytes = code == SQLITE_ROW ? sqlite3_column_bytes(statement, 0) : 0;
const bool valid = code == SQLITE_ROW && text && bytes >= 0;
if (valid)
value->assign(reinterpret_cast<const char *>(text),
static_cast<size_t>(bytes));
return sqlite3_finalize(statement) == SQLITE_OK && valid;
}
int main() {
Lardon3DAcquisitionCampaignSource sources[2]{};
std::snprintf(sources[0].path, sizeof(sources[0].path), "/input/a.arw");
std::snprintf(sources[1].path, sizeof(sources[1].path), "/input/a.jpg");
sources[0].source_kind = sources[0].metadata.source_kind =
LARDON3D_ACQUISITION_SOURCE_RAW;
sources[1].source_kind = sources[1].metadata.source_kind =
LARDON3D_ACQUISITION_SOURCE_JPEG;
for (auto &source : sources) {
source.metadata_result = LARDON3D_ACQUISITION_OK;
source.metadata.policy_version =
LARDON3D_ACQUISITION_PAIRING_POLICY_VERSION;
}
Lardon3DAcquisitionCampaignConfirmation confirmation{};
confirmation.source_count = 2;
confirmation.source_indices[0] = 0;
confirmation.source_indices[1] = 1;
Lardon3DAcquisitionCampaignTaskRequest input{};
input.sources = sources;
input.source_count = 2;
input.confirmations = &confirmation;
input.confirmation_count = 1;
input.ingest_options.representation = LARDON3D_ACQUISITION_SELECT_DEVELOP_RAW;
input.ingest_options.select_representation = 1;
input.ingest_options.imported_at = 123;
input.ingest_options.max_source_bytes = 456;
Lardon3DAcquisitionCampaignPlan input_plan{};
CHECK(lardon3d_acquisition_campaign_plan(
sources, 2, &confirmation, 1, &input_plan) ==
LARDON3D_ACQUISITION_CAMPAIGN_OK &&
input_plan.group_count == 1);
size_t size = 0;
CHECK(
lardon3d_acquisition_campaign_request_encode(&input, nullptr, 0, &size));
CHECK(size > 32);
std::vector<unsigned char> encoded(size);
CHECK(lardon3d_acquisition_campaign_request_encode(&input, encoded.data(),
encoded.size(), &size));
size_t required_size = 777;
std::vector<unsigned char> insufficient(encoded.size() - 1u);
CHECK(!lardon3d_acquisition_campaign_request_encode(
&input, insufficient.data(), insufficient.size(), &required_size) &&
required_size == encoded.size());
required_size = 777;
CHECK(!lardon3d_acquisition_campaign_request_encode(
&input, nullptr, 1, &required_size) &&
required_size == encoded.size());
required_size = 777;
CHECK(!lardon3d_acquisition_campaign_request_encode(
nullptr, nullptr, 0, &required_size) &&
required_size == 0);
CHECK(!lardon3d_acquisition_campaign_request_encode(
&input, nullptr, 0, nullptr));
Lardon3DAcquisitionCampaignSource decoded_sources[2]{};
Lardon3DAcquisitionCampaignConfirmation decoded_confirmations[2]{};
Lardon3DAcquisitionCampaignTaskRequest decoded{};
CHECK(lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), decoded_sources, 2, decoded_confirmations,
2, &decoded));
CHECK(decoded.source_count == 2 && decoded.confirmation_count == 1);
CHECK(decoded_confirmations[0].source_count == 2);
CHECK(decoded.ingest_options.representation ==
LARDON3D_ACQUISITION_SELECT_DEVELOP_RAW);
CHECK(decoded.ingest_options.select_representation == 1);
CHECK(decoded.ingest_options.imported_at == 123 &&
decoded.ingest_options.max_source_bytes == 456);
CHECK(std::strcmp(decoded_sources[0].path, "/input/a.arw") == 0);
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), nullptr, 2, decoded_confirmations, 2,
&decoded));
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), decoded_sources, 2, nullptr, 2,
&decoded));
constexpr size_t imported_at_offset = 8u + 5u * sizeof(uint32_t);
for (size_t i = 0; i < sizeof(uint64_t); ++i)
encoded[imported_at_offset + i] = 0xffu;
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), decoded_sources, 2, decoded_confirmations,
2, &decoded));
for (size_t i = 0; i < sizeof(uint64_t); ++i)
encoded[imported_at_offset + i] =
static_cast<unsigned char>(uint64_t(123) >> (8u * i));
input.ingest_options.imported_at = -1;
required_size = 777;
CHECK(!lardon3d_acquisition_campaign_request_encode(
&input, nullptr, 0, &required_size) &&
required_size == 0);
input.ingest_options.imported_at = 123;
input.ingest_options.max_source_bytes = 0;
CHECK(!lardon3d_acquisition_campaign_request_encode(&input, nullptr, 0,
&size));
input.ingest_options.max_source_bytes = 456;
encoded[8] = 2;
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), decoded_sources, 2, decoded_confirmations,
2, &decoded));
encoded[8] = 1;
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size() - 1, decoded_sources, 2,
decoded_confirmations, 2, &decoded));
CHECK(!lardon3d_acquisition_campaign_request_decode(
encoded.data(), encoded.size(), decoded_sources, 1, decoded_confirmations,
2, &decoded));
char database_path[] = "/tmp/lardon3d-campaign-task-XXXXXX";
int descriptor = mkstemp(database_path);
CHECK(descriptor >= 0 && close(descriptor) == 0 &&
unlink(database_path) == 0);
char error[LARDON3D_PROJECT_DB_ERROR_CAPACITY]{};
Lardon3DProjectDb *database = nullptr;
CHECK(lardon3d_project_db_open(database_path, &database, error) ==
LARDON3D_PROJECT_DB_OK);
Lardon3DProjectDbScanSet target{}, other{};
CHECK(lardon3d_project_db_create_scanset(database, "target", &target) ==
LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_create_scanset(database, "other", &other) ==
LARDON3D_PROJECT_DB_OK);
uint64_t allocated_task_id = 0;
CHECK(lardon3d_project_db_allocate_task_id(database, &allocated_task_id) ==
LARDON3D_PROJECT_DB_OK &&
allocated_task_id == 1);
Lardon3DTaskDurableSnapshot snapshot{};
snapshot.id = 1;
std::snprintf(snapshot.name, sizeof(snapshot.name), "campaign");
snapshot.saved_state = snapshot.recovery_state = TASK_PENDING;
Lardon3DProjectDbAcquisitionCampaignTask durable{
1, target.scanset_id, 0, 1, encoded.data(), encoded.size()};
CHECK(lardon3d_project_db_record_acquisition_campaign_task(
database, &snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, nullptr, &durable,
1) == LARDON3D_PROJECT_DB_OK);
uint64_t mismatched_task_id = 0;
CHECK(lardon3d_project_db_allocate_task_id(database, &mismatched_task_id) ==
LARDON3D_PROJECT_DB_OK &&
mismatched_task_id == 2);
Lardon3DTaskDurableSnapshot mismatched_snapshot = snapshot;
mismatched_snapshot.id = mismatched_task_id;
Lardon3DProjectDbAcquisitionCampaignTask mismatched_durable = durable;
mismatched_durable.task_id = mismatched_task_id;
/* Typed business persistence must never be recorded under another generic
* dispatch identity, even when every other field is valid. */
CHECK(lardon3d_project_db_record_acquisition_campaign_task(
database, &mismatched_snapshot, "photo_quality.triage", 1, nullptr,
&mismatched_durable, 1) == LARDON3D_PROJECT_DB_INVALID_ARGUMENT);
std::vector<unsigned char> changed = encoded;
changed.back() ^= 1u;
snapshot.progress = 50;
durable.request = changed.data();
CHECK(lardon3d_project_db_record_acquisition_campaign_task(
database, &snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, nullptr, &durable,
2) == LARDON3D_PROJECT_DB_CONSTRAINT);
Lardon3DProjectDbTask generic{};
CHECK(lardon3d_project_db_load_task(database, 1, &generic) ==
LARDON3D_PROJECT_DB_OK &&
generic.progress == 0);
snapshot.progress = 0;
durable.request = encoded.data();
Lardon3DProjectDbCapture first{}, wrong{}, second{};
CHECK(lardon3d_project_db_create_capture(database, target.scanset_id, 1,
&first) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_create_capture(database, other.scanset_id, 1,
&wrong) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_create_capture(database, target.scanset_id, 1,
&second) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, wrong.capture_id, 1) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 2, second.capture_id, 2) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) == LARDON3D_PROJECT_DB_OK);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, second.capture_id, 1) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
Lardon3DProjectDbAcquisitionCampaignTask measured_task{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, nullptr, 0, &measured_task) == LARDON3D_PROJECT_DB_OK);
CHECK(measured_task.request == nullptr &&
measured_task.request_size == encoded.size());
std::vector<unsigned char> loaded(encoded.size());
Lardon3DProjectDbAcquisitionCampaignTask loaded_task{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &loaded_task) ==
LARDON3D_PROJECT_DB_OK);
CHECK(loaded_task.next_group_id == 1 && loaded_task.group_count == 1 &&
loaded_task.request_size == encoded.size() &&
std::memcmp(loaded.data(), encoded.data(), encoded.size()) == 0);
std::vector<unsigned char> short_request(encoded.size() - 1u);
Lardon3DProjectDbAcquisitionCampaignTask short_task{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, short_request.data(), short_request.size(),
&short_task) == LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(short_task.task_id == 0 && short_task.request == nullptr &&
short_task.request_size == 0);
Lardon3DProjectDbAcquisitionCampaignCapture loaded_capture{};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) == LARDON3D_PROJECT_DB_OK &&
loaded_capture.capture_id == first.capture_id);
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 2, &loaded_capture) ==
LARDON3D_PROJECT_DB_CONSTRAINT);
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 0, &loaded_capture) ==
LARDON3D_PROJECT_DB_INVALID_ARGUMENT);
Lardon3DHardwareProfile profile{16, 4096, UINT64_MAX, false, 0, false,
false, 0, "test", ""};
Lardon3DResourcePolicy policy{};
policy.maximum_cpu_load_ratio = 1.0;
policy.maximum_io_pressure_avg10 = 100.0;
policy.io_slot_capacity = 1;
Lardon3DResourceGovernor *governor =
lardon3d_resource_governor_create(&profile, &policy);
CHECK(governor != nullptr);
sqlite3 *corruptor = nullptr;
CHECK(sqlite3_open(database_path, &corruptor) == SQLITE_OK);
CHECK(sqlite3_exec(corruptor, "PRAGMA ignore_check_constraints=ON", nullptr,
nullptr, nullptr) == SQLITE_OK);
const auto execute_sql = [&](const std::string &sql) {
return sqlite3_exec(corruptor, sql.c_str(), nullptr, nullptr, nullptr) ==
SQLITE_OK;
};
const auto campaign_sql = [&](const std::string &assignment) {
const std::string sql = "UPDATE acquisition_campaign_tasks SET " +
assignment + " WHERE task_id=1";
return execute_sql(sql);
};
const auto generic_sql = [&](const std::string &assignment) {
return execute_sql("UPDATE tasks SET " + assignment + " WHERE task_id=1");
};
const std::string valid_campaign_empty =
"scanset_id=" + std::to_string(target.scanset_id) +
",next_group_id=0,group_count=1,request=CAST(request AS BLOB)";
const auto restore_empty_prefix = [&]() {
return execute_sql(
"DELETE FROM acquisition_campaign_captures WHERE task_id=1") &&
campaign_sql(valid_campaign_empty) &&
generic_sql("task_kind='acquisition_campaign.run',"
"task_kind_version=1");
};
const auto restore_valid_prefix = [&]() {
return restore_empty_prefix() &&
execute_sql(
"INSERT INTO acquisition_campaign_captures"
"(task_id,group_id,capture_id) VALUES(1,1," +
std::to_string(first.capture_id) + ")") &&
campaign_sql("next_group_id=1");
};
Lardon3DTaskReconstructionContext count_reconstruction{
"/tmp", database, governor, nullptr};
Lardon3DTaskKindBinding count_binding{};
Lardon3DProjectDbAcquisitionCampaignTask corrupt_task{};
/* SQLite dynamic types and signed-wide values must be rejected before the
* retention transaction inserts a mapping or advances the cursor. */
const std::vector<std::string> campaign_corruptions{
"scanset_id=-1",
"scanset_id=9223372036854775807",
"scanset_id=1.5",
"scanset_id='1x'",
"next_group_id=-1",
"next_group_id=9223372036854775807",
"next_group_id=1.5",
"next_group_id='0x'",
"group_count=-1",
"group_count=0",
"group_count=4097",
"group_count=9223372036854775807",
"group_count=1.5",
"group_count='1x'",
"request=CAST(request AS TEXT)",
};
for (const std::string &assignment : campaign_corruptions) {
CHECK(restore_empty_prefix() && campaign_sql(assignment));
std::string cursor_before, cursor_after;
sqlite3_int64 mapping_count_before = -1;
sqlite3_int64 mapping_count_after = -1;
CHECK(query_text(corruptor,
"SELECT quote(next_group_id) FROM "
"acquisition_campaign_tasks WHERE task_id=1",
&cursor_before));
CHECK(query_int64(corruptor,
"SELECT COUNT(*) FROM acquisition_campaign_captures "
"WHERE task_id=1",
&mapping_count_before));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) ==
LARDON3D_PROJECT_DB_CORRUPT);
CHECK(query_text(corruptor,
"SELECT quote(next_group_id) FROM "
"acquisition_campaign_tasks WHERE task_id=1",
&cursor_after));
CHECK(query_int64(corruptor,
"SELECT COUNT(*) FROM acquisition_campaign_captures "
"WHERE task_id=1",
&mapping_count_after));
CHECK(cursor_after == cursor_before && mapping_count_before == 0 &&
mapping_count_after == 0);
}
const std::vector<std::string> generic_corruptions{
"task_kind='wrong'",
"task_kind=1",
"task_kind=1.5",
"task_kind=task_kind||char(0)||'tail'",
"task_kind_version=-1",
"task_kind_version=2",
"task_kind_version=9223372036854775807",
"task_kind_version=1.5",
"task_kind_version='1x'",
};
for (const std::string &assignment : generic_corruptions) {
CHECK(restore_empty_prefix() && generic_sql(assignment));
sqlite3_int64 mapping_count = -1;
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.group_id == 0 && loaded_capture.capture_id == 0);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) ==
LARDON3D_PROJECT_DB_CORRUPT);
CHECK(query_int64(corruptor,
"SELECT COUNT(*) FROM acquisition_campaign_captures "
"WHERE task_id=1",
&mapping_count) &&
mapping_count == 0);
}
/* A missing prefix and an ahead mapping are corruption, not resumable
* identity. Mapping output stays zero and reconstruction installs nothing. */
CHECK(restore_empty_prefix() && campaign_sql("next_group_id=1"));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.group_id == 0 && loaded_capture.capture_id == 0);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, wrong.capture_id, 1) ==
LARDON3D_PROJECT_DB_CORRUPT);
sqlite3_int64 missing_mapping_count = -1;
CHECK(query_int64(corruptor,
"SELECT COUNT(*) FROM acquisition_campaign_captures "
"WHERE task_id=1",
&missing_mapping_count) &&
missing_mapping_count == 0);
count_binding = {};
CHECK(!lardon3d_acquisition_campaign_task_reconstruct(
&snapshot, &count_reconstruction, &count_binding));
CHECK(restore_valid_prefix() && campaign_sql("next_group_id=0"));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.capture_id == 0);
CHECK(restore_valid_prefix() &&
execute_sql(
"INSERT INTO acquisition_campaign_captures"
"(task_id,group_id,capture_id) VALUES(1,2," +
std::to_string(second.capture_id) + ")"));
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.capture_id == 0);
CHECK(restore_valid_prefix() &&
execute_sql("UPDATE acquisition_campaign_captures SET capture_id=" +
std::to_string(wrong.capture_id) +
" WHERE task_id=1 AND group_id=1"));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.capture_id == 0);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) ==
LARDON3D_PROJECT_DB_CORRUPT);
std::string retained_capture;
CHECK(query_text(corruptor,
"SELECT quote(capture_id) FROM "
"acquisition_campaign_captures WHERE task_id=1",
&retained_capture) &&
retained_capture == std::to_string(wrong.capture_id));
const std::vector<std::string> mapping_corruptions{
"group_id=0",
"group_id=-1",
"group_id=1.5",
"group_id='bad'",
"capture_id=-1",
"capture_id=1.5",
"capture_id='bad'",
"capture_id=9223372036854775807",
};
for (const std::string &assignment : mapping_corruptions) {
CHECK(restore_valid_prefix() &&
execute_sql("UPDATE acquisition_campaign_captures SET " +
assignment + " WHERE task_id=1"));
std::string mapping_before, mapping_after;
CHECK(query_text(
corruptor,
"SELECT quote(group_id)||':'||quote(capture_id) FROM "
"acquisition_campaign_captures WHERE task_id=1",
&mapping_before));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_CORRUPT);
loaded_capture = {99, 99};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, 1, 1, &loaded_capture) ==
LARDON3D_PROJECT_DB_CORRUPT &&
loaded_capture.capture_id == 0);
CHECK(lardon3d_project_db_retain_acquisition_campaign_capture(
database, 1, 1, first.capture_id, 1) ==
LARDON3D_PROJECT_DB_CORRUPT);
CHECK(query_text(
corruptor,
"SELECT quote(group_id)||':'||quote(capture_id) FROM "
"acquisition_campaign_captures WHERE task_id=1",
&mapping_after));
CHECK(mapping_after == mapping_before);
}
/* A row-level count can be within v20 bounds yet disagree with the plan
* deterministically decoded from the immutable request. Recovery must reject
* that relation before installing callback ownership. */
CHECK(restore_valid_prefix() && campaign_sql("group_count=2"));
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, 1, loaded.data(), loaded.size(), &corrupt_task) ==
LARDON3D_PROJECT_DB_OK);
count_binding = {};
CHECK(!lardon3d_acquisition_campaign_task_reconstruct(
&snapshot, &count_reconstruction, &count_binding));
CHECK(restore_valid_prefix());
CHECK(sqlite3_close(corruptor) == SQLITE_OK);
char project_directory[] = "/tmp/lardon3d-campaign-project-XXXXXX";
CHECK(mkdtemp(project_directory) != nullptr);
CHECK(std::filesystem::create_directories(
std::string(project_directory) + "/.lardon3d/checkpoints"));
Lardon3DAppState app_state{};
lardon3d_app_state_init(&app_state);
app_state.project_loaded = true;
app_state.project_db = database;
app_state.resource_governor = governor;
std::snprintf(app_state.project_path, sizeof(app_state.project_path), "%s",
project_directory);
uint64_t invalid_enqueue_id = UINT64_MAX;
CHECK(!lardon3d_project_enqueue_acquisition_campaign(
&app_state, target.scanset_id, &input, &invalid_enqueue_id) &&
invalid_enqueue_id == 0);
invalid_enqueue_id = UINT64_MAX;
CHECK(!lardon3d_project_enqueue_acquisition_campaign(
nullptr, target.scanset_id, &input, &invalid_enqueue_id) &&
invalid_enqueue_id == 0);
uint64_t raw_task_id = 0;
Lardon3DTask *raw_task =
lardon3d_project_create_acquisition_campaign_task(
&app_state, target.scanset_id, &input, &raw_task_id);
CHECK(raw_task != nullptr && raw_task_id == 3);
Lardon3DResourceEstimate raw_estimate{};
CHECK(lardon3d_task_resource_estimate(raw_task, &raw_estimate));
constexpr uint64_t raw_working_bytes =
UINT64_C(2) * 1024u * 1024u * 1024u;
CHECK(raw_estimate.memory_fixed_bytes > raw_working_bytes + encoded.size() &&
raw_estimate.memory_bytes_per_item == 64u * 1024u &&
raw_estimate.desired_cpu_threads == 1 &&
raw_estimate.task_class == LARDON3D_RESOURCE_TASK_MIXED);
lardon3d_task_destroy(raw_task);
input.ingest_options.representation =
LARDON3D_ACQUISITION_SELECT_JPEG_SOURCE;
uint64_t jpeg_task_id = 0;
Lardon3DTask *jpeg_task =
lardon3d_project_create_acquisition_campaign_task(
&app_state, target.scanset_id, &input, &jpeg_task_id);
CHECK(jpeg_task != nullptr && jpeg_task_id == 4);
Lardon3DResourceEstimate jpeg_estimate{};
CHECK(lardon3d_task_resource_estimate(jpeg_task, &jpeg_estimate));
Lardon3DTaskDurableSnapshot jpeg_snapshot{};
CHECK(lardon3d_task_durable_snapshot(jpeg_task, &jpeg_snapshot));
CHECK(jpeg_estimate.memory_fixed_bytes < raw_working_bytes &&
raw_estimate.memory_fixed_bytes ==
jpeg_estimate.memory_fixed_bytes + raw_working_bytes &&
jpeg_estimate.task_class == LARDON3D_RESOURCE_TASK_IMPORT);
lardon3d_task_destroy(jpeg_task);
input.ingest_options.representation =
LARDON3D_ACQUISITION_SELECT_DEVELOP_RAW;
/* Existing v22 Tasks carry the old operational signature. It is accepted
* exactly, normalized only for admission, and never rewritten as scientific
* or generic Task identity. */
Lardon3DResourceEstimate legacy_estimate = raw_estimate;
legacy_estimate.memory_fixed_bytes -= raw_working_bytes + encoded.size();
legacy_estimate.task_class = LARDON3D_RESOURCE_TASK_IMPORT;
snapshot.estimate = legacy_estimate;
Lardon3DTaskReconstructionContext valid_reconstruction{
project_directory, database, governor, nullptr};
Lardon3DTaskKindBinding recovered{};
CHECK(lardon3d_acquisition_campaign_task_reconstruct(
&snapshot, &valid_reconstruction, &recovered));
Lardon3DTask *restored = lardon3d_task_restore_typed(
&snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, recovered.callback,
recovered.userdata, recovered.userdata_destroy);
CHECK(restored &&
lardon3d_acquisition_campaign_task_internal_configure_restored(
restored, recovered.userdata));
Lardon3DResourceDecision decision{};
Lardon3DResourceReservation *reservation = nullptr;
CHECK(lardon3d_task_internal_reserve_available(
restored, governor, &decision, &reservation));
Lardon3DResourceReservationInfo admitted{};
CHECK(reservation && lardon3d_resource_reservation_get_active(
governor, reservation, &admitted));
CHECK(admitted.memory_bytes > raw_working_bytes);
Lardon3DTaskDurableSnapshot unchanged{};
CHECK(lardon3d_task_durable_snapshot(restored, &unchanged));
CHECK(unchanged.estimate.memory_fixed_bytes ==
legacy_estimate.memory_fixed_bytes &&
unchanged.estimate.memory_bytes_per_item ==
legacy_estimate.memory_bytes_per_item &&
unchanged.estimate.task_class == legacy_estimate.task_class);
CHECK(lardon3d_resource_governor_release(governor, reservation));
lardon3d_task_destroy(restored);
Lardon3DProjectDbAcquisitionCampaignTask jpeg_persisted{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, jpeg_task_id, nullptr, 0, &jpeg_persisted) ==
LARDON3D_PROJECT_DB_OK);
CHECK(jpeg_estimate.memory_fixed_bytes > jpeg_persisted.request_size);
jpeg_snapshot.estimate = jpeg_estimate;
jpeg_snapshot.estimate.memory_fixed_bytes -= jpeg_persisted.request_size;
recovered = {};
CHECK(lardon3d_acquisition_campaign_task_reconstruct(
&jpeg_snapshot, &valid_reconstruction, &recovered));
restored = lardon3d_task_restore_typed(
&jpeg_snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, recovered.callback,
recovered.userdata, recovered.userdata_destroy);
CHECK(restored &&
lardon3d_acquisition_campaign_task_internal_configure_restored(
restored, recovered.userdata));
unchanged = {};
CHECK(lardon3d_task_durable_snapshot(restored, &unchanged) &&
unchanged.estimate.memory_fixed_bytes ==
jpeg_snapshot.estimate.memory_fixed_bytes &&
unchanged.estimate.task_class == LARDON3D_RESOURCE_TASK_IMPORT);
lardon3d_task_destroy(restored);
snapshot.estimate = raw_estimate;
++snapshot.estimate.memory_fixed_bytes;
recovered = {};
CHECK(lardon3d_acquisition_campaign_task_reconstruct(
&snapshot, &valid_reconstruction, &recovered));
restored = lardon3d_task_restore_typed(
&snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, recovered.callback,
recovered.userdata, recovered.userdata_destroy);
CHECK(restored &&
!lardon3d_acquisition_campaign_task_internal_configure_restored(
restored, recovered.userdata));
lardon3d_task_destroy(restored);
snapshot.estimate = raw_estimate;
Lardon3DAcquisitionCampaignSource execution_sources[2]{};
std::snprintf(execution_sources[0].path,
sizeof(execution_sources[0].path), "/input/group-a.jpg");
std::snprintf(execution_sources[1].path,
sizeof(execution_sources[1].path), "/input/group-b.jpg");
for (auto &source : execution_sources) {
source.source_kind = source.metadata.source_kind =
LARDON3D_ACQUISITION_SOURCE_JPEG;
source.metadata_result = LARDON3D_ACQUISITION_OK;
source.metadata.policy_version =
LARDON3D_ACQUISITION_PAIRING_POLICY_VERSION;
}
Lardon3DAcquisitionCampaignTaskRequest execution_request{};
execution_request.sources = execution_sources;
execution_request.source_count = 2;
execution_request.ingest_options.representation =
LARDON3D_ACQUISITION_SELECT_JPEG_SOURCE;
execution_request.ingest_options.select_representation = 1;
execution_request.ingest_options.imported_at = 321;
execution_request.ingest_options.max_source_bytes = 1024;
Lardon3DAcquisitionCampaignPlan execution_plan{};
CHECK(lardon3d_acquisition_campaign_plan(
execution_sources, 2, nullptr, 0, &execution_plan) ==
LARDON3D_ACQUISITION_CAMPAIGN_OK &&
execution_plan.group_count == 2);
const uint64_t fixture_captures[2]{first.capture_id, second.capture_id};
const int previous_opencv_threads = cv::getNumThreads();
cv::setNumThreads(3);
CHECK(cv::getNumThreads() == 3);
uint64_t execution_task_id = 0;
Lardon3DTask *execution_task =
lardon3d_project_create_acquisition_campaign_task(
&app_state, target.scanset_id, &execution_request,
&execution_task_id);
CHECK(execution_task && execution_task_id != 0);
Lardon3DTaskDurableSnapshot execution_snapshot{};
CHECK(lardon3d_task_durable_snapshot(execution_task, &execution_snapshot));
lardon3d_task_destroy(execution_task);
recovered = {};
CHECK(lardon3d_acquisition_campaign_task_reconstruct(
&execution_snapshot, &valid_reconstruction, &recovered));
void *execution_userdata = recovered.userdata;
restored = lardon3d_task_restore_typed(
&execution_snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, recovered.callback,
recovered.userdata, recovered.userdata_destroy);
CHECK(restored &&
lardon3d_acquisition_campaign_task_internal_configure_restored(
restored, execution_userdata) &&
lardon3d_acquisition_campaign_task_test_configure_execution(
execution_userdata, fixture_captures, 2, 0, 3));
Lardon3DResourceDecision execution_decision{};
Lardon3DResourceReservation *execution_reservation = nullptr;
CHECK(lardon3d_task_internal_reserve_available(
restored, governor, &execution_decision, &execution_reservation));
Lardon3DResourceReservationInfo execution_admission{};
CHECK(execution_reservation &&
lardon3d_resource_reservation_get_active(
governor, execution_reservation, &execution_admission) &&
execution_admission.cpu_threads == 1);
CHECK(lardon3d_task_start(restored, governor, execution_reservation));
Lardon3DTaskObservation execution_completed{};
CHECK(lardon3d_task_observation(restored, &execution_completed) &&
execution_completed.state == TASK_COMPLETED &&
execution_completed.durable_progress_known &&
execution_completed.durable_completed == 2 &&
execution_completed.durable_total == 2 &&
lardon3d_task_sequence_count(restored) == 1 &&
cv::getNumThreads() == 3);
unsigned int observed_threads[2]{};
size_t observed_count = 0;
CHECK(lardon3d_acquisition_campaign_task_test_observed_threads(
execution_userdata, observed_threads, 2, &observed_count) &&
observed_count == 2 && observed_threads[0] == 1 &&
observed_threads[1] == 1);
Lardon3DProjectDbAcquisitionCampaignTask executed_persisted{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, execution_task_id, nullptr, 0, &executed_persisted) ==
LARDON3D_PROJECT_DB_OK &&
executed_persisted.next_group_id == 2 &&
executed_persisted.group_count == 2);
Lardon3DProjectDbAcquisitionCampaignCapture execution_capture{};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, execution_task_id, 1, &execution_capture) ==
LARDON3D_PROJECT_DB_OK &&
execution_capture.capture_id == first.capture_id);
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, execution_task_id, 2, &execution_capture) ==
LARDON3D_PROJECT_DB_OK &&
execution_capture.capture_id == second.capture_id);
lardon3d_task_destroy(restored);
uint64_t failure_task_id = 0;
execution_task = lardon3d_project_create_acquisition_campaign_task(
&app_state, target.scanset_id, &execution_request, &failure_task_id);
CHECK(execution_task && failure_task_id != 0 &&
failure_task_id != execution_task_id);
Lardon3DTaskDurableSnapshot failure_snapshot{};
CHECK(lardon3d_task_durable_snapshot(execution_task, &failure_snapshot));
lardon3d_task_destroy(execution_task);
recovered = {};
CHECK(lardon3d_acquisition_campaign_task_reconstruct(
&failure_snapshot, &valid_reconstruction, &recovered));
void *failure_userdata = recovered.userdata;
restored = lardon3d_task_restore_typed(
&failure_snapshot, LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND,
LARDON3D_ACQUISITION_CAMPAIGN_TASK_KIND_VERSION, recovered.callback,
recovered.userdata, recovered.userdata_destroy);
CHECK(restored &&
lardon3d_acquisition_campaign_task_internal_configure_restored(
restored, failure_userdata) &&
lardon3d_acquisition_campaign_task_test_configure_execution(
failure_userdata, fixture_captures, 2, 2, 3));
execution_reservation = nullptr;
CHECK(lardon3d_task_internal_reserve_available(
restored, governor, &execution_decision, &execution_reservation));
CHECK(lardon3d_task_start(restored, governor, execution_reservation));
CHECK(lardon3d_task_observation(restored, &execution_completed) &&
execution_completed.state == TASK_FAILED &&
execution_completed.durable_progress_known &&
execution_completed.durable_completed == 1 &&
execution_completed.durable_total == 2 &&
lardon3d_task_sequence_count(restored) == 1 &&
cv::getNumThreads() == 3);
observed_count = 0;
observed_threads[0] = observed_threads[1] = 0;
CHECK(lardon3d_acquisition_campaign_task_test_observed_threads(
failure_userdata, observed_threads, 2, &observed_count) &&
observed_count == 2 && observed_threads[0] == 1 &&
observed_threads[1] == 1);
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, failure_task_id, nullptr, 0, &executed_persisted) ==
LARDON3D_PROJECT_DB_OK &&
executed_persisted.next_group_id == 1);
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, failure_task_id, 1, &execution_capture) ==
LARDON3D_PROJECT_DB_OK &&
execution_capture.capture_id == first.capture_id);
execution_capture = {};
CHECK(lardon3d_project_db_load_acquisition_campaign_capture(
database, failure_task_id, 2, &execution_capture) ==
LARDON3D_PROJECT_DB_NOT_FOUND &&
execution_capture.capture_id == 0);
lardon3d_task_destroy(restored);
cv::setNumThreads(previous_opencv_threads > 0 ? previous_opencv_threads : 1);
sqlite3 *id_reader = nullptr;
CHECK(sqlite3_open(database_path, &id_reader) == SQLITE_OK);
sqlite3_int64 collision_id = 0;
CHECK(query_int64(id_reader,
"SELECT value FROM metadata WHERE key='next_task_id'",
&collision_id) &&
collision_id > 0 && sqlite3_close(id_reader) == SQLITE_OK);
Lardon3DResourceEstimate collision_estimate{
1024, 0, 0, 0, 1, 1, 1, 0, 1, LARDON3D_RESOURCE_TASK_IMPORT};
Lardon3DTask *collision_task = lardon3d_task_create(
"queue collision", &collision_estimate, completed_task_callback, nullptr);
CHECK(collision_task &&
lardon3d_task_assign_id(collision_task,
static_cast<uint64_t>(collision_id)));
app_state.task_queue = lardon3d_task_queue_create(governor, 4);
CHECK(app_state.task_queue &&
lardon3d_task_queue_add(app_state.task_queue, collision_task, nullptr));
uint64_t rejected_enqueue_id = UINT64_MAX;
CHECK(!lardon3d_project_enqueue_acquisition_campaign(
&app_state, UINT64_MAX, &input, &rejected_enqueue_id) &&
rejected_enqueue_id == 0);
uint64_t durable_transfer_failure_id = UINT64_MAX;
CHECK(!lardon3d_project_enqueue_acquisition_campaign(
&app_state, target.scanset_id, &input,
&durable_transfer_failure_id) &&
durable_transfer_failure_id == static_cast<uint64_t>(collision_id));
Lardon3DProjectDbAcquisitionCampaignTask transfer_failure{};
CHECK(lardon3d_project_db_load_acquisition_campaign_task(
database, durable_transfer_failure_id, nullptr, 0,
&transfer_failure) == LARDON3D_PROJECT_DB_OK &&
transfer_failure.next_group_id == 0);
lardon3d_task_queue_destroy(app_state.task_queue);
app_state.task_queue = nullptr;
std::vector<char> overlong_project_path(LARDON3D_APP_STATE_PATH_CAPACITY + 1,
'x');
overlong_project_path.back() = '\0';
Lardon3DTaskReconstructionContext reconstruction{
overlong_project_path.data(), database, governor, nullptr};
Lardon3DTaskKindBinding binding{};
CHECK(!lardon3d_acquisition_campaign_task_reconstruct(
&snapshot, &reconstruction, &binding));
lardon3d_resource_governor_destroy(governor);
lardon3d_project_db_close(database);
CHECK(unlink(database_path) == 0);
CHECK(std::filesystem::remove_all(project_directory) > 0);
return 0;
}