|
7 | 7 |
|
8 | 8 | import static org.junit.jupiter.api.Assertions.assertEquals; |
9 | 9 | import static org.junit.jupiter.api.Assertions.assertFalse; |
| 10 | +import static org.junit.jupiter.api.Assertions.assertInstanceOf; |
10 | 11 | import static org.junit.jupiter.api.Assertions.assertNotNull; |
11 | 12 | import static org.junit.jupiter.api.Assertions.assertNull; |
12 | 13 | import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively; |
|
48 | 49 | import software.amazon.smithy.java.mcp.test.model.McpEchoInput; |
49 | 50 | import software.amazon.smithy.java.mcp.test.model.McpEchoOutput; |
50 | 51 | import software.amazon.smithy.java.mcp.test.model.Shape; |
| 52 | +import software.amazon.smithy.java.mcp.test.model.TestUnion; |
51 | 53 | import software.amazon.smithy.java.mcp.test.service.CalculateAreaOperation; |
52 | 54 | import software.amazon.smithy.java.mcp.test.service.McpEchoOperation; |
53 | 55 | import software.amazon.smithy.java.mcp.test.service.TestService; |
@@ -1022,6 +1024,170 @@ void testUnionWithNestedOption() { |
1022 | 1024 | assertEquals(77, nested.getMember("innerNumber").asNumber().intValue()); |
1023 | 1025 | } |
1024 | 1026 |
|
| 1027 | + @Test |
| 1028 | + void testUnionInList() { |
| 1029 | + initializeLatestProtocol(); |
| 1030 | + var union1 = Document.of(Map.of("stringOption", Document.of("first"))); |
| 1031 | + var union2 = Document.of(Map.of("integerOption", Document.of(42))); |
| 1032 | + var union3 = Document.of(Map.of("nestedOption", |
| 1033 | + Document.of(Map.of( |
| 1034 | + "innerString", |
| 1035 | + Document.of("nested"), |
| 1036 | + "innerNumber", |
| 1037 | + Document.of(99))))); |
| 1038 | + var unionList = Document.of(List.of(union1, union2, union3)); |
| 1039 | + |
| 1040 | + var echo = echoSingleField("unionList", unionList); |
| 1041 | + var resultList = echo.getMember("unionList").asList(); |
| 1042 | + |
| 1043 | + assertEquals(3, resultList.size()); |
| 1044 | + assertEquals("first", resultList.get(0).getMember("stringOption").asString()); |
| 1045 | + assertEquals(42, resultList.get(1).getMember("integerOption").asNumber().intValue()); |
| 1046 | + assertEquals("nested", resultList.get(2).getMember("nestedOption").getMember("innerString").asString()); |
| 1047 | + |
| 1048 | + // Verify server correctly deserialized unions inside list |
| 1049 | + var lastInputUnionList = echoOperation.getLastInput().getEcho().getUnionList(); |
| 1050 | + assertEquals(3, lastInputUnionList.size()); |
| 1051 | + assertInstanceOf(TestUnion.StringOptionMember.class, lastInputUnionList.get(0)); |
| 1052 | + assertEquals("first", ((TestUnion.StringOptionMember) lastInputUnionList.get(0)).stringOption()); |
| 1053 | + assertInstanceOf(TestUnion.IntegerOptionMember.class, lastInputUnionList.get(1)); |
| 1054 | + assertEquals(42, ((TestUnion.IntegerOptionMember) lastInputUnionList.get(1)).integerOption()); |
| 1055 | + assertInstanceOf(TestUnion.NestedOptionMember.class, lastInputUnionList.get(2)); |
| 1056 | + assertEquals("nested", |
| 1057 | + ((TestUnion.NestedOptionMember) lastInputUnionList.get(2)).nestedOption().getInnerString()); |
| 1058 | + } |
| 1059 | + |
| 1060 | + @Test |
| 1061 | + void testUnionInMap() { |
| 1062 | + initializeLatestProtocol(); |
| 1063 | + var union1 = Document.of(Map.of("stringOption", Document.of("value1"))); |
| 1064 | + var union2 = Document.of(Map.of("integerOption", Document.of(123))); |
| 1065 | + var unionMap = Document.of(Map.of( |
| 1066 | + "key1", |
| 1067 | + union1, |
| 1068 | + "key2", |
| 1069 | + union2)); |
| 1070 | + |
| 1071 | + var echo = echoSingleField("unionMap", unionMap); |
| 1072 | + var resultMap = echo.getMember("unionMap").asStringMap(); |
| 1073 | + |
| 1074 | + assertEquals(2, resultMap.size()); |
| 1075 | + assertEquals("value1", resultMap.get("key1").getMember("stringOption").asString()); |
| 1076 | + assertEquals(123, resultMap.get("key2").getMember("integerOption").asNumber().intValue()); |
| 1077 | + |
| 1078 | + // Verify server correctly deserialized unions inside map |
| 1079 | + var lastInputUnionMap = echoOperation.getLastInput().getEcho().getUnionMap(); |
| 1080 | + assertEquals(2, lastInputUnionMap.size()); |
| 1081 | + assertInstanceOf(TestUnion.StringOptionMember.class, lastInputUnionMap.get("key1")); |
| 1082 | + assertEquals("value1", ((TestUnion.StringOptionMember) lastInputUnionMap.get("key1")).stringOption()); |
| 1083 | + assertInstanceOf(TestUnion.IntegerOptionMember.class, lastInputUnionMap.get("key2")); |
| 1084 | + assertEquals(123, ((TestUnion.IntegerOptionMember) lastInputUnionMap.get("key2")).integerOption()); |
| 1085 | + } |
| 1086 | + |
| 1087 | + // ========== @oneOf Document in Collections Tests ========== |
| 1088 | + |
| 1089 | + @Test |
| 1090 | + void testOneOfDocumentInList() { |
| 1091 | + initializeLatestProtocol(); |
| 1092 | + // Input is in MCP wrapper format: {"circle": {"radius": 5}} |
| 1093 | + var shape1 = Document.of(Map.of("circle", Document.of(Map.of("radius", Document.of(10))))); |
| 1094 | + var shape2 = Document.of(Map.of("square", Document.of(Map.of("side", Document.of(20))))); |
| 1095 | + var shapeList = Document.of(List.of(shape1, shape2)); |
| 1096 | + |
| 1097 | + var echo = echoSingleField("shapeWithOneOfList", shapeList); |
| 1098 | + var resultList = echo.getMember("shapeWithOneOfList").asList(); |
| 1099 | + |
| 1100 | + // Output should be back in MCP wrapper format |
| 1101 | + assertEquals(2, resultList.size()); |
| 1102 | + assertEquals(10, resultList.get(0).getMember("circle").getMember("radius").asNumber().intValue()); |
| 1103 | + assertEquals(20, resultList.get(1).getMember("square").getMember("side").asNumber().intValue()); |
| 1104 | + |
| 1105 | + // Verify server received correctly transformed input (discriminated format internally) |
| 1106 | + var lastInputList = echoOperation.getLastInput().getEcho().getShapeWithOneOfList(); |
| 1107 | + assertEquals(2, lastInputList.size()); |
| 1108 | + // The internal format should have __type discriminator |
| 1109 | + assertEquals("smithy.java.mcp.test#Circle", lastInputList.get(0).getMember("__type").asString()); |
| 1110 | + assertEquals(10, lastInputList.get(0).getMember("radius").asNumber().intValue()); |
| 1111 | + assertEquals("smithy.java.mcp.test#Square", lastInputList.get(1).getMember("__type").asString()); |
| 1112 | + assertEquals(20, lastInputList.get(1).getMember("side").asNumber().intValue()); |
| 1113 | + } |
| 1114 | + |
| 1115 | + @Test |
| 1116 | + void testOneOfDocumentInMap() { |
| 1117 | + initializeLatestProtocol(); |
| 1118 | + var shape1 = Document.of(Map.of("circle", Document.of(Map.of("radius", Document.of(15))))); |
| 1119 | + var shape2 = Document.of(Map.of("rectangle", |
| 1120 | + Document.of(Map.of( |
| 1121 | + "length", |
| 1122 | + Document.of(30), |
| 1123 | + "breadth", |
| 1124 | + Document.of(40))))); |
| 1125 | + var shapeMap = Document.of(Map.of("key1", shape1, "key2", shape2)); |
| 1126 | + |
| 1127 | + var echo = echoSingleField("shapeWithOneOfMap", shapeMap); |
| 1128 | + var resultMap = echo.getMember("shapeWithOneOfMap").asStringMap(); |
| 1129 | + |
| 1130 | + // Output should be back in MCP wrapper format |
| 1131 | + assertEquals(2, resultMap.size()); |
| 1132 | + assertEquals(15, resultMap.get("key1").getMember("circle").getMember("radius").asNumber().intValue()); |
| 1133 | + assertEquals(30, resultMap.get("key2").getMember("rectangle").getMember("length").asNumber().intValue()); |
| 1134 | + |
| 1135 | + // Verify server received correctly transformed input (discriminated format internally) |
| 1136 | + var lastInputMap = echoOperation.getLastInput().getEcho().getShapeWithOneOfMap(); |
| 1137 | + assertEquals(2, lastInputMap.size()); |
| 1138 | + assertEquals("smithy.java.mcp.test#Circle", lastInputMap.get("key1").getMember("__type").asString()); |
| 1139 | + assertEquals(15, lastInputMap.get("key1").getMember("radius").asNumber().intValue()); |
| 1140 | + assertEquals("smithy.java.mcp.test#Rectangle", lastInputMap.get("key2").getMember("__type").asString()); |
| 1141 | + assertEquals(30, lastInputMap.get("key2").getMember("length").asNumber().intValue()); |
| 1142 | + } |
| 1143 | + |
| 1144 | + @Test |
| 1145 | + void testNestedOneOfDocumentInList() { |
| 1146 | + initializeLatestProtocol(); |
| 1147 | + |
| 1148 | + // Circle with nested shapes (list of @oneOf documents) |
| 1149 | + var nestedShape1 = Document.of(Map.of("square", Document.of(Map.of("side", Document.of(10))))); |
| 1150 | + var nestedShape2 = Document.of(Map.of("rectangle", |
| 1151 | + Document.of(Map.of( |
| 1152 | + "length", |
| 1153 | + Document.of(20), |
| 1154 | + "breadth", |
| 1155 | + Document.of(30))))); |
| 1156 | + var nestedShapeList = List.of(nestedShape1, nestedShape2); |
| 1157 | + |
| 1158 | + var circleWithNested = Document.of(Map.of("circleWithNested", |
| 1159 | + Document.of(Map.of( |
| 1160 | + "radius", |
| 1161 | + Document.of(5), |
| 1162 | + "nestedShapes", |
| 1163 | + Document.of(nestedShapeList))))); |
| 1164 | + |
| 1165 | + var echo = echoSingleField("nestedShapeWithOneOf", circleWithNested); |
| 1166 | + |
| 1167 | + // Verify output is back in MCP wrapper format |
| 1168 | + var result = echo.getMember("nestedShapeWithOneOf"); |
| 1169 | + var circleData = result.getMember("circleWithNested"); |
| 1170 | + assertEquals(5, circleData.getMember("radius").asNumber().intValue()); |
| 1171 | + |
| 1172 | + var resultNestedList = circleData.getMember("nestedShapes").asList(); |
| 1173 | + assertEquals(2, resultNestedList.size()); |
| 1174 | + assertEquals(10, resultNestedList.get(0).getMember("square").getMember("side").asNumber().intValue()); |
| 1175 | + assertEquals(20, resultNestedList.get(1).getMember("rectangle").getMember("length").asNumber().intValue()); |
| 1176 | + |
| 1177 | + // Verify server received correctly transformed input (discriminated format) |
| 1178 | + var lastInput = echoOperation.getLastInput().getEcho().getNestedShapeWithOneOf(); |
| 1179 | + assertEquals("smithy.java.mcp.test#CircleWithNested", lastInput.getMember("__type").asString()); |
| 1180 | + assertEquals(5, lastInput.getMember("radius").asNumber().intValue()); |
| 1181 | + |
| 1182 | + // Verify nested shapes were also transformed to discriminated format |
| 1183 | + var lastNestedList = lastInput.getMember("nestedShapes").asList(); |
| 1184 | + assertEquals(2, lastNestedList.size()); |
| 1185 | + assertEquals("smithy.java.mcp.test#Square", lastNestedList.get(0).getMember("__type").asString()); |
| 1186 | + assertEquals(10, lastNestedList.get(0).getMember("side").asNumber().intValue()); |
| 1187 | + assertEquals("smithy.java.mcp.test#Rectangle", lastNestedList.get(1).getMember("__type").asString()); |
| 1188 | + assertEquals(20, lastNestedList.get(1).getMember("length").asNumber().intValue()); |
| 1189 | + } |
| 1190 | + |
1025 | 1191 | // ========== Input Deserialization Verification Tests ========== |
1026 | 1192 |
|
1027 | 1193 | @Test |
|
0 commit comments