summaryrefslogtreecommitdiff
path: root/src/mongo/db/pipeline/aggregation_request_test.cpp
diff options
context:
space:
mode:
authorDavid Storch <david.storch@10gen.com>2017-02-10 11:52:18 -0500
committerDavid Storch <david.storch@10gen.com>2017-03-13 09:46:14 -0400
commit82b16740f8a66093b453a73a04b3b9bd00e5d7a0 (patch)
tree62d156fc9676526ecbea19cd03ef7a293579c4df /src/mongo/db/pipeline/aggregation_request_test.cpp
parent73f9e8b8a8422becf8694fe3d82c0e647dc71189 (diff)
downloadmongo-82b16740f8a66093b453a73a04b3b9bd00e5d7a0.tar.gz
SERVER-19758 add support for "executionStats" and "allPlansExecution" to agg explain
Like other explainable commands, aggregate can now be explained using the explain command, e.g. db.runCommand({explain: {aggregate: ...}, verbosity: "executionStats"}). The existing explain:true flag corresponds to "queryPlanner" mode and is still supported. However, explain:true cannot be specified when explaining aggregate via the explain command. Additional execution information is provided only in the $cursor section of the aggregation explain output. Having aggregation stages themselves track and report execution info is further work.
Diffstat (limited to 'src/mongo/db/pipeline/aggregation_request_test.cpp')
-rw-r--r--src/mongo/db/pipeline/aggregation_request_test.cpp105
1 files changed, 99 insertions, 6 deletions
diff --git a/src/mongo/db/pipeline/aggregation_request_test.cpp b/src/mongo/db/pipeline/aggregation_request_test.cpp
index 45313fc8a1e..a40bca8d8d1 100644
--- a/src/mongo/db/pipeline/aggregation_request_test.cpp
+++ b/src/mongo/db/pipeline/aggregation_request_test.cpp
@@ -58,7 +58,8 @@ TEST(AggregationRequestTest, ShouldParseAllKnownOptions) {
"bypassDocumentValidation: true, collation: {locale: 'en_US'}, cursor: {batchSize: 10}, "
"hint: {a: 1}}");
auto request = unittest::assertGet(AggregationRequest::parseFromBSON(nss, inputBson));
- ASSERT_TRUE(request.isExplain());
+ ASSERT_TRUE(request.getExplain());
+ ASSERT(*request.getExplain() == ExplainOptions::Verbosity::kQueryPlanner);
ASSERT_TRUE(request.shouldAllowDiskUse());
ASSERT_TRUE(request.isFromRouter());
ASSERT_TRUE(request.shouldBypassDocumentValidation());
@@ -69,6 +70,33 @@ TEST(AggregationRequestTest, ShouldParseAllKnownOptions) {
<< "en_US"));
}
+TEST(AggregationRequestTest, ShouldParseExplicitExplainFalseWithCursorOption) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], explain: false, cursor: {batchSize: 10}}");
+ auto request = unittest::assertGet(AggregationRequest::parseFromBSON(nss, inputBson));
+ ASSERT_FALSE(request.getExplain());
+ ASSERT_EQ(request.getBatchSize(), 10);
+}
+
+TEST(AggregationRequestTest, ShouldParseWithSeparateQueryPlannerExplainModeArg) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: []}");
+ auto request = unittest::assertGet(AggregationRequest::parseFromBSON(
+ nss, inputBson, ExplainOptions::Verbosity::kQueryPlanner));
+ ASSERT_TRUE(request.getExplain());
+ ASSERT(*request.getExplain() == ExplainOptions::Verbosity::kQueryPlanner);
+}
+
+TEST(AggregationRequestTest, ShouldParseWithSeparateQueryPlannerExplainModeArgAndCursorOption) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], cursor: {batchSize: 10}}");
+ auto request = unittest::assertGet(
+ AggregationRequest::parseFromBSON(nss, inputBson, ExplainOptions::Verbosity::kExecStats));
+ ASSERT_TRUE(request.getExplain());
+ ASSERT(*request.getExplain() == ExplainOptions::Verbosity::kExecStats);
+ ASSERT_EQ(request.getBatchSize(), 10);
+}
+
//
// Serialization
//
@@ -87,7 +115,7 @@ TEST(AggregationRequestTest, ShouldOnlySerializeRequiredFieldsIfNoOptionalFields
TEST(AggregationRequestTest, ShouldNotSerializeOptionalValuesIfEquivalentToDefault) {
NamespaceString nss("a.collection");
AggregationRequest request(nss, {});
- request.setExplain(false);
+ request.setExplain(boost::none);
request.setAllowDiskUse(false);
request.setFromRouter(false);
request.setBypassDocumentValidation(false);
@@ -104,11 +132,10 @@ TEST(AggregationRequestTest, ShouldNotSerializeOptionalValuesIfEquivalentToDefau
TEST(AggregationRequestTest, ShouldSerializeOptionalValuesIfSet) {
NamespaceString nss("a.collection");
AggregationRequest request(nss, {});
- request.setExplain(true);
request.setAllowDiskUse(true);
request.setFromRouter(true);
request.setBypassDocumentValidation(true);
- request.setBatchSize(10); // batchSize not serialzed when explain is true.
+ request.setBatchSize(10);
const auto hintObj = BSON("a" << 1);
request.setHint(hintObj);
const auto collationObj = BSON("locale"
@@ -118,11 +145,12 @@ TEST(AggregationRequestTest, ShouldSerializeOptionalValuesIfSet) {
auto expectedSerialization =
Document{{AggregationRequest::kCommandName, nss.coll()},
{AggregationRequest::kPipelineName, Value(std::vector<Value>{})},
- {AggregationRequest::kExplainName, true},
{AggregationRequest::kAllowDiskUseName, true},
{AggregationRequest::kFromRouterName, true},
{bypassDocumentValidationCommandOption(), true},
{AggregationRequest::kCollationName, collationObj},
+ {AggregationRequest::kCursorName,
+ Value(Document({{AggregationRequest::kBatchSizeName, 10}}))},
{AggregationRequest::kHintName, hintObj}};
ASSERT_DOCUMENT_EQ(request.serializeToCommandObj(), expectedSerialization);
}
@@ -159,6 +187,18 @@ TEST(AggregationRequestTest, ShouldAcceptHintAsString) {
<< "a_1"));
}
+TEST(AggregationRequestTest, ShouldNotSerializeBatchSizeOrExplainWhenExplainSet) {
+ NamespaceString nss("a.collection");
+ AggregationRequest request(nss, {});
+ request.setBatchSize(10);
+ request.setExplain(ExplainOptions::Verbosity::kQueryPlanner);
+
+ auto expectedSerialization =
+ Document{{AggregationRequest::kCommandName, nss.coll()},
+ {AggregationRequest::kPipelineName, Value(std::vector<Value>{})}};
+ ASSERT_DOCUMENT_EQ(request.serializeToCommandObj(), expectedSerialization);
+}
+
//
// Error cases.
//
@@ -201,13 +241,20 @@ TEST(AggregationRequestTest, ShouldRejectHintAsArray) {
AggregationRequest::parseFromBSON(NamespaceString("a.collection"), inputBson).getStatus());
}
-TEST(AggregationRequestTest, ShouldRejectNonBoolExplain) {
+TEST(AggregationRequestTest, ShouldRejectExplainIfNumber) {
NamespaceString nss("a.collection");
const BSONObj inputBson =
fromjson("{pipeline: [{$match: {a: 'abc'}}], cursor: {}, explain: 1}");
ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
}
+TEST(AggregationRequestTest, ShouldRejectExplainIfObject) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson =
+ fromjson("{pipeline: [{$match: {a: 'abc'}}], cursor: {}, explain: {}}");
+ ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
+}
+
TEST(AggregationRequestTest, ShouldRejectNonBoolFromRouter) {
NamespaceString nss("a.collection");
const BSONObj inputBson =
@@ -228,6 +275,52 @@ TEST(AggregationRequestTest, ShouldRejectNoCursorNoExplain) {
ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
}
+TEST(AggregationRequestTest, ShouldRejectExplainTrueWithSeparateExplainArg) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], explain: true}");
+ ASSERT_NOT_OK(
+ AggregationRequest::parseFromBSON(nss, inputBson, ExplainOptions::Verbosity::kExecStats)
+ .getStatus());
+}
+
+TEST(AggregationRequestTest, ShouldRejectExplainFalseWithSeparateExplainArg) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], explain: false}");
+ ASSERT_NOT_OK(
+ AggregationRequest::parseFromBSON(nss, inputBson, ExplainOptions::Verbosity::kExecStats)
+ .getStatus());
+}
+
+TEST(AggregationRequestTest, ShouldRejectExplainWithReadConcernMajority) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson =
+ fromjson("{pipeline: [], explain: true, readConcern: {level: 'majority'}}");
+ ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
+}
+
+TEST(AggregationRequestTest, ShouldRejectExplainExecStatsVerbosityWithReadConcernMajority) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], readConcern: {level: 'majority'}}");
+ ASSERT_NOT_OK(
+ AggregationRequest::parseFromBSON(nss, inputBson, ExplainOptions::Verbosity::kExecStats)
+ .getStatus());
+}
+
+TEST(AggregationRequestTest, ShouldRejectExplainWithWriteConcernMajority) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson =
+ fromjson("{pipeline: [], explain: true, writeConcern: {w: 'majority'}}");
+ ASSERT_NOT_OK(AggregationRequest::parseFromBSON(nss, inputBson).getStatus());
+}
+
+TEST(AggregationRequestTest, ShouldRejectExplainExecStatsVerbosityWithWriteConcernMajority) {
+ NamespaceString nss("a.collection");
+ const BSONObj inputBson = fromjson("{pipeline: [], writeConcern: {w: 'majority'}}");
+ ASSERT_NOT_OK(
+ AggregationRequest::parseFromBSON(nss, inputBson, ExplainOptions::Verbosity::kExecStats)
+ .getStatus());
+}
+
//
// Ignore fields parsed elsewhere.
//