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

garydgregory pushed a commit to branch 1.X
in repository https://gitbox.apache.org/repos/asf/commons-beanutils.git


The following commit(s) were added to refs/heads/1.X by this push:
     new cd7afd96 Sort members
cd7afd96 is described below

commit cd7afd96e0f98f83db61b01483319d911dee6d54
Author: Gary Gregory <[email protected]>
AuthorDate: Thu Jul 30 07:06:28 2026 -0400

    Sort members
---
 .../beanutils/DynaPropertySerializationTest.java   | 450 ++++++++++-----------
 1 file changed, 225 insertions(+), 225 deletions(-)

diff --git 
a/src/test/java/org/apache/commons/beanutils/DynaPropertySerializationTest.java 
b/src/test/java/org/apache/commons/beanutils/DynaPropertySerializationTest.java
index a8dff23a..214ac700 100644
--- 
a/src/test/java/org/apache/commons/beanutils/DynaPropertySerializationTest.java
+++ 
b/src/test/java/org/apache/commons/beanutils/DynaPropertySerializationTest.java
@@ -51,13 +51,17 @@ import org.junit.jupiter.api.Test;
 class DynaPropertySerializationTest {
 
     /**
-     * Serializes {@code prop} to a byte array.
+     * Assert that a round-tripped {@link DynaProperty} is equal to the 
original and is a distinct object.
      */
-    private static byte[] serialize(final DynaProperty prop) throws 
IOException {
-        try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
-            oos.writeObject(prop);
-            return bos.toByteArray();
-        }
+    private static void assertRoundTrip(final DynaProperty original) throws 
IOException, ClassNotFoundException {
+        final DynaProperty copy = roundTrip(original);
+        assertNotNull(copy);
+        assertNotSame(original, copy, "Deserialized instance must be a new 
object");
+        assertEquals(original.getName(), copy.getName(), "name must be 
preserved");
+        assertEquals(original.getType(), copy.getType(), "type must be 
preserved");
+        assertEquals(original.getContentType(), copy.getContentType(), 
"contentType must be preserved");
+        assertEquals(original, copy, "equals() must hold after round-trip");
+        assertEquals(original.hashCode(), copy.hashCode(), "hashCode() must 
hold after round-trip");
     }
 
     /**
@@ -69,6 +73,21 @@ class DynaPropertySerializationTest {
         }
     }
 
+    /**
+     * Returns the byte-offset of the first occurrence of {@code needle} 
inside {@code haystack}, or {@code -1} if not found.
+     */
+    private static int findSequence(final byte[] haystack, final byte[] 
needle) {
+        outer: for (int i = 0; i <= haystack.length - needle.length; i++) {
+            for (int j = 0; j < needle.length; j++) {
+                if (haystack[i + j] != needle[j]) {
+                    continue outer;
+                }
+            }
+            return i;
+        }
+        return -1;
+    }
+
     /**
      * Full round-trip: serialize then deserialize and return the 
reconstructed instance.
      */
@@ -77,38 +96,116 @@ class DynaPropertySerializationTest {
     }
 
     /**
-     * Assert that a round-tripped {@link DynaProperty} is equal to the 
original and is a distinct object.
+     * Serializes {@code prop} to a byte array.
      */
-    private static void assertRoundTrip(final DynaProperty original) throws 
IOException, ClassNotFoundException {
-        final DynaProperty copy = roundTrip(original);
-        assertNotNull(copy);
-        assertNotSame(original, copy, "Deserialized instance must be a new 
object");
-        assertEquals(original.getName(), copy.getName(), "name must be 
preserved");
-        assertEquals(original.getType(), copy.getType(), "type must be 
preserved");
-        assertEquals(original.getContentType(), copy.getContentType(), 
"contentType must be preserved");
-        assertEquals(original, copy, "equals() must hold after round-trip");
-        assertEquals(original.hashCode(), copy.hashCode(), "hashCode() must 
hold after round-trip");
+    private static byte[] serialize(final DynaProperty prop) throws 
IOException {
+        try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); 
ObjectOutputStream oos = new ObjectOutputStream(bos)) {
+            oos.writeObject(prop);
+            return bos.toByteArray();
+        }
     }
 
     @Test
-    void testRoundTripNameOnly() throws Exception {
-        // DynaProperty(String) uses Object.class as the type
-        assertRoundTrip(new DynaProperty("nameOnly"));
+    void testContentTypeIsNullForSimpleProperty() throws Exception {
+        final DynaProperty copy = roundTrip(new DynaProperty("simple", 
String.class));
+        assertNull(copy.getContentType(), "Simple (non-indexed, non-mapped) 
property must have null contentType");
     }
 
     @Test
-    void testRoundTripStringType() throws Exception {
-        assertRoundTrip(new DynaProperty("strProp", String.class));
+    void testIsIndexedPreservedAfterRoundTrip() throws Exception {
+        final DynaProperty indexed = new DynaProperty("idx", List.class, 
String.class);
+        final DynaProperty copy = roundTrip(indexed);
+        assertEquals(indexed.isIndexed(), copy.isIndexed());
     }
 
     @Test
-    void testRoundTripIntegerWrapperType() throws Exception {
-        assertRoundTrip(new DynaProperty("integerProp", Integer.class));
+    void testIsMappedPreservedAfterRoundTrip() throws Exception {
+        final DynaProperty mapped = new DynaProperty("map", Map.class, 
Integer.class);
+        final DynaProperty copy = roundTrip(mapped);
+        assertEquals(mapped.isMapped(), copy.isMapped());
     }
 
     @Test
-    void testRoundTripObjectType() throws Exception {
-        assertRoundTrip(new DynaProperty("objProp", Object.class));
+    void testMultipleSerializationsProduceSameResult() throws Exception {
+        final DynaProperty prop = new DynaProperty("multi", Integer.TYPE);
+        final DynaProperty copy1 = roundTrip(prop);
+        final DynaProperty copy2 = roundTrip(prop);
+        assertEquals(copy1, copy2);
+        assertEquals(copy1.hashCode(), copy2.hashCode());
+    }
+
+    @Test
+    void testNameIsPreservedAfterRoundTrip() throws Exception {
+        final String uniqueName = "uniquePropertyName_42";
+        final DynaProperty copy = roundTrip(new DynaProperty(uniqueName, 
String.class));
+        assertEquals(uniqueName, copy.getName());
+    }
+
+    /**
+     * Variant of the corruption test using a <em>mapped</em> property so that 
the second {@code readAnyClass} call (for contentType) is the one that receives
+     * the bad constant.
+     */
+    @Test
+    void 
testReadObjectThrowsStreamCorruptedExceptionForInvalidContentTypePrimitiveConstant()
 throws Exception {
+        // serialize Map<String, Boolean> vs Map<String, Byte> – the type 
(Map.class)
+        // is written as a non-primitive class object; the contentType is 
written as a
+        // primitive-type constant.
+        final byte[] boolContentBytes = serialize(new 
DynaProperty("corruptContent", Map.class, Boolean.TYPE));
+        final byte[] byteContentBytes = serialize(new 
DynaProperty("corruptContent", Map.class, Byte.TYPE));
+        int diffIndex = -1;
+        for (int i = 0; i < boolContentBytes.length; i++) {
+            if (boolContentBytes[i] != byteContentBytes[i]) {
+                diffIndex = i;
+                break;
+            }
+        }
+        assertNotNull(Integer.valueOf(diffIndex), "Streams must differ at the 
contentType primitive-type int");
+        final byte[] corrupted = boolContentBytes.clone();
+        corrupted[diffIndex - 3] = 0x00;
+        corrupted[diffIndex - 2] = 0x00;
+        corrupted[diffIndex - 1] = 0x00;
+        corrupted[diffIndex] = (byte) 99;
+        final IOException thrown = assertThrows(IOException.class, () -> 
deserialize(corrupted),
+                "Expected StreamCorruptedException for unrecognised primitive 
contentType constant");
+        assertInstanceOf(StreamCorruptedException.class, thrown, "Root cause 
must be StreamCorruptedException");
+    }
+
+    /**
+     * Verifies that {@link DynaProperty#readObject(ObjectInputStream)} throws 
a {@link StreamCorruptedException} when the stream contains an unrecognised
+     * primitive-type constant (i.e. an integer that is not in the range 1–8).
+     * <p>
+     * Strategy: serialize two {@code DynaProperty} instances whose types 
differ only in the primitive-type constant written by {@code writeAnyClass}
+     * (BOOLEAN_TYPE=1 vs BYTE_TYPE=2). Find the first differing byte (the 
last byte of the 4-byte int), then replace those 4 bytes with the invalid 
constant 99
+     * before attempting deserialisation.
+     * </p>
+     */
+    @Test
+    void 
testReadObjectThrowsStreamCorruptedExceptionForInvalidPrimitiveTypeConstant() 
throws Exception {
+        // serialize a DynaProperty whose type is stored as BOOLEAN_TYPE (int 
1)
+        final byte[] booleanBytes = serialize(new DynaProperty("corrupt", 
Boolean.TYPE));
+        // serialize the same name/class but with BYTE_TYPE (int 2) to locate 
the int
+        final byte[] byteBytes = serialize(new DynaProperty("corrupt", 
Byte.TYPE));
+        // The two streams should be identical except for the last byte of the 
4-byte
+        // primitive-type int (0x01 vs 0x02). Find the first (and only) 
differing byte.
+        int diffIndex = -1;
+        for (int i = 0; i < booleanBytes.length; i++) {
+            if (booleanBytes[i] != byteBytes[i]) {
+                diffIndex = i;
+                break;
+            }
+        }
+        assertNotNull(Integer.valueOf(diffIndex), "Streams must differ at the 
primitive-type int");
+        // The 4-byte int starts 3 bytes before the differing byte 
(big-endian).
+        // Overwrite all 4 bytes with the invalid constant 99 (0x00_00_00_63).
+        final byte[] corrupted = booleanBytes.clone();
+        corrupted[diffIndex - 3] = 0x00;
+        corrupted[diffIndex - 2] = 0x00;
+        corrupted[diffIndex - 1] = 0x00;
+        corrupted[diffIndex] = (byte) 99;
+        // Deserialising the corrupted stream must throw 
StreamCorruptedException.
+        final IOException thrown = assertThrows(IOException.class, () -> 
deserialize(corrupted),
+                "Expected StreamCorruptedException for unrecognised 
primitive-type constant");
+        assertInstanceOf(StreamCorruptedException.class, thrown, "Root cause 
must be StreamCorruptedException");
     }
 
     @Test
@@ -127,44 +224,41 @@ class DynaPropertySerializationTest {
     }
 
     @Test
-    void testRoundTripDoublePrimitiveType() throws Exception {
-        assertRoundTrip(new DynaProperty("doubleProp", Double.TYPE));
+    void testRoundTripConcreteListSubtype() throws Exception {
+        // ArrayList also satisfies isIndexed()
+        assertRoundTrip(new DynaProperty("arrayListProp", ArrayList.class, 
String.class));
     }
 
     @Test
-    void testRoundTripFloatPrimitiveType() throws Exception {
-        assertRoundTrip(new DynaProperty("floatProp", Float.TYPE));
+    void testRoundTripConcreteMapSubtype() throws Exception {
+        // HashMap also satisfies isMapped()
+        assertRoundTrip(new DynaProperty("hashMapProp", HashMap.class, 
Double.TYPE));
     }
 
     @Test
-    void testRoundTripIntPrimitiveType() throws Exception {
-        assertRoundTrip(new DynaProperty("intProp", Integer.TYPE));
+    void testRoundTripDoublePrimitiveType() throws Exception {
+        assertRoundTrip(new DynaProperty("doubleProp", Double.TYPE));
     }
 
     @Test
-    void testRoundTripLongPrimitiveType() throws Exception {
-        assertRoundTrip(new DynaProperty("longProp", Long.TYPE));
+    void testRoundTripFloatPrimitiveType() throws Exception {
+        assertRoundTrip(new DynaProperty("floatProp", Float.TYPE));
     }
 
     @Test
-    void testRoundTripShortPrimitiveType() throws Exception {
-        assertRoundTrip(new DynaProperty("shortProp", Short.TYPE));
+    void testRoundTripIntegerWrapperType() throws Exception {
+        assertRoundTrip(new DynaProperty("integerProp", Integer.class));
     }
 
     @Test
-    void testRoundTripObjectArrayType() throws Exception {
-        // String[] – contentType is String.class (non-primitive)
-        assertRoundTrip(new DynaProperty("strArrayProp", String[].class));
+    void testRoundTripIntPrimitiveType() throws Exception {
+        assertRoundTrip(new DynaProperty("intProp", Integer.TYPE));
     }
 
     @Test
-    void testRoundTripPrimitiveArrayType() throws Exception {
-        // int[] – constructor sets contentType = Integer.TYPE (primitive)
-        final DynaProperty prop = new DynaProperty("intArrayProp", 
int[].class);
-        assertRoundTrip(prop);
-        // Verify contentType is correctly restored as the primitive type
-        final DynaProperty copy = roundTrip(prop);
-        assertEquals(Integer.TYPE, copy.getContentType());
+    void testRoundTripListTypeWithExplicitContentType() throws Exception {
+        // List<String> – explicit contentType is an object class
+        assertRoundTrip(new DynaProperty("typedListProp", List.class, 
String.class));
     }
 
     @Test
@@ -173,12 +267,6 @@ class DynaPropertySerializationTest {
         assertRoundTrip(new DynaProperty("listProp", List.class));
     }
 
-    @Test
-    void testRoundTripListTypeWithExplicitContentType() throws Exception {
-        // List<String> – explicit contentType is an object class
-        assertRoundTrip(new DynaProperty("typedListProp", List.class, 
String.class));
-    }
-
     @Test
     void testRoundTripListTypeWithPrimitiveContentType() throws Exception {
         // List<int> – explicit contentType is a primitive type
@@ -186,9 +274,8 @@ class DynaPropertySerializationTest {
     }
 
     @Test
-    void testRoundTripConcreteListSubtype() throws Exception {
-        // ArrayList also satisfies isIndexed()
-        assertRoundTrip(new DynaProperty("arrayListProp", ArrayList.class, 
String.class));
+    void testRoundTripLongPrimitiveType() throws Exception {
+        assertRoundTrip(new DynaProperty("longProp", Long.TYPE));
     }
 
     @Test
@@ -210,61 +297,40 @@ class DynaPropertySerializationTest {
     }
 
     @Test
-    void testRoundTripConcreteMapSubtype() throws Exception {
-        // HashMap also satisfies isMapped()
-        assertRoundTrip(new DynaProperty("hashMapProp", HashMap.class, 
Double.TYPE));
-    }
-
-    @Test
-    void testNameIsPreservedAfterRoundTrip() throws Exception {
-        final String uniqueName = "uniquePropertyName_42";
-        final DynaProperty copy = roundTrip(new DynaProperty(uniqueName, 
String.class));
-        assertEquals(uniqueName, copy.getName());
-    }
-
-    @Test
-    void testTypeIsPreservedAfterRoundTripForEveryPrimitive() throws Exception 
{
-        final Class<?>[] primitives = { Boolean.TYPE, Byte.TYPE, 
Character.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE, Short.TYPE };
-        for (final Class<?> primitive : primitives) {
-            final DynaProperty copy = roundTrip(new DynaProperty("p", 
primitive));
-            assertEquals(primitive, copy.getType(), () -> "type must be 
preserved for primitive " + primitive.getName());
-        }
+    void testRoundTripNameOnly() throws Exception {
+        // DynaProperty(String) uses Object.class as the type
+        assertRoundTrip(new DynaProperty("nameOnly"));
     }
 
     @Test
-    void testContentTypeIsNullForSimpleProperty() throws Exception {
-        final DynaProperty copy = roundTrip(new DynaProperty("simple", 
String.class));
-        assertNull(copy.getContentType(), "Simple (non-indexed, non-mapped) 
property must have null contentType");
+    void testRoundTripObjectArrayType() throws Exception {
+        // String[] – contentType is String.class (non-primitive)
+        assertRoundTrip(new DynaProperty("strArrayProp", String[].class));
     }
 
     @Test
-    void testIsIndexedPreservedAfterRoundTrip() throws Exception {
-        final DynaProperty indexed = new DynaProperty("idx", List.class, 
String.class);
-        final DynaProperty copy = roundTrip(indexed);
-        assertEquals(indexed.isIndexed(), copy.isIndexed());
+    void testRoundTripObjectType() throws Exception {
+        assertRoundTrip(new DynaProperty("objProp", Object.class));
     }
 
     @Test
-    void testIsMappedPreservedAfterRoundTrip() throws Exception {
-        final DynaProperty mapped = new DynaProperty("map", Map.class, 
Integer.class);
-        final DynaProperty copy = roundTrip(mapped);
-        assertEquals(mapped.isMapped(), copy.isMapped());
+    void testRoundTripPrimitiveArrayType() throws Exception {
+        // int[] – constructor sets contentType = Integer.TYPE (primitive)
+        final DynaProperty prop = new DynaProperty("intArrayProp", 
int[].class);
+        assertRoundTrip(prop);
+        // Verify contentType is correctly restored as the primitive type
+        final DynaProperty copy = roundTrip(prop);
+        assertEquals(Integer.TYPE, copy.getContentType());
     }
 
     @Test
-    void testToStringAfterRoundTrip() throws Exception {
-        final DynaProperty original = new DynaProperty("myProp", List.class, 
String.class);
-        final DynaProperty copy = roundTrip(original);
-        assertEquals(original.toString(), copy.toString());
+    void testRoundTripShortPrimitiveType() throws Exception {
+        assertRoundTrip(new DynaProperty("shortProp", Short.TYPE));
     }
 
     @Test
-    void testMultipleSerializationsProduceSameResult() throws Exception {
-        final DynaProperty prop = new DynaProperty("multi", Integer.TYPE);
-        final DynaProperty copy1 = roundTrip(prop);
-        final DynaProperty copy2 = roundTrip(prop);
-        assertEquals(copy1, copy2);
-        assertEquals(copy1.hashCode(), copy2.hashCode());
+    void testRoundTripStringType() throws Exception {
+        assertRoundTrip(new DynaProperty("strProp", String.class));
     }
 
     @Test
@@ -276,129 +342,59 @@ class DynaPropertySerializationTest {
         assertEquals(original, copy2);
     }
 
-    /**
-     * Verifies that {@link DynaProperty#readObject(ObjectInputStream)} throws 
a {@link StreamCorruptedException} when the stream contains an unrecognised
-     * primitive-type constant (i.e. an integer that is not in the range 1–8).
-     * <p>
-     * Strategy: serialize two {@code DynaProperty} instances whose types 
differ only in the primitive-type constant written by {@code writeAnyClass}
-     * (BOOLEAN_TYPE=1 vs BYTE_TYPE=2). Find the first differing byte (the 
last byte of the 4-byte int), then replace those 4 bytes with the invalid 
constant 99
-     * before attempting deserialisation.
-     * </p>
-     */
     @Test
-    void 
testReadObjectThrowsStreamCorruptedExceptionForInvalidPrimitiveTypeConstant() 
throws Exception {
-        // serialize a DynaProperty whose type is stored as BOOLEAN_TYPE (int 
1)
-        final byte[] booleanBytes = serialize(new DynaProperty("corrupt", 
Boolean.TYPE));
-        // serialize the same name/class but with BYTE_TYPE (int 2) to locate 
the int
-        final byte[] byteBytes = serialize(new DynaProperty("corrupt", 
Byte.TYPE));
-        // The two streams should be identical except for the last byte of the 
4-byte
-        // primitive-type int (0x01 vs 0x02). Find the first (and only) 
differing byte.
-        int diffIndex = -1;
-        for (int i = 0; i < booleanBytes.length; i++) {
-            if (booleanBytes[i] != byteBytes[i]) {
-                diffIndex = i;
-                break;
-            }
-        }
-        assertNotNull(Integer.valueOf(diffIndex), "Streams must differ at the 
primitive-type int");
-        // The 4-byte int starts 3 bytes before the differing byte 
(big-endian).
-        // Overwrite all 4 bytes with the invalid constant 99 (0x00_00_00_63).
-        final byte[] corrupted = booleanBytes.clone();
-        corrupted[diffIndex - 3] = 0x00;
-        corrupted[diffIndex - 2] = 0x00;
-        corrupted[diffIndex - 1] = 0x00;
-        corrupted[diffIndex] = (byte) 99;
-        // Deserialising the corrupted stream must throw 
StreamCorruptedException.
-        final IOException thrown = assertThrows(IOException.class, () -> 
deserialize(corrupted),
-                "Expected StreamCorruptedException for unrecognised 
primitive-type constant");
-        assertInstanceOf(StreamCorruptedException.class, thrown, "Root cause 
must be StreamCorruptedException");
+    void testToStringAfterRoundTrip() throws Exception {
+        final DynaProperty original = new DynaProperty("myProp", List.class, 
String.class);
+        final DynaProperty copy = roundTrip(original);
+        assertEquals(original.toString(), copy.toString());
     }
 
-    /**
-     * Variant of the corruption test using a <em>mapped</em> property so that 
the second {@code readAnyClass} call (for contentType) is the one that receives
-     * the bad constant.
-     */
     @Test
-    void 
testReadObjectThrowsStreamCorruptedExceptionForInvalidContentTypePrimitiveConstant()
 throws Exception {
-        // serialize Map<String, Boolean> vs Map<String, Byte> – the type 
(Map.class)
-        // is written as a non-primitive class object; the contentType is 
written as a
-        // primitive-type constant.
-        final byte[] boolContentBytes = serialize(new 
DynaProperty("corruptContent", Map.class, Boolean.TYPE));
-        final byte[] byteContentBytes = serialize(new 
DynaProperty("corruptContent", Map.class, Byte.TYPE));
-        int diffIndex = -1;
-        for (int i = 0; i < boolContentBytes.length; i++) {
-            if (boolContentBytes[i] != byteContentBytes[i]) {
-                diffIndex = i;
-                break;
-            }
-        }
-        assertNotNull(Integer.valueOf(diffIndex), "Streams must differ at the 
contentType primitive-type int");
-        final byte[] corrupted = boolContentBytes.clone();
-        corrupted[diffIndex - 3] = 0x00;
-        corrupted[diffIndex - 2] = 0x00;
-        corrupted[diffIndex - 1] = 0x00;
-        corrupted[diffIndex] = (byte) 99;
-        final IOException thrown = assertThrows(IOException.class, () -> 
deserialize(corrupted),
-                "Expected StreamCorruptedException for unrecognised primitive 
contentType constant");
-        assertInstanceOf(StreamCorruptedException.class, thrown, "Root cause 
must be StreamCorruptedException");
-    }
-
-    /**
-     * Returns the byte-offset of the first occurrence of {@code needle} 
inside {@code haystack}, or {@code -1} if not found.
-     */
-    private static int findSequence(final byte[] haystack, final byte[] 
needle) {
-        outer: for (int i = 0; i <= haystack.length - needle.length; i++) {
-            for (int j = 0; j < needle.length; j++) {
-                if (haystack[i + j] != needle[j]) {
-                    continue outer;
-                }
-            }
-            return i;
+    void testTypeIsPreservedAfterRoundTripForEveryPrimitive() throws Exception 
{
+        final Class<?>[] primitives = { Boolean.TYPE, Byte.TYPE, 
Character.TYPE, Double.TYPE, Float.TYPE, Integer.TYPE, Long.TYPE, Short.TYPE };
+        for (final Class<?> primitive : primitives) {
+            final DynaProperty copy = roundTrip(new DynaProperty("p", 
primitive));
+            assertEquals(primitive, copy.getType(), () -> "type must be 
preserved for primitive " + primitive.getName());
         }
-        return -1;
     }
 
     /**
-     * Proves that {@link DynaProperty#writeObject(ObjectOutputStream)} calls 
{@code writeAnyClass} (which encodes the {@code type} field) <em>before</em>
-     * {@code defaultWriteObject} (which encodes the {@code name} field) for 
<strong>primitive types</strong>.
+     * Proves that for <strong>indexed and mapped properties</strong> the 
second {@code writeAnyClass} call (for {@code contentType}) also appears in the 
byte
+     * stream <em>before</em> the {@code name} field written by {@code 
defaultWriteObject}.
      * <p>
-     * Strategy: serialise two {@link DynaProperty} instances that have an 
identical {@code name} but different primitive types. Because the name is 
identical,
-     * both byte streams are the same from the class-descriptor through to the 
end of the default-field data. The streams diverge only at the
-     * {@code writeAnyClass} output (the primitive-type integer constant). If 
that divergence point is located <em>before</em> the name bytes in the stream, 
it
-     * proves that {@code writeAnyClass} is called first.
+     * Two mapped properties share the same name and the same {@code 
Map.class} type but differ in their {@code contentType} ({@code Boolean.TYPE} vs
+     * {@code Byte.TYPE}). Because the type ({@code Map.class}) is identical, 
the streams are the same through the first {@code writeAnyClass} call. They
+     * diverge at the second {@code writeAnyClass} call (contentType 
constant), which must still precede the name.
      * </p>
      */
     @Test
-    void testWireFormatPrimitiveTypeDataPrecedesNameField() throws Exception {
-        final String sharedName = "sharedPrimitiveName";
-        // Boolean.TYPE encodes as writeBoolean(true) + 
writeInt(BOOLEAN_TYPE=1).
-        // Byte.TYPE encodes as writeBoolean(true) + writeInt(BYTE_TYPE=2).
-        // The two streams are byte-for-byte identical except at the 
primitive-type int.
-        final byte[] boolBytes = serialize(new DynaProperty(sharedName, 
Boolean.TYPE));
-        final byte[] byteBytes = serialize(new DynaProperty(sharedName, 
Byte.TYPE));
-        // Locate the shared name in the boolean-type stream.
+    void testWireFormatContentTypeDataPrecedesNameFieldForMappedProperty() 
throws Exception {
+        final String sharedName = "sharedMappedName";
+        // Both use Map.class as the type (identical first writeAnyClass 
output).
+        // They differ only in contentType: Boolean.TYPE (constant 1) vs 
Byte.TYPE (constant 2).
+        final byte[] boolContentBytes = serialize(new DynaProperty(sharedName, 
Map.class, Boolean.TYPE));
+        final byte[] byteContentBytes = serialize(new DynaProperty(sharedName, 
Map.class, Byte.TYPE));
         final byte[] nameBytes = sharedName.getBytes(StandardCharsets.UTF_8);
-        final int namePosition = findSequence(boolBytes, nameBytes);
-        assertTrue(namePosition > 0, "Property name must be present in the 
serialized stream");
-        // The name must occupy the same position in both streams (identical 
name, identical class).
-        assertEquals(namePosition, findSequence(byteBytes, nameBytes), "Name 
must be at the same byte position in both streams");
-        // Find the first byte where the two streams diverge: this is inside 
the
-        // writeAnyClass output (the primitive-type integer constant differs: 
1 vs 2).
+        final int namePosition = findSequence(boolContentBytes, nameBytes);
+        assertTrue(namePosition > 0, "Name must be present in the serialized 
stream");
+        assertEquals(namePosition, findSequence(byteContentBytes, nameBytes), 
"Name must be at the same byte position in both streams");
+        // The streams are identical up to (and including) the type encoding 
of Map.class.
+        // They diverge at the contentType constant written by the second 
writeAnyClass call.
         int firstDiff = -1;
-        for (int i = 0; i < boolBytes.length; i++) {
-            if (boolBytes[i] != byteBytes[i]) {
+        for (int i = 0; i < boolContentBytes.length; i++) {
+            if (boolContentBytes[i] != byteContentBytes[i]) {
                 firstDiff = i;
                 break;
             }
         }
-        assertTrue(firstDiff >= 0, "Streams must diverge at the primitive-type 
constant");
-        // CRITICAL assertion: the divergence point (type data from 
writeAnyClass) must
-        // come BEFORE the name field (from defaultWriteObject).
-        assertTrue(firstDiff < namePosition, "writeAnyClass must be invoked 
before defaultWriteObject: " + "type-data divergence at byte " + firstDiff
-                + " must precede name field at byte " + namePosition);
-        // Sanity-check: both properties still round-trip correctly.
-        assertRoundTrip(new DynaProperty(sharedName, Boolean.TYPE));
-        assertRoundTrip(new DynaProperty(sharedName, Byte.TYPE));
+        assertTrue(firstDiff >= 0, "Streams must diverge at the contentType 
primitive-type constant");
+        // The second writeAnyClass output (contentType) must still precede 
the name
+        // (defaultWriteObject), confirming that both writeAnyClass calls 
happen before
+        // defaultWriteObject is invoked.
+        assertTrue(firstDiff < namePosition, "The second writeAnyClass call 
(contentType) must precede defaultWriteObject: "
+                + "content-type divergence at byte " + firstDiff + " must 
precede name at byte " + namePosition);
+        assertRoundTrip(new DynaProperty(sharedName, Map.class, Boolean.TYPE));
+        assertRoundTrip(new DynaProperty(sharedName, Map.class, Byte.TYPE));
     }
 
     /**
@@ -444,41 +440,45 @@ class DynaPropertySerializationTest {
     }
 
     /**
-     * Proves that for <strong>indexed and mapped properties</strong> the 
second {@code writeAnyClass} call (for {@code contentType}) also appears in the 
byte
-     * stream <em>before</em> the {@code name} field written by {@code 
defaultWriteObject}.
+     * Proves that {@link DynaProperty#writeObject(ObjectOutputStream)} calls 
{@code writeAnyClass} (which encodes the {@code type} field) <em>before</em>
+     * {@code defaultWriteObject} (which encodes the {@code name} field) for 
<strong>primitive types</strong>.
      * <p>
-     * Two mapped properties share the same name and the same {@code 
Map.class} type but differ in their {@code contentType} ({@code Boolean.TYPE} vs
-     * {@code Byte.TYPE}). Because the type ({@code Map.class}) is identical, 
the streams are the same through the first {@code writeAnyClass} call. They
-     * diverge at the second {@code writeAnyClass} call (contentType 
constant), which must still precede the name.
+     * Strategy: serialise two {@link DynaProperty} instances that have an 
identical {@code name} but different primitive types. Because the name is 
identical,
+     * both byte streams are the same from the class-descriptor through to the 
end of the default-field data. The streams diverge only at the
+     * {@code writeAnyClass} output (the primitive-type integer constant). If 
that divergence point is located <em>before</em> the name bytes in the stream, 
it
+     * proves that {@code writeAnyClass} is called first.
      * </p>
      */
     @Test
-    void testWireFormatContentTypeDataPrecedesNameFieldForMappedProperty() 
throws Exception {
-        final String sharedName = "sharedMappedName";
-        // Both use Map.class as the type (identical first writeAnyClass 
output).
-        // They differ only in contentType: Boolean.TYPE (constant 1) vs 
Byte.TYPE (constant 2).
-        final byte[] boolContentBytes = serialize(new DynaProperty(sharedName, 
Map.class, Boolean.TYPE));
-        final byte[] byteContentBytes = serialize(new DynaProperty(sharedName, 
Map.class, Byte.TYPE));
+    void testWireFormatPrimitiveTypeDataPrecedesNameField() throws Exception {
+        final String sharedName = "sharedPrimitiveName";
+        // Boolean.TYPE encodes as writeBoolean(true) + 
writeInt(BOOLEAN_TYPE=1).
+        // Byte.TYPE encodes as writeBoolean(true) + writeInt(BYTE_TYPE=2).
+        // The two streams are byte-for-byte identical except at the 
primitive-type int.
+        final byte[] boolBytes = serialize(new DynaProperty(sharedName, 
Boolean.TYPE));
+        final byte[] byteBytes = serialize(new DynaProperty(sharedName, 
Byte.TYPE));
+        // Locate the shared name in the boolean-type stream.
         final byte[] nameBytes = sharedName.getBytes(StandardCharsets.UTF_8);
-        final int namePosition = findSequence(boolContentBytes, nameBytes);
-        assertTrue(namePosition > 0, "Name must be present in the serialized 
stream");
-        assertEquals(namePosition, findSequence(byteContentBytes, nameBytes), 
"Name must be at the same byte position in both streams");
-        // The streams are identical up to (and including) the type encoding 
of Map.class.
-        // They diverge at the contentType constant written by the second 
writeAnyClass call.
+        final int namePosition = findSequence(boolBytes, nameBytes);
+        assertTrue(namePosition > 0, "Property name must be present in the 
serialized stream");
+        // The name must occupy the same position in both streams (identical 
name, identical class).
+        assertEquals(namePosition, findSequence(byteBytes, nameBytes), "Name 
must be at the same byte position in both streams");
+        // Find the first byte where the two streams diverge: this is inside 
the
+        // writeAnyClass output (the primitive-type integer constant differs: 
1 vs 2).
         int firstDiff = -1;
-        for (int i = 0; i < boolContentBytes.length; i++) {
-            if (boolContentBytes[i] != byteContentBytes[i]) {
+        for (int i = 0; i < boolBytes.length; i++) {
+            if (boolBytes[i] != byteBytes[i]) {
                 firstDiff = i;
                 break;
             }
         }
-        assertTrue(firstDiff >= 0, "Streams must diverge at the contentType 
primitive-type constant");
-        // The second writeAnyClass output (contentType) must still precede 
the name
-        // (defaultWriteObject), confirming that both writeAnyClass calls 
happen before
-        // defaultWriteObject is invoked.
-        assertTrue(firstDiff < namePosition, "The second writeAnyClass call 
(contentType) must precede defaultWriteObject: "
-                + "content-type divergence at byte " + firstDiff + " must 
precede name at byte " + namePosition);
-        assertRoundTrip(new DynaProperty(sharedName, Map.class, Boolean.TYPE));
-        assertRoundTrip(new DynaProperty(sharedName, Map.class, Byte.TYPE));
+        assertTrue(firstDiff >= 0, "Streams must diverge at the primitive-type 
constant");
+        // CRITICAL assertion: the divergence point (type data from 
writeAnyClass) must
+        // come BEFORE the name field (from defaultWriteObject).
+        assertTrue(firstDiff < namePosition, "writeAnyClass must be invoked 
before defaultWriteObject: " + "type-data divergence at byte " + firstDiff
+                + " must precede name field at byte " + namePosition);
+        // Sanity-check: both properties still round-trip correctly.
+        assertRoundTrip(new DynaProperty(sharedName, Boolean.TYPE));
+        assertRoundTrip(new DynaProperty(sharedName, Byte.TYPE));
     }
 }

Reply via email to