feat: assemble autofocus study evidence
This commit is contained in:
parent
1a96bcce1f
commit
6a52ef4957
9 changed files with 459 additions and 3 deletions
|
|
@ -188,3 +188,38 @@ calibration evidence.
|
|||
|
||||
The bridge performs no DB access, metadata interpretation, physical AF decision,
|
||||
thresholding, interpolation or extrapolation.
|
||||
|
||||
## Materialized study assembly v1
|
||||
|
||||
**Status: PASS / FROZEN.**
|
||||
|
||||
`CALIBRATION_AF_STUDY_ASSEMBLY_V1` composes the frozen Workflow bridge and
|
||||
`L3DAFST1` producer so a physical AF study does not need caller-written sample
|
||||
arrays.
|
||||
|
||||
The caller supplies:
|
||||
|
||||
```text
|
||||
study_context_sha256
|
||||
2..64 entries {
|
||||
materialized Calibration Workflow evidence
|
||||
exact opaque focus token
|
||||
FIT or HOLDOUT role
|
||||
}
|
||||
```
|
||||
|
||||
The assembly:
|
||||
|
||||
1. converts every entry through the frozen Workflow bridge;
|
||||
2. requires one exact oriented width/height for the whole study;
|
||||
3. rejects a repeated `calibration_evidence_sha256` even when the caller changes
|
||||
focus token or FIT/HOLDOUT role;
|
||||
4. passes the resulting bounded samples to the frozen AF-study producer;
|
||||
5. returns deterministic `L3DAFST1`, artifact SHA-256 and summary.
|
||||
|
||||
`study_context_sha256` remains caller-retained and explicit. This layer does not
|
||||
derive body/lens/focal/non-focus state from solver metadata and does not decide
|
||||
whether different focus observations belong to one physically valid domain.
|
||||
|
||||
No Project DB access, solver execution, metadata inference, thresholding,
|
||||
interpolation or extrapolation is introduced.
|
||||
|
|
|
|||
|
|
@ -952,5 +952,6 @@ numbered `prompt/` execution contract. The current dependency is physical autofo
|
|||
applicability validation for real equipment, followed by a dedicated calibrated real campaign.
|
||||
Generic autofocus applicability machinery is available. AF-study evidence can now be produced from
|
||||
already-materialized Calibration Workflow results without a second solver parser, while focus tokens
|
||||
remain explicit study annotations. The real A6000 + E PZ 16-50 autofocus applicability remains
|
||||
blocked until physical evidence validates it.
|
||||
remain explicit study annotations. Multiple independent materialized samples can now be assembled into
|
||||
one deterministic L3DAFST1 artifact without caller-written sample arrays. The real
|
||||
A6000 + E PZ 16-50 autofocus applicability remains blocked until physical evidence validates it.
|
||||
|
|
|
|||
61
include/lardon3d/calibration_af_study_assembly.h
Normal file
61
include/lardon3d/calibration_af_study_assembly.h
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_H
|
||||
#define LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_H
|
||||
|
||||
#include <lardon3d/calibration_af_study.h>
|
||||
#include <lardon3d/calibration_af_study_workflow.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_OK = 0,
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT,
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE,
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_CAPACITY,
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_CRYPTO_ERROR,
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_ENCODING_ERROR,
|
||||
} Lardon3DCalibrationAfStudyAssemblyResult;
|
||||
|
||||
typedef struct {
|
||||
const Lardon3DCalibrationWorkflowExternalEvidence *external;
|
||||
Lardon3DCalibrationAfStudySampleRole role;
|
||||
const char *focus_token;
|
||||
} Lardon3DCalibrationAfStudyAssemblyEntry;
|
||||
|
||||
typedef struct {
|
||||
/* Exact caller-retained identity of the common body/lens/focal/non-focus
|
||||
* geometric study context. The assembly does not derive or reinterpret it. */
|
||||
unsigned char study_context_sha256[
|
||||
LARDON3D_CALIBRATION_AF_STUDY_SHA256_SIZE];
|
||||
const Lardon3DCalibrationAfStudyAssemblyEntry *entries;
|
||||
size_t entry_count;
|
||||
} Lardon3DCalibrationAfStudyAssemblyInput;
|
||||
|
||||
/* Assemble 2..MAX_SAMPLES already-materialized Calibration Workflow results
|
||||
* into one deterministic L3DAFST1 artifact.
|
||||
*
|
||||
* Each entry is converted through the frozen Workflow bridge; no solver file
|
||||
* is parsed here. All samples must share exact oriented dimensions because one
|
||||
* L3DAFST1 study has one image geometry. The common optical/non-focus identity
|
||||
* remains the explicit study_context_sha256 supplied by the caller.
|
||||
*
|
||||
* Duplicate calibration_evidence_sha256 values are rejected regardless of
|
||||
* focus token or FIT/HOLDOUT role. A single physical calibration result cannot
|
||||
* therefore be relabelled to masquerade as independent AF evidence.
|
||||
*
|
||||
* This boundary performs no Project DB access, no metadata interpretation, no
|
||||
* physical applicability decision and no acceptance thresholding. */
|
||||
Lardon3DCalibrationAfStudyAssemblyResult
|
||||
lardon3d_calibration_af_study_assemble_materialized(
|
||||
const Lardon3DCalibrationAfStudyAssemblyInput *input,
|
||||
unsigned char *artifact, size_t artifact_capacity, size_t *written,
|
||||
unsigned char artifact_sha256[
|
||||
LARDON3D_CALIBRATION_AF_STUDY_SHA256_SIZE],
|
||||
Lardon3DCalibrationAfStudySummary *summary);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
19
meson.build
19
meson.build
|
|
@ -185,6 +185,7 @@ lardon3d_app = executable(
|
|||
'src/calibration_tooling_v2.c',
|
||||
'src/calibration_af_study.c',
|
||||
'src/calibration_af_study_workflow.c',
|
||||
'src/calibration_af_study_assembly.c',
|
||||
'src/calibration_workflow.cpp',
|
||||
'src/calibration_workflow_materialize.cpp',
|
||||
'src/calibration_workflow_bind.cpp',
|
||||
|
|
@ -947,6 +948,24 @@ test(
|
|||
timeout: 30,
|
||||
)
|
||||
|
||||
calibration_af_study_assembly_test = executable(
|
||||
'test-calibration-af-study-assembly',
|
||||
sources: [
|
||||
'tests/test_calibration_af_study_assembly.c',
|
||||
'src/calibration_af_study_assembly.c',
|
||||
'src/calibration_af_study_workflow.c',
|
||||
'src/calibration_af_study.c',
|
||||
],
|
||||
include_directories: include_directories('include'),
|
||||
dependencies: [openssl, cc.find_library('m')],
|
||||
)
|
||||
|
||||
test(
|
||||
'calibration-af-study-assembly',
|
||||
calibration_af_study_assembly_test,
|
||||
timeout: 30,
|
||||
)
|
||||
|
||||
calibration_workflow_v2_test = executable(
|
||||
'test-calibration-workflow-v2',
|
||||
sources: [
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ Adaptive capture settings semantics PASS/FROZEN
|
|||
Autofocus v2 foundation PASS/FROZEN
|
||||
Calibration AF study evidence v1 PASS/FROZEN
|
||||
Calibration AF study Workflow bridge v1 PASS/FROZEN
|
||||
Calibration AF study assembly v1 PASS/FROZEN
|
||||
Calibration Tooling planarity alignment PASS/FROZEN
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PASS/FROZEN
|
|||
AUTOFOCUS_V2_FOUNDATION=PASS/FROZEN
|
||||
CALIBRATION_AF_STUDY_EVIDENCE_V1=PASS/FROZEN
|
||||
CALIBRATION_AF_STUDY_WORKFLOW_BRIDGE_V1=PASS/FROZEN
|
||||
CALIBRATION_AF_STUDY_ASSEMBLY_V1=PASS/FROZEN
|
||||
CURRENT_CALIBRATION_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ Default dependency order:
|
|||
4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN;
|
||||
5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN;
|
||||
6. Adaptive capture settings / generic autofocus foundation — PASS/FROZEN;
|
||||
7. physical autofocus/optical applicability validation and dedicated calibrated real campaign — CURRENT; `CALIBRATION_AF_STUDY_EVIDENCE_V1=PASS/FROZEN` supplies deterministic measurement evidence and `CALIBRATION_AF_STUDY_WORKFLOW_BRIDGE_V1=PASS/FROZEN` converts already-materialized Calibration Workflow evidence into AF-study samples without reparsing solver artifacts; neither makes a physical applicability decision;
|
||||
7. physical autofocus/optical applicability validation and dedicated calibrated real campaign — CURRENT; `CALIBRATION_AF_STUDY_EVIDENCE_V1=PASS/FROZEN` supplies deterministic measurement evidence, `CALIBRATION_AF_STUDY_WORKFLOW_BRIDGE_V1=PASS/FROZEN` converts already-materialized Calibration Workflow evidence into AF-study samples without reparsing solver artifacts, and `CALIBRATION_AF_STUDY_ASSEMBLY_V1=PASS/FROZEN` assembles multiple independent materialized samples into one bounded L3DAFST1 artifact; none makes a physical applicability decision;
|
||||
8. real Sparse SfM proof;
|
||||
9. durable Dense/OpenMVS orchestration;
|
||||
10. mesh / refinement / texturing / export;
|
||||
|
|
|
|||
112
src/calibration_af_study_assembly.c
Normal file
112
src/calibration_af_study_assembly.c
Normal file
|
|
@ -0,0 +1,112 @@
|
|||
#include <lardon3d/calibration_af_study_assembly.h>
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
static bool nonzero_digest(const unsigned char value[32]) {
|
||||
unsigned char any = 0;
|
||||
for (size_t index = 0; index < 32; ++index) any |= value[index];
|
||||
return any != 0;
|
||||
}
|
||||
|
||||
static Lardon3DCalibrationAfStudyAssemblyResult map_bridge_result(
|
||||
Lardon3DCalibrationAfStudyWorkflowResult result) {
|
||||
switch (result) {
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_WORKFLOW_INVALID_ARGUMENT:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_WORKFLOW_INVALID_EVIDENCE:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_WORKFLOW_CRYPTO_ERROR:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_CRYPTO_ERROR;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_WORKFLOW_OK:
|
||||
break;
|
||||
}
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
}
|
||||
|
||||
static Lardon3DCalibrationAfStudyAssemblyResult map_study_result(
|
||||
Lardon3DCalibrationAfStudyResult result) {
|
||||
switch (result) {
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_INVALID_ARGUMENT:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_CAPACITY:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_CAPACITY;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_INVALID_EVIDENCE:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_ENCODING_ERROR:
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_ENCODING_ERROR;
|
||||
case LARDON3D_CALIBRATION_AF_STUDY_OK:
|
||||
break;
|
||||
}
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
}
|
||||
|
||||
Lardon3DCalibrationAfStudyAssemblyResult
|
||||
lardon3d_calibration_af_study_assemble_materialized(
|
||||
const Lardon3DCalibrationAfStudyAssemblyInput *input,
|
||||
unsigned char *artifact, size_t artifact_capacity, size_t *written,
|
||||
unsigned char artifact_sha256[32],
|
||||
Lardon3DCalibrationAfStudySummary *summary) {
|
||||
if (written) *written = 0;
|
||||
if (artifact_sha256) memset(artifact_sha256, 0, 32);
|
||||
if (summary) memset(summary, 0, sizeof(*summary));
|
||||
|
||||
if (!input || !artifact || !written || !artifact_sha256 || !summary ||
|
||||
!input->entries || input->entry_count < 2 ||
|
||||
input->entry_count > LARDON3D_CALIBRATION_AF_STUDY_MAX_SAMPLES ||
|
||||
!nonzero_digest(input->study_context_sha256))
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT;
|
||||
|
||||
Lardon3DCalibrationAfStudySample
|
||||
samples[LARDON3D_CALIBRATION_AF_STUDY_MAX_SAMPLES];
|
||||
memset(samples, 0, sizeof(samples));
|
||||
|
||||
uint32_t width = 0;
|
||||
uint32_t height = 0;
|
||||
|
||||
for (size_t index = 0; index < input->entry_count; ++index) {
|
||||
const Lardon3DCalibrationAfStudyAssemblyEntry *entry =
|
||||
&input->entries[index];
|
||||
if (!entry->external || !entry->focus_token)
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT;
|
||||
|
||||
Lardon3DCalibrationAfStudyWorkflowResult bridge =
|
||||
lardon3d_calibration_af_study_sample_from_materialized_evidence(
|
||||
entry->external, entry->role, entry->focus_token, &samples[index]);
|
||||
if (bridge != LARDON3D_CALIBRATION_AF_STUDY_WORKFLOW_OK)
|
||||
return map_bridge_result(bridge);
|
||||
|
||||
if (index == 0) {
|
||||
width = entry->external->oriented_width;
|
||||
height = entry->external->oriented_height;
|
||||
} else if (entry->external->oriented_width != width ||
|
||||
entry->external->oriented_height != height) {
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
}
|
||||
|
||||
/* Stronger than the raw L3DAFST1 producer's (token,digest) duplicate rule:
|
||||
* an already-materialized calibration result is independent evidence only
|
||||
* once, regardless of how the caller labels focus or study role. */
|
||||
for (size_t previous = 0; previous < index; ++previous) {
|
||||
if (memcmp(samples[previous].calibration_evidence_sha256,
|
||||
samples[index].calibration_evidence_sha256, 32) == 0)
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE;
|
||||
}
|
||||
}
|
||||
|
||||
Lardon3DCalibrationAfStudyInput study = {0};
|
||||
memcpy(study.study_context_sha256, input->study_context_sha256, 32);
|
||||
study.width = width;
|
||||
study.height = height;
|
||||
study.samples = samples;
|
||||
study.sample_count = input->entry_count;
|
||||
|
||||
Lardon3DCalibrationAfStudyResult result =
|
||||
lardon3d_calibration_af_study_produce(
|
||||
&study, artifact, artifact_capacity, written, artifact_sha256,
|
||||
summary);
|
||||
if (result != LARDON3D_CALIBRATION_AF_STUDY_OK)
|
||||
return map_study_result(result);
|
||||
|
||||
return LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_OK;
|
||||
}
|
||||
226
tests/test_calibration_af_study_assembly.c
Normal file
226
tests/test_calibration_af_study_assembly.c
Normal file
|
|
@ -0,0 +1,226 @@
|
|||
#include <lardon3d/calibration_af_study_assembly.h>
|
||||
|
||||
#include <openssl/evp.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CHECK(expression) \
|
||||
do { \
|
||||
if (!(expression)) { \
|
||||
fprintf(stderr, "FAIL %s:%d: %s\n", __FILE__, __LINE__, #expression); \
|
||||
return 1; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void fill_digest(unsigned char output[32], unsigned char value) {
|
||||
memset(output, value, 32);
|
||||
}
|
||||
|
||||
static int validation_sha(
|
||||
const Lardon3DCalibrationWorkflowInputBoundary *boundary,
|
||||
unsigned char output[32]) {
|
||||
static const char domain[] = "L3DCAL_WORKFLOW_VALIDATION_V1\n";
|
||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
||||
if (!ctx) return 0;
|
||||
int ok = EVP_DigestInit_ex(ctx, EVP_sha256(), NULL) == 1 &&
|
||||
EVP_DigestUpdate(ctx, domain, sizeof(domain) - 1) == 1 &&
|
||||
EVP_DigestUpdate(ctx, boundary->detection_sha256, 32) == 1 &&
|
||||
EVP_DigestUpdate(ctx, boundary->solve_sha256, 32) == 1 &&
|
||||
EVP_DigestUpdate(ctx, boundary->evidence_sha256, 32) == 1 &&
|
||||
EVP_DigestUpdate(ctx, boundary->producer_sha256, 32) == 1;
|
||||
unsigned int length = 0;
|
||||
ok = ok && EVP_DigestFinal_ex(ctx, output, &length) == 1 && length == 32;
|
||||
EVP_MD_CTX_free(ctx);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static Lardon3DCalibrationWorkflowExternalEvidence fixture(
|
||||
unsigned char identity, double focal_offset) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence value = {0};
|
||||
|
||||
fill_digest(value.boundary.session_sha256, identity);
|
||||
fill_digest(value.boundary.detection_sha256, (unsigned char)(identity + 1));
|
||||
fill_digest(value.boundary.solve_sha256, (unsigned char)(identity + 2));
|
||||
fill_digest(value.boundary.evidence_sha256, (unsigned char)(identity + 3));
|
||||
fill_digest(value.boundary.producer_sha256, 0x55);
|
||||
fill_digest(value.boundary.campaign_state_sha256, 0x66);
|
||||
fill_digest(value.boundary.optical_state_sha256,
|
||||
(unsigned char)(identity + 4));
|
||||
fill_digest(value.boundary.solver_executable_sha256, 0x88);
|
||||
fill_digest(value.boundary.solver_configuration_sha256, 0x99);
|
||||
|
||||
fill_digest(value.target_sha256, 0xA1);
|
||||
memcpy(value.optical_state_sha256, value.boundary.optical_state_sha256, 32);
|
||||
memcpy(value.solver_executable_sha256,
|
||||
value.boundary.solver_executable_sha256, 32);
|
||||
memcpy(value.solver_configuration_sha256,
|
||||
value.boundary.solver_configuration_sha256, 32);
|
||||
memcpy(value.initialization_evidence_sha256,
|
||||
value.boundary.session_sha256, 32);
|
||||
(void)validation_sha(&value.boundary, value.validation_evidence_sha256);
|
||||
|
||||
value.oriented_width = 6000;
|
||||
value.oriented_height = 4000;
|
||||
const double params[8] = {
|
||||
4000.0 + focal_offset, 4002.0 + focal_offset,
|
||||
3000.0, 2000.0, -0.1, 0.01, 0.001, -0.001,
|
||||
};
|
||||
for (size_t run = 0; run < 3; ++run)
|
||||
memcpy(value.repeated_parameters[run], params, sizeof(params));
|
||||
return value;
|
||||
}
|
||||
|
||||
static Lardon3DCalibrationAfStudyAssemblyInput make_input(
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry *entries, size_t count) {
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = {0};
|
||||
fill_digest(input.study_context_sha256, 0xD1);
|
||||
input.entries = entries;
|
||||
input.entry_count = count;
|
||||
return input;
|
||||
}
|
||||
|
||||
static int test_happy_path_and_order_independence(void) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence first = fixture(0x11, 0.0);
|
||||
Lardon3DCalibrationWorkflowExternalEvidence second = fixture(0x21, 8.0);
|
||||
Lardon3DCalibrationWorkflowExternalEvidence third = fixture(0x31, 14.0);
|
||||
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry entries[3] = {
|
||||
{&first, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:137"},
|
||||
{&second, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:151"},
|
||||
{&third, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_HOLDOUT, "focus:165"},
|
||||
};
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = make_input(entries, 3);
|
||||
|
||||
unsigned char artifact_a[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char artifact_b[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char sha_a[32];
|
||||
unsigned char sha_b[32];
|
||||
size_t written_a = 0;
|
||||
size_t written_b = 0;
|
||||
Lardon3DCalibrationAfStudySummary summary_a;
|
||||
Lardon3DCalibrationAfStudySummary summary_b;
|
||||
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact_a, sizeof(artifact_a), &written_a, sha_a,
|
||||
&summary_a) == LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_OK);
|
||||
CHECK(written_a > 0);
|
||||
CHECK(memcmp(artifact_a, "L3DAFST1", 8) == 0);
|
||||
CHECK(summary_a.sample_count == 3);
|
||||
CHECK(summary_a.fit_count == 2);
|
||||
CHECK(summary_a.holdout_count == 1);
|
||||
CHECK(summary_a.pair_count == 3);
|
||||
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry reordered[3] = {
|
||||
entries[2], entries[0], entries[1],
|
||||
};
|
||||
input.entries = reordered;
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact_b, sizeof(artifact_b), &written_b, sha_b,
|
||||
&summary_b) == LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_OK);
|
||||
CHECK(written_a == written_b);
|
||||
CHECK(memcmp(artifact_a, artifact_b, written_a) == 0);
|
||||
CHECK(memcmp(sha_a, sha_b, 32) == 0);
|
||||
CHECK(memcmp(&summary_a, &summary_b, sizeof(summary_a)) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_relabelled_duplicate_calibration_rejected(void) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence same = fixture(0x11, 0.0);
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry entries[2] = {
|
||||
{&same, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:137"},
|
||||
{&same, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_HOLDOUT, "focus:165"},
|
||||
};
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = make_input(entries, 2);
|
||||
unsigned char artifact[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char sha[32];
|
||||
size_t written = 999;
|
||||
Lardon3DCalibrationAfStudySummary summary;
|
||||
memset(sha, 0xA5, sizeof(sha));
|
||||
memset(&summary, 0xA5, sizeof(summary));
|
||||
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact, sizeof(artifact), &written, sha, &summary) ==
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE);
|
||||
CHECK(written == 0);
|
||||
unsigned char zero_sha[32] = {0};
|
||||
CHECK(memcmp(sha, zero_sha, 32) == 0);
|
||||
Lardon3DCalibrationAfStudySummary zero_summary = {0};
|
||||
CHECK(memcmp(&summary, &zero_summary, sizeof(summary)) == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_dimension_mismatch_rejected(void) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence first = fixture(0x11, 0.0);
|
||||
Lardon3DCalibrationWorkflowExternalEvidence second = fixture(0x21, 8.0);
|
||||
second.oriented_width = 5999;
|
||||
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry entries[2] = {
|
||||
{&first, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:137"},
|
||||
{&second, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_HOLDOUT, "focus:165"},
|
||||
};
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = make_input(entries, 2);
|
||||
unsigned char artifact[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char sha[32];
|
||||
size_t written = 0;
|
||||
Lardon3DCalibrationAfStudySummary summary;
|
||||
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact, sizeof(artifact), &written, sha, &summary) ==
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_invalid_bridge_evidence_rejected(void) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence first = fixture(0x11, 0.0);
|
||||
Lardon3DCalibrationWorkflowExternalEvidence second = fixture(0x21, 8.0);
|
||||
second.validation_evidence_sha256[0] ^= 1;
|
||||
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry entries[2] = {
|
||||
{&first, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:137"},
|
||||
{&second, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_HOLDOUT, "focus:165"},
|
||||
};
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = make_input(entries, 2);
|
||||
unsigned char artifact[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char sha[32];
|
||||
size_t written = 0;
|
||||
Lardon3DCalibrationAfStudySummary summary;
|
||||
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact, sizeof(artifact), &written, sha, &summary) ==
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_EVIDENCE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int test_invalid_arguments_and_capacity(void) {
|
||||
Lardon3DCalibrationWorkflowExternalEvidence first = fixture(0x11, 0.0);
|
||||
Lardon3DCalibrationWorkflowExternalEvidence second = fixture(0x21, 8.0);
|
||||
Lardon3DCalibrationAfStudyAssemblyEntry entries[2] = {
|
||||
{&first, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_FIT, "focus:137"},
|
||||
{&second, LARDON3D_CALIBRATION_AF_STUDY_SAMPLE_HOLDOUT, "focus:165"},
|
||||
};
|
||||
Lardon3DCalibrationAfStudyAssemblyInput input = make_input(entries, 1);
|
||||
unsigned char artifact[LARDON3D_CALIBRATION_AF_STUDY_MAX_ARTIFACT_BYTES];
|
||||
unsigned char sha[32];
|
||||
size_t written = 0;
|
||||
Lardon3DCalibrationAfStudySummary summary;
|
||||
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact, sizeof(artifact), &written, sha, &summary) ==
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_INVALID_ARGUMENT);
|
||||
|
||||
input.entry_count = 2;
|
||||
CHECK(lardon3d_calibration_af_study_assemble_materialized(
|
||||
&input, artifact, 8, &written, sha, &summary) ==
|
||||
LARDON3D_CALIBRATION_AF_STUDY_ASSEMBLY_CAPACITY);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
CHECK(test_happy_path_and_order_independence() == 0);
|
||||
CHECK(test_relabelled_duplicate_calibration_rejected() == 0);
|
||||
CHECK(test_dimension_mismatch_rejected() == 0);
|
||||
CHECK(test_invalid_bridge_evidence_rejected() == 0);
|
||||
CHECK(test_invalid_arguments_and_capacity() == 0);
|
||||
puts("CALIBRATION_AF_STUDY_ASSEMBLY_V1=PASS");
|
||||
return 0;
|
||||
}
|
||||
Loading…
Reference in a new issue