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

tabish pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-protonj2.git


The following commit(s) were added to refs/heads/main by this push:
     new 763d8589 PROTON-2901 Improve JMS selector and nolocal filter handling
763d8589 is described below

commit 763d858973ac0bbef34f4c761db29752650e7951
Author: Timothy Bish <[email protected]>
AuthorDate: Tue Jul 22 15:46:13 2025 -0400

    PROTON-2901 Improve JMS selector and nolocal filter handling
    
    Allow for both filters to be specified for Attach expectations and for
    the remote send API in the peer.
---
 .../test/driver/actions/AttachInjectAction.java    |  15 +-
 .../codec/primitives/UnknownDescribedType.java     |   2 +-
 .../driver/expectations/AttachExpectation.java     |  24 +++-
 .../matchers/JmsNoLocalByIdDescribedType.java      |   6 +
 .../matchers/JmsSelectorByIdDescribedType.java     |   6 +
 .../protonj2/test/driver/ReceiverHandlingTest.java | 153 +++++++++++++++++++++
 6 files changed, 185 insertions(+), 21 deletions(-)

diff --git 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/actions/AttachInjectAction.java
 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/actions/AttachInjectAction.java
index 8435417a..fb3f1d0b 100644
--- 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/actions/AttachInjectAction.java
+++ 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/actions/AttachInjectAction.java
@@ -16,7 +16,6 @@
  */
 package org.apache.qpid.protonj2.test.driver.actions;
 
-import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -519,21 +518,11 @@ public class AttachInjectAction extends 
AbstractPerformativeInjectAction<Attach>
         }
 
         public SourceBuilder withJMSSelector(String selector) {
-            final JmsSelectorByIdDescribedType jmsSelector = new 
JmsSelectorByIdDescribedType(selector);
-            final Map<String, Object> filters = new HashMap<>();
-
-            filters.put(JmsSelectorByIdDescribedType.JMS_SELECTOR_KEY, 
jmsSelector);
-
-            return withFilterMap(filters);
+            return 
withFilterMap(JmsSelectorByIdDescribedType.JMS_SELECTOR_SYMBOL_KEY, new 
JmsSelectorByIdDescribedType(selector));
         }
 
         public SourceBuilder withNoLocal() {
-            final JmsNoLocalByIdDescribedType noLocal = new 
JmsNoLocalByIdDescribedType();
-            final Map<String, Object> filters = new HashMap<>();
-
-            filters.put(JmsNoLocalByIdDescribedType.JMS_NO_LOCAL_KEY, noLocal);
-
-            return withFilterMap(filters);
+            return 
withFilterMap(JmsNoLocalByIdDescribedType.JMS_NO_LOCAL_SYMBOL_KEY, new 
JmsNoLocalByIdDescribedType());
         }
 
         public SourceBuilder withFilter(Map<Symbol, Object> filters) {
diff --git 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/codec/primitives/UnknownDescribedType.java
 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/codec/primitives/UnknownDescribedType.java
index b9f2dbe3..2d9bb7f6 100644
--- 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/codec/primitives/UnknownDescribedType.java
+++ 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/codec/primitives/UnknownDescribedType.java
@@ -41,7 +41,7 @@ public class UnknownDescribedType implements DescribedType {
         if (this == o) {
             return true;
         }
-        if (o == null || getClass() != o.getClass()) {
+        if (o == null || !DescribedType.class.isAssignableFrom(o.getClass())) {
             return false;
         }
 
diff --git 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/AttachExpectation.java
 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/AttachExpectation.java
index 1705ba2c..761d119d 100644
--- 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/AttachExpectation.java
+++ 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/AttachExpectation.java
@@ -23,7 +23,6 @@ import static org.hamcrest.CoreMatchers.nullValue;
 
 import java.nio.ByteBuffer;
 import java.util.Arrays;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.UUID;
 import java.util.function.Consumer;
@@ -53,6 +52,7 @@ import 
org.apache.qpid.protonj2.test.driver.codec.transport.Role;
 import org.apache.qpid.protonj2.test.driver.codec.transport.SenderSettleMode;
 import 
org.apache.qpid.protonj2.test.driver.matchers.JmsNoLocalByIdDescribedType;
 import 
org.apache.qpid.protonj2.test.driver.matchers.JmsSelectorByIdDescribedType;
+import org.apache.qpid.protonj2.test.driver.matchers.MapContentsMatcher;
 import org.apache.qpid.protonj2.test.driver.matchers.messaging.SourceMatcher;
 import org.apache.qpid.protonj2.test.driver.matchers.messaging.TargetMatcher;
 import 
org.apache.qpid.protonj2.test.driver.matchers.transactions.CoordinatorMatcher;
@@ -582,6 +582,9 @@ public class AttachExpectation extends 
AbstractExpectation<Attach> {
 
         private final AttachExpectation expectation;
 
+        // Only used if singular 'withJMSSelector' or 'withNoLocal' API is used
+        private MapContentsMatcher<Symbol, Object> jmsFilterMatcher;
+
         public AttachSourceMatcher(AttachExpectation expectation) {
             this.expectation = expectation;
         }
@@ -662,27 +665,34 @@ public class AttachExpectation extends 
AbstractExpectation<Attach> {
 
         @Override
         public AttachSourceMatcher withFilter(Map<String, Object> filter) {
+            jmsFilterMatcher = null;
             super.withFilter(filter);
             return this;
         }
 
         public AttachSourceMatcher withJMSSelector(String selector) {
+            if (jmsFilterMatcher == null) {
+                jmsFilterMatcher = new MapContentsMatcher<Symbol, Object>();
+            }
+
             final JmsSelectorByIdDescribedType filterType = new 
JmsSelectorByIdDescribedType(selector);
-            final Map<String, Object> filtersMap = new HashMap<>();
 
-            filtersMap.put(JmsSelectorByIdDescribedType.JMS_SELECTOR_KEY, 
filterType);
+            
jmsFilterMatcher.addExpectedEntry(Symbol.valueOf(JmsSelectorByIdDescribedType.JMS_SELECTOR_KEY),
 filterType);
 
-            super.withFilter(filtersMap);
+            super.withFilter(jmsFilterMatcher);
             return this;
         }
 
         public AttachSourceMatcher withNoLocal() {
+            if (jmsFilterMatcher == null) {
+                jmsFilterMatcher = new MapContentsMatcher<Symbol, Object>();
+            }
+
             final JmsNoLocalByIdDescribedType filterType = new 
JmsNoLocalByIdDescribedType();
-            final Map<String, Object> filtersMap = new HashMap<>();
 
-            filtersMap.put(JmsNoLocalByIdDescribedType.JMS_NO_LOCAL_KEY, 
filterType);
+            
jmsFilterMatcher.addExpectedEntry(Symbol.valueOf(JmsNoLocalByIdDescribedType.JMS_NO_LOCAL_KEY),
 filterType);
 
-            super.withFilter(filtersMap);
+            super.withFilter(jmsFilterMatcher);
             return this;
         }
 
diff --git 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsNoLocalByIdDescribedType.java
 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsNoLocalByIdDescribedType.java
index cc9d73a7..7e703677 100644
--- 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsNoLocalByIdDescribedType.java
+++ 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsNoLocalByIdDescribedType.java
@@ -17,6 +17,7 @@
 
 package org.apache.qpid.protonj2.test.driver.matchers;
 
+import org.apache.qpid.protonj2.test.driver.codec.primitives.Symbol;
 import 
org.apache.qpid.protonj2.test.driver.codec.primitives.UnknownDescribedType;
 import org.apache.qpid.protonj2.test.driver.codec.primitives.UnsignedLong;
 
@@ -30,6 +31,11 @@ public class JmsNoLocalByIdDescribedType extends 
UnknownDescribedType {
      */
     public static final String JMS_NO_LOCAL_KEY = "no-local";
 
+    /**
+     * Symbolic key name used when add the selector type to the filters map.
+     */
+    public static final Symbol JMS_NO_LOCAL_SYMBOL_KEY = 
Symbol.valueOf(JMS_NO_LOCAL_KEY);
+
     public static final UnsignedLong JMS_NO_LOCAL_ULONG_DESCRIPTOR = 
UnsignedLong.valueOf(0x0000468C00000003L);
 
     public JmsNoLocalByIdDescribedType() {
diff --git 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsSelectorByIdDescribedType.java
 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsSelectorByIdDescribedType.java
index 15c7a789..4dbed3d1 100644
--- 
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsSelectorByIdDescribedType.java
+++ 
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/JmsSelectorByIdDescribedType.java
@@ -17,6 +17,7 @@
 
 package org.apache.qpid.protonj2.test.driver.matchers;
 
+import org.apache.qpid.protonj2.test.driver.codec.primitives.Symbol;
 import 
org.apache.qpid.protonj2.test.driver.codec.primitives.UnknownDescribedType;
 import org.apache.qpid.protonj2.test.driver.codec.primitives.UnsignedLong;
 
@@ -30,6 +31,11 @@ public class JmsSelectorByIdDescribedType extends 
UnknownDescribedType {
      */
     public static final String JMS_SELECTOR_KEY = "jms-selector";
 
+    /**
+     * Symbolic key name used when add the selector type to the filters map.
+     */
+    public static final Symbol JMS_SELECTOR_SYMBOL_KEY = 
Symbol.valueOf(JMS_SELECTOR_KEY);
+
     public static final UnsignedLong JMS_SELECTOR_ULONG_DESCRIPTOR = 
UnsignedLong.valueOf(0x0000468C00000004L);
 
     public JmsSelectorByIdDescribedType(String selector) {
diff --git 
a/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/ReceiverHandlingTest.java
 
b/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/ReceiverHandlingTest.java
index 2ba07f57..891fd9d9 100644
--- 
a/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/ReceiverHandlingTest.java
+++ 
b/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/ReceiverHandlingTest.java
@@ -481,6 +481,36 @@ class ReceiverHandlingTest extends TestPeerTestsBase {
         }
     }
 
+    @Test
+    public void 
testReceiverAttachWithJMSSelectorMatchingAPIWithNonMatchingSelector() throws 
Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            
peer.expectAttach().ofReceiver().withSource().withJMSSelector("property=1").also().respond();
+            peer.start();
+
+            URI remoteURI = peer.getServerURI();
+
+            LOG.info("Test started, peer listening on: {}", remoteURI);
+
+            client.connect(remoteURI.getHost(), remoteURI.getPort());
+            client.expectAMQPHeader();
+            client.expectOpen();
+            client.expectBegin();
+            client.remoteAMQPHeader().now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            
client.remoteAttach().ofReceiver().withSource().withJMSSelector("property=2").and().now();
+
+            client.waitForScriptToComplete();
+
+            assertThrows(AssertionError.class, () -> 
peer.waitForScriptToComplete(5, TimeUnit.SECONDS));
+        }
+    }
+
     @Test
     public void testReceiverAttachWithNoLocalMatchingAPI() throws Exception {
         try (ProtonTestServer peer = new ProtonTestServer();
@@ -514,6 +544,129 @@ class ReceiverHandlingTest extends TestPeerTestsBase {
         }
     }
 
+    @Test
+    public void testReceiverAttachWithNoLocalMatchingAPIButNoLocalNotSent() 
throws Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            
peer.expectAttach().ofReceiver().withSource().withNoLocal().also().respond();
+            peer.start();
+
+            URI remoteURI = peer.getServerURI();
+
+            LOG.info("Test started, peer listening on: {}", remoteURI);
+
+            client.connect(remoteURI.getHost(), remoteURI.getPort());
+            client.expectAMQPHeader();
+            client.expectOpen();
+            client.expectBegin();
+            client.remoteAMQPHeader().now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            client.remoteAttach().ofReceiver().withSource().and().now();
+
+            client.waitForScriptToComplete(5, TimeUnit.SECONDS);
+
+            assertThrows(AssertionError.class, () -> 
peer.waitForScriptToComplete(5, TimeUnit.SECONDS));
+        }
+    }
+
+    @Test
+    public void testReceiverAttachWithNoLocalAndJMSSelectorAPI() throws 
Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            
peer.expectAttach().ofReceiver().withSource().withNoLocal().withJMSSelector("property=1").also().respond();
+            peer.expectEnd().respond();
+            peer.start();
+
+            URI remoteURI = peer.getServerURI();
+
+            LOG.info("Test started, peer listening on: {}", remoteURI);
+
+            client.connect(remoteURI.getHost(), remoteURI.getPort());
+            client.expectAMQPHeader();
+            client.expectOpen();
+            client.expectBegin();
+            
client.expectAttach().ofSender().withOfferedCapabilities(Matchers.nullValue());
+            client.expectEnd();
+            client.remoteAMQPHeader().now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            
client.remoteAttach().ofReceiver().withSource().withNoLocal().withJMSSelector("property=1").and().now();
+            client.remoteEnd().now();
+
+            client.waitForScriptToComplete(5, TimeUnit.SECONDS);
+            peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
+        }
+    }
+
+    @Test
+    public void 
testReceiverAttachWithNoLocalAndJMSSelectorAPIButMissingNoLocal() throws 
Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            
peer.expectAttach().ofReceiver().withSource().withNoLocal().withJMSSelector("property=1").also().respond();
+            peer.start();
+
+            URI remoteURI = peer.getServerURI();
+
+            LOG.info("Test started, peer listening on: {}", remoteURI);
+
+            client.connect(remoteURI.getHost(), remoteURI.getPort());
+            client.expectAMQPHeader();
+            client.expectOpen();
+            client.expectBegin();
+            client.remoteAMQPHeader().now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            
client.remoteAttach().ofReceiver().withSource().withJMSSelector("property=1").and().now();
+
+            client.waitForScriptToComplete(5, TimeUnit.SECONDS);
+
+            assertThrows(AssertionError.class, () -> 
peer.waitForScriptToComplete(5, TimeUnit.SECONDS));
+        }
+    }
+
+    @Test
+    public void 
testReceiverAttachWithNoLocalAndJMSSelectorAPIButMissingJMSSelector() throws 
Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            
peer.expectAttach().ofReceiver().withSource().withNoLocal().withJMSSelector("property=1").also().respond();
+            peer.start();
+
+            URI remoteURI = peer.getServerURI();
+
+            LOG.info("Test started, peer listening on: {}", remoteURI);
+
+            client.connect(remoteURI.getHost(), remoteURI.getPort());
+            client.expectAMQPHeader();
+            client.expectOpen();
+            client.expectBegin();
+            client.remoteAMQPHeader().now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            
client.remoteAttach().ofReceiver().withSource().withNoLocal().and().now();
+
+            client.waitForScriptToComplete(5, TimeUnit.SECONDS);
+
+            assertThrows(AssertionError.class, () -> 
peer.waitForScriptToComplete(5, TimeUnit.SECONDS));
+        }
+    }
+
     @Test
     public void testReceiverSendsRejectedDisposition() throws Exception {
         try (ProtonTestServer peer = new ProtonTestServer();


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

Reply via email to