summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWaley Chen <waleycz@gmail.com>2016-05-17 14:05:13 -0400
committerWaley Chen <waleycz@gmail.com>2016-05-17 17:27:12 -0400
commit51ee6f1952addc650b1c719cce51fcf460e6e9e8 (patch)
tree426840377be5d2b698678f009f8328e57a89d40c /src
parent44abb8db32a6fad705854793e397961dfc72d09e (diff)
downloadmongo-51ee6f1952addc650b1c719cce51fcf460e6e9e8.tar.gz
SERVER-23243 Replace Listener::getElapsedTimeMillis() in scoped_timer.cpp
Diffstat (limited to 'src')
-rw-r--r--src/mongo/db/exec/SConscript2
-rw-r--r--src/mongo/db/exec/cached_plan.cpp2
-rw-r--r--src/mongo/db/exec/multi_plan.cpp2
-rw-r--r--src/mongo/db/exec/plan_stage.cpp9
-rw-r--r--src/mongo/db/exec/plan_stage.h5
-rw-r--r--src/mongo/db/exec/queued_data_stage_test.cpp38
-rw-r--r--src/mongo/db/exec/scoped_timer.cpp9
-rw-r--r--src/mongo/db/exec/scoped_timer.h12
-rw-r--r--src/mongo/db/exec/sort_test.cpp244
-rw-r--r--src/mongo/db/exec/subplan.cpp2
-rw-r--r--src/mongo/db/pipeline/document_source_test.cpp2
-rw-r--r--src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp6
-rw-r--r--src/mongo/db/storage/mmap_v1/dur_journal.cpp1
-rw-r--r--src/mongo/dbtests/plan_ranking.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_cached_plan.cpp8
-rw-r--r--src/mongo/dbtests/query_stage_ensure_sorted.cpp162
-rw-r--r--src/mongo/dbtests/query_stage_limit_skip.cpp14
-rw-r--r--src/mongo/dbtests/query_stage_multiplan.cpp6
-rw-r--r--src/mongo/dbtests/query_stage_near.cpp20
-rw-r--r--src/mongo/dbtests/query_stage_subplan.cpp15
20 files changed, 327 insertions, 238 deletions
diff --git a/src/mongo/db/exec/SConscript b/src/mongo/db/exec/SConscript
index 931ea2abbd1..e54f69b82d7 100644
--- a/src/mongo/db/exec/SConscript
+++ b/src/mongo/db/exec/SConscript
@@ -112,6 +112,7 @@ env.CppUnitTest(
"exec",
"$BUILD_DIR/mongo/db/serveronly",
"$BUILD_DIR/mongo/dbtests/mocklib",
+ "$BUILD_DIR/mongo/util/clock_source_mock",
"$BUILD_DIR/mongo/util/ntservice_mock",
],
NO_CRUTCH = True,
@@ -127,6 +128,7 @@ env.CppUnitTest(
"$BUILD_DIR/mongo/db/serveronly",
"$BUILD_DIR/mongo/dbtests/mocklib",
"$BUILD_DIR/mongo/db/query/collation/collator_interface_mock",
+ "$BUILD_DIR/mongo/util/clock_source_mock",
"$BUILD_DIR/mongo/util/ntservice_mock",
],
NO_CRUTCH = True,
diff --git a/src/mongo/db/exec/cached_plan.cpp b/src/mongo/db/exec/cached_plan.cpp
index 7604d5ce465..3425a2562b5 100644
--- a/src/mongo/db/exec/cached_plan.cpp
+++ b/src/mongo/db/exec/cached_plan.cpp
@@ -74,7 +74,7 @@ Status CachedPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// execution work that happens here, so this is needed for the time accounting to
// make sense.
- ScopedTimer timer(&_commonStats.executionTimeMillis);
+ ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
// If we work this many times during the trial period, then we will replan the
// query from scratch.
diff --git a/src/mongo/db/exec/multi_plan.cpp b/src/mongo/db/exec/multi_plan.cpp
index 95c70b47ce0..c57e0a5f02f 100644
--- a/src/mongo/db/exec/multi_plan.cpp
+++ b/src/mongo/db/exec/multi_plan.cpp
@@ -203,7 +203,7 @@ Status MultiPlanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// execution work that happens here, so this is needed for the time accounting to
// make sense.
- ScopedTimer timer(&_commonStats.executionTimeMillis);
+ ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
size_t numWorks = getTrialPeriodWorks(getOpCtx(), _collection);
size_t numResults = getTrialPeriodNumToReturn(*_query);
diff --git a/src/mongo/db/exec/plan_stage.cpp b/src/mongo/db/exec/plan_stage.cpp
index c81679bd8cb..13062fa919f 100644
--- a/src/mongo/db/exec/plan_stage.cpp
+++ b/src/mongo/db/exec/plan_stage.cpp
@@ -33,11 +33,14 @@
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/exec/scoped_timer.h"
+#include "mongo/db/operation_context.h"
+#include "mongo/db/service_context.h"
namespace mongo {
PlanStage::StageState PlanStage::work(WorkingSetID* out) {
- ScopedTimer timer(&_commonStats.executionTimeMillis);
+ invariant(_opCtx);
+ ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
++_commonStats.works;
StageState workResult = doWork(out);
@@ -102,4 +105,8 @@ void PlanStage::reattachToOperationContext(OperationContext* opCtx) {
doReattachToOperationContext();
}
+ClockSource* PlanStage::getClock() const {
+ return _opCtx->getServiceContext()->getFastClockSource();
+}
+
} // namespace mongo
diff --git a/src/mongo/db/exec/plan_stage.h b/src/mongo/db/exec/plan_stage.h
index 3ad007c8430..c0afd992e72 100644
--- a/src/mongo/db/exec/plan_stage.h
+++ b/src/mongo/db/exec/plan_stage.h
@@ -37,9 +37,10 @@
namespace mongo {
+class ClockSource;
class Collection;
-class RecordId;
class OperationContext;
+class RecordId;
/**
* A PlanStage ("stage") is the basic building block of a "Query Execution Plan." A stage is
@@ -357,6 +358,8 @@ protected:
*/
virtual void doInvalidate(OperationContext* txn, const RecordId& dl, InvalidationType type) {}
+ ClockSource* getClock() const;
+
OperationContext* getOpCtx() const {
return _opCtx;
}
diff --git a/src/mongo/db/exec/queued_data_stage_test.cpp b/src/mongo/db/exec/queued_data_stage_test.cpp
index e26d303a833..26f41ca4c8c 100644
--- a/src/mongo/db/exec/queued_data_stage_test.cpp
+++ b/src/mongo/db/exec/queued_data_stage_test.cpp
@@ -32,8 +32,12 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/exec/working_set.h"
+#include "mongo/db/operation_context_noop.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/service_context_noop.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/clock_source_mock.h"
using namespace mongo;
@@ -42,12 +46,38 @@ namespace {
using std::unique_ptr;
using stdx::make_unique;
+class QueuedDataStageTest : public unittest::Test {
+public:
+ QueuedDataStageTest() {
+ _service = stdx::make_unique<ServiceContextNoop>();
+ _client = _service.get()->makeClient("test");
+ _opCtxNoop.reset(new OperationContextNoop(_client.get(), 0));
+ _opCtx = _opCtxNoop.get();
+ }
+
+protected:
+ OperationContext* getOpCtx() {
+ return _opCtx;
+ }
+
+private:
+ OperationContext* _opCtx;
+ std::unique_ptr<OperationContextNoop> _opCtxNoop;
+
+ std::unique_ptr<ServiceContextNoop> _service;
+
+ // UniqueClient is declared after ServiceContextNoop because
+ // members of a class are destroyed in reverse order of declaration and
+ // UniqueClient must be destroyed before the ServiceContextNoop is destroyed.
+ ServiceContext::UniqueClient _client;
+};
+
//
// Basic test that we get out valid stats objects.
//
-TEST(QueuedDataStageTest, getValidStats) {
+TEST_F(QueuedDataStageTest, getValidStats) {
WorkingSet ws;
- auto mock = make_unique<QueuedDataStage>(nullptr, &ws);
+ auto mock = make_unique<QueuedDataStage>(getOpCtx(), &ws);
const CommonStats* commonStats = mock->getCommonStats();
ASSERT_EQUALS(commonStats->works, static_cast<size_t>(0));
const SpecificStats* specificStats = mock->getSpecificStats();
@@ -59,10 +89,10 @@ TEST(QueuedDataStageTest, getValidStats) {
//
// Test that our stats are updated as we perform operations.
//
-TEST(QueuedDataStageTest, validateStats) {
+TEST_F(QueuedDataStageTest, validateStats) {
WorkingSet ws;
WorkingSetID wsID;
- auto mock = make_unique<QueuedDataStage>(nullptr, &ws);
+ auto mock = make_unique<QueuedDataStage>(getOpCtx(), &ws);
// make sure that we're at all zero
const CommonStats* stats = mock->getCommonStats();
diff --git a/src/mongo/db/exec/scoped_timer.cpp b/src/mongo/db/exec/scoped_timer.cpp
index e1db4a44ff8..8493db68116 100644
--- a/src/mongo/db/exec/scoped_timer.cpp
+++ b/src/mongo/db/exec/scoped_timer.cpp
@@ -29,16 +29,15 @@
#include "mongo/platform/basic.h"
#include "mongo/db/exec/scoped_timer.h"
-
-#include "mongo/util/net/listen.h"
+#include "mongo/util/clock_source.h"
namespace mongo {
-ScopedTimer::ScopedTimer(long long* counter)
- : _counter(counter), _start(Listener::getElapsedTimeMillis()) {}
+ScopedTimer::ScopedTimer(ClockSource* cs, long long* counter)
+ : _clock(cs), _counter(counter), _start(cs->now()) {}
ScopedTimer::~ScopedTimer() {
- long long elapsed = Listener::getElapsedTimeMillis() - _start;
+ long long elapsed = durationCount<Milliseconds>(_clock->now() - _start);
*_counter += elapsed;
}
diff --git a/src/mongo/db/exec/scoped_timer.h b/src/mongo/db/exec/scoped_timer.h
index 3e1c29fe719..da0a484fabf 100644
--- a/src/mongo/db/exec/scoped_timer.h
+++ b/src/mongo/db/exec/scoped_timer.h
@@ -30,8 +30,12 @@
#include "mongo/base/disallow_copying.h"
+#include "mongo/util/time_support.h"
+
namespace mongo {
+class ClockSource;
+
/**
* This class increments a counter by a rough estimate of the time elapsed since its
* construction when it goes out of scope.
@@ -40,19 +44,17 @@ class ScopedTimer {
MONGO_DISALLOW_COPYING(ScopedTimer);
public:
- ScopedTimer(long long* counter);
+ ScopedTimer(ClockSource* cs, long long* counter);
~ScopedTimer();
private:
- // Default constructor disallowed.
- ScopedTimer();
-
+ ClockSource* const _clock;
// Reference to the counter that we are incrementing with the elapsed time.
long long* _counter;
// Time at which the timer was constructed.
- long long _start;
+ const Date_t _start;
};
} // namespace mongo
diff --git a/src/mongo/db/exec/sort_test.cpp b/src/mongo/db/exec/sort_test.cpp
index 6a45fa27022..f0cc0d01062 100644
--- a/src/mongo/db/exec/sort_test.cpp
+++ b/src/mongo/db/exec/sort_test.cpp
@@ -34,23 +34,145 @@
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/json.h"
+#include "mongo/db/operation_context_noop.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
+#include "mongo/db/service_context.h"
+#include "mongo/db/service_context_noop.h"
#include "mongo/stdx/memory.h"
#include "mongo/unittest/unittest.h"
+#include "mongo/util/clock_source_mock.h"
using namespace mongo;
namespace {
-TEST(SortStageTest, SortEmptyWorkingSet) {
+class SortStageTest : public unittest::Test {
+public:
+ SortStageTest() {
+ _service = stdx::make_unique<ServiceContextNoop>();
+ _client = _service.get()->makeClient("test");
+ _opCtxNoop.reset(new OperationContextNoop(_client.get(), 0));
+ _opCtx = _opCtxNoop.get();
+ }
+
+ /**
+ * Test function to verify sort stage.
+ * SortStageParams will be initialized using patternStr, collator, queryStr and limit.
+ * inputStr represents the input data set in a BSONObj.
+ * {input: [doc1, doc2, doc3, ...]}
+ * expectedStr represents the expected sorted data set.
+ * {output: [docA, docB, docC, ...]}
+ */
+ void testWork(const char* patternStr,
+ CollatorInterface* collator,
+ const char* queryStr,
+ int limit,
+ const char* inputStr,
+ const char* expectedStr) {
+ // WorkingSet is not owned by stages
+ // so it's fine to declare
+ WorkingSet ws;
+
+ // QueuedDataStage will be owned by SortStage.
+ auto queuedDataStage = stdx::make_unique<QueuedDataStage>(getOpCtx(), &ws);
+ BSONObj inputObj = fromjson(inputStr);
+ BSONElement inputElt = inputObj.getField("input");
+ ASSERT(inputElt.isABSONObj());
+ BSONObjIterator inputIt(inputElt.embeddedObject());
+ while (inputIt.more()) {
+ BSONElement elt = inputIt.next();
+ ASSERT(elt.isABSONObj());
+ BSONObj obj = elt.embeddedObject().getOwned();
+
+ // Insert obj from input array into working set.
+ WorkingSetID id = ws.allocate();
+ WorkingSetMember* wsm = ws.get(id);
+ wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj);
+ wsm->transitionToOwnedObj();
+ queuedDataStage->pushBack(id);
+ }
+
+ // Initialize SortStageParams
+ // Setting limit to 0 means no limit
+ SortStageParams params;
+ params.pattern = fromjson(patternStr);
+ params.collator = collator;
+ params.limit = limit;
+
+ auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
+ getOpCtx(), queuedDataStage.release(), &ws, params.pattern, fromjson(queryStr));
+
+ SortStage sort(getOpCtx(), params, &ws, sortKeyGen.release());
+
+ WorkingSetID id = WorkingSet::INVALID_ID;
+ PlanStage::StageState state = PlanStage::NEED_TIME;
+
+ // Keep working sort stage until data is available.
+ while (state == PlanStage::NEED_TIME) {
+ state = sort.work(&id);
+ }
+
+ // QueuedDataStage's state should be EOF when sort is ready to advance.
+ ASSERT_TRUE(sort.child()->child()->isEOF());
+
+ // While there's data to be retrieved, state should be equal to ADVANCED.
+ // Insert documents into BSON document in this format:
+ // {output: [docA, docB, docC, ...]}
+ BSONObjBuilder bob;
+ BSONArrayBuilder arr(bob.subarrayStart("output"));
+ while (state == PlanStage::ADVANCED) {
+ WorkingSetMember* member = ws.get(id);
+ const BSONObj& obj = member->obj.value();
+ arr.append(obj);
+ state = sort.work(&id);
+ }
+ arr.doneFast();
+ BSONObj outputObj = bob.obj();
+
+ // Sort stage should be EOF after data is retrieved.
+ ASSERT_EQUALS(state, PlanStage::IS_EOF);
+ ASSERT_TRUE(sort.isEOF());
+
+ // Finally, we get to compare the sorted results against what we expect.
+ BSONObj expectedObj = fromjson(expectedStr);
+ if (outputObj != expectedObj) {
+ mongoutils::str::stream ss;
+ // Even though we have the original string representation of the expected output,
+ // we invoke BSONObj::toString() to get a format consistent with outputObj.
+ ss << "Unexpected sort result with query=" << queryStr << "; pattern=" << patternStr
+ << "; limit=" << limit << ":\n"
+ << "Expected: " << expectedObj.toString() << "\n"
+ << "Actual: " << outputObj.toString() << "\n";
+ FAIL(ss);
+ }
+ }
+
+protected:
+ OperationContext* getOpCtx() {
+ return _opCtx;
+ }
+
+private:
+ OperationContext* _opCtx;
+ std::unique_ptr<OperationContextNoop> _opCtxNoop;
+
+ std::unique_ptr<ServiceContextNoop> _service;
+
+ // UniqueClient is declared after ServiceContextNoop because
+ // members of a class are destroyed in reverse order of declaration and
+ // UniqueClient must be destroyed before the ServiceContextNoop is destroyed.
+ ServiceContext::UniqueClient _client;
+};
+
+TEST_F(SortStageTest, SortEmptyWorkingSet) {
WorkingSet ws;
// QueuedDataStage will be owned by SortStage.
- auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws);
+ auto queuedDataStage = stdx::make_unique<QueuedDataStage>(getOpCtx(), &ws);
auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
- nullptr, queuedDataStage.release(), &ws, BSONObj(), BSONObj());
+ getOpCtx(), queuedDataStage.release(), &ws, BSONObj(), BSONObj());
SortStageParams params;
- SortStage sort(nullptr, params, &ws, sortKeyGen.release());
+ SortStage sort(getOpCtx(), params, &ws, sortKeyGen.release());
// Check initial EOF state.
ASSERT_FALSE(sort.isEOF());
@@ -71,98 +193,6 @@ TEST(SortStageTest, SortEmptyWorkingSet) {
ASSERT_TRUE(sort.isEOF());
}
-/**
- * Test function to verify sort stage.
- * SortStageParams will be initialized using patternStr, collator, queryStr and limit.
- * inputStr represents the input data set in a BSONObj.
- * {input: [doc1, doc2, doc3, ...]}
- * expectedStr represents the expected sorted data set.
- * {output: [docA, docB, docC, ...]}
- */
-void testWork(const char* patternStr,
- CollatorInterface* collator,
- const char* queryStr,
- int limit,
- const char* inputStr,
- const char* expectedStr) {
- // WorkingSet is not owned by stages
- // so it's fine to declare
- WorkingSet ws;
-
- // QueuedDataStage will be owned by SortStage.
- auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws);
- BSONObj inputObj = fromjson(inputStr);
- BSONElement inputElt = inputObj.getField("input");
- ASSERT(inputElt.isABSONObj());
- BSONObjIterator inputIt(inputElt.embeddedObject());
- while (inputIt.more()) {
- BSONElement elt = inputIt.next();
- ASSERT(elt.isABSONObj());
- BSONObj obj = elt.embeddedObject().getOwned();
-
- // Insert obj from input array into working set.
- WorkingSetID id = ws.allocate();
- WorkingSetMember* wsm = ws.get(id);
- wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj);
- wsm->transitionToOwnedObj();
- queuedDataStage->pushBack(id);
- }
-
- // Initialize SortStageParams
- // Setting limit to 0 means no limit
- SortStageParams params;
- params.pattern = fromjson(patternStr);
- params.collator = collator;
- params.limit = limit;
-
- auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
- nullptr, queuedDataStage.release(), &ws, params.pattern, fromjson(queryStr));
-
- SortStage sort(nullptr, params, &ws, sortKeyGen.release());
-
- WorkingSetID id = WorkingSet::INVALID_ID;
- PlanStage::StageState state = PlanStage::NEED_TIME;
-
- // Keep working sort stage until data is available.
- while (state == PlanStage::NEED_TIME) {
- state = sort.work(&id);
- }
-
- // QueuedDataStage's state should be EOF when sort is ready to advance.
- ASSERT_TRUE(sort.child()->child()->isEOF());
-
- // While there's data to be retrieved, state should be equal to ADVANCED.
- // Insert documents into BSON document in this format:
- // {output: [docA, docB, docC, ...]}
- BSONObjBuilder bob;
- BSONArrayBuilder arr(bob.subarrayStart("output"));
- while (state == PlanStage::ADVANCED) {
- WorkingSetMember* member = ws.get(id);
- const BSONObj& obj = member->obj.value();
- arr.append(obj);
- state = sort.work(&id);
- }
- arr.doneFast();
- BSONObj outputObj = bob.obj();
-
- // Sort stage should be EOF after data is retrieved.
- ASSERT_EQUALS(state, PlanStage::IS_EOF);
- ASSERT_TRUE(sort.isEOF());
-
- // Finally, we get to compare the sorted results against what we expect.
- BSONObj expectedObj = fromjson(expectedStr);
- if (outputObj != expectedObj) {
- mongoutils::str::stream ss;
- // Even though we have the original string representation of the expected output,
- // we invoke BSONObj::toString() to get a format consistent with outputObj.
- ss << "Unexpected sort result with query=" << queryStr << "; pattern=" << patternStr
- << "; limit=" << limit << ":\n"
- << "Expected: " << expectedObj.toString() << "\n"
- << "Actual: " << outputObj.toString() << "\n";
- FAIL(ss);
- }
-}
-
//
// Limit values
// The server interprets limit values from the user as follows:
@@ -176,7 +206,7 @@ void testWork(const char* patternStr,
// Implementation should keep all items fetched from child.
//
-TEST(SortStageTest, SortAscending) {
+TEST_F(SortStageTest, SortAscending) {
testWork("{a: 1}",
nullptr,
"{}",
@@ -185,7 +215,7 @@ TEST(SortStageTest, SortAscending) {
"{output: [{a: 1}, {a: 2}, {a: 3}]}");
}
-TEST(SortStageTest, SortDescending) {
+TEST_F(SortStageTest, SortDescending) {
testWork("{a: -1}",
nullptr,
"{}",
@@ -194,7 +224,7 @@ TEST(SortStageTest, SortDescending) {
"{output: [{a: 3}, {a: 2}, {a: 1}]}");
}
-TEST(SortStageTest, SortIrrelevantSortKey) {
+TEST_F(SortStageTest, SortIrrelevantSortKey) {
testWork("{b: 1}",
nullptr,
"{}",
@@ -209,7 +239,7 @@ TEST(SortStageTest, SortIrrelevantSortKey) {
// and discard the rest.
//
-TEST(SortStageTest, SortAscendingWithLimit) {
+TEST_F(SortStageTest, SortAscendingWithLimit) {
testWork("{a: 1}",
nullptr,
"{}",
@@ -218,7 +248,7 @@ TEST(SortStageTest, SortAscendingWithLimit) {
"{output: [{a: 1}, {a: 2}]}");
}
-TEST(SortStageTest, SortDescendingWithLimit) {
+TEST_F(SortStageTest, SortDescendingWithLimit) {
testWork("{a: -1}",
nullptr,
"{}",
@@ -233,7 +263,7 @@ TEST(SortStageTest, SortDescendingWithLimit) {
// and discard the rest.
//
-TEST(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) {
+TEST_F(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) {
testWork("{a: 1}",
nullptr,
"{}",
@@ -242,7 +272,7 @@ TEST(SortStageTest, SortAscendingWithLimitGreaterThanInputSize) {
"{output: [{a: 1}, {a: 2}, {a: 3}]}");
}
-TEST(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) {
+TEST_F(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) {
testWork("{a: -1}",
nullptr,
"{}",
@@ -256,16 +286,16 @@ TEST(SortStageTest, SortDescendingWithLimitGreaterThanInputSize) {
// Implementation should optimize this into a running maximum.
//
-TEST(SortStageTest, SortAscendingWithLimitOfOne) {
+TEST_F(SortStageTest, SortAscendingWithLimitOfOne) {
testWork("{a: 1}", nullptr, "{}", 1, "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 1}]}");
}
-TEST(SortStageTest, SortDescendingWithLimitOfOne) {
+TEST_F(SortStageTest, SortDescendingWithLimitOfOne) {
testWork(
"{a: -1}", nullptr, "{}", 1, "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 3}]}");
}
-TEST(SortStageTest, SortAscendingWithCollation) {
+TEST_F(SortStageTest, SortAscendingWithCollation) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
testWork("{a: 1}",
&collator,
@@ -275,7 +305,7 @@ TEST(SortStageTest, SortAscendingWithCollation) {
"{output: [{a: 'aa'}, {a: 'ba'}, {a: 'ab'}]}");
}
-TEST(SortStageTest, SortDescendingWithCollation) {
+TEST_F(SortStageTest, SortDescendingWithCollation) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
testWork("{a: -1}",
&collator,
diff --git a/src/mongo/db/exec/subplan.cpp b/src/mongo/db/exec/subplan.cpp
index b694a4cc902..8be5da178dc 100644
--- a/src/mongo/db/exec/subplan.cpp
+++ b/src/mongo/db/exec/subplan.cpp
@@ -494,7 +494,7 @@ Status SubplanStage::choosePlanWholeQuery(PlanYieldPolicy* yieldPolicy) {
Status SubplanStage::pickBestPlan(PlanYieldPolicy* yieldPolicy) {
// Adds the amount of time taken by pickBestPlan() to executionTimeMillis. There's lots of
// work that happens here, so this is needed for the time accounting to make sense.
- ScopedTimer timer(&_commonStats.executionTimeMillis);
+ ScopedTimer timer(getClock(), &_commonStats.executionTimeMillis);
// Plan each branch of the $or.
Status subplanningStatus = planSubqueries();
diff --git a/src/mongo/db/pipeline/document_source_test.cpp b/src/mongo/db/pipeline/document_source_test.cpp
index 80423154a8d..b8f96fd1f60 100644
--- a/src/mongo/db/pipeline/document_source_test.cpp
+++ b/src/mongo/db/pipeline/document_source_test.cpp
@@ -37,9 +37,9 @@
#include "mongo/db/pipeline/pipeline.h"
#include "mongo/db/service_context.h"
#include "mongo/db/service_context_noop.h"
-#include "mongo/stdx/memory.h"
#include "mongo/db/storage/storage_options.h"
#include "mongo/dbtests/dbtests.h"
+#include "mongo/stdx/memory.h"
#include "mongo/util/clock_source_mock.h"
#include "mongo/unittest/temp_dir.h"
diff --git a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
index 79517b5b193..542c61dc8ce 100644
--- a/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
+++ b/src/mongo/db/s/migration_chunk_cloner_source_legacy.cpp
@@ -88,8 +88,8 @@ BSONObj createRecvChunkCommitRequest(const NamespaceString& nss,
*/
class DeleteNotificationStage final : public PlanStage {
public:
- DeleteNotificationStage(MigrationChunkClonerSourceLegacy* cloner)
- : PlanStage("SHARDING_NOTIFY_DELETE", nullptr), _cloner(cloner) {}
+ DeleteNotificationStage(MigrationChunkClonerSourceLegacy* cloner, OperationContext* txn)
+ : PlanStage("SHARDING_NOTIFY_DELETE", txn), _cloner(cloner) {}
void doInvalidate(OperationContext* txn, const RecordId& dl, InvalidationType type) override {
if (type == INVALIDATION_DELETION) {
@@ -527,7 +527,7 @@ Status MigrationChunkClonerSourceLegacy::_storeCurrentLocs(OperationContext* txn
auto statusWithPlanExecutor =
PlanExecutor::make(txn,
stdx::make_unique<WorkingSet>(),
- stdx::make_unique<DeleteNotificationStage>(this),
+ stdx::make_unique<DeleteNotificationStage>(this, txn),
collection,
PlanExecutor::YIELD_MANUAL);
invariant(statusWithPlanExecutor.isOK());
diff --git a/src/mongo/db/storage/mmap_v1/dur_journal.cpp b/src/mongo/db/storage/mmap_v1/dur_journal.cpp
index ea3b02d9476..524085a87e9 100644
--- a/src/mongo/db/storage/mmap_v1/dur_journal.cpp
+++ b/src/mongo/db/storage/mmap_v1/dur_journal.cpp
@@ -58,7 +58,6 @@
#include "mongo/util/hex.h"
#include "mongo/util/log.h"
#include "mongo/util/mongoutils/str.h"
-#include "mongo/util/net/listen.h" // getelapsedtimemillis
#include "mongo/util/progress_meter.h"
#include "mongo/util/timer.h"
diff --git a/src/mongo/dbtests/plan_ranking.cpp b/src/mongo/dbtests/plan_ranking.cpp
index 8871e17a5bf..970f7d02ac9 100644
--- a/src/mongo/dbtests/plan_ranking.cpp
+++ b/src/mongo/dbtests/plan_ranking.cpp
@@ -51,12 +51,9 @@
#include "mongo/db/query/stage_builder.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/stdx/memory.h"
-#include "mongo/util/clock_source_mock.h"
namespace mongo {
-const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>();
-
// How we access the external setParameter testing bool.
extern std::atomic<bool> internalQueryForceIntersectionPlans; // NOLINT
@@ -132,7 +129,8 @@ public:
_mps->addPlan(solutions[i], root, ws.get());
}
// This is what sets a backup plan, should we test for it.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL,
+ _txn.getServiceContext()->getFastClockSource());
_mps->pickBestPlan(&yieldPolicy);
ASSERT(_mps->bestPlanChosen());
diff --git a/src/mongo/dbtests/query_stage_cached_plan.cpp b/src/mongo/dbtests/query_stage_cached_plan.cpp
index 1d41db88d93..f090e61f8c4 100644
--- a/src/mongo/dbtests/query_stage_cached_plan.cpp
+++ b/src/mongo/dbtests/query_stage_cached_plan.cpp
@@ -47,11 +47,9 @@
#include "mongo/db/query/query_planner_params.h"
#include "mongo/dbtests/dbtests.h"
#include "mongo/stdx/memory.h"
-#include "mongo/util/clock_source_mock.h"
namespace QueryStageCachedPlan {
-const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>();
static const NamespaceString nss("unittests.QueryStageCachedPlan");
class QueryStageCachedPlanBase {
@@ -149,7 +147,8 @@ public:
&_txn, collection, &_ws, cq.get(), plannerParams, decisionWorks, mockChild.release());
// This should succeed after triggering a replan.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL,
+ _txn.getServiceContext()->getFastClockSource());
ASSERT_OK(cachedPlanStage.pickBestPlan(&yieldPolicy));
// Make sure that we get 2 legit results back.
@@ -220,7 +219,8 @@ public:
&_txn, collection, &_ws, cq.get(), plannerParams, decisionWorks, mockChild.release());
// This should succeed after triggering a replan.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL,
+ _txn.getServiceContext()->getFastClockSource());
ASSERT_OK(cachedPlanStage.pickBestPlan(&yieldPolicy));
// Make sure that we get 2 legit results back.
diff --git a/src/mongo/dbtests/query_stage_ensure_sorted.cpp b/src/mongo/dbtests/query_stage_ensure_sorted.cpp
index 8ba3b552eeb..f89bbd42ea5 100644
--- a/src/mongo/dbtests/query_stage_ensure_sorted.cpp
+++ b/src/mongo/dbtests/query_stage_ensure_sorted.cpp
@@ -28,6 +28,7 @@
#include "mongo/platform/basic.h"
+#include "mongo/db/client.h"
#include "mongo/db/exec/ensure_sorted.h"
#include "mongo/db/exec/sort_key_generator.h"
#include "mongo/db/exec/queued_data_stage.h"
@@ -40,12 +41,81 @@ namespace mongo {
namespace {
-TEST(QueryStageEnsureSorted, EnsureSortedEmptyWorkingSet) {
+class QueryStageEnsureSortedTest : public unittest::Test {
+public:
+ /**
+ * Test function to verify the EnsureSortedStage.
+ * patternStr is the JSON representation of the sort pattern BSONObj.
+ * inputStr represents the input data set in a BSONObj.
+ * {input: [doc1, doc2, doc3, ...]}
+ * expectedStr represents the expected output data set.
+ * {output: [docA, docB, docC, ...]}
+ * collator is passed to EnsureSortedStage() for string comparisons.
+ */
+ void testWork(const char* patternStr,
+ const char* inputStr,
+ const char* expectedStr,
+ CollatorInterface* collator = nullptr) {
+ WorkingSet ws;
+ auto queuedDataStage = stdx::make_unique<QueuedDataStage>(_opCtx, &ws);
+ BSONObj inputObj = fromjson(inputStr);
+ BSONElement inputElt = inputObj["input"];
+ ASSERT(inputElt.isABSONObj());
+
+ for (auto&& elt : inputElt.embeddedObject()) {
+ ASSERT(elt.isABSONObj());
+ BSONObj obj = elt.embeddedObject().getOwned();
+
+ // Insert obj from input array into working set.
+ WorkingSetID id = ws.allocate();
+ WorkingSetMember* wsm = ws.get(id);
+ wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj);
+ wsm->transitionToOwnedObj();
+ queuedDataStage->pushBack(id);
+ }
+
+ // Initialization.
+ BSONObj pattern = fromjson(patternStr);
+ auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
+ _opCtx, queuedDataStage.release(), &ws, pattern, BSONObj());
+ EnsureSortedStage ess(_opCtx, pattern, collator, &ws, sortKeyGen.release());
+ WorkingSetID id = WorkingSet::INVALID_ID;
+ PlanStage::StageState state = PlanStage::NEED_TIME;
+
+ // Documents are inserted into BSON document in this format:
+ // {output: [docA, docB, docC, ...]}
+ BSONObjBuilder bob;
+ BSONArrayBuilder arr(bob.subarrayStart("output"));
+ while (state != PlanStage::IS_EOF) {
+ state = ess.work(&id);
+ ASSERT_NE(state, PlanStage::DEAD);
+ ASSERT_NE(state, PlanStage::FAILURE);
+ if (state == PlanStage::ADVANCED) {
+ WorkingSetMember* member = ws.get(id);
+ const BSONObj& obj = member->obj.value();
+ arr.append(obj);
+ }
+ }
+ ASSERT_TRUE(ess.isEOF());
+ arr.doneFast();
+ BSONObj outputObj = bob.obj();
+
+ // Compare the results against what we expect.
+ BSONObj expectedObj = fromjson(expectedStr);
+ ASSERT_EQ(outputObj, expectedObj);
+ }
+
+protected:
+ const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext();
+ OperationContext* const _opCtx = _uniqOpCtx.get();
+};
+
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedEmptyWorkingSet) {
WorkingSet ws;
- auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws);
+ auto queuedDataStage = stdx::make_unique<QueuedDataStage>(_opCtx, &ws);
auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
- nullptr, queuedDataStage.release(), &ws, BSONObj(), BSONObj());
- EnsureSortedStage ess(nullptr, BSONObj(), nullptr, &ws, sortKeyGen.release());
+ _opCtx, queuedDataStage.release(), &ws, BSONObj(), BSONObj());
+ EnsureSortedStage ess(_opCtx, BSONObj(), nullptr, &ws, sortKeyGen.release());
WorkingSetID id = WorkingSet::INVALID_ID;
PlanStage::StageState state = PlanStage::NEED_TIME;
@@ -56,81 +126,19 @@ TEST(QueryStageEnsureSorted, EnsureSortedEmptyWorkingSet) {
ASSERT_EQ(state, PlanStage::IS_EOF);
}
-/**
- * Test function to verify the EnsureSortedStage.
- * patternStr is the JSON representation of the sort pattern BSONObj.
- * inputStr represents the input data set in a BSONObj.
- * {input: [doc1, doc2, doc3, ...]}
- * expectedStr represents the expected output data set.
- * {output: [docA, docB, docC, ...]}
- * collator is passed to EnsureSortedStage() for string comparisons.
- */
-void testWork(const char* patternStr,
- const char* inputStr,
- const char* expectedStr,
- const CollatorInterface* collator = nullptr) {
- WorkingSet ws;
- auto queuedDataStage = stdx::make_unique<QueuedDataStage>(nullptr, &ws);
- BSONObj inputObj = fromjson(inputStr);
- BSONElement inputElt = inputObj["input"];
- ASSERT(inputElt.isABSONObj());
-
- for (auto&& elt : inputElt.embeddedObject()) {
- ASSERT(elt.isABSONObj());
- BSONObj obj = elt.embeddedObject().getOwned();
-
- // Insert obj from input array into working set.
- WorkingSetID id = ws.allocate();
- WorkingSetMember* wsm = ws.get(id);
- wsm->obj = Snapshotted<BSONObj>(SnapshotId(), obj);
- wsm->transitionToOwnedObj();
- queuedDataStage->pushBack(id);
- }
-
- // Initialization.
- BSONObj pattern = fromjson(patternStr);
- auto sortKeyGen = stdx::make_unique<SortKeyGeneratorStage>(
- nullptr, queuedDataStage.release(), &ws, pattern, BSONObj());
- EnsureSortedStage ess(nullptr, pattern, collator, &ws, sortKeyGen.release());
- WorkingSetID id = WorkingSet::INVALID_ID;
- PlanStage::StageState state = PlanStage::NEED_TIME;
-
- // Documents are inserted into BSON document in this format:
- // {output: [docA, docB, docC, ...]}
- BSONObjBuilder bob;
- BSONArrayBuilder arr(bob.subarrayStart("output"));
- while (state != PlanStage::IS_EOF) {
- state = ess.work(&id);
- ASSERT_NE(state, PlanStage::DEAD);
- ASSERT_NE(state, PlanStage::FAILURE);
- if (state == PlanStage::ADVANCED) {
- WorkingSetMember* member = ws.get(id);
- const BSONObj& obj = member->obj.value();
- arr.append(obj);
- }
- }
- ASSERT_TRUE(ess.isEOF());
- arr.doneFast();
- BSONObj outputObj = bob.obj();
-
- // Compare the results against what we expect.
- BSONObj expectedObj = fromjson(expectedStr);
- ASSERT_EQ(outputObj, expectedObj);
-}
-
//
// EnsureSorted on already sorted order should make no change.
//
-TEST(QueryStageEnsureSorted, EnsureAlreadySortedAscending) {
+TEST_F(QueryStageEnsureSortedTest, EnsureAlreadySortedAscending) {
testWork("{a: 1}", "{input: [{a: 1}, {a: 2}, {a: 3}]}", "{output: [{a: 1}, {a: 2}, {a: 3}]}");
}
-TEST(QueryStageEnsureSorted, EnsureAlreadySortedDescending) {
+TEST_F(QueryStageEnsureSortedTest, EnsureAlreadySortedDescending) {
testWork("{a: -1}", "{input: [{a: 3}, {a: 2}, {a: 1}]}", "{output: [{a: 3}, {a: 2}, {a: 1}]}");
}
-TEST(QueryStageEnsureSorted, EnsureIrrelevantSortKey) {
+TEST_F(QueryStageEnsureSortedTest, EnsureIrrelevantSortKey) {
testWork("{b: 1}", "{input: [{a: 2}, {a: 1}, {a: 3}]}", "{output: [{a: 2}, {a: 1}, {a: 3}]}");
}
@@ -138,33 +146,29 @@ TEST(QueryStageEnsureSorted, EnsureIrrelevantSortKey) {
// EnsureSorted should drop unsorted results.
//
-TEST(QueryStageEnsureSorted, EnsureSortedOnAscending) {
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedOnAscending) {
testWork("{a: 1}",
"{input: [{a: 1}, {a: 2}, {a: 0}, {a: 4}, {a: 6}]}",
"{output: [{a: 1}, {a: 2}, {a: 4}, {a: 6}]}");
}
-TEST(QueryStageEnsureSorted, EnsureSortedOnDescending) {
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedOnDescending) {
testWork("{a: -1}",
"{input: [{a: 6}, {a: 4}, {a: 3}, {a: 9}, {a: 8}]}",
"{output: [{a: 6}, {a: 4}, {a: 3}]}");
}
-TEST(QueryStageEnsureSorted, EnsureSortedCompoundKey) {
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedCompoundKey) {
testWork("{a: -1, b: 1}",
"{input: [{a: 6, b: 10}, {a: 6, b: 8}, {a: 6, b: 12}, {a: 9, b: 13}, {a: 5, b: 1}]}",
"{output: [{a: 6, b: 10}, {a: 6, b: 12}, {a: 5, b: 1}]}");
}
-TEST(QueryStageEnsureSorted, EnsureSortedStringsNullCollator) {
- const CollatorInterface* collator = nullptr;
- testWork("{a: 1}",
- "{input: [{a: 'abc'}, {a: 'cba'}]}",
- "{output: [{a: 'abc'}, {a: 'cba'}]}",
- collator);
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedStringsNullCollator) {
+ testWork("{a: 1}", "{input: [{a: 'abc'}, {a: 'cba'}]}", "{output: [{a: 'abc'}, {a: 'cba'}]}");
}
-TEST(QueryStageEnsureSorted, EnsureSortedStringsCollator) {
+TEST_F(QueryStageEnsureSortedTest, EnsureSortedStringsCollator) {
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
testWork("{a: 1}", "{input: [{a: 'abc'}, {a: 'cba'}]}", "{output: [{a: 'abc'}]}", &collator);
}
diff --git a/src/mongo/dbtests/query_stage_limit_skip.cpp b/src/mongo/dbtests/query_stage_limit_skip.cpp
index 2bb8e3b1faf..0009f32ea8c 100644
--- a/src/mongo/dbtests/query_stage_limit_skip.cpp
+++ b/src/mongo/dbtests/query_stage_limit_skip.cpp
@@ -34,6 +34,7 @@
#include "mongo/platform/basic.h"
#include "mongo/client/dbclientcursor.h"
+#include "mongo/db/client.h"
#include "mongo/db/exec/limit.h"
#include "mongo/db/exec/plan_stage.h"
#include "mongo/db/exec/queued_data_stage.h"
@@ -55,8 +56,8 @@ using stdx::make_unique;
static const int N = 50;
/* Populate a QueuedDataStage and return it. Caller owns it. */
-QueuedDataStage* getMS(WorkingSet* ws) {
- auto ms = make_unique<QueuedDataStage>(nullptr, ws);
+QueuedDataStage* getMS(OperationContext* opCtx, WorkingSet* ws) {
+ auto ms = make_unique<QueuedDataStage>(opCtx, ws);
// Put N ADVANCED results into the mock stage, and some other stalling results (YIELD/TIME).
for (int i = 0; i < N; ++i) {
@@ -96,13 +97,18 @@ public:
for (int i = 0; i < 2 * N; ++i) {
WorkingSet ws;
- unique_ptr<PlanStage> skip = make_unique<SkipStage>(nullptr, i, &ws, getMS(&ws));
+ unique_ptr<PlanStage> skip = make_unique<SkipStage>(_opCtx, i, &ws, getMS(_opCtx, &ws));
ASSERT_EQUALS(max(0, N - i), countResults(skip.get()));
- unique_ptr<PlanStage> limit = make_unique<LimitStage>(nullptr, i, &ws, getMS(&ws));
+ unique_ptr<PlanStage> limit =
+ make_unique<LimitStage>(_opCtx, i, &ws, getMS(_opCtx, &ws));
ASSERT_EQUALS(min(N, i), countResults(limit.get()));
}
}
+
+protected:
+ const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext();
+ OperationContext* const _opCtx = _uniqOpCtx.get();
};
class All : public Suite {
diff --git a/src/mongo/dbtests/query_stage_multiplan.cpp b/src/mongo/dbtests/query_stage_multiplan.cpp
index 1ea517f1253..a76bfbe22c1 100644
--- a/src/mongo/dbtests/query_stage_multiplan.cpp
+++ b/src/mongo/dbtests/query_stage_multiplan.cpp
@@ -114,6 +114,8 @@ public:
protected:
const ServiceContext::UniqueOperationContext _txnPtr = cc().makeOperationContext();
OperationContext& _txn = *_txnPtr;
+ ClockSource* const _clock = _txn.getServiceContext()->getFastClockSource();
+
DBDirectClient _client;
};
@@ -180,7 +182,7 @@ public:
mps->addPlan(createQuerySolution(), secondRoot.release(), sharedWs.get());
// Plan 0 aka the first plan aka the index scan should be the best.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
mps->pickBestPlan(&yieldPolicy);
ASSERT(mps->bestPlanChosen());
ASSERT_EQUALS(0, mps->bestPlanIdx());
@@ -264,7 +266,7 @@ public:
}
// This sets a backup plan.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
mps->pickBestPlan(&yieldPolicy);
ASSERT(mps->bestPlanChosen());
ASSERT(mps->hasBackupPlan());
diff --git a/src/mongo/dbtests/query_stage_near.cpp b/src/mongo/dbtests/query_stage_near.cpp
index 58833e6a2bf..d973779e7ed 100644
--- a/src/mongo/dbtests/query_stage_near.cpp
+++ b/src/mongo/dbtests/query_stage_near.cpp
@@ -34,6 +34,7 @@
#include "mongo/platform/basic.h"
#include "mongo/base/owned_pointer_vector.h"
+#include "mongo/db/client.h"
#include "mongo/db/exec/near.h"
#include "mongo/db/exec/queued_data_stage.h"
#include "mongo/db/exec/working_set_common.h"
@@ -48,6 +49,12 @@ using std::unique_ptr;
using std::vector;
using stdx::make_unique;
+class QueryStageNearTest : public unittest::Test {
+protected:
+ const ServiceContext::UniqueOperationContext _uniqOpCtx = cc().makeOperationContext();
+ OperationContext* const _opCtx = _uniqOpCtx.get();
+};
+
/**
* Stage which implements a basic distance search, and interprets the "distance" field of
* fetched documents as the distance.
@@ -63,8 +70,9 @@ public:
double max;
};
- MockNearStage(WorkingSet* workingSet)
- : NearStage(NULL, "MOCK_DISTANCE_SEARCH_STAGE", STAGE_UNKNOWN, workingSet, NULL), _pos(0) {}
+ MockNearStage(OperationContext* opCtx, WorkingSet* workingSet)
+ : NearStage(opCtx, "MOCK_DISTANCE_SEARCH_STAGE", STAGE_UNKNOWN, workingSet, NULL),
+ _pos(0) {}
void addInterval(vector<BSONObj> data, double min, double max) {
_intervals.mutableVector().push_back(new MockInterval(data, min, max));
@@ -139,11 +147,11 @@ static void assertAscendingAndValid(const vector<BSONObj>& results) {
}
}
-TEST(query_stage_near, Basic) {
+TEST_F(QueryStageNearTest, Basic) {
vector<BSONObj> mockData;
WorkingSet workingSet;
- MockNearStage nearStage(&workingSet);
+ MockNearStage nearStage(_opCtx, &workingSet);
// First set of results
mockData.clear();
@@ -174,11 +182,11 @@ TEST(query_stage_near, Basic) {
assertAscendingAndValid(results);
}
-TEST(query_stage_near, EmptyResults) {
+TEST_F(QueryStageNearTest, EmptyResults) {
vector<BSONObj> mockData;
WorkingSet workingSet;
- MockNearStage nearStage(&workingSet);
+ MockNearStage nearStage(_opCtx, &workingSet);
// Empty set of results
mockData.clear();
diff --git a/src/mongo/dbtests/query_stage_subplan.cpp b/src/mongo/dbtests/query_stage_subplan.cpp
index 419cd04d08d..825152c4007 100644
--- a/src/mongo/dbtests/query_stage_subplan.cpp
+++ b/src/mongo/dbtests/query_stage_subplan.cpp
@@ -43,11 +43,9 @@
#include "mongo/db/query/canonical_query.h"
#include "mongo/db/query/get_executor.h"
#include "mongo/dbtests/dbtests.h"
-#include "mongo/util/clock_source_mock.h"
namespace QueryStageSubplan {
-const std::unique_ptr<ClockSource> clockSource = stdx::make_unique<ClockSourceMock>();
static const NamespaceString nss("unittests.QueryStageSubplan");
class QueryStageSubplanBase {
@@ -89,6 +87,7 @@ protected:
const ServiceContext::UniqueOperationContext _txnPtr = cc().makeOperationContext();
OperationContext& _txn = *_txnPtr;
+ ClockSource* _clock = _txn.getServiceContext()->getFastClockSource();
private:
DBDirectClient _client;
@@ -132,7 +131,7 @@ public:
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
// Plan selection should succeed due to falling back on regular planning.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
}
};
@@ -175,7 +174,7 @@ public:
std::unique_ptr<SubplanStage> subplan(
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
// Nothing is in the cache yet, so neither branch should have been planned from
@@ -233,7 +232,7 @@ public:
std::unique_ptr<SubplanStage> subplan(
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
// Nothing is in the cache yet, so neither branch should have been planned from
@@ -292,7 +291,7 @@ public:
std::unique_ptr<SubplanStage> subplan(
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
// Nothing is in the cache yet, so neither branch should have been planned from
@@ -549,7 +548,7 @@ public:
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
// Plan selection should succeed due to falling back on regular planning.
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
// Work the stage until it produces all results.
@@ -607,7 +606,7 @@ public:
std::unique_ptr<SubplanStage> subplan(
new SubplanStage(&_txn, collection, &ws, plannerParams, cq.get()));
- PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, clockSource.get());
+ PlanYieldPolicy yieldPolicy(PlanExecutor::YIELD_MANUAL, _clock);
ASSERT_OK(subplan->pickBestPlan(&yieldPolicy));
size_t numResults = 0;