Skip to content

Commit ebc7fc3

Browse files
committed
Add XMP sidecar/embedded tests to metatransfer
Extend CLI and Python metatransfer smoke tests to cover XMP sidecar and embedded behavior. Creates a JPEG fixture with embedded XMP and adds checks for dual-write (embedded_and_sidecar), embed-only sidecar cleanup (strip_existing), and sidecar-only embedded-strip flows. Verifies output files, sidecar creation/removal, and that embedded XMP content is present or removed as expected for both the native binary and the Python wrapper.
1 parent 1226e9d commit ebc7fc3

File tree

2 files changed

+249
-0
lines changed

2 files changed

+249
-0
lines changed

tests/cli_metatransfer_smoke_test.cmake

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,15 @@ file(MAKE_DIRECTORY "${WORK_DIR}")
1616
set(_jpg "${WORK_DIR}/sample.jpg")
1717
set(_icc_jpg "${WORK_DIR}/sample_icc.jpg")
1818
set(_target_jpg "${WORK_DIR}/target.jpg")
19+
set(_target_jpg_xmp "${WORK_DIR}/target_xmp.jpg")
1920
set(_dump_dir "${WORK_DIR}/payloads")
2021
set(_edited_jpg "${WORK_DIR}/edited.jpg")
22+
set(_dual_jpg "${WORK_DIR}/dual_write.jpg")
23+
set(_dual_jpg_sidecar "${WORK_DIR}/dual_write.xmp")
24+
set(_embed_only_strip_jpg "${WORK_DIR}/embed_only_strip.jpg")
25+
set(_embed_only_strip_sidecar "${WORK_DIR}/embed_only_strip.xmp")
26+
set(_sidecar_only_strip_jpg "${WORK_DIR}/sidecar_only_strip.jpg")
27+
set(_sidecar_only_strip_sidecar "${WORK_DIR}/sidecar_only_strip.xmp")
2128
set(_target_jxl "${WORK_DIR}/target.jxl")
2229
set(_edited_jxl "${WORK_DIR}/edited.jxl")
2330
set(_target_jp2 "${WORK_DIR}/target.jp2")
@@ -96,6 +103,18 @@ if(NOT _rv_write_target EQUAL 0)
96103
"failed to write target jpeg fixture (${_rv_write_target})\nstdout:\n${_out_write_target}\nstderr:\n${_err_write_target}")
97104
endif()
98105

106+
execute_process(
107+
COMMAND python3 -c
108+
"from pathlib import Path; xml=b\"<x:xmpmeta xmlns:x='adobe:ns:meta/'><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'><rdf:Description xmlns:xmp='http://ns.adobe.com/xap/1.0/'><xmp:CreatorTool>Target Embedded Existing</xmp:CreatorTool></rdf:Description></rdf:RDF></x:xmpmeta>\"; app1=b'http://ns.adobe.com/xap/1.0/\\x00'+xml; ln=(len(app1)+2).to_bytes(2,'big'); Path(r'''${_target_jpg_xmp}''').write_bytes(b'\\xFF\\xD8\\xFF\\xE1'+ln+app1+b'\\xFF\\xD9')"
109+
RESULT_VARIABLE _rv_write_target_xmp
110+
OUTPUT_VARIABLE _out_write_target_xmp
111+
ERROR_VARIABLE _err_write_target_xmp
112+
)
113+
if(NOT _rv_write_target_xmp EQUAL 0)
114+
message(FATAL_ERROR
115+
"failed to write target jpeg xmp fixture (${_rv_write_target_xmp})\nstdout:\n${_out_write_target_xmp}\nstderr:\n${_err_write_target_xmp}")
116+
endif()
117+
99118
# Minimal JXL container target: signature + jxlc codestream box.
100119
execute_process(
101120
COMMAND python3 -c
@@ -1131,6 +1150,107 @@ if(_edited_size LESS 10)
11311150
"metatransfer wrote suspiciously small edited output (${_edited_size})\nstdout:\n${_out_edit}\nstderr:\n${_err_edit}")
11321151
endif()
11331152

1153+
execute_process(
1154+
COMMAND "${METATRANSFER_BIN}" --no-build-info
1155+
--source-meta "${_jpg}"
1156+
--target-jpeg "${_target_jpg}"
1157+
--xmp-writeback embedded_and_sidecar
1158+
--output "${_dual_jpg}" --force
1159+
RESULT_VARIABLE _rv_dual
1160+
OUTPUT_VARIABLE _out_dual
1161+
ERROR_VARIABLE _err_dual
1162+
)
1163+
if(NOT _rv_dual EQUAL 0)
1164+
message(FATAL_ERROR
1165+
"metatransfer dual-write jpeg edit failed (${_rv_dual})\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
1166+
endif()
1167+
if(NOT EXISTS "${_dual_jpg}")
1168+
message(FATAL_ERROR
1169+
"metatransfer dual-write did not write jpeg output\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
1170+
endif()
1171+
if(NOT EXISTS "${_dual_jpg_sidecar}")
1172+
message(FATAL_ERROR
1173+
"metatransfer dual-write did not write xmp sidecar\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
1174+
endif()
1175+
if(NOT _out_dual MATCHES "xmp_sidecar_output=.*dual_write\\.xmp")
1176+
message(FATAL_ERROR
1177+
"metatransfer dual-write missing xmp sidecar summary\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
1178+
endif()
1179+
execute_process(
1180+
COMMAND python3 -c
1181+
"from pathlib import Path; b=Path(r'''${_dual_jpg_sidecar}''').read_bytes(); import sys; sys.exit(0 if (b.find(b'<x:xmpmeta')!=-1 or b.find(b'<rdf:RDF')!=-1) else 1)"
1182+
RESULT_VARIABLE _rv_dual_check
1183+
OUTPUT_VARIABLE _out_dual_check
1184+
ERROR_VARIABLE _err_dual_check
1185+
)
1186+
if(NOT _rv_dual_check EQUAL 0)
1187+
message(FATAL_ERROR
1188+
"metatransfer dual-write sidecar content check failed (${_rv_dual_check})\nstdout:\n${_out_dual_check}\nstderr:\n${_err_dual_check}")
1189+
endif()
1190+
1191+
file(WRITE "${_embed_only_strip_sidecar}" "stale sidecar\n")
1192+
execute_process(
1193+
COMMAND "${METATRANSFER_BIN}" --no-build-info
1194+
--source-meta "${_jpg}"
1195+
--target-jpeg "${_target_jpg}"
1196+
--xmp-destination-sidecar strip_existing
1197+
--output "${_embed_only_strip_jpg}" --force
1198+
RESULT_VARIABLE _rv_embed_strip
1199+
OUTPUT_VARIABLE _out_embed_strip
1200+
ERROR_VARIABLE _err_embed_strip
1201+
)
1202+
if(NOT _rv_embed_strip EQUAL 0)
1203+
message(FATAL_ERROR
1204+
"metatransfer embedded-only sidecar cleanup failed (${_rv_embed_strip})\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
1205+
endif()
1206+
if(NOT EXISTS "${_embed_only_strip_jpg}")
1207+
message(FATAL_ERROR
1208+
"metatransfer embedded-only cleanup did not write jpeg output\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
1209+
endif()
1210+
if(EXISTS "${_embed_only_strip_sidecar}")
1211+
message(FATAL_ERROR
1212+
"metatransfer embedded-only cleanup did not remove stale sidecar\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
1213+
endif()
1214+
if(NOT _out_embed_strip MATCHES "xmp_sidecar_removed=.*embed_only_strip\\.xmp")
1215+
message(FATAL_ERROR
1216+
"metatransfer embedded-only cleanup missing sidecar removal summary\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
1217+
endif()
1218+
1219+
execute_process(
1220+
COMMAND "${METATRANSFER_BIN}" --no-build-info
1221+
--source-meta "${_jpg}"
1222+
--target-jpeg "${_target_jpg_xmp}"
1223+
--xmp-writeback sidecar
1224+
--xmp-destination-embedded strip_existing
1225+
--output "${_sidecar_only_strip_jpg}" --force
1226+
RESULT_VARIABLE _rv_sidecar_strip
1227+
OUTPUT_VARIABLE _out_sidecar_strip
1228+
ERROR_VARIABLE _err_sidecar_strip
1229+
)
1230+
if(NOT _rv_sidecar_strip EQUAL 0)
1231+
message(FATAL_ERROR
1232+
"metatransfer sidecar-only embedded-strip failed (${_rv_sidecar_strip})\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
1233+
endif()
1234+
if(NOT EXISTS "${_sidecar_only_strip_jpg}")
1235+
message(FATAL_ERROR
1236+
"metatransfer sidecar-only embedded-strip did not write jpeg output\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
1237+
endif()
1238+
if(NOT EXISTS "${_sidecar_only_strip_sidecar}")
1239+
message(FATAL_ERROR
1240+
"metatransfer sidecar-only embedded-strip did not write xmp sidecar\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
1241+
endif()
1242+
execute_process(
1243+
COMMAND python3 -c
1244+
"from pathlib import Path; b=Path(r'''${_sidecar_only_strip_jpg}''').read_bytes(); import sys; sys.exit(0 if (b.find(b'Target Embedded Existing')==-1 and b.find(b'http://ns.adobe.com/xap/1.0/')==-1) else 1)"
1245+
RESULT_VARIABLE _rv_sidecar_strip_check
1246+
OUTPUT_VARIABLE _out_sidecar_strip_check
1247+
ERROR_VARIABLE _err_sidecar_strip_check
1248+
)
1249+
if(NOT _rv_sidecar_strip_check EQUAL 0)
1250+
message(FATAL_ERROR
1251+
"metatransfer sidecar-only embedded-strip output still contains embedded xmp (${_rv_sidecar_strip_check})\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}\ncheck_stderr:\n${_err_sidecar_strip_check}")
1252+
endif()
1253+
11341254
execute_process(
11351255
COMMAND "${METATRANSFER_BIN}" --no-build-info
11361256
--source-meta "${_jpg}"

tests/python_metatransfer_edit_smoke_test.cmake

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ file(MAKE_DIRECTORY "${WORK_DIR}")
2020
set(_src_jpg "${WORK_DIR}/source.jpg")
2121
set(_src_icc_jpg "${WORK_DIR}/source_icc.jpg")
2222
set(_target_jpg "${WORK_DIR}/target.jpg")
23+
set(_target_jpg_xmp "${WORK_DIR}/target_xmp.jpg")
2324
set(_edited_jpg "${WORK_DIR}/edited.jpg")
25+
set(_dual_jpg "${WORK_DIR}/dual_write.jpg")
26+
set(_dual_jpg_sidecar "${WORK_DIR}/dual_write.xmp")
27+
set(_embed_only_strip_jpg "${WORK_DIR}/embed_only_strip.jpg")
28+
set(_embed_only_strip_sidecar "${WORK_DIR}/embed_only_strip.xmp")
29+
set(_sidecar_only_strip_jpg "${WORK_DIR}/sidecar_only_strip.jpg")
30+
set(_sidecar_only_strip_sidecar "${WORK_DIR}/sidecar_only_strip.xmp")
2431
set(_target_tif "${WORK_DIR}/target.tif")
2532
set(_edited_tif "${WORK_DIR}/edited.tif")
2633
set(_target_jxl "${WORK_DIR}/target.jxl")
@@ -85,6 +92,18 @@ if(NOT _rv_target_jpg EQUAL 0)
8592
"failed to write python metatransfer target jpeg fixture (${_rv_target_jpg})\nstdout:\n${_out_target_jpg}\nstderr:\n${_err_target_jpg}")
8693
endif()
8794

95+
execute_process(
96+
COMMAND "${OPENMETA_PYTHON_EXECUTABLE}" -c
97+
"from pathlib import Path; xml=b\"<x:xmpmeta xmlns:x='adobe:ns:meta/'><rdf:RDF xmlns:rdf='http://www.w3.org/1999/02/22-rdf-syntax-ns#'><rdf:Description xmlns:xmp='http://ns.adobe.com/xap/1.0/'><xmp:CreatorTool>Target Embedded Existing</xmp:CreatorTool></rdf:Description></rdf:RDF></x:xmpmeta>\"; app1=b'http://ns.adobe.com/xap/1.0/\\x00'+xml; ln=(len(app1)+2).to_bytes(2,'big'); Path(r'''${_target_jpg_xmp}''').write_bytes(b'\\xFF\\xD8\\xFF\\xE1'+ln+app1+b'\\xFF\\xD9')"
98+
RESULT_VARIABLE _rv_target_jpg_xmp
99+
OUTPUT_VARIABLE _out_target_jpg_xmp
100+
ERROR_VARIABLE _err_target_jpg_xmp
101+
)
102+
if(NOT _rv_target_jpg_xmp EQUAL 0)
103+
message(FATAL_ERROR
104+
"failed to write python metatransfer target jpeg xmp fixture (${_rv_target_jpg_xmp})\nstdout:\n${_out_target_jpg_xmp}\nstderr:\n${_err_target_jpg_xmp}")
105+
endif()
106+
88107
execute_process(
89108
COMMAND "${OPENMETA_PYTHON_EXECUTABLE}" -c
90109
"from pathlib import Path; b=bytearray(); b+=b'II'; b+=(42).to_bytes(2,'little'); b+=(8).to_bytes(4,'little'); b+=(0).to_bytes(2,'little'); b+=(0).to_bytes(4,'little'); Path(r'''${_target_tif}''').write_bytes(bytes(b))"
@@ -199,6 +218,116 @@ if(NOT _rv_jpg_check EQUAL 0)
199218
"python metatransfer jpeg output check failed (${_rv_jpg_check})\nstdout:\n${_out_jpg_check}\nstderr:\n${_err_jpg_check}")
200219
endif()
201220

221+
execute_process(
222+
COMMAND "${CMAKE_COMMAND}" -E env
223+
"PYTHONPATH=${OPENMETA_PYTHONPATH}"
224+
"${OPENMETA_PYTHON_EXECUTABLE}" -m openmeta.python.metatransfer
225+
--no-build-info
226+
--target-jpeg "${_target_jpg}"
227+
--xmp-writeback embedded_and_sidecar
228+
-o "${_dual_jpg}"
229+
"${_src_jpg}"
230+
RESULT_VARIABLE _rv_dual
231+
OUTPUT_VARIABLE _out_dual
232+
ERROR_VARIABLE _err_dual
233+
)
234+
if(NOT _rv_dual EQUAL 0)
235+
message(FATAL_ERROR
236+
"python metatransfer dual-write jpeg edit failed (${_rv_dual})\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
237+
endif()
238+
if(NOT EXISTS "${_dual_jpg}")
239+
message(FATAL_ERROR
240+
"python metatransfer dual-write did not write jpeg output\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
241+
endif()
242+
if(NOT EXISTS "${_dual_jpg_sidecar}")
243+
message(FATAL_ERROR
244+
"python metatransfer dual-write did not write xmp sidecar\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
245+
endif()
246+
if(NOT _out_dual MATCHES "xmp_sidecar_output=.*dual_write\\.xmp")
247+
message(FATAL_ERROR
248+
"python metatransfer dual-write missing xmp sidecar summary\nstdout:\n${_out_dual}\nstderr:\n${_err_dual}")
249+
endif()
250+
execute_process(
251+
COMMAND "${OPENMETA_PYTHON_EXECUTABLE}" -c
252+
"from pathlib import Path; b=Path(r'''${_dual_jpg_sidecar}''').read_bytes(); import sys; sys.exit(0 if (b.find(b'<x:xmpmeta')!=-1 or b.find(b'<rdf:RDF')!=-1) else 1)"
253+
RESULT_VARIABLE _rv_dual_check
254+
OUTPUT_VARIABLE _out_dual_check
255+
ERROR_VARIABLE _err_dual_check
256+
)
257+
if(NOT _rv_dual_check EQUAL 0)
258+
message(FATAL_ERROR
259+
"python metatransfer dual-write sidecar content check failed (${_rv_dual_check})\nstdout:\n${_out_dual_check}\nstderr:\n${_err_dual_check}")
260+
endif()
261+
262+
file(WRITE "${_embed_only_strip_sidecar}" "stale sidecar\n")
263+
execute_process(
264+
COMMAND "${CMAKE_COMMAND}" -E env
265+
"PYTHONPATH=${OPENMETA_PYTHONPATH}"
266+
"${OPENMETA_PYTHON_EXECUTABLE}" -m openmeta.python.metatransfer
267+
--no-build-info
268+
--target-jpeg "${_target_jpg}"
269+
--xmp-destination-sidecar strip_existing
270+
-o "${_embed_only_strip_jpg}"
271+
"${_src_jpg}"
272+
RESULT_VARIABLE _rv_embed_strip
273+
OUTPUT_VARIABLE _out_embed_strip
274+
ERROR_VARIABLE _err_embed_strip
275+
)
276+
if(NOT _rv_embed_strip EQUAL 0)
277+
message(FATAL_ERROR
278+
"python metatransfer embedded-only sidecar cleanup failed (${_rv_embed_strip})\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
279+
endif()
280+
if(NOT EXISTS "${_embed_only_strip_jpg}")
281+
message(FATAL_ERROR
282+
"python metatransfer embedded-only cleanup did not write jpeg output\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
283+
endif()
284+
if(EXISTS "${_embed_only_strip_sidecar}")
285+
message(FATAL_ERROR
286+
"python metatransfer embedded-only cleanup did not remove stale sidecar\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
287+
endif()
288+
if(NOT _out_embed_strip MATCHES "xmp_sidecar_removed=.*embed_only_strip\\.xmp")
289+
message(FATAL_ERROR
290+
"python metatransfer embedded-only cleanup missing sidecar removal summary\nstdout:\n${_out_embed_strip}\nstderr:\n${_err_embed_strip}")
291+
endif()
292+
293+
execute_process(
294+
COMMAND "${CMAKE_COMMAND}" -E env
295+
"PYTHONPATH=${OPENMETA_PYTHONPATH}"
296+
"${OPENMETA_PYTHON_EXECUTABLE}" -m openmeta.python.metatransfer
297+
--no-build-info
298+
--target-jpeg "${_target_jpg_xmp}"
299+
--xmp-writeback sidecar
300+
--xmp-destination-embedded strip_existing
301+
-o "${_sidecar_only_strip_jpg}"
302+
"${_src_jpg}"
303+
RESULT_VARIABLE _rv_sidecar_strip
304+
OUTPUT_VARIABLE _out_sidecar_strip
305+
ERROR_VARIABLE _err_sidecar_strip
306+
)
307+
if(NOT _rv_sidecar_strip EQUAL 0)
308+
message(FATAL_ERROR
309+
"python metatransfer sidecar-only embedded-strip failed (${_rv_sidecar_strip})\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
310+
endif()
311+
if(NOT EXISTS "${_sidecar_only_strip_jpg}")
312+
message(FATAL_ERROR
313+
"python metatransfer sidecar-only embedded-strip did not write jpeg output\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
314+
endif()
315+
if(NOT EXISTS "${_sidecar_only_strip_sidecar}")
316+
message(FATAL_ERROR
317+
"python metatransfer sidecar-only embedded-strip did not write xmp sidecar\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}")
318+
endif()
319+
execute_process(
320+
COMMAND "${OPENMETA_PYTHON_EXECUTABLE}" -c
321+
"from pathlib import Path; b=Path(r'''${_sidecar_only_strip_jpg}''').read_bytes(); import sys; sys.exit(0 if (b.find(b'Target Embedded Existing')==-1 and b.find(b'http://ns.adobe.com/xap/1.0/')==-1) else 1)"
322+
RESULT_VARIABLE _rv_sidecar_strip_check
323+
OUTPUT_VARIABLE _out_sidecar_strip_check
324+
ERROR_VARIABLE _err_sidecar_strip_check
325+
)
326+
if(NOT _rv_sidecar_strip_check EQUAL 0)
327+
message(FATAL_ERROR
328+
"python metatransfer sidecar-only embedded-strip output still contains embedded xmp (${_rv_sidecar_strip_check})\nstdout:\n${_out_sidecar_strip}\nstderr:\n${_err_sidecar_strip}\ncheck_stderr:\n${_err_sidecar_strip_check}")
329+
endif()
330+
202331
file(WRITE "${_check_tiff_py}" [=[
203332
import sys
204333
from pathlib import Path

0 commit comments

Comments
 (0)