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]