TEST(MockDBClientConnTest, Delay) {
        MockRemoteDBServer server("test");
        server.setCommandReply("serverStatus", BSON("ok" << 1));
        server.setDelay(150);

        MockDBClientConnection conn(&server);

        {
            mongo::Timer timer;
            conn.query("x.x");
            const int nowInMilliSec = timer.millis();
            ASSERT_GREATER_THAN_OR_EQUALS(nowInMilliSec, 140);
            ASSERT_LESS_THAN_OR_EQUALS(nowInMilliSec, 160);
        }

        {
            mongo::Timer timer;
            BSONObj response;
            conn.runCommand("x.x", BSON("serverStatus" << 1), response);
            const int nowInMilliSec = timer.millis();
            ASSERT_GREATER_THAN_OR_EQUALS(nowInMilliSec, 140);
            ASSERT_LESS_THAN_OR_EQUALS(nowInMilliSec, 160);
        }

        ASSERT_EQUALS(1U, server.getQueryCount());
        ASSERT_EQUALS(1U, server.getCmdCount());
    }
TEST(MockDBClientConnTest, Delay) {
    MockRemoteDBServer server("test");
    server.setCommandReply("serverStatus", BSON("ok" << 1));
    server.setDelay(150);

    MockDBClientConnection conn(&server);

    {
        mongo::Timer timer;
        conn.query("x.x");
        const int nowInMilliSec = timer.millis();
        // Use a more lenient lower bound since some platforms like Windows
        // don't guarantee that sleeps will not wake up earlier (unlike
        // nanosleep we use for Linux)
        ASSERT_GREATER_THAN_OR_EQUALS(nowInMilliSec, 130);
    }

    {
        mongo::Timer timer;
        BSONObj response;
        conn.runCommand("x.x", BSON("serverStatus" << 1), response);
        const int nowInMilliSec = timer.millis();
        ASSERT_GREATER_THAN_OR_EQUALS(nowInMilliSec, 130);
    }

    ASSERT_EQUALS(1U, server.getQueryCount());
    ASSERT_EQUALS(1U, server.getCmdCount());
}
Example #3
0
        /**
         * Use the MultiPlanRunner to pick the best plan for the query 'cq'.  Goes through
         * normal planning to generate solutions and feeds them to the MPR.
         *
         * Takes ownership of 'cq'.  Caller DOES NOT own the returned QuerySolution*.
         */
        QuerySolution* pickBestPlan(CanonicalQuery* cq) {
            Client::ReadContext ctx(ns);
            Collection* collection = ctx.ctx().db()->getCollection(ns);

            QueryPlannerParams plannerParams;
            fillOutPlannerParams(collection, cq, &plannerParams);
            // Turn this off otherwise it pops up in some plans.
            plannerParams.options &= ~QueryPlannerParams::KEEP_MUTATIONS;

            // Plan.
            vector<QuerySolution*> solutions;
            Status status = QueryPlanner::plan(*cq, plannerParams, &solutions);
            ASSERT(status.isOK());

            ASSERT_GREATER_THAN_OR_EQUALS(solutions.size(), 1U);

            // Fill out the MPR.
            _mpr.reset(new MultiPlanRunner(collection, cq));

            // Put each solution from the planner into the MPR.
            for (size_t i = 0; i < solutions.size(); ++i) {
                WorkingSet* ws;
                PlanStage* root;
                ASSERT(StageBuilder::build(*solutions[i], &root, &ws));
                // Takes ownership of all arguments.
                _mpr->addPlan(solutions[i], root, ws);
            }

            // And return a pointer to the best solution.  The MPR owns the pointer.
            size_t bestPlan = numeric_limits<size_t>::max();
            BSONObj unused;
            ASSERT(_mpr->pickBestPlan(&bestPlan, &unused));
            ASSERT_LESS_THAN(bestPlan, solutions.size());
            return solutions[bestPlan];
        }
Example #4
0
    void run() {
        // Insert a ton of documents with a: [1, 2, 3]
        for (size_t i = 0; i < 1000; ++i) {
            insert(BSON("a" << BSON_ARRAY(1 << 2 << 3)));
        }

        // Insert a ton of other documents with a: [4, 5, 6]
        for (size_t i = 0; i < 1000; ++i) {
            insert(BSON("a" << BSON_ARRAY(4 << 5 << 6)));
        }

        // Make an index on a:1
        addIndex(BSON("a" << 1));

        AutoGetCollectionForRead ctx(&_txn, ns());
        Collection* coll = ctx.getCollection();

        // Set up the distinct stage.
        std::vector<IndexDescriptor*> indexes;
        coll->getIndexCatalog()->findIndexesByKeyPattern(&_txn, BSON("a" << 1), false, &indexes);
        verify(indexes.size() == 1);

        DistinctParams params;
        params.descriptor = indexes[0];
        ASSERT_TRUE(params.descriptor->isMultikey(&_txn));

        verify(params.descriptor);
        params.direction = 1;
        // Distinct-ing over the 0-th field of the keypattern.
        params.fieldNo = 0;
        // We'll look at all values in the bounds.
        params.bounds.isSimpleRange = false;
        OrderedIntervalList oil("a");
        oil.intervals.push_back(IndexBoundsBuilder::allValues());
        params.bounds.fields.push_back(oil);

        WorkingSet ws;
        DistinctScan distinct(&_txn, params, &ws);

        // We should see each number in the range [1, 6] exactly once.
        std::set<int> seen;

        WorkingSetID wsid;
        PlanStage::StageState state;
        while (PlanStage::IS_EOF != (state = distinct.work(&wsid))) {
            if (PlanStage::ADVANCED == state) {
                // Check int value.
                int currentNumber = getIntFieldDotted(ws, wsid, "a");
                ASSERT_GREATER_THAN_OR_EQUALS(currentNumber, 1);
                ASSERT_LESS_THAN_OR_EQUALS(currentNumber, 6);

                // Should see this number only once.
                ASSERT_TRUE(seen.find(currentNumber) == seen.end());
                seen.insert(currentNumber);
            }
        }

        ASSERT_EQUALS(6U, seen.size());
    }
Example #5
0
// Test a run of the controller and the data it logs to log file
TEST(FTDCControllerTest, TestFull) {
    unittest::TempDir tempdir("metrics_testpath");
    boost::filesystem::path dir(tempdir.path());

    createDirectoryClean(dir);

    FTDCConfig config;
    config.enabled = true;
    config.period = Milliseconds(1);
    config.maxFileSizeBytes = FTDCConfig::kMaxFileSizeBytesDefault;
    config.maxDirectorySizeBytes = FTDCConfig::kMaxDirectorySizeBytesDefault;

    FTDCController c(dir, config);

    auto c1 = std::unique_ptr<FTDCMetricsCollectorMock2>(new FTDCMetricsCollectorMock2());
    auto c2 = std::unique_ptr<FTDCMetricsCollectorMockRotate>(new FTDCMetricsCollectorMockRotate());

    auto c1Ptr = c1.get();
    auto c2Ptr = c2.get();

    c1Ptr->setSignalOnCount(100);

    c.addPeriodicCollector(std::move(c1));

    c.addOnRotateCollector(std::move(c2));

    c.start();

    // Wait for 100 samples to have occured
    c1Ptr->wait();

    c.stop();

    auto docsPeriodic = c1Ptr->getDocs();
    ASSERT_GREATER_THAN_OR_EQUALS(docsPeriodic.size(), 100UL);

    auto docsRotate = c2Ptr->getDocs();
    ASSERT_EQUALS(docsRotate.size(), 1UL);

    std::vector<BSONObj> allDocs;
    allDocs.insert(allDocs.end(), docsRotate.begin(), docsRotate.end());
    allDocs.insert(allDocs.end(), docsPeriodic.begin(), docsPeriodic.end());

    auto files = scanDirectory(dir);

    ASSERT_EQUALS(files.size(), 2UL);

    auto alog = files[0];

    ValidateDocumentList(alog, allDocs);
}
Example #6
0
        /**
         * Use the MultiPlanRunner to pick the best plan for the query 'cq'.  Goes through
         * normal planning to generate solutions and feeds them to the MPR.
         *
         * Takes ownership of 'cq'.  Caller DOES NOT own the returned QuerySolution*.
         */
        QuerySolution* pickBestPlan(CanonicalQuery* cq) {
            Client::ReadContext ctx(&_txn, ns);
            Collection* collection = ctx.ctx().db()->getCollection(&_txn, ns);

            QueryPlannerParams plannerParams;
            fillOutPlannerParams(&_txn, collection, cq, &plannerParams);
            // Turn this off otherwise it pops up in some plans.
            plannerParams.options &= ~QueryPlannerParams::KEEP_MUTATIONS;

            // Plan.
            vector<QuerySolution*> solutions;
            Status status = QueryPlanner::plan(*cq, plannerParams, &solutions);
            ASSERT(status.isOK());

            ASSERT_GREATER_THAN_OR_EQUALS(solutions.size(), 1U);

            // Fill out the MPR.
            _mps.reset(new MultiPlanStage(&_txn, collection, cq));
            WorkingSet* ws = new WorkingSet();
            // Put each solution from the planner into the MPR.
            for (size_t i = 0; i < solutions.size(); ++i) {
                PlanStage* root;
                ASSERT(StageBuilder::build(&_txn, collection, *solutions[i], ws, &root));
                // Takes ownership of all arguments.
                _mps->addPlan(solutions[i], root, ws);
            }

            _mps->pickBestPlan(); // This is what sets a backup plan, should we test for it.
            ASSERT(_mps->bestPlanChosen());

            size_t bestPlanIdx = _mps->bestPlanIdx();
            ASSERT_LESS_THAN(bestPlanIdx, solutions.size());

            // And return a pointer to the best solution.
            return _mps->bestSolution();
        }
Example #7
0
    void run() {
        Client::WriteContext ctx(ns());
        Database* db = ctx.ctx().db();
        Collection* coll = db->getCollection(ns());
        if (!coll) {
            coll = db->createCollection(ns());
        }

        for (int i = 0; i < 50; ++i) {
            insert(BSON("foo" << i << "bar" << i));
        }

        addIndex(BSON("foo" << 1));
        addIndex(BSON("bar" << 1));

        WorkingSet ws;
        scoped_ptr<AndHashStage> ah(new AndHashStage(&ws, NULL));

        // Foo <= 20
        IndexScanParams params;
        params.descriptor = getIndex(BSON("foo" << 1), coll);
        params.bounds.isSimpleRange = true;
        params.bounds.startKey = BSON("" << 20);
        params.bounds.endKey = BSONObj();
        params.bounds.endKeyInclusive = true;
        params.direction = -1;
        ah->addChild(new IndexScan(params, &ws, NULL));

        // Bar >= 10
        params.descriptor = getIndex(BSON("bar" << 1), coll);
        params.bounds.startKey = BSON("" << 10);
        params.bounds.endKey = BSONObj();
        params.bounds.endKeyInclusive = true;
        params.direction = 1;
        ah->addChild(new IndexScan(params, &ws, NULL));

        // ah reads the first child into its hash table.
        // ah should read foo=20, foo=19, ..., foo=0 in that order.
        // Read half of them...
        for (int i = 0; i < 10; ++i) {
            WorkingSetID out;
            PlanStage::StageState status = ah->work(&out);
            ASSERT_EQUALS(PlanStage::NEED_TIME, status);
        }

        // ...yield
        ah->prepareToYield();
        // ...invalidate one of the read objects
        set<DiskLoc> data;
        getLocs(&data, coll);
        for (set<DiskLoc>::const_iterator it = data.begin(); it != data.end(); ++it) {
            if (it->obj()["foo"].numberInt() == 15) {
                ah->invalidate(*it);
                remove(it->obj());
                break;
            }
        }
        ah->recoverFromYield();

        // And expect to find foo==15 it flagged for review.
        const unordered_set<WorkingSetID>& flagged = ws.getFlagged();
        ASSERT_EQUALS(size_t(1), flagged.size());

        // Expect to find the right value of foo in the flagged item.
        WorkingSetMember* member = ws.get(*flagged.begin());
        ASSERT_TRUE(NULL != member);
        ASSERT_EQUALS(WorkingSetMember::OWNED_OBJ, member->state);
        BSONElement elt;
        ASSERT_TRUE(member->getFieldDotted("foo", &elt));
        ASSERT_EQUALS(15, elt.numberInt());

        // Now, finish up the AND.  Since foo == bar, we would have 11 results, but we subtract
        // one because of a mid-plan invalidation, so 10.
        int count = 0;
        while (!ah->isEOF()) {
            WorkingSetID id;
            PlanStage::StageState status = ah->work(&id);
            if (PlanStage::ADVANCED != status) {
                continue;
            }

            ++count;
            member = ws.get(id);

            ASSERT_TRUE(member->getFieldDotted("foo", &elt));
            ASSERT_LESS_THAN_OR_EQUALS(elt.numberInt(), 20);
            ASSERT_NOT_EQUALS(15, elt.numberInt());
            ASSERT_TRUE(member->getFieldDotted("bar", &elt));
            ASSERT_GREATER_THAN_OR_EQUALS(elt.numberInt(), 10);
        }

        ASSERT_EQUALS(10, count);
    }
Example #8
0
// Test a full buffer
TEST(FTDCFileManagerTest, TestFull) {
    Client* client = &cc();
    FTDCConfig c;
    c.maxFileSizeBytes = 300;
    c.maxDirectorySizeBytes = 1000;
    c.maxSamplesPerInterimMetricChunk = 1;

    unittest::TempDir tempdir("metrics_testpath");
    boost::filesystem::path dir(tempdir.path());
    createDirectoryClean(dir);

    FTDCCollectorCollection rotate;
    auto swMgr = FTDCFileManager::create(&c, dir, &rotate, client);
    ASSERT_OK(swMgr.getStatus());
    auto mgr = std::move(swMgr.getValue());

    // Test a large numbers of zeros, and incremental numbers in a full buffer
    for (int j = 0; j < 10; j++) {
        ASSERT_OK(mgr->writeSampleAndRotateIfNeeded(client,
                                                    BSON("name"
                                                         << "joe"
                                                         << "key1"
                                                         << 3230792343LL
                                                         << "key2"
                                                         << 235135),
                                                    Date_t()));

        for (size_t i = 0; i <= FTDCConfig::kMaxSamplesPerArchiveMetricChunkDefault - 2; i++) {
            ASSERT_OK(
                mgr->writeSampleAndRotateIfNeeded(client,
                                                  BSON("name"
                                                       << "joe"
                                                       << "key1"
                                                       << static_cast<long long int>(i * j * 37)
                                                       << "key2"
                                                       << static_cast<long long int>(i *
                                                                                     (645 << j))),
                                                  Date_t()));
        }

        ASSERT_OK(mgr->writeSampleAndRotateIfNeeded(client,
                                                    BSON("name"
                                                         << "joe"
                                                         << "key1"
                                                         << 34
                                                         << "key2"
                                                         << 45),
                                                    Date_t()));

        // Add Value
        ASSERT_OK(mgr->writeSampleAndRotateIfNeeded(client,
                                                    BSON("name"
                                                         << "joe"
                                                         << "key1"
                                                         << 34
                                                         << "key2"
                                                         << 45),
                                                    Date_t()));
    }

    mgr->close();

    auto files = scanDirectory(dir);

    int sum = 0;
    for (auto& file : files) {
        int fs = boost::filesystem::file_size(file);
        ASSERT_TRUE(fs < c.maxFileSizeBytes * 1.10);
        unittest::log() << "File " << file.generic_string() << " has size " << fs;
        if (file.generic_string().find("interim") == std::string::npos) {
            sum += fs;
        }
    }

    ASSERT_LESS_THAN_OR_EQUALS(sum, c.maxDirectorySizeBytes * 1.10);
    ASSERT_GREATER_THAN_OR_EQUALS(sum, c.maxDirectorySizeBytes * 0.90);
}