This is an automated email from the ASF dual-hosted git repository.

THausherr pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/tika.git


The following commit(s) were added to refs/heads/main by this push:
     new b08d4c2057 [TIKA-4841] Add unit tests for Metadata reserved-key 
blocking, write limiter, and composite properties (#2948)
b08d4c2057 is described below

commit b08d4c20571a294f9be23d76ae5a64d97b5ce54f
Author: Vasiliy Mikhailov <[email protected]>
AuthorDate: Wed Aug 26 16:14:38 2026 +0300

    [TIKA-4841] Add unit tests for Metadata reserved-key blocking, write 
limiter, and composite properties (#2948)
---
 .../org/apache/tika/metadata/TestMetadata.java     | 119 +++++++++++++++++++++
 1 file changed, 119 insertions(+)

diff --git a/tika-core/src/test/java/org/apache/tika/metadata/TestMetadata.java 
b/tika-core/src/test/java/org/apache/tika/metadata/TestMetadata.java
index e1fc1f62bc..5f2d6a233e 100644
--- a/tika-core/src/test/java/org/apache/tika/metadata/TestMetadata.java
+++ b/tika-core/src/test/java/org/apache/tika/metadata/TestMetadata.java
@@ -18,8 +18,10 @@ package org.apache.tika.metadata;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 import static org.junit.jupiter.api.Assertions.fail;
 
@@ -27,6 +29,7 @@ import java.text.DateFormat;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Random;
 import java.util.TimeZone;
 import java.util.concurrent.Callable;
@@ -38,6 +41,7 @@ import java.util.concurrent.Future;
 import org.junit.jupiter.api.Test;
 
 import org.apache.tika.TikaTest;
+import org.apache.tika.metadata.writelimiter.MetadataWriteLimiter;
 import org.apache.tika.utils.DateUtils;
 
 //Junit imports
@@ -461,6 +465,121 @@ public class TestMetadata extends TikaTest {
         assertEquals("key=value1", m.toString());
     }
 
+    /**
+     * Two Metadata instances that differ only in a value under the same key
+     * must not be equal, so value-distinct metadata are never collapsed.
+     */
+    @Test
+    public void testValueDistinctMetadataNotEqual() {
+        Metadata m1 = new Metadata();
+        m1.add("k1", "v1");
+        Metadata m2 = new Metadata();
+        m2.add("k1", "v2");
+        assertNotEquals(m1, m2);
+    }
+
+    /**
+     * Writing to reserved keys must throw an exception.
+     */
+    @Test
+    public void testReservedKeyBlockedOnUntrustedMetadata() {
+        String reservedKey = TikaCoreProperties.TIKA_META_PREFIX + "reserved";
+        Metadata m = new Metadata();
+        assertThrows(IllegalArgumentException.class, () -> m.add(reservedKey, 
"value"));
+    }
+
+    /**
+     * Reserved keys are accepted when addTrusted() is used.
+     */
+    @Test
+    public void testReservedKeyAllowedOnTrustedMetadata() {
+        String reservedKey = TikaCoreProperties.TIKA_META_PREFIX + "reserved";
+        Metadata m = new Metadata();
+        m.addTrusted(reservedKey, "value");
+        assertEquals("value", m.get(reservedKey));
+    }
+
+    /**
+     * A write limiter that drops everything must prevent {@code set} from
+     * persisting a value, so persistence stays under the limiter's control.
+     */
+    @Test
+    public void testWriteLimiterBlocksSet() {
+        Metadata m = new Metadata(blockingLimiter());
+        m.set("key", "value");
+        assertNull(m.get("key"));
+    }
+
+    /**
+     * {@code set(String, String)} must delegate to the limiter with the exact
+     * field and value it was given.
+     */
+    @Test
+    public void testWriteLimiterInvokedOnSet() {
+        RecordingLimiter limiter = new RecordingLimiter();
+        Metadata m = new Metadata(limiter);
+        m.set("key", "value");
+        assertTrue(limiter.setCalled);
+        assertEquals("key", limiter.lastSetField);
+        assertEquals("value", limiter.lastSetValue);
+    }
+
+    /**
+     * The {@code set(Property, String)} overload must delegate to the limiter
+     * using the property's name and the given value.
+     */
+    @Test
+    public void testWriteLimiterInvokedOnSetProperty() {
+        RecordingLimiter limiter = new RecordingLimiter();
+        Metadata m = new Metadata(limiter);
+        m.set(TikaCoreProperties.TITLE, "title");
+        assertTrue(limiter.setCalled);
+        assertEquals(TikaCoreProperties.TITLE.getName(), limiter.lastSetField);
+        assertEquals("title", limiter.lastSetValue);
+    }
+
+    /**
+     * A write limiter that ignores every field, so nothing is persisted.
+     */
+    private static MetadataWriteLimiter blockingLimiter() {
+        return new MetadataWriteLimiter() {
+            @Override
+            public void add(String field, String value, Map<String, String[]> 
data) {
+            }
+
+            @Override
+            public void set(String field, String value, Map<String, String[]> 
data) {
+            }
+        };
+    }
+
+    /**
+     * A spy limiter that records the field and value it was invoked with on
+     * {@code set} and writes the value through to the backing map.
+     */
+    private static final class RecordingLimiter implements 
MetadataWriteLimiter {
+        private boolean setCalled;
+        private String lastSetField;
+        private String lastSetValue;
+
+        @Override
+        public void add(String field, String value, Map<String, String[]> 
data) {
+            if (value != null) {
+                data.put(field, new String[]{value});
+            }
+        }
+
+        @Override
+        public void set(String field, String value, Map<String, String[]> 
data) {
+            setCalled = true;
+            lastSetField = field;
+            lastSetValue = value;
+            if (value != null) {
+                data.put(field, new String[]{value});
+            }
+        }
+    }
+
     private static class MetadataDateAdder implements Callable<Integer> {
         private final Random random = new Random();
 

Reply via email to