lardon3d/tests/test_acquisition_pairing.cpp

498 lines
23 KiB
C++

#include <lardon3d/acquisition_pairing.h>
#include <libexif/exif-data.h>
#include <libraw/libraw.h>
#include <cassert>
#include <cstdio>
#include <cstring>
#include <string>
#include <vector>
#include <unistd.h>
namespace {
extern "C" void lardon3d_acquisition_test_extract_raw_image_unique_id(
const libraw_data_t *raw, Lardon3DAcquisitionMetadata *metadata);
extern "C" void lardon3d_acquisition_test_extract_raw_fixed_text(
const libraw_data_t *raw, Lardon3DAcquisitionMetadata *metadata);
Lardon3DAcquisitionMetadata metadata() {
Lardon3DAcquisitionMetadata value = {};
value.policy_version = LARDON3D_ACQUISITION_PAIRING_POLICY_VERSION;
value.source_kind = LARDON3D_ACQUISITION_SOURCE_RAW;
return value;
}
void set_text(Lardon3DAcquisitionMetadata &value, uint32_t field, char *destination,
size_t capacity, const char *text) {
assert(std::strlen(text) < capacity);
std::strcpy(destination, text);
value.present_fields |= field;
}
Lardon3DAcquisitionPairResult compare(const Lardon3DAcquisitionMetadata &left,
const Lardon3DAcquisitionMetadata &right,
bool same_asset = false, bool basename_hint = false) {
Lardon3DAcquisitionPairResult result = {};
assert(lardon3d_acquisition_compare(&left, &right, same_asset, basename_hint, &result) ==
LARDON3D_ACQUISITION_OK);
return result;
}
void test_pairing_policy() {
auto left = metadata();
auto right = metadata();
set_text(left, LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID, left.image_unique_id,
sizeof(left.image_unique_id), "UID-1");
set_text(right, LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID, right.image_unique_id,
sizeof(right.image_unique_id), "UID-1");
assert(compare(left, right).decision == LARDON3D_ACQUISITION_SAME_ACQUISITION_STRONG);
auto result = compare(left, right, false, true);
assert(result.decision == LARDON3D_ACQUISITION_SAME_ACQUISITION_STRONG);
assert((result.evidence & LARDON3D_ACQUISITION_EVIDENCE_BASENAME_HINT) != 0u);
auto empty_left = metadata();
auto empty_right = metadata();
result = compare(empty_left, empty_right, false, true); /* DSC03350.ARW / DSC03350.JPG */
assert(result.decision == LARDON3D_ACQUISITION_INSUFFICIENT);
assert(result.evidence == LARDON3D_ACQUISITION_EVIDENCE_BASENAME_HINT);
set_text(empty_left, LARDON3D_ACQUISITION_FIELD_DATETIME_ORIGINAL,
empty_left.datetime_original, sizeof(empty_left.datetime_original),
"2026:08:27 12:34:56");
set_text(empty_right, LARDON3D_ACQUISITION_FIELD_DATETIME_ORIGINAL,
empty_right.datetime_original, sizeof(empty_right.datetime_original),
"2026:08:27 12:34:56");
assert(compare(empty_left, empty_right).decision ==
LARDON3D_ACQUISITION_SAME_ACQUISITION_CANDIDATE);
set_text(empty_left, LARDON3D_ACQUISITION_FIELD_MODEL, empty_left.model,
sizeof(empty_left.model), "ILCE-7M4");
set_text(empty_right, LARDON3D_ACQUISITION_FIELD_MODEL, empty_right.model,
sizeof(empty_right.model), "ILCE-7M4");
assert(compare(empty_left, empty_right).decision ==
LARDON3D_ACQUISITION_SAME_ACQUISITION_CANDIDATE);
std::strcpy(right.image_unique_id, "UID-2");
result = compare(left, right);
assert(result.decision == LARDON3D_ACQUISITION_DIFFERENT);
assert(result.contradictions ==
LARDON3D_ACQUISITION_CONTRADICTION_IMAGE_UNIQUE_ID);
auto serial_left = metadata();
auto serial_right = metadata();
set_text(serial_left, LARDON3D_ACQUISITION_FIELD_BODY_SERIAL, serial_left.body_serial,
sizeof(serial_left.body_serial), "BODY-A");
set_text(serial_right, LARDON3D_ACQUISITION_FIELD_BODY_SERIAL, serial_right.body_serial,
sizeof(serial_right.body_serial), "BODY-B");
assert(compare(serial_left, serial_right).decision == LARDON3D_ACQUISITION_DIFFERENT);
serial_right = metadata();
assert(compare(serial_left, serial_right).decision == LARDON3D_ACQUISITION_INSUFFICIENT);
auto other_device = metadata();
set_text(other_device, LARDON3D_ACQUISITION_FIELD_BODY_SERIAL, other_device.body_serial,
sizeof(other_device.body_serial), "BODY-B");
set_text(other_device, LARDON3D_ACQUISITION_FIELD_DATETIME_ORIGINAL,
other_device.datetime_original, sizeof(other_device.datetime_original),
"2026:08:27 12:34:56");
set_text(serial_left, LARDON3D_ACQUISITION_FIELD_DATETIME_ORIGINAL,
serial_left.datetime_original, sizeof(serial_left.datetime_original),
"2026:08:27 12:34:56");
assert(compare(serial_left, other_device, false, true).decision ==
LARDON3D_ACQUISITION_DIFFERENT);
assert(compare(left, left, true, true).decision == LARDON3D_ACQUISITION_INSUFFICIENT);
}
void test_selector() {
auto source = metadata();
auto candidate_b = metadata();
auto candidate_c = metadata();
set_text(source, LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID, source.image_unique_id,
sizeof(source.image_unique_id), "SHARED");
set_text(candidate_b, LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID,
candidate_b.image_unique_id, sizeof(candidate_b.image_unique_id), "SHARED");
set_text(candidate_c, LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID,
candidate_c.image_unique_id, sizeof(candidate_c.image_unique_id), "SHARED");
Lardon3DAcquisitionCandidate candidates[2] = {
{20u, &candidate_b, 0u, 0u, {}},
{30u, &candidate_c, 0u, 0u, {}},
};
Lardon3DAcquisitionSelection selection = {};
assert(lardon3d_acquisition_select_candidate(&source, candidates, 2u, &selection) ==
LARDON3D_ACQUISITION_OK);
assert(selection.decision == LARDON3D_ACQUISITION_AMBIGUOUS);
assert(selection.top_candidate_count == 2u);
assert(selection.selected_candidate_id == 0u);
const auto temporary = candidates[0];
candidates[0] = candidates[1];
candidates[1] = temporary;
assert(lardon3d_acquisition_select_candidate(&source, candidates, 2u, &selection) ==
LARDON3D_ACQUISITION_OK);
assert(selection.decision == LARDON3D_ACQUISITION_AMBIGUOUS);
assert(selection.top_candidate_count == 2u);
assert(selection.selected_candidate_id == 0u);
}
void test_non_terminated_public_text_is_unavailable() {
auto left = metadata();
auto right = metadata();
std::memset(left.image_unique_id, 'X', sizeof(left.image_unique_id));
std::memset(right.image_unique_id, 'X', sizeof(right.image_unique_id));
left.present_fields |= LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID;
right.present_fields |= LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID;
auto result = compare(left, right);
assert(result.decision == LARDON3D_ACQUISITION_INSUFFICIENT);
assert(result.evidence == 0u);
assert(result.contradictions == 0u);
std::memcpy(right.image_unique_id, "VALID", 6u);
result = compare(left, right);
assert(result.decision == LARDON3D_ACQUISITION_INSUFFICIENT);
assert(result.evidence == 0u);
assert(result.contradictions == 0u);
}
void add_ascii(ExifData *data, ExifIfd ifd, ExifTag tag, const char *value) {
ExifEntry *entry = exif_entry_new();
assert(entry != nullptr);
entry->tag = tag;
entry->format = EXIF_FORMAT_ASCII;
const size_t value_size = std::strlen(value) + 2u;
assert(value_size <= UINT32_MAX);
entry->components = static_cast<unsigned long>(value_size);
entry->size = static_cast<unsigned int>(value_size);
entry->data = static_cast<unsigned char *>(std::malloc(entry->size));
assert(entry->data != nullptr);
std::memcpy(entry->data, value, std::strlen(value));
entry->data[entry->size - 2u] = ' ';
entry->data[entry->size - 1u] = '\0';
exif_content_add_entry(data->ifd[ifd], entry);
exif_entry_unref(entry);
}
std::string temporary_path(const char *suffix) {
char path[] = "/tmp/lardon3d-acquisition-XXXXXX";
const int descriptor = mkstemp(path);
assert(descriptor >= 0);
close(descriptor);
std::string result(path);
result += suffix;
assert(std::rename(path, result.c_str()) == 0);
return result;
}
void write_exif_jpeg(const std::string &path) {
ExifData *data = exif_data_new();
assert(data != nullptr);
exif_data_set_byte_order(data, EXIF_BYTE_ORDER_INTEL);
add_ascii(data, EXIF_IFD_0, EXIF_TAG_MAKE, "Sony");
add_ascii(data, EXIF_IFD_0, EXIF_TAG_MODEL, "ILCE-7M4");
add_ascii(data, EXIF_IFD_EXIF, EXIF_TAG_DATE_TIME_ORIGINAL, "2026:08:27 12:34:56");
add_ascii(data, EXIF_IFD_EXIF, EXIF_TAG_SUB_SEC_TIME_ORIGINAL, "123");
add_ascii(data, EXIF_IFD_EXIF, EXIF_TAG_OFFSET_TIME_ORIGINAL, "+02:00");
add_ascii(data, EXIF_IFD_EXIF, EXIF_TAG_BODY_SERIAL_NUMBER, "BODY-42");
add_ascii(data, EXIF_IFD_EXIF, EXIF_TAG_IMAGE_UNIQUE_ID, "IMAGE-99");
unsigned char *encoded = nullptr;
unsigned int encoded_size = 0u;
exif_data_save_data(data, &encoded, &encoded_size);
assert(encoded != nullptr && encoded_size > 0u && encoded_size <= UINT16_MAX - 2u);
FILE *file = std::fopen(path.c_str(), "wb");
assert(file != nullptr);
const unsigned char soi[] = {0xffu, 0xd8u, 0xffu, 0xe1u};
const unsigned int segment_size = encoded_size + 2u;
const unsigned char length[] = {static_cast<unsigned char>(segment_size >> 8u),
static_cast<unsigned char>(segment_size & 0xffu)};
const unsigned char eoi[] = {0xffu, 0xd9u};
assert(std::fwrite(soi, 1u, sizeof(soi), file) == sizeof(soi));
assert(std::fwrite(length, 1u, sizeof(length), file) == sizeof(length));
assert(std::fwrite(encoded, 1u, encoded_size, file) == encoded_size);
assert(std::fwrite(eoi, 1u, sizeof(eoi), file) == sizeof(eoi));
assert(std::fclose(file) == 0);
std::free(encoded);
exif_data_unref(data);
}
void append_bytes(const std::string &path, const unsigned char *bytes, size_t size) {
FILE *file = std::fopen(path.c_str(), "ab");
assert(file != nullptr);
assert(std::fwrite(bytes, 1u, size, file) == size);
assert(std::fclose(file) == 0);
}
void write_bytes(const std::string &path, const unsigned char *bytes, size_t size) {
FILE *file = std::fopen(path.c_str(), "wb");
assert(file != nullptr);
assert(std::fwrite(bytes, 1u, size, file) == size);
assert(std::fclose(file) == 0);
}
void assert_jpeg_corrupt(const unsigned char *bytes, size_t size) {
const std::string path = temporary_path(".jpg");
write_bytes(path, bytes, size);
Lardon3DAcquisitionMetadata value = {};
assert(lardon3d_acquisition_extract_metadata(path.c_str(), &value) ==
LARDON3D_ACQUISITION_CORRUPT_SOURCE);
assert(unlink(path.c_str()) == 0);
}
void assert_jpeg_structurally_accepted(const unsigned char *bytes, size_t size) {
const std::string path = temporary_path(".jpg");
write_bytes(path, bytes, size);
Lardon3DAcquisitionMetadata value = {};
const Lardon3DAcquisitionResult result =
lardon3d_acquisition_extract_metadata(path.c_str(), &value);
assert(result == LARDON3D_ACQUISITION_OK ||
result == LARDON3D_ACQUISITION_METADATA_UNAVAILABLE);
assert(unlink(path.c_str()) == 0);
}
void test_extraction() {
const std::string jpeg = temporary_path(".jpg");
write_exif_jpeg(jpeg);
Lardon3DAcquisitionMetadata value = {};
assert(lardon3d_acquisition_extract_metadata(jpeg.c_str(), &value) ==
LARDON3D_ACQUISITION_OK);
assert(value.source_kind == LARDON3D_ACQUISITION_SOURCE_JPEG);
assert(std::strcmp(value.make, "Sony") == 0);
assert(std::strcmp(value.model, "ILCE-7M4") == 0);
assert(std::strcmp(value.datetime_original, "2026:08:27 12:34:56") == 0);
assert(std::strcmp(value.subsec_original, "123") == 0);
assert(std::strcmp(value.offset_original, "+02:00") == 0);
assert(std::strcmp(value.body_serial, "BODY-42") == 0);
assert(std::strcmp(value.image_unique_id, "IMAGE-99") == 0);
assert(unlink(jpeg.c_str()) == 0);
const std::string padded = temporary_path(".jpg");
write_exif_jpeg(padded);
const unsigned char zero_padding[37] = {};
append_bytes(padded, zero_padding, sizeof(zero_padding));
assert(lardon3d_acquisition_extract_metadata(padded.c_str(), &value) ==
LARDON3D_ACQUISITION_OK);
assert(value.source_kind == LARDON3D_ACQUISITION_SOURCE_JPEG);
assert(std::strcmp(value.make, "Sony") == 0);
assert(std::strcmp(value.model, "ILCE-7M4") == 0);
assert(std::strcmp(value.datetime_original, "2026:08:27 12:34:56") == 0);
assert(std::strcmp(value.subsec_original, "123") == 0);
assert(std::strcmp(value.offset_original, "+02:00") == 0);
assert(std::strcmp(value.body_serial, "BODY-42") == 0);
assert(std::strcmp(value.image_unique_id, "IMAGE-99") == 0);
assert(unlink(padded.c_str()) == 0);
const unsigned char missing_eoi[] = {0xffu, 0xd8u, 0xffu, 0xe0u,
0x00u, 0x02u};
assert_jpeg_corrupt(missing_eoi, sizeof(missing_eoi));
const unsigned char truncated_segment[] = {0xffu, 0xd8u, 0xffu, 0xe1u,
0x00u, 0x08u, 0x11u};
assert_jpeg_corrupt(truncated_segment, sizeof(truncated_segment));
const unsigned char payload_eoi[] = {0xffu, 0xd8u, 0xffu, 0xe2u, 0x00u,
0x06u, 0xffu, 0xd9u, 0x11u, 0x22u};
assert_jpeg_corrupt(payload_eoi, sizeof(payload_eoi));
const std::string trailing_garbage = temporary_path(".jpg");
write_exif_jpeg(trailing_garbage);
const unsigned char nonzero_padding[] = {0x00u, 0x01u};
append_bytes(trailing_garbage, nonzero_padding, sizeof(nonzero_padding));
assert(lardon3d_acquisition_extract_metadata(trailing_garbage.c_str(), &value) ==
LARDON3D_ACQUISITION_CORRUPT_SOURCE);
assert(unlink(trailing_garbage.c_str()) == 0);
const unsigned char entropy_markers[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x08u, 0x01u, 0x01u, 0x00u, 0x00u,
0x3fu, 0x00u, 0x12u, 0xffu, 0x00u, 0x34u, 0xffu, 0xd0u, 0x56u, 0xffu,
0xffu, 0xd9u};
const std::string entropy = temporary_path(".jpg");
write_bytes(entropy, entropy_markers, sizeof(entropy_markers));
const Lardon3DAcquisitionResult entropy_result =
lardon3d_acquisition_extract_metadata(entropy.c_str(), &value);
assert(entropy_result == LARDON3D_ACQUISITION_OK ||
entropy_result == LARDON3D_ACQUISITION_METADATA_UNAVAILABLE);
assert(unlink(entropy.c_str()) == 0);
const unsigned char mismatched_sos_length[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x06u, 0x01u, 0x01u,
0x00u, 0x00u, 0xffu, 0xd9u};
assert_jpeg_corrupt(mismatched_sos_length, sizeof(mismatched_sos_length));
const unsigned char zero_sos_components[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x06u, 0x00u, 0x00u,
0x00u, 0x00u, 0xffu, 0xd9u};
assert_jpeg_corrupt(zero_sos_components, sizeof(zero_sos_components));
const unsigned char too_many_sos_components[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x10u, 0x05u, 0x01u, 0x00u,
0x02u, 0x00u, 0x03u, 0x00u, 0x04u, 0x00u, 0x05u, 0x00u, 0x00u,
0x3fu, 0x00u, 0xffu, 0xd9u};
assert_jpeg_corrupt(too_many_sos_components, sizeof(too_many_sos_components));
const unsigned char entropy_dnl[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x08u, 0x01u, 0x01u, 0x00u,
0x00u, 0x3fu, 0x00u, 0x12u, 0xffu, 0xdcu, 0x00u, 0x04u, 0x00u,
0x2au, 0x34u, 0xffu, 0x00u, 0x56u, 0xffu, 0xd1u, 0x78u, 0xffu,
0xd9u};
const std::string entropy_dnl_path = temporary_path(".jpg");
write_bytes(entropy_dnl_path, entropy_dnl, sizeof(entropy_dnl));
const Lardon3DAcquisitionResult entropy_dnl_result =
lardon3d_acquisition_extract_metadata(entropy_dnl_path.c_str(), &value);
assert(entropy_dnl_result == LARDON3D_ACQUISITION_OK ||
entropy_dnl_result == LARDON3D_ACQUISITION_METADATA_UNAVAILABLE);
assert(unlink(entropy_dnl_path.c_str()) == 0);
const unsigned char malformed_dnl_length[] = {
0xffu, 0xd8u, 0xffu, 0xdcu, 0x00u, 0x02u, 0xffu, 0xd9u};
assert_jpeg_corrupt(malformed_dnl_length, sizeof(malformed_dnl_length));
const unsigned char zero_dnl_line_count[] = {
0xffu, 0xd8u, 0xffu, 0xdcu, 0x00u, 0x04u, 0x00u, 0x00u, 0xffu, 0xd9u};
assert_jpeg_corrupt(zero_dnl_line_count, sizeof(zero_dnl_line_count));
const unsigned char marker_level_dnl_does_not_start_entropy[] = {
0xffu, 0xd8u, 0xffu, 0xdcu, 0x00u, 0x04u, 0x00u, 0x2au,
0x12u, 0xffu, 0xd9u};
assert_jpeg_corrupt(marker_level_dnl_does_not_start_entropy,
sizeof(marker_level_dnl_does_not_start_entropy));
const unsigned char mpf_primary[] = {
0xffu, 0xd8u, 0xffu, 0xe2u, 0x00u, 0x06u, 'M', 'P', 'F', 0x00u,
0xffu, 0xd9u};
const unsigned char ordinary_image[] = {0xffu, 0xd8u, 0xffu, 0xd9u};
std::vector<unsigned char> mpf_two_images(std::begin(mpf_primary), std::end(mpf_primary));
mpf_two_images.insert(mpf_two_images.end(), 9u, 0u);
mpf_two_images.insert(mpf_two_images.end(), std::begin(ordinary_image),
std::end(ordinary_image));
mpf_two_images.insert(mpf_two_images.end(), 11u, 0u);
assert_jpeg_structurally_accepted(mpf_two_images.data(), mpf_two_images.size());
std::vector<unsigned char> no_mpf_second(std::begin(ordinary_image),
std::end(ordinary_image));
no_mpf_second.insert(no_mpf_second.end(), 3u, 0u);
no_mpf_second.insert(no_mpf_second.end(), std::begin(ordinary_image),
std::end(ordinary_image));
assert_jpeg_corrupt(no_mpf_second.data(), no_mpf_second.size());
std::vector<unsigned char> mpf_garbage(std::begin(mpf_primary), std::end(mpf_primary));
mpf_garbage.insert(mpf_garbage.end(), 5u, 0u);
mpf_garbage.push_back(0x42u);
assert_jpeg_corrupt(mpf_garbage.data(), mpf_garbage.size());
std::vector<unsigned char> mpf_truncated(std::begin(mpf_primary), std::end(mpf_primary));
const unsigned char truncated_second[] = {0xffu, 0xd8u, 0xffu, 0xe0u, 0x00u};
mpf_truncated.insert(mpf_truncated.end(), std::begin(truncated_second),
std::end(truncated_second));
assert_jpeg_corrupt(mpf_truncated.data(), mpf_truncated.size());
std::vector<unsigned char> mpf_missing_second_eoi(std::begin(mpf_primary),
std::end(mpf_primary));
const unsigned char second_without_eoi[] = {0xffu, 0xd8u, 0xffu, 0xe0u, 0x00u, 0x02u};
mpf_missing_second_eoi.insert(mpf_missing_second_eoi.end(),
std::begin(second_without_eoi),
std::end(second_without_eoi));
assert_jpeg_corrupt(mpf_missing_second_eoi.data(), mpf_missing_second_eoi.size());
std::vector<unsigned char> too_many_images(std::begin(mpf_primary),
std::end(mpf_primary));
for (size_t index = 1u; index < 9u; ++index) {
too_many_images.insert(too_many_images.end(), std::begin(ordinary_image),
std::end(ordinary_image));
}
assert_jpeg_corrupt(too_many_images.data(), too_many_images.size());
const unsigned char embedded_boundaries_in_payload[] = {
0xffu, 0xd8u, 0xffu, 0xe1u, 0x00u, 0x06u, 0xffu, 0xd8u, 0xffu, 0xd9u,
0xffu, 0xd9u};
assert_jpeg_structurally_accepted(embedded_boundaries_in_payload,
sizeof(embedded_boundaries_in_payload));
const unsigned char stuffed_boundaries_in_entropy[] = {
0xffu, 0xd8u, 0xffu, 0xdau, 0x00u, 0x08u, 0x01u, 0x01u, 0x00u,
0x00u, 0x3fu, 0x00u, 0xffu, 0x00u, 0xd8u, 0xffu, 0x00u, 0xd9u,
0xffu, 0xd9u};
assert_jpeg_structurally_accepted(stuffed_boundaries_in_entropy,
sizeof(stuffed_boundaries_in_entropy));
std::vector<unsigned char> mpf_nonzero_final = mpf_two_images;
mpf_nonzero_final.push_back(0x01u);
assert_jpeg_corrupt(mpf_nonzero_final.data(), mpf_nonzero_final.size());
const std::string malformed = temporary_path(".jpg");
FILE *file = std::fopen(malformed.c_str(), "wb");
assert(file != nullptr);
const unsigned char bad[] = {0xffu, 0xd8u, 0x00u};
assert(std::fwrite(bad, 1u, sizeof(bad), file) == sizeof(bad));
assert(std::fclose(file) == 0);
assert(lardon3d_acquisition_extract_metadata(malformed.c_str(), &value) ==
LARDON3D_ACQUISITION_CORRUPT_SOURCE);
assert(unlink(malformed.c_str()) == 0);
const std::string unsupported = temporary_path(".bin");
file = std::fopen(unsupported.c_str(), "wb");
assert(file != nullptr);
assert(std::fwrite("not an image", 1u, 12u, file) == 12u);
assert(std::fclose(file) == 0);
assert(lardon3d_acquisition_extract_metadata(unsupported.c_str(), &value) ==
LARDON3D_ACQUISITION_UNSUPPORTED_FORMAT);
assert(unlink(unsupported.c_str()) == 0);
}
void test_raw_image_unique_id_mapping() {
libraw_data_t raw = {};
Lardon3DAcquisitionMetadata value = {};
std::memcpy(raw.color.ImageUniqueID, "RAW-UID-42 ", 11u);
lardon3d_acquisition_test_extract_raw_image_unique_id(&raw, &value);
assert(std::strcmp(value.image_unique_id, "RAW-UID-42") == 0);
assert((value.present_fields & LARDON3D_ACQUISITION_FIELD_IMAGE_UNIQUE_ID) != 0u);
}
void test_non_terminated_raw_fixed_text_mapping() {
libraw_data_t raw = {};
Lardon3DAcquisitionMetadata value = {};
std::memset(raw.idata.make, 'M', sizeof(raw.idata.make));
std::memset(raw.idata.model, 'D', sizeof(raw.idata.model));
std::memset(raw.shootinginfo.BodySerial, 'S', sizeof(raw.shootinginfo.BodySerial));
lardon3d_acquisition_test_extract_raw_fixed_text(&raw, &value);
assert(std::strlen(value.make) == sizeof(raw.idata.make));
assert(std::strlen(value.model) == sizeof(raw.idata.model));
assert(std::strlen(value.body_serial) == sizeof(raw.shootinginfo.BodySerial));
assert((value.present_fields & LARDON3D_ACQUISITION_FIELD_MAKE) != 0u);
assert((value.present_fields & LARDON3D_ACQUISITION_FIELD_MODEL) != 0u);
assert((value.present_fields & LARDON3D_ACQUISITION_FIELD_BODY_SERIAL) != 0u);
}
} // namespace
int main(int argc, char **argv) {
if (argc == 3 && std::strcmp(argv[1], "--extract") == 0) {
Lardon3DAcquisitionMetadata value = {};
const Lardon3DAcquisitionResult result =
lardon3d_acquisition_extract_metadata(argv[2], &value);
std::printf("METADATA_RESULT=%d\n", static_cast<int>(result));
if (result == LARDON3D_ACQUISITION_OK) {
std::printf("MAKE=%s\nMODEL=%s\nDATETIME_ORIGINAL=%s\nSUBSEC_ORIGINAL=%s\n"
"BODY_SERIAL=%s\nIMAGE_UNIQUE_ID=%s\nWIDTH=%u\nHEIGHT=%u\n"
"ORIENTATION=%u\nPRESENT_FIELDS=%u\n",
value.make, value.model, value.datetime_original,
value.subsec_original, value.body_serial, value.image_unique_id,
value.width, value.height, static_cast<unsigned int>(value.orientation),
value.present_fields);
}
return result == LARDON3D_ACQUISITION_OK ? 0 : 1;
}
if (argc != 1) {
std::fprintf(stderr, "usage: %s [--extract PATH]\n", argv[0]);
return 64;
}
test_pairing_policy();
test_selector();
test_non_terminated_public_text_is_unavailable();
test_extraction();
test_raw_image_unique_id_mapping();
test_non_terminated_raw_fixed_text_mapping();
return 0;
}