From e59392ba1874452bde05ee6fa8edfe29fe44490d Mon Sep 17 00:00:00 2001 From: zhan7236 <76658920+zhan7236@users.noreply.github.com> Date: Tue, 23 Dec 2025 06:00:03 +0000 Subject: [PATCH 1/3] feat(java): add xlang tests for Union types - Add StructWithUnionFields class with Union through Union6 fields - Add testStructWithUnionFields() to test Union types as struct fields - Add testTopLevelUnion() to test serializing top-level Union objects - Skip Union tests in GoXlangTest and RustXlangTest (not yet supported) --- .../java/org/apache/fory/GoXlangTest.java | 12 ++ .../java/org/apache/fory/RustXlangTest.java | 12 ++ .../java/org/apache/fory/XlangTestBase.java | 103 ++++++++++++++++++ 3 files changed, 127 insertions(+) diff --git a/java/fory-core/src/test/java/org/apache/fory/GoXlangTest.java b/java/fory-core/src/test/java/org/apache/fory/GoXlangTest.java index efdef16a01..e4e5e17018 100644 --- a/java/fory-core/src/test/java/org/apache/fory/GoXlangTest.java +++ b/java/fory-core/src/test/java/org/apache/fory/GoXlangTest.java @@ -233,4 +233,16 @@ public void testTwoEnumFieldCompatible() throws java.io.IOException { public void testEnumSchemaEvolutionCompatible() throws java.io.IOException { super.testEnumSchemaEvolutionCompatible(); } + + @Test + @Override + public void testStructWithUnionFields() throws java.io.IOException { + throw new SkipException("Union types not yet supported in Go"); + } + + @Test + @Override + public void testTopLevelUnion() throws java.io.IOException { + throw new SkipException("Union types not yet supported in Go"); + } } diff --git a/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java b/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java index 58f09e3770..51ad37553d 100644 --- a/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java +++ b/java/fory-core/src/test/java/org/apache/fory/RustXlangTest.java @@ -86,4 +86,16 @@ protected CommandContext buildCommandContext(String caseName, Path dataFile) { .build(); return new CommandContext(command, env, new File("../../rust")); } + + @Test + @Override + public void testStructWithUnionFields() throws java.io.IOException { + throw new SkipException("Union types not yet supported in Rust"); + } + + @Test + @Override + public void testTopLevelUnion() throws java.io.IOException { + throw new SkipException("Union types not yet supported in Rust"); + } } diff --git a/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java b/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java index 516a9ac9e2..d8bf16da55 100644 --- a/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java +++ b/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java @@ -1575,6 +1575,109 @@ public void testEnumSchemaEvolutionCompatible() throws java.io.IOException { Assert.assertNull(result2.f2); } + // ============================================================================ + // Union type tests + // ============================================================================ + + /** Struct containing Union fields of different arities (Union through Union6). */ + @Data + public static class StructWithUnionFields { + public org.apache.fory.type.union.Union union; + public org.apache.fory.type.union.Union2 union2; + public org.apache.fory.type.union.Union3 union3; + public org.apache.fory.type.union.Union4 union4; + public org.apache.fory.type.union.Union5 union5; + public org.apache.fory.type.union.Union6 union6; + } + + @Test + public void testStructWithUnionFields() throws java.io.IOException { + String caseName = "test_struct_with_union_fields"; + Fory fory = + Fory.builder() + .withLanguage(Language.XLANG) + .withCompatibleMode(CompatibleMode.SCHEMA_CONSISTENT) + .withCodegen(false) + .build(); + fory.register(StructWithUnionFields.class, 200); + + StructWithUnionFields obj = new StructWithUnionFields(); + obj.union = new org.apache.fory.type.union.Union(0, 42); + obj.union2 = org.apache.fory.type.union.Union2.ofT1("hello"); + obj.union3 = org.apache.fory.type.union.Union3.ofT2("world"); + obj.union4 = org.apache.fory.type.union.Union4.ofT3(3.14); + obj.union5 = org.apache.fory.type.union.Union5.ofT4(true); + obj.union6 = org.apache.fory.type.union.Union6.ofT5(999L); + + MemoryBuffer buffer = MemoryUtils.buffer(128); + fory.serialize(buffer, obj); + + ExecutionContext ctx = prepareExecution(caseName, buffer.getBytes(0, buffer.writerIndex())); + runPeer(ctx); + + MemoryBuffer buffer2 = readBuffer(ctx.dataFile()); + StructWithUnionFields result = (StructWithUnionFields) fory.deserialize(buffer2); + + Assert.assertEquals(result.union.getIndex(), 0); + Assert.assertEquals(result.union.getValue(), 42); + Assert.assertEquals(result.union2.getIndex(), 0); + Assert.assertEquals(result.union2.getValue(), "hello"); + Assert.assertTrue(result.union2.isT1()); + Assert.assertEquals(result.union3.getIndex(), 1); + Assert.assertEquals(result.union3.getValue(), "world"); + Assert.assertTrue(result.union3.isT2()); + Assert.assertEquals(result.union4.getIndex(), 2); + Assert.assertEquals((Double) result.union4.getValue(), 3.14, 0.001); + Assert.assertTrue(result.union4.isT3()); + Assert.assertEquals(result.union5.getIndex(), 3); + Assert.assertEquals(result.union5.getValue(), true); + Assert.assertTrue(result.union5.isT4()); + Assert.assertEquals(result.union6.getIndex(), 4); + Assert.assertEquals(result.union6.getValue(), 999L); + Assert.assertTrue(result.union6.isT5()); + } + + @Test + public void testTopLevelUnion() throws java.io.IOException { + String caseName = "test_top_level_union"; + Fory fory = + Fory.builder() + .withLanguage(Language.XLANG) + .withCompatibleMode(CompatibleMode.SCHEMA_CONSISTENT) + .withCodegen(false) + .build(); + + // Test Union with integer value + org.apache.fory.type.union.Union union1 = new org.apache.fory.type.union.Union(0, 42); + MemoryBuffer buffer = MemoryUtils.buffer(64); + fory.serialize(buffer, union1); + + ExecutionContext ctx1 = + prepareExecution(caseName + "_int", buffer.getBytes(0, buffer.writerIndex())); + runPeer(ctx1); + + MemoryBuffer buffer2 = readBuffer(ctx1.dataFile()); + org.apache.fory.type.union.Union result1 = + (org.apache.fory.type.union.Union) fory.deserialize(buffer2); + Assert.assertEquals(result1.getIndex(), 0); + Assert.assertEquals(result1.getValue(), 42); + + // Test Union with string value + org.apache.fory.type.union.Union union2 = new org.apache.fory.type.union.Union(1, "hello"); + buffer = MemoryUtils.buffer(64); + fory.serialize(buffer, union2); + + ExecutionContext ctx2 = + prepareExecution(caseName + "_str", buffer.getBytes(0, buffer.writerIndex())); + runPeer(ctx2); + + MemoryBuffer buffer3 = readBuffer(ctx2.dataFile()); + org.apache.fory.type.union.Union result2 = + (org.apache.fory.type.union.Union) fory.deserialize(buffer3); + Assert.assertEquals(result2.getIndex(), 1); + Assert.assertEquals(result2.getValue(), "hello"); + } + @SuppressWarnings("unchecked") private void assertStringEquals(Object actual, Object expected, boolean useToString) { if (useToString) { From 374576aaf8ce150ef8551397aeb0f28f4b4f7d53 Mon Sep 17 00:00:00 2001 From: zhan7236 <76658920+zhan7236@users.noreply.github.com> Date: Tue, 23 Dec 2025 06:13:37 +0000 Subject: [PATCH 2/3] test(java): skip Union xlang tests for C++ (not yet supported) --- .../src/test/java/org/apache/fory/CPPXlangTest.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/java/fory-core/src/test/java/org/apache/fory/CPPXlangTest.java b/java/fory-core/src/test/java/org/apache/fory/CPPXlangTest.java index 05175abba8..0886d6100f 100644 --- a/java/fory-core/src/test/java/org/apache/fory/CPPXlangTest.java +++ b/java/fory-core/src/test/java/org/apache/fory/CPPXlangTest.java @@ -130,4 +130,16 @@ private void runBazelCommand(String... args) throws IOException { public void testConsistentNamed() throws java.io.IOException { super.testConsistentNamed(); } + + @Test + @Override + public void testStructWithUnionFields() throws java.io.IOException { + throw new SkipException("Union types not yet supported in C++"); + } + + @Test + @Override + public void testTopLevelUnion() throws java.io.IOException { + throw new SkipException("Union types not yet supported in C++"); + } } From b308470d1950911d6e5bdd091a853fb4822885c2 Mon Sep 17 00:00:00 2001 From: zhan7236 <76658920+zhan7236@users.noreply.github.com> Date: Tue, 23 Dec 2025 14:46:41 +0000 Subject: [PATCH 3/3] refactor(java): use imports for Union types instead of qualified class names --- .../java/org/apache/fory/XlangTestBase.java | 40 ++++++++++--------- 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java b/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java index d8bf16da55..6b86a37e32 100644 --- a/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java +++ b/java/fory-core/src/test/java/org/apache/fory/XlangTestBase.java @@ -39,6 +39,12 @@ import org.apache.fory.memory.MemoryUtils; import org.apache.fory.serializer.Serializer; import org.apache.fory.test.TestUtils; +import org.apache.fory.type.union.Union; +import org.apache.fory.type.union.Union2; +import org.apache.fory.type.union.Union3; +import org.apache.fory.type.union.Union4; +import org.apache.fory.type.union.Union5; +import org.apache.fory.type.union.Union6; import org.apache.fory.util.MurmurHash3; import org.testng.Assert; import org.testng.annotations.BeforeClass; @@ -1582,12 +1588,12 @@ public void testEnumSchemaEvolutionCompatible() throws java.io.IOException { /** Struct containing Union fields of different arities (Union through Union6). */ @Data public static class StructWithUnionFields { - public org.apache.fory.type.union.Union union; - public org.apache.fory.type.union.Union2 union2; - public org.apache.fory.type.union.Union3 union3; - public org.apache.fory.type.union.Union4 union4; - public org.apache.fory.type.union.Union5 union5; - public org.apache.fory.type.union.Union6 union6; + public Union union; + public Union2 union2; + public Union3 union3; + public Union4 union4; + public Union5 union5; + public Union6 union6; } @Test @@ -1602,12 +1608,12 @@ public void testStructWithUnionFields() throws java.io.IOException { fory.register(StructWithUnionFields.class, 200); StructWithUnionFields obj = new StructWithUnionFields(); - obj.union = new org.apache.fory.type.union.Union(0, 42); - obj.union2 = org.apache.fory.type.union.Union2.ofT1("hello"); - obj.union3 = org.apache.fory.type.union.Union3.ofT2("world"); - obj.union4 = org.apache.fory.type.union.Union4.ofT3(3.14); - obj.union5 = org.apache.fory.type.union.Union5.ofT4(true); - obj.union6 = org.apache.fory.type.union.Union6.ofT5(999L); + obj.union = new Union(0, 42); + obj.union2 = Union2.ofT1("hello"); + obj.union3 = Union3.ofT2("world"); + obj.union4 = Union4.ofT3(3.14); + obj.union5 = Union5.ofT4(true); + obj.union6 = Union6.ofT5(999L); MemoryBuffer buffer = MemoryUtils.buffer(128); fory.serialize(buffer, obj); @@ -1648,7 +1654,7 @@ public void testTopLevelUnion() throws java.io.IOException { .build(); // Test Union with integer value - org.apache.fory.type.union.Union union1 = new org.apache.fory.type.union.Union(0, 42); + Union union1 = new Union(0, 42); MemoryBuffer buffer = MemoryUtils.buffer(64); fory.serialize(buffer, union1); @@ -1657,13 +1663,12 @@ public void testTopLevelUnion() throws java.io.IOException { runPeer(ctx1); MemoryBuffer buffer2 = readBuffer(ctx1.dataFile()); - org.apache.fory.type.union.Union result1 = - (org.apache.fory.type.union.Union) fory.deserialize(buffer2); + Union result1 = (Union) fory.deserialize(buffer2); Assert.assertEquals(result1.getIndex(), 0); Assert.assertEquals(result1.getValue(), 42); // Test Union with string value - org.apache.fory.type.union.Union union2 = new org.apache.fory.type.union.Union(1, "hello"); + Union union2 = new Union(1, "hello"); buffer = MemoryUtils.buffer(64); fory.serialize(buffer, union2); @@ -1672,8 +1677,7 @@ public void testTopLevelUnion() throws java.io.IOException { runPeer(ctx2); MemoryBuffer buffer3 = readBuffer(ctx2.dataFile()); - org.apache.fory.type.union.Union result2 = - (org.apache.fory.type.union.Union) fory.deserialize(buffer3); + Union result2 = (Union) fory.deserialize(buffer3); Assert.assertEquals(result2.getIndex(), 1); Assert.assertEquals(result2.getValue(), "hello"); }