You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ta...@apache.org on 2024/08/22 20:45:01 UTC

(qpid-protonj2) branch main updated (9eaf5e00 -> 7ae9aa3e)

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

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


    from 9eaf5e00 PROTON-2845 Improve output of failed match when validating messages
     new cc1f7e7d PROTON-2845 Override base class optional API to return specific types
     new 7ae9aa3e PROTON-2845 Add transfer expectation API for any valid body section

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../driver/expectations/AttachExpectation.java     |   5 +
 .../test/driver/expectations/CloseExpectation.java |   5 +
 .../driver/expectations/DeclareExpectation.java    |   5 +
 .../driver/expectations/DetachExpectation.java     |   5 +
 .../driver/expectations/DischargeExpectation.java  |   5 +
 .../expectations/DispositionExpectation.java       |   5 +
 .../driver/expectations/EmptyFrameExpectation.java |   5 +
 .../test/driver/expectations/EndExpectation.java   |   5 +
 .../test/driver/expectations/FlowExpectation.java  |   5 +
 .../test/driver/expectations/OpenExpectation.java  |   5 +
 .../driver/expectations/TransferExpectation.java   |   5 +
 .../matchers/transport/TransferMessageMatcher.java |  33 +++++-
 .../matchers/types/EncodedAmqpTypeMatcher.java     |   3 +-
 .../types/EncodedAnyBodySectionMatcher.java        | 113 +++++++++++++++++++++
 .../matchers/types/EncodedBodySectionMatcher.java  |  21 ++--
 .../protonj2/test/driver/SenderHandlingTest.java   |  52 ++++++++++
 16 files changed, 263 insertions(+), 14 deletions(-)
 create mode 100644 protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAnyBodySectionMatcher.java
 copy protonj2/src/main/java/org/apache/qpid/protonj2/codec/encoders/AbstractDescribedTypeEncoder.java => protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedBodySectionMatcher.java (67%)


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


(qpid-protonj2) 01/02: PROTON-2845 Override base class optional API to return specific types

Posted by ta...@apache.org.
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

commit cc1f7e7da10019c4ed553cf0c0be3c25a831bf6a
Author: Timothy Bish <ta...@gmail.com>
AuthorDate: Thu Aug 22 16:15:51 2024 -0400

    PROTON-2845 Override base class optional API to return specific types
    
    Make writing some tests simpler by returning the correct type from the
    optional() API method in the base class of performative expectations
---
 .../qpid/protonj2/test/driver/expectations/AttachExpectation.java    | 5 +++++
 .../qpid/protonj2/test/driver/expectations/CloseExpectation.java     | 5 +++++
 .../qpid/protonj2/test/driver/expectations/DeclareExpectation.java   | 5 +++++
 .../qpid/protonj2/test/driver/expectations/DetachExpectation.java    | 5 +++++
 .../qpid/protonj2/test/driver/expectations/DischargeExpectation.java | 5 +++++
 .../protonj2/test/driver/expectations/DispositionExpectation.java    | 5 +++++
 .../protonj2/test/driver/expectations/EmptyFrameExpectation.java     | 5 +++++
 .../qpid/protonj2/test/driver/expectations/EndExpectation.java       | 5 +++++
 .../qpid/protonj2/test/driver/expectations/FlowExpectation.java      | 5 +++++
 .../qpid/protonj2/test/driver/expectations/OpenExpectation.java      | 5 +++++
 .../qpid/protonj2/test/driver/expectations/TransferExpectation.java  | 5 +++++
 11 files changed, 55 insertions(+)

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 aa951f15..ad076921 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
@@ -88,6 +88,11 @@ public class AttachExpectation extends AbstractExpectation<Attach> {
         return this;
     }
 
+    @Override
+    public AttachExpectation optional() {
+        return (AttachExpectation) super.optional();
+    }
+
     @Override
     public AttachExpectation withPredicate(Predicate<Attach> predicate) {
         super.withPredicate(predicate);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/CloseExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/CloseExpectation.java
index bbb4c925..8078485c 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/CloseExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/CloseExpectation.java
@@ -48,6 +48,11 @@ public class CloseExpectation extends AbstractExpectation<Close> {
         super(driver);
     }
 
+    @Override
+    public CloseExpectation optional() {
+        return (CloseExpectation) super.optional();
+    }
+
     public CloseInjectAction respond() {
         response = new CloseInjectAction(driver);
         driver.addScriptedElement(response);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DeclareExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DeclareExpectation.java
index 0c6b86dc..cf563efc 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DeclareExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DeclareExpectation.java
@@ -102,6 +102,11 @@ public class DeclareExpectation extends TransferExpectation {
 
     //----- Type specific with methods that perform simple equals checks
 
+    @Override
+    public DeclareExpectation optional() {
+        return (DeclareExpectation) super.optional();
+    }
+
     @Override
     public DeclareExpectation onChannel(int channel) {
         super.onChannel(channel);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DetachExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DetachExpectation.java
index 8a127e0b..7ebaaddd 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DetachExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DetachExpectation.java
@@ -62,6 +62,11 @@ public class DetachExpectation extends AbstractExpectation<Detach> {
         return this;
     }
 
+    @Override
+    public DetachExpectation optional() {
+        return (DetachExpectation) super.optional();
+    }
+
     public DetachInjectAction respond() {
         response = new DetachInjectAction(driver);
         driver.addScriptedElement(response);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DischargeExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DischargeExpectation.java
index f3956dda..35addffd 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DischargeExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DischargeExpectation.java
@@ -43,6 +43,11 @@ public class DischargeExpectation extends TransferExpectation {
         withPayload(matcher);
     }
 
+    @Override
+    public DischargeExpectation optional() {
+        return (DischargeExpectation) super.optional();
+    }
+
     @Override
     public DischargeExpectation onChannel(int channel) {
         super.onChannel(channel);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DispositionExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DispositionExpectation.java
index add9614f..b664518c 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DispositionExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/DispositionExpectation.java
@@ -61,6 +61,11 @@ public class DispositionExpectation extends AbstractExpectation<Disposition> {
         withFirst(notNullValue());
     }
 
+    @Override
+    public DispositionExpectation optional() {
+        return (DispositionExpectation) super.optional();
+    }
+
     @Override
     public DispositionExpectation onChannel(int channel) {
         super.onChannel(channel);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EmptyFrameExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EmptyFrameExpectation.java
index b29a027a..d7f95d0c 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EmptyFrameExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EmptyFrameExpectation.java
@@ -42,6 +42,11 @@ public class EmptyFrameExpectation extends AbstractExpectation<HeartBeat> {
         return this;
     }
 
+    @Override
+    public EmptyFrameExpectation optional() {
+        return (EmptyFrameExpectation) super.optional();
+    }
+
     public EmptyFrameInjectAction respond() {
         EmptyFrameInjectAction response = new EmptyFrameInjectAction(driver);
         driver.addScriptedElement(response);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EndExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EndExpectation.java
index edc84868..401055d2 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EndExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/EndExpectation.java
@@ -56,6 +56,11 @@ public class EndExpectation extends AbstractExpectation<End> {
         return this;
     }
 
+    @Override
+    public EndExpectation optional() {
+        return (EndExpectation) super.optional();
+    }
+
     public EndInjectAction respond() {
         response = new EndInjectAction(driver);
         driver.addScriptedElement(response);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/FlowExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/FlowExpectation.java
index 3a2cb410..fb9d2a82 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/FlowExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/FlowExpectation.java
@@ -57,6 +57,11 @@ public class FlowExpectation extends AbstractExpectation<Flow> {
         withOutgoingWindow(notNullValue());
     }
 
+    @Override
+    public FlowExpectation optional() {
+        return (FlowExpectation) super.optional();
+    }
+
     @Override
     public FlowExpectation onChannel(int channel) {
         super.onChannel(channel);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/OpenExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/OpenExpectation.java
index e3e446f9..20c8a0a5 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/OpenExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/OpenExpectation.java
@@ -59,6 +59,11 @@ public class OpenExpectation extends AbstractExpectation<Open> {
         onChannel(0);  // Open must used channel zero.
     }
 
+    @Override
+    public OpenExpectation optional() {
+        return (OpenExpectation) super.optional();
+    }
+
     @Override
     public OpenExpectation withPredicate(Predicate<Open> predicate) {
         super.withPredicate(predicate);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/TransferExpectation.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/TransferExpectation.java
index 4788aa58..e26fcd99 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/TransferExpectation.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/expectations/TransferExpectation.java
@@ -74,6 +74,11 @@ public class TransferExpectation extends AbstractExpectation<Transfer> {
         withHandle(notNullValue());
     }
 
+    @Override
+    public TransferExpectation optional() {
+        return (TransferExpectation) super.optional();
+    }
+
     @Override
     public TransferExpectation withPredicate(Predicate<Transfer> predicate) {
         super.withPredicate(predicate);


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org


(qpid-protonj2) 02/02: PROTON-2845 Add transfer expectation API for any valid body section

Posted by ta...@apache.org.
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

commit 7ae9aa3ef24d8e15f578c52ec8aabedaf2363175
Author: Timothy Bish <ta...@gmail.com>
AuthorDate: Thu Aug 22 16:41:38 2024 -0400

    PROTON-2845 Add transfer expectation API for any valid body section
    
    Allows writing tests where any valid body section is fine in cases where
    the test is only looking at basic structure of the message or only
    looking at annotations, properties etc
---
 .../matchers/transport/TransferMessageMatcher.java |  33 +++++-
 .../matchers/types/EncodedAmqpTypeMatcher.java     |   3 +-
 .../types/EncodedAnyBodySectionMatcher.java        | 113 +++++++++++++++++++++
 .../matchers/types/EncodedBodySectionMatcher.java  |  33 ++++++
 .../protonj2/test/driver/SenderHandlingTest.java   |  52 ++++++++++
 5 files changed, 230 insertions(+), 4 deletions(-)

diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/transport/TransferMessageMatcher.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/transport/TransferMessageMatcher.java
index decd74ff..66972c20 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/transport/TransferMessageMatcher.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/transport/TransferMessageMatcher.java
@@ -30,8 +30,9 @@ import org.apache.qpid.protonj2.test.driver.codec.primitives.UnsignedInteger;
 import org.apache.qpid.protonj2.test.driver.codec.transport.Transfer;
 import org.apache.qpid.protonj2.test.driver.expectations.TransferExpectation;
 import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedAmqpSequenceMatcher;
-import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedAmqpTypeMatcher;
 import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedAmqpValueMatcher;
+import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedAnyBodySectionMatcher;
+import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedBodySectionMatcher;
 import org.apache.qpid.protonj2.test.driver.matchers.types.EncodedDataMatcher;
 import org.apache.qpid.protonj2.test.driver.util.StringUtils;
 import org.hamcrest.Description;
@@ -53,7 +54,7 @@ public class TransferMessageMatcher extends TypeSafeMatcher<ByteBuffer> {
     private MessageAnnotationsMatcher messageAnnotationsMatcher;
     private PropertiesMatcher propertiesMatcher;
     private ApplicationPropertiesMatcher applicationPropertiesMatcher;
-    private List<EncodedAmqpTypeMatcher> bodySectionMatchers = new ArrayList<>();
+    private List<EncodedBodySectionMatcher> bodySectionMatchers = new ArrayList<>();
     private FooterMatcher footersMatcher;
 
     // String buckets for mismatch error descriptions.
@@ -378,6 +379,34 @@ public class TransferMessageMatcher extends TypeSafeMatcher<ByteBuffer> {
         return this;
     }
 
+    public TransferMessageMatcher withValidBodySection() {
+        final EncodedAnyBodySectionMatcher matcher = new EncodedAnyBodySectionMatcher(footersMatcher != null);
+
+        if (headersMatcher != null) {
+            headersMatcher.getInnerMatcher().setAllowTrailingBytes(true);
+        }
+        if (deliveryAnnotationsMatcher != null) {
+            deliveryAnnotationsMatcher.getInnerMatcher().setAllowTrailingBytes(true);
+        }
+        if (messageAnnotationsMatcher != null) {
+            messageAnnotationsMatcher.getInnerMatcher().setAllowTrailingBytes(true);
+        }
+        if (propertiesMatcher != null) {
+            propertiesMatcher.getInnerMatcher().setAllowTrailingBytes(true);
+        }
+        if (applicationPropertiesMatcher != null) {
+            applicationPropertiesMatcher.getInnerMatcher().setAllowTrailingBytes(true);
+        }
+
+        if (!bodySectionMatchers.isEmpty()) {
+            bodySectionMatchers.get(bodySectionMatchers.size() - 1).setAllowTrailingBytes(true);
+        }
+
+        bodySectionMatchers.add(matcher);
+
+        return this;
+    }
+
     public FooterMatcher withFooters() {
         if (footersMatcher == null) {
             footersMatcher = new FooterMatcher(this);
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAmqpTypeMatcher.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAmqpTypeMatcher.java
index 0eaf4de0..63d4fa3f 100644
--- a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAmqpTypeMatcher.java
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAmqpTypeMatcher.java
@@ -33,9 +33,8 @@ import org.apache.qpid.protonj2.test.driver.codec.primitives.UnsignedLong;
 import org.hamcrest.Description;
 import org.hamcrest.Matcher;
 import org.hamcrest.Matchers;
-import org.hamcrest.TypeSafeMatcher;
 
-public abstract class EncodedAmqpTypeMatcher extends TypeSafeMatcher<ByteBuffer> {
+public abstract class EncodedAmqpTypeMatcher extends EncodedBodySectionMatcher {
 
     private final Symbol descriptorSymbol;
     private final UnsignedLong descriptorCode;
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAnyBodySectionMatcher.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAnyBodySectionMatcher.java
new file mode 100644
index 00000000..0265d7a6
--- /dev/null
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedAnyBodySectionMatcher.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.qpid.protonj2.test.driver.matchers.types;
+
+import java.nio.ByteBuffer;
+
+import org.apache.qpid.protonj2.test.driver.codec.Codec;
+import org.apache.qpid.protonj2.test.driver.codec.primitives.DescribedType;
+import org.apache.qpid.protonj2.test.driver.codec.primitives.Symbol;
+import org.apache.qpid.protonj2.test.driver.codec.primitives.UnsignedLong;
+import org.hamcrest.Description;
+
+/**
+ * Encoded type matcher that validates that the encoded AMQP type is a valid body
+ * section in the standard AMQP message format set of allowed sections, Data, AmqpValue
+ * or AmqpSequence.
+ */
+public class EncodedAnyBodySectionMatcher extends EncodedBodySectionMatcher {
+
+    private static final Symbol AMQP_VALUE_DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:amqp-value:*");
+    private static final UnsignedLong AMQP_VALUE_DESCRIPTOR_CODE = UnsignedLong.valueOf(0x0000000000000077L);
+    private static final Symbol AMQP_SEQUENCE_DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:amqp-sequence:list");
+    private static final UnsignedLong AMQP_SEQUENCE_DESCRIPTOR_CODE = UnsignedLong.valueOf(0x0000000000000076L);
+    private static final Symbol DATA_DESCRIPTOR_SYMBOL = Symbol.valueOf("amqp:data:binary");
+    private static final UnsignedLong DATA_DESCRIPTOR_CODE = UnsignedLong.valueOf(0x0000000000000075L);
+
+    private boolean allowTrailingBytes;
+    private DescribedType decodedDescribedType;
+    private boolean unexpectedTrailingBytes;
+
+    public EncodedAnyBodySectionMatcher() {
+        this(false);
+    }
+
+    public EncodedAnyBodySectionMatcher(boolean allowTrailingBytes) {
+        this.allowTrailingBytes = allowTrailingBytes;
+    }
+
+    @Override
+    public void setAllowTrailingBytes(boolean allowTrailingBytes) {
+        this.allowTrailingBytes = allowTrailingBytes;
+    }
+
+    @Override
+    public boolean isAllowTrailngBytes() {
+        return allowTrailingBytes;
+    }
+
+    @Override
+    protected boolean matchesSafely(ByteBuffer receivedBinary) {
+        int length = receivedBinary.remaining();
+        Codec data = Codec.Factory.create();
+        long decoded = data.decode(receivedBinary);
+        decodedDescribedType = data.getDescribedType();
+        Object descriptor = decodedDescribedType.getDescriptor();
+
+        if (!AMQP_VALUE_DESCRIPTOR_CODE.equals(descriptor) &&
+            !AMQP_VALUE_DESCRIPTOR_SYMBOL.equals(descriptor) &&
+            !AMQP_SEQUENCE_DESCRIPTOR_CODE.equals(descriptor) &&
+            !AMQP_SEQUENCE_DESCRIPTOR_SYMBOL.equals(descriptor) &&
+            !DATA_DESCRIPTOR_CODE.equals(descriptor) &&
+            !DATA_DESCRIPTOR_SYMBOL.equals(descriptor)) {
+
+            return false;
+        }
+
+        // We are strict and require the encoding to have a value.
+        if (decodedDescribedType.getDescribed() == null) {
+            return false;
+        }
+
+        if (decoded < length && !allowTrailingBytes) {
+            unexpectedTrailingBytes = true;
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
+    public void describeTo(Description description) {
+        description.appendText("a body section of any AMQP Value, Sequence or Data section.");
+    }
+
+    @Override
+    protected void describeMismatchSafely(ByteBuffer item, Description mismatchDescription) {
+        mismatchDescription.appendText("\nActual encoded form: ").appendValue(item);
+
+        if (decodedDescribedType != null) {
+            mismatchDescription.appendText("\nExpected descriptor of AMQP Value, Sequence or Data section: ");
+            mismatchDescription.appendText("\nActual described type: ").appendValue(decodedDescribedType);
+        }
+
+        if (unexpectedTrailingBytes) {
+            mismatchDescription.appendText("\nUnexpected trailing bytes in provided bytes after decoding!");
+        }
+    }
+}
diff --git a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedBodySectionMatcher.java b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedBodySectionMatcher.java
new file mode 100644
index 00000000..839e3686
--- /dev/null
+++ b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/matchers/types/EncodedBodySectionMatcher.java
@@ -0,0 +1,33 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.qpid.protonj2.test.driver.matchers.types;
+
+import java.nio.ByteBuffer;
+
+import org.hamcrest.TypeSafeMatcher;
+
+/**
+ * Base marker type for any Body Section type matcher.
+ */
+public abstract class EncodedBodySectionMatcher extends TypeSafeMatcher<ByteBuffer> {
+
+    public abstract void setAllowTrailingBytes(boolean allowTrailingBytes);
+
+    public abstract boolean isAllowTrailngBytes();
+
+}
diff --git a/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/SenderHandlingTest.java b/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/SenderHandlingTest.java
index b4858625..3ea157aa 100644
--- a/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/SenderHandlingTest.java
+++ b/protonj2-test-driver/src/test/java/org/apache/qpid/protonj2/test/driver/SenderHandlingTest.java
@@ -1006,4 +1006,56 @@ class SenderHandlingTest extends TestPeerTestsBase {
             peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
         }
     }
+
+    @Test
+    public void testMatchAnyBodySectionMatcherExpectation() throws Exception {
+        try (ProtonTestServer peer = new ProtonTestServer();
+             ProtonTestClient client = new ProtonTestClient()) {
+
+            peer.expectAMQPHeader().respondWithAMQPHeader();
+            peer.expectOpen().respond();
+            peer.expectBegin().respond();
+            peer.expectAttach().ofSender().respond().withHandle(42);
+            peer.remoteFlow().withLinkCredit(1).queue();
+            // Script a full message using the inject API
+            peer.expectTransfer().withMessage().withMessageFormat(1)
+                                               .withProperties().withCorrelationId("test").and()
+                                               .withDeliveryAnnotations().also()
+                                               .withApplicationProperties().and()
+                                               .withMessageAnnotations().also()
+                                               .withValidBodySection()
+                                               .withHeader().withDurability(true).and()
+                                               .withFooters();
+            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().ofReceiver().withHandle(42);
+            client.expectFlow().withLinkCredit(1).withHandle(42);
+            client.remoteTransfer().withMessage().withMessageFormat(1)
+                                                 .withHeader().withDurability(true).also()
+                                                 .withApplicationProperties().withProperty("ap", "pa").also()
+                                                 .withDeliveryAnnotations().withAnnotation("da", "ad").also()
+                                                 .withProperties().withCorrelationId("test").also()
+                                                 .withMessageAnnotations().withAnnotation("ma", "am").also()
+                                                 .withFooter().withFooter("footer", "1").also()
+                                                 .withBody().withData(new byte[] {0, 1, 2}).also()
+                                                 .queue();
+
+            // Now start and then await the remote grant of credit and out send of a transfer
+            client.remoteHeader(AMQPHeader.getAMQPHeader()).now();
+            client.remoteOpen().now();
+            client.remoteBegin().now();
+            client.remoteAttach().ofSender().withHandle(2).now();
+
+            client.waitForScriptToComplete(5, TimeUnit.SECONDS);
+            peer.waitForScriptToComplete(5, TimeUnit.SECONDS);
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org