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

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

commit 0cfd2c50bea5de632f2ddf80faaecae1519179fc
Author: opencode <[email protected]>
AuthorDate: Sun Oct 11 14:45:37 2026 +0200

    Count entries with a null value in the size of a replicated map
    
    The size and the values collection only counted active entries that
    carried a non-null value, while the entry and key views included every
    active entry. A put of a null value is stored as an active local entry,
    because the replication gate does not accept a null value, so the size
    no longer matched the size of the entry set, which the map contract
    requires, and the empty check inherited the inconsistency.
    
    Both views now use the same filter as the entry and key views and count
    active entries with a null value, like the standard map implementations
    that permit null values do.
---
 .../tribes/tipis/AbstractReplicatedMap.java        |  4 ++--
 .../tribes/tipis/TestAbstractReplicatedMap.java    | 22 ++++++++++++++++++++++
 2 files changed, 24 insertions(+), 2 deletions(-)

diff --git a/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java 
b/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
index ead1263dd8..ac43555133 100644
--- a/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
+++ b/java/org/apache/catalina/tribes/tipis/AbstractReplicatedMap.java
@@ -1537,7 +1537,7 @@ public abstract class AbstractReplicatedMap<K, V>
         int counter = 0;
         for (Entry<K,MapEntry<K,V>> e : innerMap.entrySet()) {
             MapEntry<K,V> entry = e.getValue();
-            if (entry != null && entry.isActive() && entry.getValue() != null) 
{
+            if (entry != null && entry.isActive()) {
                 counter++;
             }
         }
@@ -1564,7 +1564,7 @@ public abstract class AbstractReplicatedMap<K, V>
         List<V> values = new ArrayList<>();
         for (Entry<K,MapEntry<K,V>> e : innerMap.entrySet()) {
             MapEntry<K,V> entry = e.getValue();
-            if (entry != null && entry.isActive() && entry.getValue() != null) 
{
+            if (entry != null && entry.isActive()) {
                 values.add(entry.getValue());
             }
         }
diff --git 
a/test/org/apache/catalina/tribes/tipis/TestAbstractReplicatedMap.java 
b/test/org/apache/catalina/tribes/tipis/TestAbstractReplicatedMap.java
index e4da5f26fa..ae82476a55 100644
--- a/test/org/apache/catalina/tribes/tipis/TestAbstractReplicatedMap.java
+++ b/test/org/apache/catalina/tribes/tipis/TestAbstractReplicatedMap.java
@@ -244,4 +244,26 @@ public class TestAbstractReplicatedMap {
         Assert.assertNull(map.getInternal(key));
         Assert.assertEquals(0, channel.sendCalls.get());
     }
+
+    /*
+     * A put stores an entry with a null value, so the size must count it like 
the entry and key
+     * views do. The size previously filtered such an entry out, breaking the 
map contract that the
+     * size equals the size of the entry set, and the isEmpty inherited the 
inconsistency.
+     */
+    @Test
+    public void testSizeCountsActiveEntriesWithNullValue() throws Exception {
+        LazyReplicatedMap<String,String> map = new 
LazyReplicatedMap<String,String>(
+                (key, value) -> {
+                    // Not made primary here
+                }, new TestChannel(), 1000, "TestAbstractReplicatedMap", null);
+        map.put("key", "value");
+        map.put("other", null);
+
+        Assert.assertEquals(2, map.size());
+        Assert.assertEquals(2, map.entrySet().size());
+        Assert.assertEquals(2, map.keySet().size());
+        Assert.assertEquals(2, map.values().size());
+        Assert.assertFalse(map.isEmpty());
+        Assert.assertTrue(map.values().contains(null));
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to