diff options
author | Jacob Evans <jacob.evans@10gen.com> | 2019-01-18 19:22:12 -0500 |
---|---|---|
committer | Jacob Evans <jacob.evans@10gen.com> | 2019-01-23 16:43:38 -0500 |
commit | e7b1c689b632610399ab716a98f125605dd8a11c (patch) | |
tree | 649ade121c425d99733c8687e21023000f87ed82 /src | |
parent | 8ab7fe8a562b55b824b130734764a207f26e592d (diff) | |
download | mongo-e7b1c689b632610399ab716a98f125605dd8a11c.tar.gz |
SERVER-39104 Use uint8_t for stitch lib BSON types
Diffstat (limited to 'src')
-rw-r--r-- | src/mongo/embedded/stitch_support/stitch_support.cpp | 63 | ||||
-rw-r--r-- | src/mongo/embedded/stitch_support/stitch_support.h | 26 | ||||
-rw-r--r-- | src/mongo/embedded/stitch_support/stitch_support_test.cpp | 198 |
3 files changed, 159 insertions, 128 deletions
diff --git a/src/mongo/embedded/stitch_support/stitch_support.cpp b/src/mongo/embedded/stitch_support/stitch_support.cpp index c907c4a9d20..15ee4dcbb6f 100644 --- a/src/mongo/embedded/stitch_support/stitch_support.cpp +++ b/src/mongo/embedded/stitch_support/stitch_support.cpp @@ -382,6 +382,22 @@ int capi_status_get_code(const stitch_support_v1_status* const status) noexcept return status->statusImpl.exception_code; } +/** + * toInterfaceType changes the compiler's interpretation from our internal BSON type 'char*' to + * 'uint8_t*' which is the interface type of the Stitch library. + */ +auto toInterfaceType(char* bson) noexcept { + return static_cast<uint8_t*>(static_cast<void*>(bson)); +} + +/** + * fromInterfaceType changes the compiler's interpretation from 'uint8_t*' which is the BSON + * interface type of the Stitch library to our internal type 'char*'. + */ +auto fromInterfaceType(const uint8_t* bson) noexcept { + return static_cast<const char*>(static_cast<const void*>(bson)); +} + } // namespace } // namespace mongo @@ -418,10 +434,12 @@ void MONGO_API_CALL stitch_support_v1_status_destroy(stitch_support_v1_status* c delete status; } -stitch_support_v1_collator* MONGO_API_CALL stitch_support_v1_collator_create( - stitch_support_v1_lib* lib, const char* collationBSON, stitch_support_v1_status* const status) { +stitch_support_v1_collator* MONGO_API_CALL +stitch_support_v1_collator_create(stitch_support_v1_lib* lib, + const uint8_t* collationBSON, + stitch_support_v1_status* const status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj collationSpecExpr(collationBSON); + mongo::BSONObj collationSpecExpr(mongo::fromInterfaceType(collationBSON)); return mongo::collator_create(lib, collationSpecExpr); }); } @@ -433,11 +451,11 @@ void MONGO_API_CALL stitch_support_v1_collator_destroy(stitch_support_v1_collato stitch_support_v1_matcher* MONGO_API_CALL stitch_support_v1_matcher_create(stitch_support_v1_lib* lib, - const char* filterBSON, + const uint8_t* filterBSON, stitch_support_v1_collator* collator, stitch_support_v1_status* const status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj filter(filterBSON); + mongo::BSONObj filter(mongo::fromInterfaceType(filterBSON)); return mongo::matcher_create(lib, filter, collator); }); } @@ -449,12 +467,12 @@ void MONGO_API_CALL stitch_support_v1_matcher_destroy(stitch_support_v1_matcher* stitch_support_v1_projection* MONGO_API_CALL stitch_support_v1_projection_create(stitch_support_v1_lib* lib, - const char* specBSON, + const uint8_t* specBSON, stitch_support_v1_matcher* matcher, stitch_support_v1_collator* collator, stitch_support_v1_status* const status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj spec(specBSON); + mongo::BSONObj spec(mongo::fromInterfaceType(specBSON)); return mongo::projection_create(lib, spec, matcher, collator); }); } @@ -466,21 +484,21 @@ stitch_support_v1_projection_destroy(stitch_support_v1_projection* const project } int MONGO_API_CALL stitch_support_v1_check_match(stitch_support_v1_matcher* matcher, - const char* documentBSON, + const uint8_t* documentBSON, bool* isMatch, stitch_support_v1_status* status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj document(documentBSON); + mongo::BSONObj document(mongo::fromInterfaceType(documentBSON)); *isMatch = matcher->matcher.matches(document, nullptr); }); } -char* MONGO_API_CALL +uint8_t* MONGO_API_CALL stitch_support_v1_projection_apply(stitch_support_v1_projection* const projection, - const char* documentBSON, + const uint8_t* documentBSON, stitch_support_v1_status* status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj document(documentBSON); + mongo::BSONObj document(mongo::fromInterfaceType(documentBSON)); auto outputResult = projection->projectionExec.project(document); auto outputObj = uassertStatusOK(outputResult); @@ -492,21 +510,22 @@ stitch_support_v1_projection_apply(stitch_support_v1_projection* const projectio output); static_cast<void>(std::copy_n(outputObj.objdata(), outputSize, output)); - return output; + return mongo::toInterfaceType(output); }); } stitch_support_v1_update* MONGO_API_CALL stitch_support_v1_update_create(stitch_support_v1_lib* lib, - const char* updateExprBSON, - const char* arrayFiltersBSON, + const uint8_t* updateExprBSON, + const uint8_t* arrayFiltersBSON, stitch_support_v1_matcher* matcher, stitch_support_v1_collator* collator, stitch_support_v1_status* status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj updateExpr(updateExprBSON); + mongo::BSONObj updateExpr(mongo::fromInterfaceType(updateExprBSON)); mongo::BSONArray arrayFilters( - (arrayFiltersBSON ? mongo::BSONObj(arrayFiltersBSON) : mongo::BSONObj())); + (arrayFiltersBSON ? mongo::BSONObj(mongo::fromInterfaceType(arrayFiltersBSON)) + : mongo::BSONObj())); return mongo::update_create(lib, updateExpr, arrayFilters, matcher, collator); }); } @@ -516,13 +535,13 @@ void MONGO_API_CALL stitch_support_v1_update_destroy(stitch_support_v1_update* c static_cast<void>(enterCXX(nullStatus, [=]() { delete update; })); } -char* MONGO_API_CALL +uint8_t* MONGO_API_CALL stitch_support_v1_update_apply(stitch_support_v1_update* const update, - const char* documentBSON, + const uint8_t* documentBSON, stitch_support_v1_update_details* update_details, stitch_support_v1_status* status) { return enterCXX(mongo::getStatusImpl(status), [&]() { - mongo::BSONObj document(documentBSON); + mongo::BSONObj document(mongo::fromInterfaceType(documentBSON)); std::string matchedField; if (update->updateDriver.needMatchDetails()) { @@ -568,7 +587,7 @@ stitch_support_v1_update_apply(stitch_support_v1_update* const update, update_details->modifiedPaths = modifiedPaths.serialize(); } - return output; + return mongo::toInterfaceType(output); }); } @@ -593,7 +612,7 @@ const char* MONGO_API_CALL stitch_support_v1_update_details_path( return update_details->modifiedPaths[path_index].c_str(); } -void MONGO_API_CALL stitch_support_v1_bson_free(char* bson) { +void MONGO_API_CALL stitch_support_v1_bson_free(uint8_t* bson) { mongo::StitchSupportStatusImpl* nullStatus = nullptr; static_cast<void>(enterCXX(nullStatus, [=]() { delete[](bson); })); } diff --git a/src/mongo/embedded/stitch_support/stitch_support.h b/src/mongo/embedded/stitch_support/stitch_support.h index c75dc732820..7e8b2969370 100644 --- a/src/mongo/embedded/stitch_support/stitch_support.h +++ b/src/mongo/embedded/stitch_support/stitch_support.h @@ -247,8 +247,10 @@ typedef struct stitch_support_v1_collator stitch_support_v1_collator; * This function will fail if the collationBSON is invalid. On failure, it returns NULL and * populates the 'status' object if it is not NULL. */ -STITCH_SUPPORT_API stitch_support_v1_collator* MONGO_API_CALL stitch_support_v1_collator_create( - stitch_support_v1_lib* lib, const char* collationBSON, stitch_support_v1_status* const status); +STITCH_SUPPORT_API stitch_support_v1_collator* MONGO_API_CALL +stitch_support_v1_collator_create(stitch_support_v1_lib* lib, + const uint8_t* collationBSON, + stitch_support_v1_status* const status); /** * Destroys a valid stitch_support_v1_collator object. @@ -285,7 +287,7 @@ typedef struct stitch_support_v1_matcher stitch_support_v1_matcher; */ STITCH_SUPPORT_API stitch_support_v1_matcher* MONGO_API_CALL stitch_support_v1_matcher_create(stitch_support_v1_lib* lib, - const char* filterBSON, + const uint8_t* filterBSON, stitch_support_v1_collator* collator, stitch_support_v1_status* status); @@ -316,7 +318,7 @@ stitch_support_v1_matcher_destroy(stitch_support_v1_matcher* const matcher); */ STITCH_SUPPORT_API int MONGO_API_CALL stitch_support_v1_check_match(stitch_support_v1_matcher* matcher, - const char* documentBSON, + const uint8_t* documentBSON, bool* isMatch, stitch_support_v1_status* status); @@ -360,7 +362,7 @@ typedef struct stitch_support_v1_projection stitch_support_v1_projection; */ STITCH_SUPPORT_API stitch_support_v1_projection* MONGO_API_CALL stitch_support_v1_projection_create(stitch_support_v1_lib* lib, - const char* specBSON, + const uint8_t* specBSON, stitch_support_v1_matcher* matcher, stitch_support_v1_collator* collator, stitch_support_v1_status* status); @@ -391,9 +393,9 @@ stitch_support_v1_projection_destroy(stitch_support_v1_projection* const project * that the associated matcher matches the input document. A non-matching input document will * trigger an assertion failure. */ -STITCH_SUPPORT_API char* MONGO_API_CALL +STITCH_SUPPORT_API uint8_t* MONGO_API_CALL stitch_support_v1_projection_apply(stitch_support_v1_projection* const projection, - const char* documentBSON, + const uint8_t* documentBSON, stitch_support_v1_status* status); /** @@ -468,8 +470,8 @@ typedef struct stitch_support_v1_update stitch_support_v1_update; */ STITCH_SUPPORT_API stitch_support_v1_update* MONGO_API_CALL stitch_support_v1_update_create(stitch_support_v1_lib* lib, - const char* updateBSON, - const char* arrayFiltersBSON, + const uint8_t* updateBSON, + const uint8_t* arrayFiltersBSON, stitch_support_v1_matcher* matcher, stitch_support_v1_collator* collator, stitch_support_v1_status* status); @@ -500,9 +502,9 @@ stitch_support_v1_update_destroy(stitch_support_v1_update* const update); * that the associated matcher matches the input document. A non-matching input document will * trigger an assertion failure. */ -STITCH_SUPPORT_API char* MONGO_API_CALL +STITCH_SUPPORT_API uint8_t* MONGO_API_CALL stitch_support_v1_update_apply(stitch_support_v1_update* const update, - const char* documentBSON, + const uint8_t* documentBSON, stitch_support_v1_update_details* update_details, stitch_support_v1_status* status); @@ -513,7 +515,7 @@ stitch_support_v1_update_apply(stitch_support_v1_update* const update, * This function can be called at any time to deallocate a BSON buffer and will not invalidate any * library object. */ -STITCH_SUPPORT_API void MONGO_API_CALL stitch_support_v1_bson_free(char* bson); +STITCH_SUPPORT_API void MONGO_API_CALL stitch_support_v1_bson_free(uint8_t* bson); #ifdef __cplusplus } // extern "C" diff --git a/src/mongo/embedded/stitch_support/stitch_support_test.cpp b/src/mongo/embedded/stitch_support/stitch_support_test.cpp index 456a080799c..a1c3af47886 100644 --- a/src/mongo/embedded/stitch_support/stitch_support_test.cpp +++ b/src/mongo/embedded/stitch_support/stitch_support_test.cpp @@ -41,10 +41,8 @@ namespace { -using mongo::fromjson; using mongo::makeGuard; using mongo::ScopeGuard; -using mongo::tojson; class StitchSupportTest : public mongo::unittest::Test { protected: @@ -71,18 +69,38 @@ protected: updateDetails = nullptr; } + /** + * toBSONForAPI is a custom converter from json which satisfies the unusual uint8_t type that + * stitch_support_v1 uses for BSON. The intermediate BSONObj is also returned since its lifetime + * governs the lifetime of the uint8_t*. + */ + auto toBSONForAPI(const char* json) { + auto bson = mongo::fromjson(json); + return std::make_pair(static_cast<const uint8_t*>(static_cast<const void*>(bson.objdata())), + bson); + } + + /** + * fromBSONForAPI is a custom converter to json which satisfies the unusual uint8_t type that + * stitch_support_v1 uses for BSON. + */ + auto fromBSONForAPI(const uint8_t* bson) { + return mongo::tojson( + mongo::BSONObj(static_cast<const char*>(static_cast<const void*>(bson)))); + } + auto checkMatch(const char* filterJSON, std::vector<const char*> documentsJSON, stitch_support_v1_collator* collator = nullptr) { - auto matcher = stitch_support_v1_matcher_create( - lib, fromjson(filterJSON).objdata(), collator, nullptr); + auto matcher = + stitch_support_v1_matcher_create(lib, toBSONForAPI(filterJSON).first, collator, nullptr); ASSERT(matcher); ON_BLOCK_EXIT([matcher] { stitch_support_v1_matcher_destroy(matcher); }); return std::all_of( documentsJSON.begin(), documentsJSON.end(), [=](const char* documentJSON) { bool isMatch; stitch_support_v1_check_match( - matcher, fromjson(documentJSON).objdata(), &isMatch, nullptr); + matcher, toBSONForAPI(documentJSON).first, &isMatch, nullptr); return isMatch; }); } @@ -92,8 +110,8 @@ protected: stitch_support_v1_collator* collator = nullptr) { auto matchStatus = stitch_support_v1_status_create(); ON_BLOCK_EXIT([matchStatus] { stitch_support_v1_status_destroy(matchStatus); }); - auto matcher = stitch_support_v1_matcher_create( - lib, fromjson(filterJSON).objdata(), collator, matchStatus); + auto matcher = + stitch_support_v1_matcher_create(lib, toBSONForAPI(filterJSON).first, collator, matchStatus); if (matcher) { stitch_support_v1_matcher_destroy(matcher); FAIL("Expected stich_support_v1_matcher_create to fail"); @@ -115,15 +133,15 @@ protected: bool denyProjectionCollator = false) { stitch_support_v1_matcher* matcher = nullptr; if (filterJSON) { - matcher = stitch_support_v1_matcher_create( - lib, fromjson(filterJSON).objdata(), collator, nullptr); + matcher = + stitch_support_v1_matcher_create(lib, toBSONForAPI(filterJSON).first, collator, nullptr); ASSERT(matcher); } ON_BLOCK_EXIT([matcher] { stitch_support_v1_matcher_destroy(matcher); }); auto projection = stitch_support_v1_projection_create(lib, - fromjson(specJSON).objdata(), + toBSONForAPI(specJSON).first, matcher, denyProjectionCollator ? nullptr : collator, nullptr); @@ -136,8 +154,8 @@ protected: std::back_inserter(results), [=](const char* documentJSON) { auto bson = stitch_support_v1_projection_apply( - projection, fromjson(documentJSON).objdata(), nullptr); - auto result = tojson(mongo::BSONObj(bson)); + projection, toBSONForAPI(documentJSON).first, nullptr); + auto result = fromBSONForAPI(bson); stitch_support_v1_bson_free(bson); return result; }); @@ -154,14 +172,14 @@ protected: stitch_support_v1_matcher* matcher = nullptr; if (filterJSON) { - matcher = stitch_support_v1_matcher_create( - lib, fromjson(filterJSON).objdata(), collator, nullptr); + matcher = + stitch_support_v1_matcher_create(lib, toBSONForAPI(filterJSON).first, collator, nullptr); ASSERT(matcher); } ON_BLOCK_EXIT([matcher] { stitch_support_v1_matcher_destroy(matcher); }); auto projection = stitch_support_v1_projection_create( - lib, fromjson(specJSON).objdata(), matcher, collator, projectionStatus); + lib, toBSONForAPI(specJSON).first, matcher, collator, projectionStatus); if (projection) { stitch_support_v1_projection_destroy(projection); FAIL("Expected stich_support_v1_projection_create to fail"); @@ -175,46 +193,43 @@ protected: return std::string(stitch_support_v1_status_get_explanation(projectionStatus)); } - void checkUpdate(const char* expr, + auto checkUpdate(const char* expr, const char* document, - mongo::BSONObj expectedResult, const char* match = nullptr, const char* arrayFilters = nullptr, const char* collatorObj = nullptr) { stitch_support_v1_collator* collator = nullptr; if (collatorObj) { - collator = - stitch_support_v1_collator_create(lib, fromjson(collatorObj).objdata(), nullptr); + collator = stitch_support_v1_collator_create(lib, toBSONForAPI(collatorObj).first, nullptr); } ON_BLOCK_EXIT([collator] { stitch_support_v1_collator_destroy(collator); }); stitch_support_v1_matcher* matcher = nullptr; if (match) { - matcher = - stitch_support_v1_matcher_create(lib, fromjson(match).objdata(), collator, nullptr); + matcher = stitch_support_v1_matcher_create(lib, toBSONForAPI(match).first, collator, nullptr); ASSERT(matcher); } ON_BLOCK_EXIT([matcher] { stitch_support_v1_matcher_destroy(matcher); }); - stitch_support_v1_update* update = stitch_support_v1_update_create( - lib, - fromjson(expr).objdata(), - arrayFilters ? fromjson(arrayFilters).objdata() : nullptr, - matcher, - collator, - status); + stitch_support_v1_update* update = + stitch_support_v1_update_create(lib, + toBSONForAPI(expr).first, + arrayFilters ? toBSONForAPI(arrayFilters).first : nullptr, + matcher, + collator, + status); ASSERT(update); ON_BLOCK_EXIT([update] { stitch_support_v1_update_destroy(update); }); - char* updateResult = stitch_support_v1_update_apply( - update, fromjson(document).objdata(), updateDetails, status); + auto updateResult = + stitch_support_v1_update_apply(update, toBSONForAPI(document).first, updateDetails, status); ASSERT_EQ(0, stitch_support_v1_status_get_code(status)) << stitch_support_v1_status_get_error(status) << ":" << stitch_support_v1_status_get_explanation(status); ASSERT(updateResult); ON_BLOCK_EXIT([updateResult] { stitch_support_v1_bson_free(updateResult); }); - ASSERT_BSONOBJ_EQ(mongo::BSONObj(updateResult), expectedResult); + return std::string(fromBSONForAPI(updateResult)); } auto checkUpdateStatus(const char* expr, @@ -227,26 +242,25 @@ protected: stitch_support_v1_collator* collator = nullptr; if (collatorObj) { - collator = - stitch_support_v1_collator_create(lib, fromjson(collatorObj).objdata(), nullptr); + collator = stitch_support_v1_collator_create(lib, toBSONForAPI(collatorObj).first, nullptr); } ON_BLOCK_EXIT([collator] { stitch_support_v1_collator_destroy(collator); }); stitch_support_v1_matcher* matcher = nullptr; if (match) { - matcher = - stitch_support_v1_matcher_create(lib, fromjson(match).objdata(), collator, nullptr); + matcher = stitch_support_v1_matcher_create(lib, toBSONForAPI(match).first, collator, nullptr); ASSERT(matcher); } ON_BLOCK_EXIT([matcher] { stitch_support_v1_matcher_destroy(matcher); }); - stitch_support_v1_update* update = stitch_support_v1_update_create( - lib, - fromjson(expr).objdata(), - arrayFilters ? fromjson(arrayFilters).objdata() : nullptr, - matcher, - collator, - updateStatus); + stitch_support_v1_update* update = + stitch_support_v1_update_create(lib, + toBSONForAPI(expr).first, + arrayFilters ? toBSONForAPI(arrayFilters).first : nullptr, + matcher, + collator, + updateStatus); + if (!update) { ASSERT_EQ(STITCH_SUPPORT_V1_ERROR_EXCEPTION, stitch_support_v1_status_get_error(updateStatus)); @@ -254,8 +268,8 @@ protected: ASSERT_NE(0, stitch_support_v1_status_get_code(updateStatus)); } else { ON_BLOCK_EXIT([update] { stitch_support_v1_update_destroy(update); }); - char* updateResult = stitch_support_v1_update_apply( - update, fromjson(document).objdata(), updateDetails, updateStatus); + auto updateResult = stitch_support_v1_update_apply( + update, toBSONForAPI(document).first, updateDetails, updateStatus); ASSERT_NE(0, stitch_support_v1_status_get_code(updateStatus)); ASSERT(!updateResult); } @@ -330,7 +344,7 @@ TEST_F(StitchSupportTest, CheckMatchWorksWithStatus) { TEST_F(StitchSupportTest, CheckMatchWorksWithCollation) { auto collator = stitch_support_v1_collator_create( - lib, fromjson("{locale: 'en', strength: 2}").objdata(), nullptr); + lib, toBSONForAPI("{locale: 'en', strength: 2}").first, nullptr); ON_BLOCK_EXIT([collator] { stitch_support_v1_collator_destroy(collator); }); ASSERT_TRUE(checkMatch("{a: 'word'}", {"{a: 'WORD', b: 'other'}"}, collator)); } @@ -364,7 +378,7 @@ TEST_F(StitchSupportTest, CheckProjectionProducesExpectedStatus) { TEST_F(StitchSupportTest, CheckProjectionCollatesRespectfully) { auto collator = stitch_support_v1_collator_create( - lib, fromjson("{locale: 'en', strength: 2}").objdata(), nullptr); + lib, toBSONForAPI("{locale: 'en', strength: 2}").first, nullptr); ON_BLOCK_EXIT([collator] { stitch_support_v1_collator_destroy(collator); }); ASSERT_EQ("{ \"_id\" : 1, \"a\" : [ \"mixEdCaSe\" ] }", checkProjection("{a: {$elemMatch: {$eq: 'MiXedcAse'}}}", @@ -381,81 +395,77 @@ TEST_F(StitchSupportTest, CheckProjectionCollatesRespectfully) { } TEST_F(StitchSupportTest, TestUpdateSingleElement) { - checkUpdate("{$set: {a: 2}}", "{a: 1}", fromjson("{a: 2}")); - ASSERT_EQ(getModifiedPaths(), "[a]"); + ASSERT_EQ("{ \"a\" : 2 }", checkUpdate("{$set: {a: 2}}", "{a: 1}")); + ASSERT_EQ("[a]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestReplacementStyleUpdateReportsNoModifiedPaths) { // Replacement-style updates report no modified paths because this functionality is not // currently needed by Stitch. - checkUpdate("{a: 2}", "{a: 1}", fromjson("{a: 2}")); - ASSERT_EQ(getModifiedPaths(), "[]"); + ASSERT_EQ("{ \"a\" : 2 }", checkUpdate("{a: 2}", "{a: 1}")); + ASSERT_EQ("[]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdateArrayElement) { - checkUpdate("{$set: {'a.0': 2}}", "{a: [1, 2]}", fromjson("{a: [2, 2]}")); - ASSERT_EQ(getModifiedPaths(), "[a.0]"); + ASSERT_EQ("{ \"a\" : [ 2, 2 ] }", checkUpdate("{$set: {'a.0': 2}}", "{a: [1, 2]}")); + ASSERT_EQ("[a.0]", getModifiedPaths()); - checkUpdate("{$set: {'a.0.b': 2}}", "{a: [{b: 1}]}", fromjson("{a: [{b: 2}]}")); - ASSERT_EQ(getModifiedPaths(), "[a.0.b]"); + ASSERT_EQ("{ \"a\" : [ { \"b\" : 2 } ] }", + checkUpdate("{$set: {'a.0.b': 2}}", "{a: [{b: 1}]}")); + ASSERT_EQ("[a.0.b]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdateAddToArray) { - checkUpdate("{$set: {'a.1.b': 2}}", "{a: [{b: 1}]}", fromjson("{a: [{b: 1}, {b: 2}]}")); - ASSERT_EQ(getModifiedPaths(), "[a]"); + ASSERT_EQ("{ \"a\" : [ { \"b\" : 1 }, { \"b\" : 2 } ] }", + checkUpdate("{$set: {'a.1.b': 2}}", "{a: [{b: 1}]}")); + ASSERT_EQ("[a]", getModifiedPaths()); - checkUpdate( - "{$set: {'a.1.b': 2, c: 3}}", "{a: [{b: 1}]}", fromjson("{a: [{b: 1}, {b: 2}], c: 3}")); - ASSERT_EQ(getModifiedPaths(), "[a, c]"); + ASSERT_EQ("{ \"a\" : [ { \"b\" : 1 }, { \"b\" : 2 } ], \"c\" : 3 }", + checkUpdate("{$set: {'a.1.b': 2, c: 3}}", "{a: [{b: 1}]}")); + ASSERT_EQ("[a, c]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdatePullFromArray) { - checkUpdate("{$pull: {'a': 2}}", "{a: [3, 2, 1]}", fromjson("{a: [3, 1]}")); - ASSERT_EQ(getModifiedPaths(), "[a]"); + ASSERT_EQ("{ \"a\" : [ 3, 1 ] }", checkUpdate("{$pull: {'a': 2}}", "{a: [3, 2, 1]}")); + ASSERT_EQ("[a]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestPositionalUpdates) { - checkUpdate("{$set: {'a.$': 3}}", "{a: [1, 2]}", fromjson("{a: [1, 3]}"), "{a: 2}"); - ASSERT_EQ(getModifiedPaths(), "[a.1]"); - - checkUpdate("{$set: {'a.$.b': 3}}", - "{a: [{b: 1}, {b: 2}]}", - fromjson("{a: [{b: 1}, {b: 3}]}"), - "{'a.b': 2}"); - ASSERT_EQ(getModifiedPaths(), "[a.1.b]"); + ASSERT_EQ("{ \"a\" : [ 1, 3 ] }", checkUpdate("{$set: {'a.$': 3}}", "{a: [1, 2]}", "{a: 2}")); + ASSERT_EQ("[a.1]", getModifiedPaths()); + + ASSERT_EQ("{ \"a\" : [ { \"b\" : 1 }, { \"b\" : 3 } ] }", + checkUpdate("{$set: {'a.$.b': 3}}", "{a: [{b: 1}, {b: 2}]}", "{'a.b': 2}")); + ASSERT_EQ("[a.1.b]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdatesWithArrayFilters) { - checkUpdate( - "{$set: {'a.$[i]': 3}}", "{a: [1, 2]}", fromjson("{a: [1, 3]}"), nullptr, "[{'i': 2}]"); - ASSERT_EQ(getModifiedPaths(), "[a.1]"); - - checkUpdate("{$set: {'a.$[i].b': 3}}", - "{a: [{b: 1}, {b: 2}]}", - fromjson("{a: [{b: 1}, {b: 3}]}"), - nullptr, - "[{'i.b': 2}]"); - ASSERT_EQ(getModifiedPaths(), "[a.1.b]"); + ASSERT_EQ("{ \"a\" : [ 1, 3 ] }", + checkUpdate("{$set: {'a.$[i]': 3}}", "{a: [1, 2]}", nullptr, "[{'i': 2}]")); + ASSERT_EQ("[a.1]", getModifiedPaths()); + + ASSERT_EQ( + "{ \"a\" : [ { \"b\" : 1 }, { \"b\" : 3 } ] }", + checkUpdate("{$set: {'a.$[i].b': 3}}", "{a: [{b: 1}, {b: 2}]}", nullptr, "[{'i.b': 2}]")); + ASSERT_EQ("[a.1.b]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdateRespectsTheCollation) { auto caseInsensitive = "{locale: 'en', strength: 2}"; - checkUpdate("{$addToSet: {a: 'santa'}}", - "{a: ['Santa', 'Elf']}", - fromjson("{a: ['Santa', 'Elf']}"), - nullptr, - nullptr, - caseInsensitive); + ASSERT_EQ("{ \"a\" : [ \"Santa\", \"Elf\" ] }", + checkUpdate("{$addToSet: {a: 'santa'}}", + "{a: ['Santa', 'Elf']}", + nullptr, + nullptr, + caseInsensitive)); // $addToSet with existing element is considered a no-op, but the array is marked as modified. - ASSERT_EQ(getModifiedPaths(), "[a]"); - - checkUpdate("{$pull: {a: 'santa'}}", - "{a: ['Santa', 'Elf']}", - fromjson("{a: ['Elf']}"), - nullptr, - nullptr, - caseInsensitive); - ASSERT_EQ(getModifiedPaths(), "[a]"); + ASSERT_EQ("[a]", getModifiedPaths()); + + ASSERT_EQ( + "{ \"a\" : [ \"Elf\" ] }", + checkUpdate( + "{$pull: {a: 'santa'}}", "{a: ['Santa', 'Elf']}", nullptr, nullptr, caseInsensitive)); + ASSERT_EQ("[a]", getModifiedPaths()); } TEST_F(StitchSupportTest, TestUpdateProducesProperStatus) { |