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 9eaf5e00 PROTON-2845 Improve output of failed match when validating
messages
9eaf5e00 is described below
commit 9eaf5e00e4c3953c526f00ac0df2980859c7b5a3
Author: Timothy Bish <[email protected]>
AuthorDate: Wed Aug 7 18:24:45 2024 -0400
PROTON-2845 Improve output of failed match when validating messages
When checking on scripted transfer payload contents the output should
provide more information to make it clear what failed in the contents
matching.
---
.../matchers/transport/TransferMessageMatcher.java | 38 +--
.../protonj2/test/driver/util/StringUtils.java | 327 +++++++++++++++++++++
2 files changed, 348 insertions(+), 17 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 25cb5a80..decd74ff 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
@@ -33,6 +33,7 @@ import
org.apache.qpid.protonj2.test.driver.matchers.types.EncodedAmqpSequenceMa
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.EncodedDataMatcher;
+import org.apache.qpid.protonj2.test.driver.util.StringUtils;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.hamcrest.StringDescription;
@@ -88,8 +89,9 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
bytesConsumed +=
headersMatcher.getInnerMatcher().verify(receivedSlice.slice());
receivedSlice.position(bytesConsumed);
} catch (Throwable t) {
- headerMatcherFailureDescription = "\nActual encoded form of
remaining bytes passed to MessageHeaderMatcher: " + receivedSlice;
- headerMatcherFailureDescription += "\nMessageHeaderMatcher
generated throwable: " + t;
+ headerMatcherFailureDescription = "\nBuffer of bytes passed to
Header Matcher: " + receivedSlice;
+ headerMatcherFailureDescription += "\nActual encoded form of
remaining bytes passed: " + StringUtils.toQuotedString(receivedSlice);
+ headerMatcherFailureDescription += "\nHeader Matcher generated
throwable: " + t.getMessage();
return false;
}
@@ -101,9 +103,9 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
bytesConsumed +=
deliveryAnnotationsMatcher.getInnerMatcher().verify(receivedSlice.slice());
receivedSlice.position(bytesConsumed);
} catch (Throwable t) {
- deliveryAnnotationsMatcherFailureDescription = "\nActual
encoded form of remaining bytes passed " +
- "to
DeliveryAnnotationsMatcher: " + receivedSlice;
- deliveryAnnotationsMatcherFailureDescription +=
"\nDeliveryAnnotationsMatcher generated throwable: " + t;
+ deliveryAnnotationsMatcherFailureDescription = "\nBuffer of
bytes passed to Delivery Annotations Matcher: " + receivedSlice;
+ deliveryAnnotationsMatcherFailureDescription += "\nActual
encoded form of remaining bytes passed: " +
StringUtils.toQuotedString(receivedSlice);
+ deliveryAnnotationsMatcherFailureDescription += "\nDelivery
Annotations Matcher generated throwable: " + t.getMessage();
return false;
}
@@ -115,9 +117,9 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
bytesConsumed +=
messageAnnotationsMatcher.getInnerMatcher().verify(receivedSlice.slice());
receivedSlice.position(bytesConsumed);
} catch (Throwable t) {
- messageAnnotationsMatcherFailureDescription = "\nActual
encoded form of remaining bytes passed to " +
-
"MessageAnnotationsMatcher: " + receivedSlice;
- messageAnnotationsMatcherFailureDescription +=
"\nMessageAnnotationsMatcher generated throwable: " + t;
+ messageAnnotationsMatcherFailureDescription = "\nBuffer of
bytes passed to Message Annotations Matcher: " + receivedSlice;
+ messageAnnotationsMatcherFailureDescription += "\nActual
encoded form of remaining bytes passed: " +
StringUtils.toQuotedString(receivedSlice);
+ messageAnnotationsMatcherFailureDescription += "\nMessage
Annotations Matcher generated throwable: " + t.getMessage();
return false;
}
@@ -129,9 +131,9 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
bytesConsumed +=
propertiesMatcher.getInnerMatcher().verify(receivedSlice.slice());
receivedSlice.position(bytesConsumed);
} catch (Throwable t) {
- propertiesMatcherFailureDescription = "\nActual encoded form
of remaining bytes passed to " +
- "PropertiesMatcher: " +
receivedSlice;
- propertiesMatcherFailureDescription += "\nPropertiesMatcher
generated throwable: " + t;
+ propertiesMatcherFailureDescription = "\nBuffer of bytes
passed to Properties Matcher: " + receivedSlice;
+ propertiesMatcherFailureDescription += "\nActual encoded form
of remaining bytes passed: " + StringUtils.toQuotedString(receivedSlice);
+ propertiesMatcherFailureDescription += "\nProperties Matcher
generated throwable: " + t.getMessage();
return false;
}
@@ -143,9 +145,9 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
bytesConsumed +=
applicationPropertiesMatcher.getInnerMatcher().verify(receivedSlice.slice());
receivedSlice.position(bytesConsumed);
} catch (Throwable t) {
- applicationPropertiesMatcherFailureDescription = "\nActual
encoded form of remaining bytes passed to " +
-
"ApplicationPropertiesMatcher: " + receivedSlice;
- applicationPropertiesMatcherFailureDescription +=
"\nApplicationPropertiesMatcher generated throwable: " + t;
+ applicationPropertiesMatcherFailureDescription = "\nBuffer of
bytes passed to Application Properties Matcher: " + receivedSlice;
+ applicationPropertiesMatcherFailureDescription += "\nActual
encoded form of remaining bytes passed: " +
StringUtils.toQuotedString(receivedSlice);
+ applicationPropertiesMatcherFailureDescription +=
"\nApplication Properties Matcher generated throwable: " + t.getMessage();
return false;
}
@@ -161,9 +163,11 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
if (!contentMatches) {
Description desc = new StringDescription();
msgContentMatcher.describeTo(desc);
- msgContentMatcher.describeMismatch(receivedSlice, desc);
+ msgContentMatcher.describeMismatch(slicedMsgContext, desc);
- msgContentMatcherFailureDescription =
"\nMessageContentMatcher mismatch Description:";
+ msgContentMatcherFailureDescription = "\nBuffer of bytes
passed to message contents Matcher: " + slicedMsgContext;
+ msgContentMatcherFailureDescription += "\nActual encoded
form of remaining bytes passed: " + StringUtils.toQuotedString(receivedSlice);
+ msgContentMatcherFailureDescription +=
"\nMessageContentMatcher mismatch Description:";
msgContentMatcherFailureDescription += desc.toString();
return false;
@@ -181,7 +185,7 @@ public class TransferMessageMatcher extends
TypeSafeMatcher<ByteBuffer> {
} catch (Throwable t) {
footerMatcherFailureDescription = "\nActual encoded form of
remaining bytes passed to " +
"FooterMatcher: " +
receivedSlice;
- footerMatcherFailureDescription += "\nFooterMatcher generated
throwable: " + t;
+ footerMatcherFailureDescription += "\nFooterMatcher generated
throwable: " + t.getMessage();
return false;
}
diff --git
a/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/util/StringUtils.java
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/util/StringUtils.java
new file mode 100644
index 00000000..ee5ac18a
--- /dev/null
+++
b/protonj2-test-driver/src/main/java/org/apache/qpid/protonj2/test/driver/util/StringUtils.java
@@ -0,0 +1,327 @@
+/*
+ *
+ * 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.util;
+
+import java.nio.ByteBuffer;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.qpid.protonj2.test.driver.codec.primitives.Binary;
+import org.apache.qpid.protonj2.test.driver.codec.primitives.Symbol;
+
+/**
+ * Set of {@link String} utilities used in the proton code.
+ */
+public class StringUtils {
+
+ private static final int DEFAULT_QUOTED_STRING_LIMIT = 64;
+
+ /**
+ * Converts the given String[] into a Symbol[] array.
+ *
+ * @param stringArray
+ * The given String[] to convert.
+ *
+ * @return a new Symbol array that contains Symbol versions of the input
Strings.
+ */
+ public static Symbol[] toSymbolArray(String[] stringArray) {
+ Symbol[] result = null;
+
+ if (stringArray != null) {
+ result = new Symbol[stringArray.length];
+ for (int i = 0; i < stringArray.length; ++i) {
+ result[i] = Symbol.valueOf(stringArray[i]);
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given Symbol[] into a String[] array.
+ *
+ * @param symbolArray
+ * The given Symbol[] to convert.
+ *
+ * @return a new String array that contains String versions of the input
Symbol.
+ */
+ public static String[] toStringArray(Symbol[] symbolArray) {
+ String[] result = null;
+
+ if (symbolArray != null) {
+ result = new String[symbolArray.length];
+ for (int i = 0; i < symbolArray.length; ++i) {
+ result[i] = symbolArray[i].toString();
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given String keyed {@link Map} into a matching Symbol
keyed {@link Map}.
+ *
+ * @param stringsMap
+ * The given String keyed {@link Map} to convert.
+ *
+ * @return a new Symbol keyed {@link Map} that contains Symbol versions of
the input String keys.
+ */
+ public static Map<Symbol, Object> toSymbolKeyedMap(Map<String, Object>
stringsMap) {
+ final Map<Symbol, Object> result;
+
+ if (stringsMap != null) {
+ result = new HashMap<>(stringsMap.size());
+ stringsMap.forEach((key, value) -> {
+ result.put(Symbol.valueOf(key), value);
+ });
+ } else {
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given Symbol keyed {@link Map} into a matching String
keyed {@link Map}.
+ *
+ * @param symbolMap
+ * The given String keyed {@link Map} to convert.
+ *
+ * @return a new String keyed {@link Map} that contains String versions of
the input Symbol keys.
+ */
+ public static Map<String, Object> toStringKeyedMap(Map<Symbol, Object>
symbolMap) {
+ Map<String, Object> result;
+
+ if (symbolMap != null) {
+ result = new LinkedHashMap<>(symbolMap.size());
+ symbolMap.forEach((key, value) -> {
+ result.put(key.toString(), value);
+ });
+ } else {
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given String {@link Collection} into a Symbol array.
+ *
+ * @param stringsSet
+ * The given String {@link Collection} to convert.
+ *
+ * @return a new Symbol array that contains String versions of the input
Symbols.
+ */
+ public static Symbol[] toSymbolArray(Collection<String> stringsSet) {
+ final Symbol[] result;
+
+ if (stringsSet != null) {
+ result = new Symbol[stringsSet.size()];
+ int index = 0;
+ for (String entry : stringsSet) {
+ result[index++] = Symbol.valueOf(entry);
+ }
+ } else {
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given String {@link Collection} into a matching Symbol
{@link Set}.
+ *
+ * @param stringsSet
+ * The given String {@link Collection} to convert.
+ *
+ * @return a new Symbol {@link Set} that contains String versions of the
input Symbols.
+ */
+ public static Set<Symbol> toSymbolSet(Collection<String> stringsSet) {
+ final Set<Symbol> result;
+
+ if (stringsSet != null) {
+ result = new LinkedHashSet<>(stringsSet.size());
+ stringsSet.forEach((entry) -> {
+ result.add(Symbol.valueOf(entry));
+ });
+ } else {
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the given Symbol array into a matching String {@link Set}.
+ *
+ * @param symbols
+ * The given Symbol array to convert.
+ *
+ * @return a new String {@link Set} that contains String versions of the
input Symbols.
+ */
+ public static Set<String> toStringSet(Symbol[] symbols) {
+ Set<String> result;
+
+ if (symbols != null) {
+ result = new LinkedHashSet<>(symbols.length);
+ for (Symbol symbol : symbols) {
+ result.add(symbol.toString());
+ }
+ } else {
+ result = null;
+ }
+
+ return result;
+ }
+
+ /**
+ * Converts the Binary to a quoted string using a default max length
before truncation value and
+ * appends a truncation indication if the string required truncation.
+ *
+ * @param buffer
+ * the {@link Binary} to convert into String format.
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final Binary buffer) {
+ return toQuotedString(buffer, DEFAULT_QUOTED_STRING_LIMIT, true);
+ }
+
+ /**
+ * Converts the Binary to a quoted string using a default max length
before truncation value.
+ *
+ * @param buffer
+ * the {@link Binary} to convert into String format.
+ * @param appendIfTruncated
+ * appends "...(truncated)" if not all of the payload is present in
the string
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final Binary buffer, final boolean
appendIfTruncated) {
+ return toQuotedString(buffer, DEFAULT_QUOTED_STRING_LIMIT,
appendIfTruncated);
+ }
+
+ /**
+ * Converts the Binary to a quoted string.
+ *
+ * @param buffer
+ * the {@link Binary} to convert into String format.
+ * @param stringLength
+ * the maximum length of stringified content (excluding the quotes,
and truncated indicator)
+ * @param appendIfTruncated
+ * appends "...(truncated)" if not all of the payload is present in
the string
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final Binary buffer, final int
stringLength, final boolean appendIfTruncated) {
+ if (buffer == null) {
+ return "\"\"";
+ } else {
+ return toQuotedString(buffer.asByteBuffer(), stringLength,
appendIfTruncated);
+ }
+ }
+
+ /**
+ * Converts the ProtonBuffer to a quoted string using a default max length
before truncation value and
+ * appends a truncation indication if the string required truncation.
+ *
+ * @param buffer
+ * the {@link ByteBuffer} to convert into String format.
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final ByteBuffer buffer) {
+ return toQuotedString(buffer, DEFAULT_QUOTED_STRING_LIMIT, true);
+ }
+
+ /**
+ * Converts the ProtonBuffer to a quoted string using a default max length
before truncation value.
+ *
+ * @param buffer
+ * the {@link ByteBuffer} to convert into String format.
+ * @param appendIfTruncated
+ * appends "...(truncated)" if not all of the payload is present in
the string
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final ByteBuffer buffer, final boolean
appendIfTruncated) {
+ return toQuotedString(buffer, DEFAULT_QUOTED_STRING_LIMIT,
appendIfTruncated);
+ }
+
+ /**
+ * Converts the ProtonBuffer to a quoted string.
+ *
+ * @param buffer
+ * the {@link ByteBuffer} to convert into String format.
+ * @param stringLength
+ * the maximum length of stringified content (excluding the quotes,
and truncated indicator)
+ * @param appendIfTruncated
+ * appends "...(truncated)" if not all of the payload is present in
the string
+ *
+ * @return the converted string
+ */
+ public static String toQuotedString(final ByteBuffer buffer, final int
stringLength, final boolean appendIfTruncated) {
+ if (buffer == null) {
+ return "\"\"";
+ }
+
+ StringBuilder str = new StringBuilder();
+ str.append("\"");
+
+ final int byteToRead = buffer.remaining();
+ int size = 0;
+ boolean truncated = false;
+
+ for (int i = 0; i < byteToRead; ++i) {
+ byte c = buffer.get(i);
+
+ if (c > 31 && c < 127 && c != '\\') {
+ if (size + 1 <= stringLength) {
+ size += 1;
+ str.append((char) c);
+ } else {
+ truncated = true;
+ break;
+ }
+ } else {
+ if (size + 4 <= stringLength) {
+ size += 4;
+ str.append(String.format("\\x%02x", c));
+ } else {
+ truncated = true;
+ break;
+ }
+ }
+ }
+
+ str.append("\"");
+
+ if (truncated && appendIfTruncated) {
+ str.append("...(truncated)");
+ }
+
+ return str.toString();
+ }
+}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]