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,
|
The bridge performs no DB access, metadata interpretation, physical AF decision,
|
||||||
thresholding, interpolation or extrapolation.
|
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.
|
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
|
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
|
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
|
remain explicit study annotations. Multiple independent materialized samples can now be assembled into
|
||||||
blocked until physical evidence validates it.
|
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_tooling_v2.c',
|
||||||
'src/calibration_af_study.c',
|
'src/calibration_af_study.c',
|
||||||
'src/calibration_af_study_workflow.c',
|
'src/calibration_af_study_workflow.c',
|
||||||
|
'src/calibration_af_study_assembly.c',
|
||||||
'src/calibration_workflow.cpp',
|
'src/calibration_workflow.cpp',
|
||||||
'src/calibration_workflow_materialize.cpp',
|
'src/calibration_workflow_materialize.cpp',
|
||||||
'src/calibration_workflow_bind.cpp',
|
'src/calibration_workflow_bind.cpp',
|
||||||
|
|
@ -947,6 +948,24 @@ test(
|
||||||
timeout: 30,
|
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(
|
calibration_workflow_v2_test = executable(
|
||||||
'test-calibration-workflow-v2',
|
'test-calibration-workflow-v2',
|
||||||
sources: [
|
sources: [
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ Adaptive capture settings semantics PASS/FROZEN
|
||||||
Autofocus v2 foundation PASS/FROZEN
|
Autofocus v2 foundation PASS/FROZEN
|
||||||
Calibration AF study evidence v1 PASS/FROZEN
|
Calibration AF study evidence v1 PASS/FROZEN
|
||||||
Calibration AF study Workflow bridge v1 PASS/FROZEN
|
Calibration AF study Workflow bridge v1 PASS/FROZEN
|
||||||
|
Calibration AF study assembly v1 PASS/FROZEN
|
||||||
Calibration Tooling planarity alignment PASS/FROZEN
|
Calibration Tooling planarity alignment PASS/FROZEN
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ ADAPTIVE_CAPTURE_SETTINGS_CONTRACT=PASS/FROZEN
|
||||||
AUTOFOCUS_V2_FOUNDATION=PASS/FROZEN
|
AUTOFOCUS_V2_FOUNDATION=PASS/FROZEN
|
||||||
CALIBRATION_AF_STUDY_EVIDENCE_V1=PASS/FROZEN
|
CALIBRATION_AF_STUDY_EVIDENCE_V1=PASS/FROZEN
|
||||||
CALIBRATION_AF_STUDY_WORKFLOW_BRIDGE_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
|
CURRENT_CALIBRATION_NEXT=PHYSICAL_AUTOFOCUS_OPTICAL_APPLICABILITY_VALIDATION
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ Default dependency order:
|
||||||
4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN;
|
4. Heterogeneous calibration publication / Tooling / Bootstrap evolution — PASS/FROZEN;
|
||||||
5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN;
|
5. Heterogeneous Workflow v2 truthful READY proof — PASS/FROZEN;
|
||||||
6. Adaptive capture settings / generic autofocus foundation — 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;
|
8. real Sparse SfM proof;
|
||||||
9. durable Dense/OpenMVS orchestration;
|
9. durable Dense/OpenMVS orchestration;
|
||||||
10. mesh / refinement / texturing / export;
|
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