diff options
Diffstat (limited to 'src/mongo')
-rw-r--r-- | src/mongo/idl/idl_test.cpp | 227 | ||||
-rw-r--r-- | src/mongo/idl/idl_test_types.h | 50 | ||||
-rw-r--r-- | src/mongo/idl/unittest.idl | 74 |
3 files changed, 350 insertions, 1 deletions
diff --git a/src/mongo/idl/idl_test.cpp b/src/mongo/idl/idl_test.cpp index 4f26af506c9..00328d11648 100644 --- a/src/mongo/idl/idl_test.cpp +++ b/src/mongo/idl/idl_test.cpp @@ -227,6 +227,8 @@ TEST(IDLOneTypeTests, TestNamespaceString) { ASSERT_EQUALS(element.type(), String); auto testStruct = One_namespacestring::parse(ctxt, testDoc); + assert_same_types<decltype(testStruct.getValue()), const NamespaceString&>(); + ASSERT_EQUALS(testStruct.getValue(), NamespaceString("foo.bar")); // Positive: Test we can roundtrip from the just parsed document @@ -1084,5 +1086,230 @@ TEST(IDLCustomType, TestDerivedParser) { } } +// Chained type testing +// Check each of types +// Check for round-tripping of fields and documents + +// Positive: demonstrate a class struct chained types +TEST(IDLChainedType, TestChainedType) { + IDLParserErrorContext ctxt("root"); + + auto testDoc = BSON("field1" + << "abc" + << "field2" + << 5); + + auto testStruct = Chained_struct_only::parse(ctxt, testDoc); + + assert_same_types<decltype(testStruct.getChainedType()), const mongo::ChainedType&>(); + assert_same_types<decltype(testStruct.getAnotherChainedType()), + const mongo::AnotherChainedType&>(); + + ASSERT_EQUALS(testStruct.getChainedType().getField1(), "abc"); + ASSERT_EQUALS(testStruct.getAnotherChainedType().getField2(), 5); + + // Positive: Test we can roundtrip from the just parsed document + { + BSONObjBuilder builder; + testStruct.serialize(&builder); + auto loopbackDoc = builder.obj(); + + ASSERT_BSONOBJ_EQ(testDoc, loopbackDoc); + } + + // Positive: Test we can serialize from nothing the same document + { + BSONObjBuilder builder; + Chained_struct_only one_new; + ChainedType ct; + ct.setField1("abc"); + one_new.setChainedType(ct); + AnotherChainedType act; + act.setField2(5); + one_new.setAnotherChainedType(act); + one_new.serialize(&builder); + + auto serializedDoc = builder.obj(); + ASSERT_BSONOBJ_EQ(testDoc, serializedDoc); + } +} + +// Positive: demonstrate a struct with chained types ignoring extra fields +TEST(IDLChainedType, TestExtraFields) { + IDLParserErrorContext ctxt("root"); + + auto testDoc = BSON("field1" + << "abc" + << "field2" + << 5 + << "field3" + << 123456); + + auto testStruct = Chained_struct_only::parse(ctxt, testDoc); + ASSERT_EQUALS(testStruct.getChainedType().getField1(), "abc"); + ASSERT_EQUALS(testStruct.getAnotherChainedType().getField2(), 5); +} + + +// Negative: demonstrate a struct with chained types with duplicate fields +TEST(IDLChainedType, TestDuplicateFields) { + IDLParserErrorContext ctxt("root"); + + auto testDoc = BSON("field1" + << "abc" + << "field2" + << 5 + << "field2" + << 123456); + + ASSERT_THROWS(Chained_struct_only::parse(ctxt, testDoc), UserException); +} + + +// Positive: demonstrate a struct with chained structs +TEST(IDLChainedType, TestChainedStruct) { + IDLParserErrorContext ctxt("root"); + + auto testDoc = BSON("anyField" << 123.456 << "objectField" << BSON("random" + << "pair") + << "field3" + << "abc"); + + auto testStruct = Chained_struct_mixed::parse(ctxt, testDoc); + + assert_same_types<decltype(testStruct.getChained_any_basic_type()), + const Chained_any_basic_type&>(); + assert_same_types<decltype(testStruct.getChained_object_basic_type()), + const Chained_object_basic_type&>(); + + ASSERT_EQUALS(testStruct.getField3(), "abc"); + + // Positive: Test we can roundtrip from the just parsed document + { + BSONObjBuilder builder; + testStruct.serialize(&builder); + auto loopbackDoc = builder.obj(); + + ASSERT_BSONOBJ_EQ(testDoc, loopbackDoc); + } +} + +// Negative: demonstrate a struct with chained structs and extra fields +TEST(IDLChainedType, TestChainedStructWithExtraFields) { + IDLParserErrorContext ctxt("root"); + + // Extra field + { + auto testDoc = BSON("field3" + << "abc" + << "anyField" + << 123.456 + << "objectField" + << BSON("random" + << "pair") + << "extraField" + << 787); + ASSERT_THROWS(Chained_struct_mixed::parse(ctxt, testDoc), UserException); + } + + + // Duplicate any + { + auto testDoc = BSON("field3" + << "abc" + << "anyField" + << 123.456 + << "objectField" + << BSON("random" + << "pair") + << "anyField" + << 787); + ASSERT_THROWS(Chained_struct_mixed::parse(ctxt, testDoc), UserException); + } + + // Duplicate object + { + auto testDoc = BSON("objectField" << BSON("fake" + << "thing") + << "field3" + << "abc" + << "anyField" + << 123.456 + << "objectField" + << BSON("random" + << "pair")); + ASSERT_THROWS(Chained_struct_mixed::parse(ctxt, testDoc), UserException); + } + + // Duplicate field3 + { + auto testDoc = BSON("field3" + << "abc" + << "anyField" + << 123.456 + << "objectField" + << BSON("random" + << "pair") + << "field3" + << "def"); + ASSERT_THROWS(Chained_struct_mixed::parse(ctxt, testDoc), UserException); + } +} + + +// Positive: demonstrate a struct with chained structs and types +TEST(IDLChainedType, TestChainedMixedStruct) { + IDLParserErrorContext ctxt("root"); + + auto testDoc = BSON("field1" + << "abc" + << "field2" + << 5 + << "stringField" + << "def" + << "field3" + << 456); + + auto testStruct = Chained_struct_type_mixed::parse(ctxt, testDoc); + + assert_same_types<decltype(testStruct.getChainedType()), const mongo::ChainedType&>(); + assert_same_types<decltype(testStruct.getAnotherChainedType()), + const mongo::AnotherChainedType&>(); + + ASSERT_EQUALS(testStruct.getChainedType().getField1(), "abc"); + ASSERT_EQUALS(testStruct.getAnotherChainedType().getField2(), 5); + ASSERT_EQUALS(testStruct.getChained_string_basic_type().getStringField(), "def"); + ASSERT_EQUALS(testStruct.getField3(), 456); + + // Positive: Test we can roundtrip from the just parsed document + { + BSONObjBuilder builder; + testStruct.serialize(&builder); + auto loopbackDoc = builder.obj(); + + ASSERT_BSONOBJ_EQ(testDoc, loopbackDoc); + } + + // Positive: Test we can serialize from nothing the same document + { + BSONObjBuilder builder; + Chained_struct_type_mixed one_new; + ChainedType ct; + ct.setField1("abc"); + one_new.setChainedType(ct); + AnotherChainedType act; + act.setField2(5); + one_new.setAnotherChainedType(act); + one_new.setField3(456); + Chained_string_basic_type csbt; + csbt.setStringField("def"); + one_new.setChained_string_basic_type(csbt); + one_new.serialize(&builder); + + auto serializedDoc = builder.obj(); + ASSERT_BSONOBJ_EQ(testDoc, serializedDoc); + } +} + } // namespace } // namespace mongo diff --git a/src/mongo/idl/idl_test_types.h b/src/mongo/idl/idl_test_types.h index 6e03d48b470..44e26c47912 100644 --- a/src/mongo/idl/idl_test_types.h +++ b/src/mongo/idl/idl_test_types.h @@ -113,4 +113,54 @@ private: std::vector<std::uint8_t> _vec; }; +/** + * Simple class that demonstrates the contract a class must implement to parse an IDL "chain" type + * from the IDL parser. + */ +class ChainedType { +public: + static ChainedType parse(const BSONObj& obj) { + ChainedType object; + object._str = obj["field1"].str(); + return object; + } + + void serialize(BSONObjBuilder* builder) const { + builder->append("field1", _str); + } + + StringData getField1() const { + return _str; + } + void setField1(StringData value) { + _str = value.toString(); + } + +private: + std::string _str; +}; + +class AnotherChainedType { +public: + static AnotherChainedType parse(const BSONObj& obj) { + AnotherChainedType object; + object._num = obj["field2"].numberLong(); + return object; + } + + void serialize(BSONObjBuilder* builder) const { + builder->append("field2", _num); + } + + std::int64_t getField2() const { + return _num; + } + void setField2(std::int64_t value) { + _num = value; + } + +private: + std::int64_t _num; +}; + } // namespace mongo diff --git a/src/mongo/idl/unittest.idl b/src/mongo/idl/unittest.idl index 7aecd720ad4..6b6337ed69a 100644 --- a/src/mongo/idl/unittest.idl +++ b/src/mongo/idl/unittest.idl @@ -97,6 +97,27 @@ types: ################################################################################################## # +# Test types used in parser chaining testing +# +################################################################################################## + + ChainedType: + bson_serialization_type: chain + description: "An Chain Type to test chaining" + cpp_type: "mongo::ChainedType" + serializer: mongo::ChainedType::serialize + deserializer: mongo::ChainedType::parse + + AnotherChainedType: + bson_serialization_type: chain + description: "Another Chain Type to test chaining" + cpp_type: "mongo::AnotherChainedType" + serializer: mongo::AnotherChainedType::serialize + deserializer: mongo::AnotherChainedType::parse + + +################################################################################################## +# # Unit test structs for a single value to ensure type validation works correctly # ################################################################################################## @@ -368,4 +389,55 @@ structs: field6o: type: array<one_string> optional: true -# + +################################################################################################## +# +# Test Chained Types +# +################################################################################################## + + chained_string_basic_type: + description: Base struct type for a chained string + strict: false + fields: + stringField: string + + chained_any_basic_type: + description: Base struct type for a chained any + strict: false + fields: + anyField: any_basic_type + + chained_object_basic_type: + description: Base struct type for a chained object + strict: false + fields: + objectField: object_basic_type + + chained_struct_only: + description: UnitTest for chained struct with only chained types + strict: false + chained_types: + - ChainedType + - AnotherChainedType + + chained_struct_mixed: + description: Chained struct with chained structs and fields + strict: true + chained_structs: + - chained_any_basic_type + - chained_object_basic_type + fields: + field3: string + + chained_struct_type_mixed: + description: Chained struct with chained types, structs, and fields + strict: false + chained_types: + - ChainedType + - AnotherChainedType + chained_structs: + - chained_string_basic_type + fields: + field3: + type: int |