@@ -1618,4 +1618,155 @@ TEST(TypeSystemTest, MatchKind) {
16181618 }
16191619}
16201620
1621+ namespace {
1622+
1623+ // Helper to construct a SerializableTypeSystem with a single
1624+ // SerializableTypeDefinitionEntry from a struct definition.
1625+ SerializableTypeSystem makeSerializableWithStruct (
1626+ Uri uri, SerializableStructDefinition structDef) {
1627+ SerializableTypeDefinitionEntry entry;
1628+ entry.definition ()->set_structDef (std::move (structDef));
1629+
1630+ SerializableTypeSystem sts;
1631+ sts.types ()[std::move (uri)] = std::move (entry);
1632+ return sts;
1633+ }
1634+
1635+ } // namespace
1636+
1637+ TEST (FromSerializableTest, Empty) {
1638+ SerializableTypeSystem sts;
1639+ auto typeSystem = fromSerializable (std::move (sts));
1640+ EXPECT_TRUE (typeSystem->getKnownUris ()->empty ());
1641+ }
1642+
1643+ TEST (FromSerializableTest, SimpleStruct) {
1644+ auto sts = makeSerializableWithStruct (
1645+ " meta.com/test/MyStruct" ,
1646+ def::Struct ({
1647+ def::Field (def::Identity (1 , " field1" ), def::Optional, TypeIds::I32),
1648+ def::Field (
1649+ def::Identity (2 , " field2" ), def::AlwaysPresent, TypeIds::String),
1650+ }));
1651+
1652+ auto typeSystem = fromSerializable (std::move (sts));
1653+
1654+ auto defRef =
1655+ typeSystem->getUserDefinedTypeOrThrow (Uri (" meta.com/test/MyStruct" ));
1656+ EXPECT_TRUE (defRef.isStruct ());
1657+
1658+ const auto & fields = defRef.asStruct ().fields ();
1659+ EXPECT_EQ (fields.size (), 2 );
1660+ EXPECT_EQ (fields[0 ].identity ().name (), " field1" );
1661+ EXPECT_TRUE (fields[0 ].type ().isI32 ());
1662+ EXPECT_EQ (fields[1 ].identity ().name (), " field2" );
1663+ EXPECT_TRUE (fields[1 ].type ().isString ());
1664+ }
1665+
1666+ TEST (FromSerializableTest, MultipleTypesWithReferences) {
1667+ SerializableTypeDefinitionEntry structEntry;
1668+ structEntry.definition ()->set_structDef (
1669+ def::Struct ({
1670+ def::Field (
1671+ def::Identity (1 , " inner" ),
1672+ def::Optional,
1673+ TypeIds::uri (" meta.com/test/InnerUnion" )),
1674+ }));
1675+
1676+ SerializableTypeDefinitionEntry unionEntry;
1677+ unionEntry.definition ()->set_unionDef (
1678+ def::Union ({
1679+ def::Field (def::Identity (1 , " x" ), def::Optional, TypeIds::I64),
1680+ }));
1681+
1682+ SerializableTypeSystem sts;
1683+ sts.types ()[" meta.com/test/OuterStruct" ] = std::move (structEntry);
1684+ sts.types ()[" meta.com/test/InnerUnion" ] = std::move (unionEntry);
1685+
1686+ auto typeSystem = fromSerializable (std::move (sts));
1687+
1688+ auto outerRef =
1689+ typeSystem->getUserDefinedTypeOrThrow (Uri (" meta.com/test/OuterStruct" ));
1690+ EXPECT_TRUE (outerRef.isStruct ());
1691+ EXPECT_EQ (outerRef.asStruct ().fields ().size (), 1 );
1692+
1693+ const auto & innerFieldType = outerRef.asStruct ().fields ()[0 ].type ();
1694+ EXPECT_TRUE (innerFieldType.isUnion ());
1695+
1696+ auto innerRef =
1697+ typeSystem->getUserDefinedTypeOrThrow (Uri (" meta.com/test/InnerUnion" ));
1698+ EXPECT_TRUE (innerRef.isUnion ());
1699+ EXPECT_EQ (innerRef.asUnion ().fields ().size (), 1 );
1700+ EXPECT_TRUE (innerRef.asUnion ().fields ()[0 ].type ().isI64 ());
1701+ }
1702+
1703+ TEST (FromSerializableTest, EnumType) {
1704+ SerializableTypeDefinitionEntry entry;
1705+ entry.definition ()->set_enumDef (
1706+ def::Enum ({{" FOO" , 0 }, {" BAR" , 1 }, {" BAZ" , 2 }}));
1707+
1708+ SerializableTypeSystem sts;
1709+ sts.types ()[" meta.com/test/MyEnum" ] = std::move (entry);
1710+
1711+ auto typeSystem = fromSerializable (std::move (sts));
1712+
1713+ auto defRef =
1714+ typeSystem->getUserDefinedTypeOrThrow (Uri (" meta.com/test/MyEnum" ));
1715+ EXPECT_TRUE (defRef.isEnum ());
1716+ EXPECT_EQ (defRef.asEnum ().values ().size (), 3 );
1717+ EXPECT_EQ (defRef.asEnum ().values ()[0 ].name , " FOO" );
1718+ EXPECT_EQ (defRef.asEnum ().values ()[1 ].i32 , 1 );
1719+ }
1720+
1721+ TEST (FromSerializableTest, EquivalentToBuilderPath) {
1722+ // Build via TypeSystemBuilder directly
1723+ TypeSystemBuilder builder;
1724+ builder.addType (
1725+ " meta.com/test/S" ,
1726+ def::Struct ({
1727+ def::Field (def::Identity (1 , " f" ), def::Optional, TypeIds::Bool),
1728+ }));
1729+ auto fromBuilder = std::move (builder).build ();
1730+
1731+ // Build via fromSerializable
1732+ auto sts = makeSerializableWithStruct (
1733+ " meta.com/test/S" ,
1734+ def::Struct ({
1735+ def::Field (def::Identity (1 , " f" ), def::Optional, TypeIds::Bool),
1736+ }));
1737+ auto fromHelper = fromSerializable (std::move (sts));
1738+
1739+ // Both should produce equivalent TypeSystems
1740+ auto refBuilder =
1741+ fromBuilder->getUserDefinedTypeOrThrow (Uri (" meta.com/test/S" ));
1742+ auto refHelper =
1743+ fromHelper->getUserDefinedTypeOrThrow (Uri (" meta.com/test/S" ));
1744+
1745+ EXPECT_EQ (refBuilder.asStruct ().fields ().size (), 1 );
1746+ EXPECT_EQ (refHelper.asStruct ().fields ().size (), 1 );
1747+ EXPECT_EQ (
1748+ refBuilder.asStruct ().fields ()[0 ].identity ().name (),
1749+ refHelper.asStruct ().fields ()[0 ].identity ().name ());
1750+ EXPECT_EQ (
1751+ refBuilder.asStruct ().fields ()[0 ].type ().kind (),
1752+ refHelper.asStruct ().fields ()[0 ].type ().kind ());
1753+ }
1754+
1755+ TEST (FromSerializableTest, ThrowsOnDuplicateFieldIds) {
1756+ // Constructing a SerializableTypeSystem with a map means URIs are inherently
1757+ // unique in the map itself, but we can verify the builder still validates
1758+ // definitions correctly (e.g. duplicate field IDs within a struct).
1759+ SerializableTypeSystem sts;
1760+
1761+ SerializableTypeDefinitionEntry entry;
1762+ entry.definition ()->set_structDef (
1763+ def::Struct ({
1764+ def::Field (def::Identity (1 , " a" ), def::Optional, TypeIds::I32),
1765+ def::Field (def::Identity (1 , " b" ), def::Optional, TypeIds::I64),
1766+ }));
1767+ sts.types ()[" meta.com/test/BadStruct" ] = std::move (entry);
1768+
1769+ EXPECT_THROW (fromSerializable (std::move (sts)), InvalidTypeError);
1770+ }
1771+
16211772} // namespace apache::thrift::type_system
0 commit comments