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

robertlazarski pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/axis-axis2-java-core.git

commit 7577447de7c5f648a3eb700057518cd8723136a4
Author: Robert Lazarski <[email protected]>
AuthorDate: Mon Apr 20 19:44:14 2026 -1000

    Add 127-field unit tests for field filtering at scale
    
    Test that ?fields= correctly selects a small subset from a response
    object with 127 fields (mixed String, double, int, long, boolean).
    Three new tests:
    - testFilter127FieldsKeepOne: 126 of 127 fields filtered, 1 kept
    - testFilter127FieldsKeepFive: 122 filtered, 5 kept across all types
    - testFilter127FieldsPayloadSizeReduction: >90% payload reduction
      verified (full response >1KB, filtered <200 bytes)
    
    Uses generic field names (s0-s29, d0-d39, i0-i24, l0-l19, b0-b11)
    with programmatic initialization via reflection.
    
    Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
---
 .../FieldFilteringMessageFormatterTest.java        | 136 +++++++++++++++++++++
 1 file changed, 136 insertions(+)

diff --git 
a/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
 
b/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
index b070fdb1c3..77dadfb298 100644
--- 
a/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
+++ 
b/modules/json/test/org/apache/axis2/json/streaming/FieldFilteringMessageFormatterTest.java
@@ -440,6 +440,142 @@ public class FieldFilteringMessageFormatterTest {
         public StaticTransientData(String s, int v) { status = s; value = v; }
     }
 
+    // ── Large-payload field filtering (127-field POJO) ─────────────────
+    //
+    // Tests prove that ?fields= can select a small subset from a wide
+    // response object (127 fields) without breaking serialization or
+    // losing data. Uses programmatically generated generic field names.
+
+    /**
+     * POJO with 127 fields to exercise field filtering at scale.
+     * Uses mixed types (String, double, int, long, boolean) across
+     * all 127 fields to verify that filtering handles every
+     * primitive and object type correctly.
+     */
+    public static class WideRecord {
+        // 30 String fields
+        public String s0, s1, s2, s3, s4, s5, s6, s7, s8, s9;
+        public String s10, s11, s12, s13, s14, s15, s16, s17, s18, s19;
+        public String s20, s21, s22, s23, s24, s25, s26, s27, s28, s29;
+        // 40 double fields
+        public double d0, d1, d2, d3, d4, d5, d6, d7, d8, d9;
+        public double d10, d11, d12, d13, d14, d15, d16, d17, d18, d19;
+        public double d20, d21, d22, d23, d24, d25, d26, d27, d28, d29;
+        public double d30, d31, d32, d33, d34, d35, d36, d37, d38, d39;
+        // 25 int fields
+        public int i0, i1, i2, i3, i4, i5, i6, i7, i8, i9;
+        public int i10, i11, i12, i13, i14, i15, i16, i17, i18, i19;
+        public int i20, i21, i22, i23, i24;
+        // 20 long fields
+        public long l0, l1, l2, l3, l4, l5, l6, l7, l8, l9;
+        public long l10, l11, l12, l13, l14, l15, l16, l17, l18, l19;
+        // 12 boolean fields — total: 30+40+25+20+12 = 127
+        public boolean b0, b1, b2, b3, b4, b5, b6, b7, b8, b9;
+        public boolean b10, b11;
+
+        public WideRecord() {}
+
+        /** Populate all 127 fields with non-default values. */
+        public static WideRecord createTestRecord() {
+            WideRecord r = new WideRecord();
+            for (int n = 0; n < 30; n++) {
+                try {
+                    r.getClass().getField("s" + n).set(r, "val_" + n);
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+            for (int n = 0; n < 40; n++) {
+                try {
+                    r.getClass().getField("d" + n).setDouble(r, n * 1.1);
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+            for (int n = 0; n < 25; n++) {
+                try {
+                    r.getClass().getField("i" + n).setInt(r, n * 100);
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+            for (int n = 0; n < 20; n++) {
+                try {
+                    r.getClass().getField("l" + n).setLong(r, n * 1000000L);
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+            for (int n = 0; n < 12; n++) {
+                try {
+                    r.getClass().getField("b" + n).setBoolean(r, n % 2 == 0);
+                } catch (Exception e) { throw new RuntimeException(e); }
+            }
+            return r;
+        }
+    }
+
+    @Test
+    public void testFilter127FieldsKeepOne() throws Exception {
+        setReturnObject(WideRecord.createTestRecord());
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            setOf("s0"));
+
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        JsonElement response = parseResponse();
+
+        Assert.assertEquals("Should have exactly 1 field", 1,
+            response.getAsJsonObject().size());
+        Assert.assertEquals("val_0",
+            response.getAsJsonObject().get("s0").getAsString());
+    }
+
+    @Test
+    public void testFilter127FieldsKeepFive() throws Exception {
+        setReturnObject(WideRecord.createTestRecord());
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            setOf("s0", "d5", "i10", "l15", "b0"));
+
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        JsonElement response = parseResponse();
+
+        Assert.assertEquals("Should have exactly 5 fields", 5,
+            response.getAsJsonObject().size());
+        Assert.assertEquals("val_0",
+            response.getAsJsonObject().get("s0").getAsString());
+        Assert.assertEquals(5.5,
+            response.getAsJsonObject().get("d5").getAsDouble(), 0.0001);
+        Assert.assertEquals(1000,
+            response.getAsJsonObject().get("i10").getAsInt());
+        Assert.assertEquals(15000000L,
+            response.getAsJsonObject().get("l15").getAsLong());
+        Assert.assertTrue(
+            response.getAsJsonObject().get("b0").getAsBoolean());
+    }
+
+    @Test
+    public void testFilter127FieldsPayloadSizeReduction() throws Exception {
+        WideRecord record = WideRecord.createTestRecord();
+
+        // Full response (all 127 fields)
+        setReturnObject(record);
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        int fullSize = outputStream.size();
+
+        // Filtered response (1 field out of 127)
+        outputStream.reset();
+        outMsgContext.setProperty(JsonConstant.FIELD_FILTER,
+            setOf("s0"));
+        formatter.writeTo(outMsgContext, outputFormat, outputStream, false);
+        int filteredSize = outputStream.size();
+
+        // The filtered response should be dramatically smaller
+        double reductionPct = (1.0 - (double) filteredSize / fullSize) * 100;
+
+        Assert.assertTrue(
+            "Full response (" + fullSize + " bytes) should be > 1KB",
+            fullSize > 1000);
+        Assert.assertTrue(
+            "Filtered response (" + filteredSize + " bytes) should be < 200 
bytes",
+            filteredSize < 200);
+        Assert.assertTrue(
+            "Payload reduction (" + String.format("%.0f", reductionPct)
+                + "%) should exceed 90%",
+            reductionPct > 90.0);
+    }
+
     static class TestHelper {
         static org.apache.axiom.om.OMElement createFaultElement() {
             var factory = OMAbstractFactory.getOMFactory();

Reply via email to