summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacob Evans <jacob.evans@10gen.com>2019-01-18 19:22:12 -0500
committerJacob Evans <jacob.evans@10gen.com>2019-01-23 16:43:38 -0500
commite7b1c689b632610399ab716a98f125605dd8a11c (patch)
tree649ade121c425d99733c8687e21023000f87ed82
parent8ab7fe8a562b55b824b130734764a207f26e592d (diff)
downloadmongo-e7b1c689b632610399ab716a98f125605dd8a11c.tar.gz
SERVER-39104 Use uint8_t for stitch lib BSON types
-rw-r--r--src/mongo/embedded/stitch_support/stitch_support.cpp63
-rw-r--r--src/mongo/embedded/stitch_support/stitch_support.h26
-rw-r--r--src/mongo/embedded/stitch_support/stitch_support_test.cpp198
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) {