diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/adapter/AbstractBinaryAdapter.java b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/adapter/AbstractBinaryAdapter.java index 56c15d659..673759bb1 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/adapter/AbstractBinaryAdapter.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/datatype/adapter/AbstractBinaryAdapter.java @@ -48,17 +48,41 @@ protected AbstractBinaryAdapter( super(ByteBuffer.class, itemClass, castExecutor); } + /** + * Get the binary decoder to use to decode encoded data. + * + * @return the decoder + */ @NonNull protected abstract BinaryDecoder getDecoder(); + /** + * Get the binary encoder to use to encode data. + * + * @return the encoder + */ @NonNull protected abstract BinaryEncoder getEncoder(); + /** + * Get the raw bytes, encoded as UTF8, for the provided text string. + * + * @param text + * the text string to get the bytes for + * @return the UTF8 encoded bytes for the text string + */ @NonNull private static byte[] stringToBytes(@NonNull String text) { - return text.getBytes(StandardCharsets.UTF_8); + return ObjectUtils.notNull(text.getBytes(StandardCharsets.UTF_8)); } + /** + * Get a text string based on the provided raw bytes, encoded as UTF8. + * + * @param bytes + * a byte array encoded as UTF8 + * @return the decoded text string + */ @NonNull private static String bytesToString(@NonNull byte[] bytes) { return new String(bytes, StandardCharsets.UTF_8); @@ -68,6 +92,14 @@ private static String elide(@NonNull String text, int length) { return text.length() <= length ? text : text.substring(0, length) + "…"; } + /** + * Encode the provided bytes using the encoding supported by this class. + * + * @param decodedBytes + * the bytes to encode + * @return the encoded bytes + * @see #getEncoder() + */ @NonNull public byte[] encode(@NonNull byte[] decodedBytes) { try { @@ -79,24 +111,58 @@ public byte[] encode(@NonNull byte[] decodedBytes) { } } + /** + * Encode the provided bytes using the encoding supported by this class. + * + * @param decodedBuffer + * a buffer containing the bytes to encode + * @return a buffer containing the encoded bytes + * @see #getEncoder() + */ @NonNull public ByteBuffer encodeToByteBuffer(@NonNull ByteBuffer decodedBuffer) { byte[] decodedBytes = bufferToBytes(decodedBuffer, false); return encodeToByteBuffer(decodedBytes); } + /** + * Encode the provided string using the encoding supported by this class. + *

+ * The provided string is first encoded as a stream of UTF8 bytes. + * + * @param decodedText + * the string to encode + * @return a buffer containing the encoded bytes + * @see #getEncoder() + */ @NonNull - public ByteBuffer encodeToByteBuffer(String decodedText) { + public ByteBuffer encodeToByteBuffer(@NonNull String decodedText) { byte[] decodedBytes = stringToBytes(decodedText); return encodeToByteBuffer(decodedBytes); } + /** + * Encode the provided bytes using the encoding supported by this class. + * + * @param decodedBytes + * the bytes to encode + * @return a buffer containing the encoded bytes + * @see #getEncoder() + */ @NonNull - public ByteBuffer encodeToByteBuffer(byte[] decodedBytes) { + public ByteBuffer encodeToByteBuffer(@NonNull byte[] decodedBytes) { byte[] encodedBytes = encode(decodedBytes); return ObjectUtils.notNull(ByteBuffer.wrap(encodedBytes)); } + /** + * Decode the provided bytes using the encoding supported by this class. + * + * @param enodedBytes + * the bytes to decode + * @return the decoded bytes + * @see #getDecoder() + */ @NonNull public byte[] decode(@NonNull byte[] enodedBytes) { try { @@ -108,6 +174,14 @@ public byte[] decode(@NonNull byte[] enodedBytes) { } } + /** + * Decode the provided bytes using the encoding supported by this class. + * + * @param encodedBuffer + * a buffer containing the the bytes to decode + * @return a buffer containing the decoded bytes + * @see #getDecoder() + */ @NonNull public ByteBuffer decode(@NonNull ByteBuffer encodedBuffer) { byte[] encodedBytes = bufferToBytes(encodedBuffer, false); @@ -115,6 +189,16 @@ public ByteBuffer decode(@NonNull ByteBuffer encodedBuffer) { return ObjectUtils.notNull(ByteBuffer.wrap(decodedBytes)); } + /** + * Decode the provided bytes using the encoding supported by this class. + *

+ * The decoded bytes are decoded as a stream of UTF8 bytes to produce the string. + * + * @param encodedBytes + * the bytes to decode + * @return the decoded string + * @see #getDecoder() + */ @NonNull public String decodeToString(@NonNull byte[] encodedBytes) { byte[] decodedBytes = decode(encodedBytes); @@ -169,6 +253,15 @@ public ByteBuffer copy(Object obj) { return clone; } + /** + * Get the array of bytes stored in the buffer. + * + * @param buffer + * the buffer + * @param copy + * if {@code true} ensure the resulting array is a copy + * @return the array of bytes + */ @NonNull public static byte[] bufferToBytes(@NonNull ByteBuffer buffer, boolean copy) { byte[] array; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Decode.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Decode.java new file mode 100644 index 000000000..90fc35e35 --- /dev/null +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Decode.java @@ -0,0 +1,62 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.metapath.function.library; + +import gov.nist.secauto.metaschema.core.metapath.DynamicContext; +import gov.nist.secauto.metaschema.core.metapath.MetapathConstants; +import gov.nist.secauto.metaschema.core.metapath.function.FunctionUtils; +import gov.nist.secauto.metaschema.core.metapath.function.IArgument; +import gov.nist.secauto.metaschema.core.metapath.function.IFunction; +import gov.nist.secauto.metaschema.core.metapath.item.IItem; +import gov.nist.secauto.metaschema.core.metapath.item.ISequence; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IBase64BinaryItem; +import gov.nist.secauto.metaschema.core.metapath.item.atomic.IStringItem; +import gov.nist.secauto.metaschema.core.util.ObjectUtils; + +import java.util.List; + +import edu.umd.cs.findbugs.annotations.NonNull; + +/** + * Provides a new Metapath function that decodes provided encoded text using base64. + * + */ +public final class MpBase64Decode { + private static final String NAME = "base64-decode-text"; + + @NonNull + static final IFunction SIGNATURE_ONE_ARG = IFunction.builder() + .name(NAME) + .namespace(MetapathConstants.NS_METAPATH_FUNCTIONS_EXTENDED) + .deterministic() + .contextIndependent() + .focusIndependent() + .argument(IArgument.builder() + .name("encodedText") + .type(IBase64BinaryItem.type()) + .one() + .build()) + .returnType(IStringItem.type()) + .returnOne() + .functionHandler(MpBase64Decode::executeOneArg) + .build(); + + private MpBase64Decode() { + // disable construction + } + + @SuppressWarnings("unused") + @NonNull + private static ISequence executeOneArg( + @NonNull IFunction function, + @NonNull List> arguments, + @NonNull DynamicContext dynamicContext, + IItem focus) { + IBase64BinaryItem encodedText + = FunctionUtils.asType(ObjectUtils.requireNonNull(arguments.get(0).getFirstItem(true))); + return ISequence.of(encodedText.decodeAsString()); + } +} diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Encode.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Encode.java index 665c7942c..d1dd98202 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Encode.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/function/library/MpBase64Encode.java @@ -21,8 +21,7 @@ import edu.umd.cs.findbugs.annotations.NonNull; /** - * Provides new Metapath functions that evaluate a Metapath recursively over - * sequences generated by evaluating that expression. + * Provides a new Metapath function that encodes provided text using base64. */ public final class MpBase64Encode { private static final String NAME = "base64-encode-text"; diff --git a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItem.java b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItem.java index 30df72be6..7cc600e88 100644 --- a/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItem.java +++ b/core/src/main/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItem.java @@ -35,31 +35,63 @@ default IAtomicOrUnionType getType() { return type(); } - static IBase64BinaryItem encode(@NonNull String value) { - return valueOf(MetaschemaDataTypeProvider.BASE64.encodeToByteBuffer(value)); + /** + * Base64 encode the provided string. + *

+ * The provided string is first encoded as a stream of UTF8 bytes. + * + * @param text + * the string to encode + * @return a base64 item representing the encoded data + */ + static IBase64BinaryItem encode(@NonNull String text) { + return valueOf(MetaschemaDataTypeProvider.BASE64.encodeToByteBuffer(text)); } + /** + * Base64 encode the provided bytes. + * + * @param bytes + * the bytes to encode + * @return a base64 item representing the encoded data + */ @NonNull static IBase64BinaryItem encode(@NonNull byte[] bytes) { return valueOf(MetaschemaDataTypeProvider.BASE64.encodeToByteBuffer(bytes)); } + /** + * Base64 encode the bytes from the provided buffer. + * + * @param buffer + * the bytes to encode + * @return a base64 item representing the encoded data + */ @NonNull static IBase64BinaryItem encode(@NonNull ByteBuffer buffer) { return valueOf(MetaschemaDataTypeProvider.BASE64.encodeToByteBuffer(buffer)); } + /** + * Base64 decode this item as a new hex binary item. + * + * @return a new hex binary item containing the decoded bytes + */ default IHexBinaryItem decode() { return IHexBinaryItem.valueOf(MetaschemaDataTypeProvider.BASE64.decode(asByteBuffer())); } + /** + * Base64 decode this item as a string. + * + * @return a new string item containing the decoded text + */ default IStringItem decodeAsString() { return IStringItem.valueOf(MetaschemaDataTypeProvider.BASE64.decodeToString(asBytes())); } /** - * Construct a new base64 byte sequence item using the provided base64 encoded - * string {@code value}. + * Construct a new base64 byte sequence item using the provided base64 encoded string {@code value}. * * @param value * a string representing base64 encoded data @@ -82,12 +114,11 @@ static IBase64BinaryItem valueOf(@NonNull String value) { } /** - * Construct a new URI base64 encoded byte sequence using the provided - * {@link ByteBuffer} {@code value}. + * Construct a new URI base64 encoded byte sequence using the provided {@link ByteBuffer} + * {@code value}. *

- * The provided buffer will be managed by this instance. Make a copy of the - * buffer to ensure that the position, limit, and mark of the original are not - * affect by this. + * The provided buffer will be managed by this instance. Make a copy of the buffer to ensure that + * the position, limit, and mark of the original are not affect by this. * * @param buffer * a byte buffer @@ -103,8 +134,7 @@ static IBase64BinaryItem valueOf(@NonNull ByteBuffer buffer) { * * @param item * the item to cast - * @return the original item if it is already this type, otherwise a new item - * cast to this type + * @return the original item if it is already this type, otherwise a new item cast to this type * @throws InvalidValueForCastFunctionException * if the provided {@code item} cannot be cast to this type */ @@ -135,8 +165,8 @@ default int compareTo(IAnyAtomicItem item) { * * @param item * the item to compare with this value - * @return a negative integer, zero, or a positive integer if this value is less - * than, equal to, or greater than the {@code item}. + * @return a negative integer, zero, or a positive integer if this value is less than, equal to, or + * greater than the {@code item}. */ default int compareTo(@NonNull IBase64BinaryItem item) { return asByteBuffer().compareTo(item.asByteBuffer()); diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/adapter/Base64AdapterTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/adapter/Base64AdapterTest.java new file mode 100644 index 000000000..f23d66826 --- /dev/null +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/datatype/adapter/Base64AdapterTest.java @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: none + * SPDX-License-Identifier: CC0-1.0 + */ + +package gov.nist.secauto.metaschema.core.datatype.adapter; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.nio.ByteBuffer; +import java.util.stream.Stream; + +import edu.umd.cs.findbugs.annotations.NonNull; + +class Base64AdapterTest { + private static Stream provideValuesForEncodeDecode() { + return Stream.of( + Arguments.of("The quick brown fox jumps over the lazy dog", + "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="), + Arguments.of("Mr. Watson, come here, I need you", "TXIuIFdhdHNvbiwgY29tZSBoZXJlLCBJIG5lZWQgeW91"), + Arguments.of( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu luctus lorem. Aliquam malesuada lorem" + + " nisi, ut tincidunt neque feugiat vitae. Fusce pretium nunc ac sapien feugiat accumsan. Proin eget" + + " ligula non turpis laoreet fermentum. Aliquam mi justo, gravida id vulputate id, venenatis eu felis." + + " Vestibulum commodo, magna quis sollicitudin consectetur, eros erat elementum libero, nec euismod" + + " elit arcu non diam. Sed iaculis dui lacus, vitae placerat velit iaculis quis. Sed in ligula in eros" + + " luctus porttitor. Nullam in laoreet leo. Cras sed nisl eget turpis sollicitudin molestie et eget" + + " tellus. Vivamus aliquam odio et dui mattis, in rhoncus mauris hendrerit. Nam viverra mattis risus" + + " non tristique.", + "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gRXRpYW0gZXUgbHVjdHVzIGxvcmVtLi" + + "BBbGlxdWFtIG1hbGVzdWFkYSBsb3JlbSBuaXNpLCB1dCB0aW5jaWR1bnQgbmVxdWUgZmV1Z2lhdCB2aXRhZS4gRnVzY2UgcHJldG" + + "l1bSBudW5jIGFjIHNhcGllbiBmZXVnaWF0IGFjY3Vtc2FuLiBQcm9pbiBlZ2V0IGxpZ3VsYSBub24gdHVycGlzIGxhb3JlZXQgZm" + + "VybWVudHVtLiBBbGlxdWFtIG1pIGp1c3RvLCBncmF2aWRhIGlkIHZ1bHB1dGF0ZSBpZCwgdmVuZW5hdGlzIGV1IGZlbGlzLiBWZX" + + "N0aWJ1bHVtIGNvbW1vZG8sIG1hZ25hIHF1aXMgc29sbGljaXR1ZGluIGNvbnNlY3RldHVyLCBlcm9zIGVyYXQgZWxlbWVudHVtIG" + + "xpYmVybywgbmVjIGV1aXNtb2QgZWxpdCBhcmN1IG5vbiBkaWFtLiBTZWQgaWFjdWxpcyBkdWkgbGFjdXMsIHZpdGFlIHBsYWNlcm" + + "F0IHZlbGl0IGlhY3VsaXMgcXVpcy4gU2VkIGluIGxpZ3VsYSBpbiBlcm9zIGx1Y3R1cyBwb3J0dGl0b3IuIE51bGxhbSBpbiBsYW" + + "9yZWV0IGxlby4gQ3JhcyBzZWQgbmlzbCBlZ2V0IHR1cnBpcyBzb2xsaWNpdHVkaW4gbW9sZXN0aWUgZXQgZWdldCB0ZWxsdXMuIF" + + "ZpdmFtdXMgYWxpcXVhbSBvZGlvIGV0IGR1aSBtYXR0aXMsIGluIHJob25jdXMgbWF1cmlzIGhlbmRyZXJpdC4gTmFtIHZpdmVycm" + + "EgbWF0dGlzIHJpc3VzIG5vbiB0cmlzdGlxdWUu")); + } + + @ParameterizedTest + @MethodSource("provideValuesForEncodeDecode") + void testEncodeDecodeEncode(@NonNull String expectedDecodedString, @NonNull String expectedEncodedString) { + // test encode to buffer + ByteBuffer encodedBuffer = MetaschemaDataTypeProvider.BASE64.encodeToByteBuffer(expectedDecodedString); + encodedBuffer.mark(); + String encodedString = MetaschemaDataTypeProvider.BASE64.asString(encodedBuffer); + assertEquals(expectedEncodedString, encodedString); + + // test decode from buffer + ByteBuffer decodedBuffer = MetaschemaDataTypeProvider.BASE64.decode(encodedBuffer); + decodedBuffer.mark(); + String decodedString = MetaschemaDataTypeProvider.BASE64.asString(decodedBuffer); + assertEquals(expectedDecodedString, decodedString); + } +} diff --git a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItemTest.java b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItemTest.java index dc39268c4..552a3de66 100644 --- a/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItemTest.java +++ b/core/src/test/java/gov/nist/secauto/metaschema/core/metapath/item/atomic/IBase64BinaryItemTest.java @@ -63,8 +63,24 @@ private static Stream provideValuesForEncodeDecode() { "VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZw=="), Arguments.of("Mr. Watson, come here, I need you", "TXIuIFdhdHNvbiwgY29tZSBoZXJlLCBJIG5lZWQgeW91"), Arguments.of( - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu luctus lorem. Aliquam malesuada lorem nisi, ut tincidunt neque feugiat vitae. Fusce pretium nunc ac sapien feugiat accumsan. Proin eget ligula non turpis laoreet fermentum. Aliquam mi justo, gravida id vulputate id, venenatis eu felis. Vestibulum commodo, magna quis sollicitudin consectetur, eros erat elementum libero, nec euismod elit arcu non diam. Sed iaculis dui lacus, vitae placerat velit iaculis quis. Sed in ligula in eros luctus porttitor. Nullam in laoreet leo. Cras sed nisl eget turpis sollicitudin molestie et eget tellus. Vivamus aliquam odio et dui mattis, in rhoncus mauris hendrerit. Nam viverra mattis risus non tristique.", - "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gRXRpYW0gZXUgbHVjdHVzIGxvcmVtLiBBbGlxdWFtIG1hbGVzdWFkYSBsb3JlbSBuaXNpLCB1dCB0aW5jaWR1bnQgbmVxdWUgZmV1Z2lhdCB2aXRhZS4gRnVzY2UgcHJldGl1bSBudW5jIGFjIHNhcGllbiBmZXVnaWF0IGFjY3Vtc2FuLiBQcm9pbiBlZ2V0IGxpZ3VsYSBub24gdHVycGlzIGxhb3JlZXQgZmVybWVudHVtLiBBbGlxdWFtIG1pIGp1c3RvLCBncmF2aWRhIGlkIHZ1bHB1dGF0ZSBpZCwgdmVuZW5hdGlzIGV1IGZlbGlzLiBWZXN0aWJ1bHVtIGNvbW1vZG8sIG1hZ25hIHF1aXMgc29sbGljaXR1ZGluIGNvbnNlY3RldHVyLCBlcm9zIGVyYXQgZWxlbWVudHVtIGxpYmVybywgbmVjIGV1aXNtb2QgZWxpdCBhcmN1IG5vbiBkaWFtLiBTZWQgaWFjdWxpcyBkdWkgbGFjdXMsIHZpdGFlIHBsYWNlcmF0IHZlbGl0IGlhY3VsaXMgcXVpcy4gU2VkIGluIGxpZ3VsYSBpbiBlcm9zIGx1Y3R1cyBwb3J0dGl0b3IuIE51bGxhbSBpbiBsYW9yZWV0IGxlby4gQ3JhcyBzZWQgbmlzbCBlZ2V0IHR1cnBpcyBzb2xsaWNpdHVkaW4gbW9sZXN0aWUgZXQgZWdldCB0ZWxsdXMuIFZpdmFtdXMgYWxpcXVhbSBvZGlvIGV0IGR1aSBtYXR0aXMsIGluIHJob25jdXMgbWF1cmlzIGhlbmRyZXJpdC4gTmFtIHZpdmVycmEgbWF0dGlzIHJpc3VzIG5vbiB0cmlzdGlxdWUu")); + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Etiam eu luctus lorem. Aliquam malesuada lorem" + + " nisi, ut tincidunt neque feugiat vitae. Fusce pretium nunc ac sapien feugiat accumsan. Proin eget" + + " ligula non turpis laoreet fermentum. Aliquam mi justo, gravida id vulputate id, venenatis eu felis." + + " Vestibulum commodo, magna quis sollicitudin consectetur, eros erat elementum libero, nec euismod" + + " elit arcu non diam. Sed iaculis dui lacus, vitae placerat velit iaculis quis. Sed in ligula in eros" + + " luctus porttitor. Nullam in laoreet leo. Cras sed nisl eget turpis sollicitudin molestie et eget" + + " tellus. Vivamus aliquam odio et dui mattis, in rhoncus mauris hendrerit. Nam viverra mattis risus" + + " non tristique.", + "TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gRXRpYW0gZXUgbHVjdHVzIGxvcmVtLi" + + "BBbGlxdWFtIG1hbGVzdWFkYSBsb3JlbSBuaXNpLCB1dCB0aW5jaWR1bnQgbmVxdWUgZmV1Z2lhdCB2aXRhZS4gRnVzY2UgcHJldG" + + "l1bSBudW5jIGFjIHNhcGllbiBmZXVnaWF0IGFjY3Vtc2FuLiBQcm9pbiBlZ2V0IGxpZ3VsYSBub24gdHVycGlzIGxhb3JlZXQgZm" + + "VybWVudHVtLiBBbGlxdWFtIG1pIGp1c3RvLCBncmF2aWRhIGlkIHZ1bHB1dGF0ZSBpZCwgdmVuZW5hdGlzIGV1IGZlbGlzLiBWZX" + + "N0aWJ1bHVtIGNvbW1vZG8sIG1hZ25hIHF1aXMgc29sbGljaXR1ZGluIGNvbnNlY3RldHVyLCBlcm9zIGVyYXQgZWxlbWVudHVtIG" + + "xpYmVybywgbmVjIGV1aXNtb2QgZWxpdCBhcmN1IG5vbiBkaWFtLiBTZWQgaWFjdWxpcyBkdWkgbGFjdXMsIHZpdGFlIHBsYWNlcm" + + "F0IHZlbGl0IGlhY3VsaXMgcXVpcy4gU2VkIGluIGxpZ3VsYSBpbiBlcm9zIGx1Y3R1cyBwb3J0dGl0b3IuIE51bGxhbSBpbiBsYW" + + "9yZWV0IGxlby4gQ3JhcyBzZWQgbmlzbCBlZ2V0IHR1cnBpcyBzb2xsaWNpdHVkaW4gbW9sZXN0aWUgZXQgZWdldCB0ZWxsdXMuIF" + + "ZpdmFtdXMgYWxpcXVhbSBvZGlvIGV0IGR1aSBtYXR0aXMsIGluIHJob25jdXMgbWF1cmlzIGhlbmRyZXJpdC4gTmFtIHZpdmVycm" + + "EgbWF0dGlzIHJpc3VzIG5vbiB0cmlzdGlxdWUu")); } @ParameterizedTest