539 lines
25 KiB
C++
539 lines
25 KiB
C++
#include <cstdlib>
|
|
#include <iostream>
|
|
#include <string>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
#define main lardon3d_pre_sfm_real_execution_main
|
|
#include "pre_sfm_real_execution.cpp"
|
|
#undef main
|
|
|
|
#define CHECK(condition) \
|
|
do { \
|
|
if (!(condition)) { \
|
|
std::cerr << "failed line " << __LINE__ << ": " << #condition << '\n'; \
|
|
return EXIT_FAILURE; \
|
|
} \
|
|
} while (false)
|
|
|
|
static bool parse_case(std::initializer_list<const char *> arguments,
|
|
Options &options) {
|
|
std::vector<std::string> storage(arguments.begin(), arguments.end());
|
|
std::vector<char *> argv;
|
|
argv.reserve(storage.size());
|
|
for (std::string &argument : storage) argv.push_back(argument.data());
|
|
return parse_options(static_cast<int>(argv.size()), argv.data(), options);
|
|
}
|
|
|
|
static int invoke_case(std::initializer_list<const char *> arguments) {
|
|
std::vector<std::string> storage(arguments.begin(), arguments.end());
|
|
std::vector<char *> argv;
|
|
argv.reserve(storage.size());
|
|
for (std::string &argument : storage) argv.push_back(argument.data());
|
|
return lardon3d_pre_sfm_real_execution_main(
|
|
static_cast<int>(argv.size()), argv.data());
|
|
}
|
|
|
|
static bool capture_matcher_evidence(Runtime &runtime, std::string &output) {
|
|
FILE *capture = std::tmpfile();
|
|
if (!capture) return false;
|
|
const int saved_stdout = dup(STDOUT_FILENO);
|
|
if (saved_stdout < 0 || std::fflush(stdout) != 0 ||
|
|
dup2(fileno(capture), STDOUT_FILENO) < 0) {
|
|
if (saved_stdout >= 0) close(saved_stdout);
|
|
std::fclose(capture);
|
|
return false;
|
|
}
|
|
(void)end_matcher_evidence(runtime);
|
|
const bool flushed = std::fflush(stdout) == 0;
|
|
const bool restored = dup2(saved_stdout, STDOUT_FILENO) >= 0;
|
|
close(saved_stdout);
|
|
bool read_ok = flushed && restored && std::fseek(capture, 0, SEEK_SET) == 0;
|
|
char buffer[1024];
|
|
while (read_ok) {
|
|
const size_t count = std::fread(buffer, 1, sizeof(buffer), capture);
|
|
output.append(buffer, count);
|
|
if (count < sizeof(buffer)) {
|
|
read_ok = std::feof(capture) != 0 && std::ferror(capture) == 0;
|
|
break;
|
|
}
|
|
}
|
|
return std::fclose(capture) == 0 && read_ok;
|
|
}
|
|
|
|
static bool json_valid_and_submit_cpu(const std::string &line,
|
|
bool require_submit_cpu) {
|
|
sqlite3 *database = nullptr;
|
|
sqlite3_stmt *statement = nullptr;
|
|
bool ok = sqlite3_open(":memory:", &database) == SQLITE_OK &&
|
|
sqlite3_prepare_v2(
|
|
database,
|
|
"SELECT json_valid(?1), json_extract(?1, "
|
|
"'$.vulkan_submit_cpu_ns')",
|
|
-1, &statement, nullptr) == SQLITE_OK &&
|
|
sqlite3_bind_text(statement, 1, line.c_str(), -1,
|
|
SQLITE_TRANSIENT) == SQLITE_OK &&
|
|
sqlite3_step(statement) == SQLITE_ROW &&
|
|
sqlite3_column_int(statement, 0) == 1;
|
|
if (ok && require_submit_cpu) {
|
|
ok = sqlite3_column_type(statement, 1) == SQLITE_INTEGER &&
|
|
sqlite3_column_int64(statement, 1) == 123456789;
|
|
}
|
|
if (statement) sqlite3_finalize(statement);
|
|
if (database && sqlite3_close(database) != SQLITE_OK) ok = false;
|
|
return ok;
|
|
}
|
|
|
|
static bool matcher_evidence_aggregate_case() {
|
|
Lardon3DHardwareProfile profile{};
|
|
profile.logical_cpu_count = 16;
|
|
profile.page_size_bytes = 4096;
|
|
profile.memory_total_bytes = UINT64_C(16) * 1024 * 1024 * 1024;
|
|
profile.gpu_available = true;
|
|
profile.gpu_uses_shared_memory = true;
|
|
std::snprintf(profile.cpu_architecture, sizeof(profile.cpu_architecture),
|
|
"%s", "test");
|
|
Lardon3DResourcePolicy policy{};
|
|
if (!lardon3d_resource_policy_default(&profile, &policy)) return false;
|
|
policy.gpu_slot_capacity = 1;
|
|
Lardon3DResourceGovernor *governor =
|
|
lardon3d_resource_governor_create(&profile, &policy);
|
|
if (!governor) return false;
|
|
|
|
Lardon3DTaskCapabilityEnvelope envelope{};
|
|
envelope.count = 1;
|
|
envelope.capabilities[0].estimate.memory_bytes_per_item = 10 * 1024 * 1024;
|
|
envelope.capabilities[0].estimate.minimum_batch_size = 4;
|
|
envelope.capabilities[0].estimate.maximum_batch_size = 4;
|
|
envelope.capabilities[0].estimate.desired_cpu_threads = 1;
|
|
envelope.capabilities[0].estimate.desired_gpu_slots = 1;
|
|
envelope.capabilities[0].estimate.desired_io_slots = 1;
|
|
envelope.capabilities[0].estimate.task_class = LARDON3D_RESOURCE_TASK_GPU;
|
|
envelope.capabilities[0].backend = LARDON3D_RESOURCE_BACKEND_ORB_VULKAN;
|
|
envelope.capabilities[0].inflight_limit = 2;
|
|
envelope.capabilities[0].minimum_inflight_limit = 2;
|
|
envelope.capabilities[0].gpu_memory_bytes_per_inflight = 640 * 1024;
|
|
Lardon3DResourceSnapshot snapshot{};
|
|
if (clock_gettime(CLOCK_MONOTONIC, &snapshot.captured_at) != 0) {
|
|
lardon3d_resource_governor_destroy(governor);
|
|
return false;
|
|
}
|
|
snapshot.memory_available_bytes = UINT64_C(8) * 1024 * 1024 * 1024;
|
|
snapshot.swap_activity_known = true;
|
|
Lardon3DResourceCapabilitySelection selection{};
|
|
Lardon3DResourceReservation *reservation = nullptr;
|
|
const bool admitted =
|
|
lardon3d_resource_governor_internal_reserve_capability(
|
|
governor, &snapshot, LARDON3D_MATCHER_TASK_KIND,
|
|
LARDON3D_MATCHER_TASK_KIND_VERSION, &envelope, &selection,
|
|
&reservation) &&
|
|
reservation;
|
|
const bool released =
|
|
admitted && lardon3d_resource_governor_release(governor, reservation);
|
|
Lardon3DResourceExecutionMetrics metrics{};
|
|
metrics.vulkan_submits = 2;
|
|
metrics.vulkan_completions = 2;
|
|
metrics.vulkan_submit_cpu_ns = 123456789;
|
|
metrics.vulkan_fence_wait_ns = 11;
|
|
metrics.vulkan_readback_ns = 12;
|
|
metrics.vulkan_gpu_time_known = true;
|
|
metrics.vulkan_gpu_ns = 13;
|
|
metrics.vulkan_starvation_ns = 14;
|
|
metrics.matcher_cpu_ns = 15;
|
|
metrics.publication_ns = 16;
|
|
metrics.local_ineligible_fallback_items = 1;
|
|
const bool recorded = released &&
|
|
lardon3d_resource_governor_internal_record_fallback_items(
|
|
governor, LARDON3D_MATCHER_TASK_KIND,
|
|
LARDON3D_MATCHER_TASK_KIND_VERSION, &selection,
|
|
LARDON3D_RESOURCE_FALLBACK_ITEM_LOCAL_INELIGIBLE, 1) &&
|
|
lardon3d_resource_governor_internal_record_sequence_execution_metrics(
|
|
governor, LARDON3D_MATCHER_TASK_KIND,
|
|
LARDON3D_MATCHER_TASK_KIND_VERSION, &selection, 1000, 1,
|
|
LARDON3D_RESOURCE_BACKEND_MIXED,
|
|
"vulkan-and-ineligible-pair-cpu-fallback", &metrics);
|
|
Runtime runtime{};
|
|
runtime.state.resource_governor = governor;
|
|
runtime.state.hardware_profile = profile;
|
|
runtime.matcher_inflight_override = 2;
|
|
runtime.matcher_batch_override = 4;
|
|
begin_matcher_evidence(runtime);
|
|
std::string output;
|
|
const bool captured = recorded && capture_matcher_evidence(runtime, output);
|
|
lardon3d_resource_governor_destroy(governor);
|
|
if (!captured) {
|
|
std::cerr << "unable to construct/capture Matcher evidence fixture: "
|
|
<< "admitted=" << admitted << " released=" << released
|
|
<< " recorded=" << recorded << '\n';
|
|
return false;
|
|
}
|
|
|
|
bool saw_aggregate = false;
|
|
size_t offset = 0;
|
|
while (offset < output.size()) {
|
|
const size_t newline = output.find('\n', offset);
|
|
const size_t end = newline == std::string::npos ? output.size() : newline;
|
|
const std::string line = output.substr(offset, end - offset);
|
|
if (!line.empty()) {
|
|
const bool aggregate = line.find(
|
|
"\"record\":\"matcher_evidence_aggregate\"") !=
|
|
std::string::npos;
|
|
if (!json_valid_and_submit_cpu(line, aggregate)) {
|
|
std::cerr << "invalid Matcher evidence JSON: " << line << '\n';
|
|
return false;
|
|
}
|
|
saw_aggregate = saw_aggregate || aggregate;
|
|
}
|
|
if (newline == std::string::npos) break;
|
|
offset = newline + 1;
|
|
}
|
|
const bool exact_field =
|
|
output.find("\"vulkan_submit_cpu_ns\":123456789") !=
|
|
std::string::npos;
|
|
const bool affinity_fields =
|
|
output.find("\"runtime_thread_policy_active\":true") !=
|
|
std::string::npos &&
|
|
output.find("\"mesa_shader_cache_disabled\":true") !=
|
|
std::string::npos &&
|
|
output.find("\"runtime_thread_policy_reason\":"
|
|
"\"worker-self-affinity-plus-mesa-disk-cache-disabled\"") !=
|
|
std::string::npos &&
|
|
output.find("auxiliary_affinity_active") == std::string::npos;
|
|
const bool inflight_field =
|
|
output.find("\"matcher_inflight_override\":2") != std::string::npos;
|
|
const bool batch_field =
|
|
output.find("\"matcher_batch_override\":4") != std::string::npos;
|
|
const bool experiment_fields =
|
|
output.find("\"experiment_valid\":false") != std::string::npos &&
|
|
output.find("\"experiment_reason\":\"backend-telemetry-unavailable\"") !=
|
|
std::string::npos &&
|
|
output.find("\"local_ineligible_fallback_sequences\":1") !=
|
|
std::string::npos &&
|
|
output.find("\"local_ineligible_fallback_items\":1") !=
|
|
std::string::npos &&
|
|
output.find("\"backend_failure_fallback_items\":0") !=
|
|
std::string::npos &&
|
|
output.find("\"backend_other_fallback_items\":0") !=
|
|
std::string::npos &&
|
|
output.find(
|
|
"\"comparison_requires_equal_local_ineligible_fallback_items\":"
|
|
"true") != std::string::npos;
|
|
if (!saw_aggregate || !exact_field || !affinity_fields || !inflight_field ||
|
|
!batch_field || !experiment_fields)
|
|
std::cerr << "missing exact Matcher aggregate field: " << output << '\n';
|
|
return saw_aggregate && exact_field && affinity_fields && inflight_field &&
|
|
batch_field && experiment_fields;
|
|
}
|
|
|
|
static bool forced_matcher_experiment_validation_case() {
|
|
Runtime runtime{};
|
|
runtime.matcher_inflight_override = 1;
|
|
Lardon3DResourceSequenceAggregate aggregate{};
|
|
aggregate.admission_count = 2;
|
|
aggregate.sequence_count = 2;
|
|
aggregate.selected_backend_admissions[
|
|
LARDON3D_RESOURCE_BACKEND_ORB_VULKAN] = 2;
|
|
aggregate.actual_backend_sequences[
|
|
LARDON3D_RESOURCE_BACKEND_ORB_VULKAN] = 2;
|
|
aggregate.vulkan_submits = 4;
|
|
aggregate.vulkan_completions = 4;
|
|
Lardon3DResourceSequenceDiagnostic last{};
|
|
last.backend = LARDON3D_RESOURCE_BACKEND_ORB_VULKAN;
|
|
last.actual_backend = LARDON3D_RESOURCE_BACKEND_ORB_VULKAN;
|
|
last.cpu_threads = 1;
|
|
last.gpu_slots = 1;
|
|
last.batch_size = 2;
|
|
last.inflight_limit = 1;
|
|
last.io_slots = 1;
|
|
last.memory_bytes = 2 * 10 * 1024 * 1024;
|
|
last.gpu_memory_bytes = 640 * 1024;
|
|
MatcherExperimentValidation validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (!validated.valid || validated.local_ineligible_fallback_items != 0)
|
|
return false;
|
|
|
|
/* The second controlled cohort differs only in admitted inflight/payload;
|
|
* selected backend, CPU/GPU/batch/helpers, and scientific output stay fixed. */
|
|
runtime.matcher_inflight_override = 2;
|
|
last.inflight_limit = 2;
|
|
last.gpu_memory_bytes = 2 * 640 * 1024;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (!validated.valid) return false;
|
|
|
|
runtime.matcher_batch_override = 4;
|
|
last.batch_size = 4;
|
|
last.memory_bytes = 4 * 10 * 1024 * 1024;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (!validated.valid) return false;
|
|
last.batch_size = 2;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (validated.valid ||
|
|
std::string(validated.reason) != "forced-contract-mismatch")
|
|
return false;
|
|
runtime.matcher_batch_override = 0;
|
|
last.batch_size = 2;
|
|
last.memory_bytes = 2 * 10 * 1024 * 1024;
|
|
|
|
aggregate.actual_backend_sequences[
|
|
LARDON3D_RESOURCE_BACKEND_ORB_VULKAN] = 1;
|
|
aggregate.actual_backend_sequences[LARDON3D_RESOURCE_BACKEND_MIXED] = 1;
|
|
aggregate.backend_fallback_sequences = 1;
|
|
aggregate.backend_ineligible_fallback_sequences = 1;
|
|
aggregate.local_ineligible_fallback_items = 3;
|
|
aggregate.durable_items = 4;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (!validated.valid || validated.local_ineligible_fallback_items != 3)
|
|
return false;
|
|
aggregate.local_ineligible_fallback_items = 0;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (validated.valid ||
|
|
std::string(validated.reason) !=
|
|
"fallback-item-classification-mismatch")
|
|
return false;
|
|
|
|
aggregate.backend_ineligible_fallback_sequences = 0;
|
|
aggregate.backend_failure_fallback_sequences = 1;
|
|
aggregate.local_ineligible_fallback_items = 0;
|
|
aggregate.backend_failure_fallback_items = 1;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (validated.valid || std::string(validated.reason) != "backend-failure")
|
|
return false;
|
|
|
|
aggregate.backend_failure_fallback_sequences = 0;
|
|
aggregate.backend_failure_fallback_items = 0;
|
|
aggregate.backend_other_fallback_items = 1;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
if (validated.valid ||
|
|
std::string(validated.reason) != "unclassified-backend-fallback")
|
|
return false;
|
|
|
|
aggregate = {};
|
|
aggregate.admission_count = 1;
|
|
aggregate.sequence_count = 1;
|
|
aggregate.selected_backend_admissions[LARDON3D_RESOURCE_BACKEND_CPU] = 1;
|
|
aggregate.actual_backend_sequences[LARDON3D_RESOURCE_BACKEND_CPU] = 1;
|
|
validated = validate_forced_matcher_experiment(
|
|
runtime, true, aggregate, true, last, true, 0, 0, false);
|
|
return !validated.valid &&
|
|
std::string(validated.reason) ==
|
|
"selected-contract-not-exclusively-vulkan";
|
|
}
|
|
|
|
int main() {
|
|
CHECK(unsetenv("MESA_SHADER_CACHE_DISABLE") == 0);
|
|
CHECK(lardon3d_resource_governor_internal_configure_driver_policy() ==
|
|
LARDON3D_RESOURCE_DRIVER_POLICY_DEFAULTED);
|
|
CHECK(std::string(std::getenv("MESA_SHADER_CACHE_DISABLE")) == "true");
|
|
CHECK(lardon3d_resource_governor_internal_configure_driver_policy() ==
|
|
LARDON3D_RESOURCE_DRIVER_POLICY_INHERITED_SAFE);
|
|
CHECK(setenv("MESA_SHADER_CACHE_DISABLE", "false", 1) == 0);
|
|
CHECK(lardon3d_resource_governor_internal_configure_driver_policy() ==
|
|
LARDON3D_RESOURCE_DRIVER_POLICY_REJECTED_UNSAFE);
|
|
CHECK(std::string(std::getenv("MESA_SHADER_CACHE_DISABLE")) == "false");
|
|
CHECK(setenv("MESA_SHADER_CACHE_DISABLE", "true", 1) == 0);
|
|
|
|
Runtime geometric_reset{};
|
|
geometric_reset.geometric_maximum_swap_pages_in_delta = 17;
|
|
geometric_reset.geometric_maximum_swap_pages_out_delta = 19;
|
|
geometric_reset.geometric_maximum_process_rss_bytes = 23;
|
|
begin_geometric_evidence(geometric_reset);
|
|
CHECK(geometric_reset.geometric_maximum_swap_pages_in_delta == 0 &&
|
|
geometric_reset.geometric_maximum_swap_pages_out_delta == 0 &&
|
|
geometric_reset.geometric_maximum_process_rss_bytes == 0);
|
|
geometric_reset.geometric_evidence_active = false;
|
|
|
|
Lardon3DProjectRecoveryEntry recovery_entry{};
|
|
recovery_entry.status = LARDON3D_PROJECT_RECOVERABLE;
|
|
recovery_entry.snapshot.recovery_state = TASK_PENDING;
|
|
std::snprintf(recovery_entry.task_kind, sizeof(recovery_entry.task_kind),
|
|
"%s", LARDON3D_TRACK_BUILDER_TASK_KIND);
|
|
recovery_entry.task_kind_version = LARDON3D_TRACK_BUILDER_TASK_KIND_VERSION;
|
|
GeometryRecoveryKind recovery_kind{};
|
|
CHECK(geometry_recovery_kind(recovery_entry, recovery_kind));
|
|
CHECK(recovery_kind == GeometryRecoveryKind::kTrackBuilder);
|
|
++recovery_entry.task_kind_version;
|
|
CHECK(!geometry_recovery_kind(recovery_entry, recovery_kind));
|
|
std::snprintf(recovery_entry.task_kind, sizeof(recovery_entry.task_kind),
|
|
"unknown.task");
|
|
recovery_entry.task_kind_version = 1;
|
|
CHECK(!geometry_recovery_kind(recovery_entry, recovery_kind));
|
|
|
|
Options options;
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened"}, options));
|
|
CHECK(options.matcher_mode == MatcherMode::kAuto &&
|
|
options.matcher_pipeline == MatcherPipeline::kRolling &&
|
|
!options.has_matcher_mode && !options.has_matcher_pipeline &&
|
|
!options.has_matcher_inflight_override &&
|
|
options.matcher_inflight_override == 0 &&
|
|
!options.has_matcher_batch_override &&
|
|
options.matcher_batch_override == 0);
|
|
|
|
options = {};
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "auto",
|
|
"--matcher-pipeline", "synchronous"}, options));
|
|
CHECK(options.matcher_mode == MatcherMode::kAuto &&
|
|
options.matcher_pipeline == MatcherPipeline::kSynchronous &&
|
|
options.has_matcher_mode && options.has_matcher_pipeline);
|
|
|
|
options = {};
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "vulkan",
|
|
"--matcher-pipeline", "rolling", "--gpu-budget", "1"},
|
|
options));
|
|
CHECK(options.matcher_mode == MatcherMode::kVulkan &&
|
|
options.matcher_pipeline == MatcherPipeline::kRolling);
|
|
|
|
options = {};
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "auto",
|
|
"--matcher-pipeline", "rolling", "--matcher-inflight",
|
|
"1"}, options));
|
|
CHECK(options.matcher_inflight_override == 1 &&
|
|
options.has_matcher_inflight_override);
|
|
options = {};
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "2"},
|
|
options));
|
|
CHECK(options.matcher_inflight_override == 2 &&
|
|
options.has_matcher_inflight_override);
|
|
for (const unsigned batch : {2U, 4U, 8U, 12U}) {
|
|
options = {};
|
|
const std::string batch_text = std::to_string(batch);
|
|
CHECK(parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1",
|
|
"--matcher-batch", batch_text.c_str()}, options));
|
|
CHECK(options.matcher_batch_override == batch &&
|
|
options.has_matcher_batch_override);
|
|
}
|
|
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "invalid"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-pipeline", "invalid"},
|
|
options));
|
|
for (const char *invalid_inflight : {"0", "3", "01", "+1", "2x"}) {
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight",
|
|
invalid_inflight}, options));
|
|
}
|
|
for (const char *invalid_batch : {"1", "3", "6", "10", "16", "02",
|
|
"+2", "4x"}) {
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1",
|
|
"--matcher-batch", invalid_batch}, options));
|
|
}
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-candidate-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "auto"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-candidate-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1"},
|
|
options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-candidate-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1",
|
|
"--matcher-batch", "2"}, options));
|
|
options = {};
|
|
CHECK(parse_case({"runner", "--resume-geometry-existing", "--project-dir",
|
|
"/tmp/not-opened", "--stop-after-gv"}, options));
|
|
CHECK(options.stop_after_gv && !options.stop_after_matcher);
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--stop-after-gv"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-candidate-existing", "--project-dir",
|
|
"/tmp/not-opened", "--stop-after-gv"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--mode", "s21", "--project-dir",
|
|
"/tmp/not-opened", "--root", "/tmp",
|
|
"--stop-after-gv"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-geometry-existing", "--project-dir",
|
|
"/tmp/not-opened", "--stop-after-matcher",
|
|
"--stop-after-gv"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--resume-geometry-existing", "--project-dir",
|
|
"/tmp/not-opened", "--cpu-budget", "2"}, options));
|
|
options = {};
|
|
CHECK(!parse_case({"runner", "--mode", "s21", "--project-dir",
|
|
"/tmp/not-opened", "--root", "/tmp", "--matcher-mode",
|
|
"auto"}, options));
|
|
|
|
/* These contradictions are rejected by main before project inspection or a
|
|
* durable Task allocation, which is the CLI contract the harness relies on. */
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "cpu",
|
|
"--matcher-pipeline", "synchronous"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "vulkan",
|
|
"--gpu-budget", "0"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "2",
|
|
"--gpu-budget", "0"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "cpu",
|
|
"--matcher-inflight", "1"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-mode", "vulkan",
|
|
"--matcher-inflight", "1"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-pipeline", "synchronous",
|
|
"--matcher-inflight", "2"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-batch", "2"}) == 2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-pipeline", "synchronous",
|
|
"--matcher-inflight", "1", "--matcher-batch", "2"}) ==
|
|
2);
|
|
CHECK(invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1",
|
|
"--matcher-batch", "4", "--gpu-budget", "0"}) == 2);
|
|
|
|
/* The runner owns all three process controls only for one invocation. Even a
|
|
* project-validation exit must restore exact inherited values, while absent
|
|
* controls remain absent after the same path. */
|
|
CHECK(setenv(LARDON3D_MATCHER_TASK_BENCHMARK_SYNCHRONOUS_ENV,
|
|
"inherited-pipeline", 1) == 0 &&
|
|
setenv(LARDON3D_MATCHER_TASK_BENCHMARK_INFLIGHT_ENV,
|
|
"inherited-inflight", 1) == 0 &&
|
|
setenv(LARDON3D_MATCHER_TASK_BENCHMARK_BATCH_ENV,
|
|
"inherited-batch", 1) == 0 &&
|
|
invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "2",
|
|
"--matcher-batch", "8"}) == 2 &&
|
|
std::string(std::getenv(
|
|
LARDON3D_MATCHER_TASK_BENCHMARK_SYNCHRONOUS_ENV)) ==
|
|
"inherited-pipeline" &&
|
|
std::string(std::getenv(
|
|
LARDON3D_MATCHER_TASK_BENCHMARK_INFLIGHT_ENV)) ==
|
|
"inherited-inflight" &&
|
|
std::string(std::getenv(
|
|
LARDON3D_MATCHER_TASK_BENCHMARK_BATCH_ENV)) ==
|
|
"inherited-batch" &&
|
|
unsetenv(LARDON3D_MATCHER_TASK_BENCHMARK_SYNCHRONOUS_ENV) == 0 &&
|
|
unsetenv(LARDON3D_MATCHER_TASK_BENCHMARK_INFLIGHT_ENV) == 0 &&
|
|
unsetenv(LARDON3D_MATCHER_TASK_BENCHMARK_BATCH_ENV) == 0 &&
|
|
invoke_case({"runner", "--resume-pre-gv-existing", "--project-dir",
|
|
"/tmp/not-opened", "--matcher-inflight", "1",
|
|
"--matcher-batch", "4"}) == 2 &&
|
|
std::getenv(LARDON3D_MATCHER_TASK_BENCHMARK_SYNCHRONOUS_ENV) ==
|
|
nullptr &&
|
|
std::getenv(LARDON3D_MATCHER_TASK_BENCHMARK_INFLIGHT_ENV) == nullptr &&
|
|
std::getenv(LARDON3D_MATCHER_TASK_BENCHMARK_BATCH_ENV) == nullptr);
|
|
CHECK(matcher_evidence_aggregate_case());
|
|
CHECK(forced_matcher_experiment_validation_case());
|
|
return EXIT_SUCCESS;
|
|
}
|