Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 41 additions & 4 deletions tests/cow/media_validator.php
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,8 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-mime-thumb.png', "source generated MIME thumb bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-mime-empty.jpg', "source generated empty MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-mime-empty-thumb.png', "source generated empty MIME thumb bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-mime-numeric.jpg', "source generated numeric MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-mime-numeric-thumb.png', "source generated numeric MIME thumb bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-content-mime.jpg', "source generated content MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-content-mime-thumb.jpg', "%PDF-1.4 generated content MIME drift bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-generated-dimensions.jpg', "source invalid generated dimensions original bytes\n");
Expand All @@ -1025,6 +1027,8 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-mime-original.png', "source backup MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-mime-empty-current.jpg', "source backup empty MIME current bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-mime-empty-original.png', "source backup empty MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-mime-numeric-current.jpg', "source backup numeric MIME current bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-mime-numeric-original.png', "source backup numeric MIME original bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-content-mime-current.jpg', "source backup content MIME current bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-content-mime-original.jpg', "%PDF-1.4 backup content MIME drift bytes\n");
write_test_file($source_root . '/wp-content/uploads/2026/05/source-backup-dimensions-current.jpg', "source backup dimensions current bytes\n");
Expand Down Expand Up @@ -1239,6 +1243,19 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
],
],
]);
$generated_mime_numeric_id = insert_attachment($db, 'Source media numeric generated MIME type', '2026/05/source-generated-mime-numeric.jpg', [
'file' => '2026/05/source-generated-mime-numeric.jpg',
'width' => 640,
'height' => 480,
'sizes' => [
'thumbnail' => [
'file' => 'source-generated-mime-numeric-thumb.png',
'width' => 150,
'height' => 150,
'mime-type' => 123,
],
],
]);
$generated_content_mime_drift_id = insert_attachment($db, 'Source media generated content MIME type drift', '2026/05/source-generated-content-mime.jpg', [
'file' => '2026/05/source-generated-content-mime.jpg',
'width' => 640,
Expand Down Expand Up @@ -1422,6 +1439,20 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
],
'sizes' => [],
]);
$backup_mime_numeric_id = insert_attachment($db, 'Source media numeric backup MIME type', '2026/05/source-backup-mime-numeric-current.jpg', [
'file' => '2026/05/source-backup-mime-numeric-current.jpg',
'width' => 640,
'height' => 480,
'backup_sizes' => [
'full-orig' => [
'file' => 'source-backup-mime-numeric-original.png',
'width' => 1200,
'height' => 900,
'mime-type' => 456,
],
],
'sizes' => [],
]);
$backup_content_mime_drift_id = insert_attachment($db, 'Source media backup content MIME drift', '2026/05/source-backup-content-mime-current.jpg', [
'file' => '2026/05/source-backup-content-mime-current.jpg',
'width' => 640,
Expand Down Expand Up @@ -1619,7 +1650,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $

assert_same($result['status'], 'completed_with_conflicts', 'media validator holds incomplete generated-size metadata for review');
assert_same((int)($result['plugin_validators'] ?? 0), 1, 'media validator is discovered from mu-plugins during merge');
assert_same((int)($result['plugin_validator_conflicts'] ?? 0), 122, 'media validator records missing required metadata, invalid metadata, invalid shapes, dimensions, image metadata, filesize and MIME drift, invalid file entries, generated-size, original-image, backup-size, missing-file, metadata-file drift, unsafe path, duplicate upload conflicts, and built-in WordPress upload conflicts');
assert_same((int)($result['plugin_validator_conflicts'] ?? 0), 126, 'media validator records missing required metadata, invalid metadata, invalid shapes, dimensions, image metadata, filesize and MIME drift, invalid file entries, generated-size, original-image, backup-size, missing-file, metadata-file drift, unsafe path, duplicate upload conflicts, and built-in WordPress upload conflicts');
assert_same(
scalar($target, "SELECT meta_value FROM wp_postmeta WHERE post_id = $attachment_id AND meta_key = '_wp_attached_file'"),
'2026/05/source-generated-missing-file-key.jpg',
Expand Down Expand Up @@ -1711,7 +1742,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
'records' => 'conflicts',
'conflict_type' => 'plugin-wp-attachment-metadata-invalid-shape',
]);
assert_same(count($invalid_shape_audit['conflicts']), 14, 'media validator exposes malformed image_meta, generated-size, original_image, and backup-size metadata shapes as plugin-scoped audit conflicts');
assert_same(count($invalid_shape_audit['conflicts']), 16, 'media validator exposes malformed image_meta, generated-size, original_image, and backup-size metadata shapes as plugin-scoped audit conflicts');
$invalid_shape_payloads = array_map(
fn($conflict) => cow_merge_decode_payload_json((string)$conflict['chosen_payload'], 'media validator invalid-shape payload'),
$invalid_shape_audit['conflicts']
Expand All @@ -1729,6 +1760,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
'_wp_attachment_metadata.backup_sizes.full-orig.file',
'_wp_attachment_metadata.backup_sizes.full-orig.file',
'_wp_attachment_metadata.backup_sizes.full-orig.mime-type',
'_wp_attachment_metadata.backup_sizes.full-orig.mime-type',
'_wp_attachment_metadata.dimensions',
'_wp_attachment_metadata.image_meta',
'_wp_attachment_metadata.original_image',
Expand All @@ -1738,6 +1770,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
'_wp_attachment_metadata.sizes.thumbnail.file',
'_wp_attachment_metadata.sizes.thumbnail.file',
'_wp_attachment_metadata.sizes.thumbnail.mime-type',
'_wp_attachment_metadata.sizes.thumbnail.mime-type',
], 'media validator invalid-shape audit identifies every malformed metadata field');
assert_true(
in_array([], $invalid_shape_files_by_field['_wp_attachment_metadata.sizes.thumbnail.file'] ?? [], true),
Expand All @@ -1755,11 +1788,13 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
$invalid_shape_payload_preview = implode("\n", array_map(fn($payload) => json_encode($payload, JSON_UNESCAPED_SLASHES), $invalid_shape_payloads));
assert_true(str_contains($invalid_shape_payload_preview, (string)$generated_subdir_id), 'built-in WordPress upload invalid-shape audit includes the generated subdir attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$generated_mime_empty_id), 'built-in WordPress upload invalid-shape audit includes the empty generated MIME attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$generated_mime_numeric_id), 'built-in WordPress upload invalid-shape audit includes the numeric generated MIME attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$image_meta_drift_id), 'built-in WordPress upload invalid-shape audit includes the malformed image_meta attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$original_image_empty_id), 'built-in WordPress upload invalid-shape audit includes the empty original_image attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$original_image_subdir_id), 'built-in WordPress upload invalid-shape audit includes the original_image subdir attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$backup_subdir_id), 'built-in WordPress upload invalid-shape audit includes the backup subdir attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$backup_mime_empty_id), 'built-in WordPress upload invalid-shape audit includes the empty backup MIME attachment ID');
assert_true(str_contains($invalid_shape_payload_preview, (string)$backup_mime_numeric_id), 'built-in WordPress upload invalid-shape audit includes the numeric backup MIME attachment ID');

$original_dimension_audit = cow_merge_audit_report($metadata, (int)$result['run_id'], 10, [
'scope' => 'plugin',
Expand Down Expand Up @@ -1902,12 +1937,12 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
assert_true(str_contains($invalid_file_entry_preview, (string)$symlink_backup_id), 'media validator invalid-file-entry audit includes the symlink backup attachment ID');
assert_true($invalid_symlink_entry_type_recorded, 'media validator invalid-file-entry audit records symlink entry types');

$mime_audit = cow_merge_audit_report($metadata, (int)$result['run_id'], 10, [
$mime_audit = cow_merge_audit_report($metadata, (int)$result['run_id'], 20, [
'scope' => 'plugin',
'records' => 'conflicts',
'conflict_type' => 'plugin-wp-media-mime-drift',
]);
assert_same(count($mime_audit['conflicts']), 10, 'media validator exposes image, AVIF, PDF, content-signature, generated-size, and backup-size MIME drift as plugin-scoped audit conflicts');
assert_same(count($mime_audit['conflicts']), 12, 'media validator exposes image, AVIF, PDF, content-signature, generated-size, and backup-size MIME drift as plugin-scoped audit conflicts');
$mime_preview = implode("\n", array_map(fn($conflict) => (string)($conflict['chosen_preview'] ?? ''), $mime_audit['conflicts']));
assert_true(str_contains($mime_preview, 'source-mime-drift.jpg'), 'media validator MIME drift audit includes the affected attachment');
assert_true(str_contains($mime_preview, 'application/pdf'), 'media validator MIME drift audit includes the declared MIME type');
Expand All @@ -1924,6 +1959,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
assert_true(str_contains($mime_preview, 'image/png'), 'media validator MIME drift audit includes the expected generated MIME type');
assert_true(str_contains($mime_preview, (string)$generated_mime_drift_id), 'media validator MIME drift audit includes the generated-size attachment ID');
assert_true(str_contains($mime_preview, (string)$generated_mime_empty_id), 'media validator MIME drift audit includes the empty generated MIME attachment ID');
assert_true(str_contains($mime_preview, (string)$generated_mime_numeric_id), 'media validator MIME drift audit includes the numeric generated MIME attachment ID');
assert_true(str_contains($mime_preview, (string)$generated_content_mime_drift_id), 'media validator MIME drift audit includes the generated content-signature attachment ID');
$generated_mime_recorded = false;
$backup_mime_recorded = false;
Expand Down Expand Up @@ -1965,6 +2001,7 @@ function insert_attachment_with_single_meta(SQLite3 $db, string $title, string $
assert_true($backup_content_mime_recorded, 'media validator MIME drift audit payload identifies backup bytes that disagree with the backup extension');
assert_true(str_contains($mime_preview, (string)$backup_mime_drift_id), 'media validator MIME drift audit includes the backup-size attachment ID');
assert_true(str_contains($mime_preview, (string)$backup_mime_empty_id), 'media validator MIME drift audit includes the empty backup MIME attachment ID');
assert_true(str_contains($mime_preview, (string)$backup_mime_numeric_id), 'media validator MIME drift audit includes the numeric backup MIME attachment ID');

$wp_upload_mime_audit = cow_merge_audit_report($metadata, (int)$result['run_id'], 10, [
'scope' => 'plugin',
Expand Down
Loading