/** * Check number of results returned from sort. */ void checkCount(int count) { // No limit, should get all objects back. // Otherwise, result set should be smaller of limit and input data size. if (limit() > 0 && limit() < numObj()) { ASSERT_EQUALS(limit(), count); } else { ASSERT_EQUALS(numObj(), count); } }
IndexScanBase() { Client::WriteContext ctx(ns()); for (int i = 0; i < numObj(); ++i) { BSONObjBuilder bob; bob.append("foo", i); bob.append("baz", i); bob.append("bar", numObj() - i); _client.insert(ns(), bob.obj()); } addIndex(BSON("foo" << 1)); addIndex(BSON("foo" << 1 << "baz" << 1)); }
/** * A template used by many tests below. * Fill out numObj objects, sort them in the order provided by 'direction'. * If extAllowed is true, sorting will use use external sorting if available. * If limit is not zero, we limit the output of the sort stage to 'limit' results. */ void sortAndCheck(int direction) { WorkingSet* ws = new WorkingSet(); MockStage* ms = new MockStage(ws); // Insert a mix of the various types of data. insertVarietyOfObjects(ms); SortStageParams params; params.pattern = BSON("foo" << direction); // Must fetch so we can look at the doc as a BSONObj. PlanExecutor runner(ws, new FetchStage(ws, new SortStage(params, ws, ms), NULL)); // Look at pairs of objects to make sure that the sort order is pairwise (and therefore // totally) correct. BSONObj last; ASSERT_EQUALS(Runner::RUNNER_ADVANCED, runner.getNext(&last, NULL)); // Count 'last'. int count = 1; BSONObj current; while (Runner::RUNNER_ADVANCED == runner.getNext(¤t, NULL)) { int cmp = sgn(current.woSortOrder(last, params.pattern)); // The next object should be equal to the previous or oriented according to the sort // pattern. ASSERT(cmp == 0 || cmp == 1); ++count; last = current; } // No limit, should get all objects back. ASSERT_EQUALS(numObj(), count); }
void makeGeoData() { Client::WriteContext ctx(ns()); for (int i = 0; i < numObj(); ++i) { double lat = double(rand()) / RAND_MAX; double lng = double(rand()) / RAND_MAX; _client.insert(ns(), BSON("geo" << BSON_ARRAY(lng << lat))); } }
QueryStageCollectionScanBase() : _client(&_txn) { Client::WriteContext ctx(&_txn, ns()); for (int i = 0; i < numObj(); ++i) { BSONObjBuilder bob; bob.append("foo", i); _client.insert(ns(), bob.obj()); } ctx.commit(); }
void run() { Client::ReadContext ctx(&_txn, ns()); CollectionScanParams params; params.collection = ctx.ctx().db()->getCollection( &_txn, ns() ); params.direction = CollectionScanParams::BACKWARD; params.tailable = false; WorkingSet* ws = new WorkingSet(); PlanStage* ps = new CollectionScan(&_txn, params, ws, NULL); PlanExecutor runner(ws, ps, params.collection); int count = 0; for (BSONObj obj; PlanExecutor::ADVANCED == runner.getNext(&obj, NULL); ) { ++count; ASSERT_EQUALS(numObj() - count, obj["foo"].numberInt()); } ASSERT_EQUALS(numObj(), count); }
void run() { Client::WriteContext ctx(&_txn, ns()); Collection* coll = ctx.ctx().db()->getCollection( &_txn, ns() ); // Get the DiskLocs that would be returned by an in-order scan. vector<DiskLoc> locs; getLocs(coll, CollectionScanParams::FORWARD, &locs); // Configure the scan. CollectionScanParams params; params.collection = coll; params.direction = CollectionScanParams::FORWARD; params.tailable = false; WorkingSet ws; scoped_ptr<CollectionScan> scan(new CollectionScan(&_txn, params, &ws, NULL)); int count = 0; while (count < 10) { WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState state = scan->work(&id); if (PlanStage::ADVANCED == state) { WorkingSetMember* member = ws.get(id); ASSERT_EQUALS(coll->docFor(&_txn, locs[count])["foo"].numberInt(), member->obj["foo"].numberInt()); ++count; } } // Remove locs[count]. scan->saveState(); scan->invalidate(locs[count], INVALIDATION_DELETION); remove(coll->docFor(&_txn, locs[count])); scan->restoreState(&_txn); // Skip over locs[count]. ++count; // Expect the rest. while (!scan->isEOF()) { WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState state = scan->work(&id); if (PlanStage::ADVANCED == state) { WorkingSetMember* member = ws.get(id); ASSERT_EQUALS(coll->docFor(&_txn, locs[count])["foo"].numberInt(), member->obj["foo"].numberInt()); ++count; } } ctx.commit(); ASSERT_EQUALS(numObj(), count); }
void run() { makeGeoData(); addIndex(BSON("geo" << "2d")); // 2d should also work. IndexScanParams params; params.descriptor = getIndex(BSON("geo" << "2d")); params.startKey = BSON("geo" << BSON("$near" << BSON_ARRAY(0 << 0))); params.endKey = BSONObj(); params.endKeyInclusive = true; params.direction = 1; ASSERT_EQUALS(countResults(params), numObj()); }
/** * We feed a mix of (key, unowned, owned) data to the sort stage. */ void insertVarietyOfObjects(MockStage* ms) { set<DiskLoc> locs; getLocs(&locs); set<DiskLoc>::iterator it = locs.begin(); for (int i = 0; i < numObj(); ++i, ++it) { // Insert some owned obj data. WorkingSetMember member; member.state = WorkingSetMember::OWNED_OBJ; member.obj = it->obj().getOwned(); ASSERT(member.obj.isOwned()); ms->pushBack(member); } }
void run() { // Add numObj() geo points. Make sure we get them back. makeGeoData(); addIndex(BSON("geo" << "2dsphere")); IndexScanParams params; params.descriptor = getIndex(BSON("geo" << "2dsphere")); params.startKey = BSON("geo" << BSON("$geoNear" << BSON("$geometry" << BSON("type" << "Point" << "coordinates" << BSON_ARRAY(0 << 0))))); params.endKey = BSONObj(); params.endKeyInclusive = true; params.direction = 1; ASSERT_EQUALS(countResults(params), numObj()); }
/** * We feed a mix of (key, unowned, owned) data to the sort stage. */ void insertVarietyOfObjects(MockStage* ms, Collection* coll) { set<DiskLoc> locs; getLocs(&locs, coll); set<DiskLoc>::iterator it = locs.begin(); for (int i = 0; i < numObj(); ++i, ++it) { ASSERT_FALSE(it == locs.end()); // Insert some owned obj data. WorkingSetMember member; member.loc = *it; member.state = WorkingSetMember::LOC_AND_UNOWNED_OBJ; member.obj = coll->docFor(&_txn, *it); ms->pushBack(member); } }
void run() { Client::WriteContext ctx(&_txn, ns()); Database* db = ctx.ctx().db(); Collection* coll = db->getCollection(&_txn, ns()); if (!coll) { coll = db->createCollection(&_txn, ns()); } WorkingSet* ws = new WorkingSet(); MockStage* ms = new MockStage(ws); for (int i = 0; i < numObj(); ++i) { WorkingSetMember member; member.state = WorkingSetMember::OWNED_OBJ; member.obj = fromjson("{a: [1,2,3], b:[1,2,3], c:[1,2,3], d:[1,2,3,4]}"); ms->pushBack(member); member.obj = fromjson("{a:1, b:1, c:1}"); ms->pushBack(member); } SortStageParams params; params.collection = coll; params.pattern = BSON("b" << -1 << "c" << 1 << "a" << 1); params.limit = 0; // We don't get results back since we're sorting some parallel arrays. PlanExecutor runner(ws, new FetchStage(&_txn, ws, new SortStage(&_txn, params, ws, ms), NULL, coll), coll); PlanExecutor::ExecState runnerState = runner.getNext(NULL, NULL); ASSERT_EQUALS(PlanExecutor::EXEC_ERROR, runnerState); ctx.commit(); }
void run() { Client::ReadContext ctx(&_txn, ns()); // Configure the scan. CollectionScanParams params; params.collection = ctx.ctx().db()->getCollection( &_txn, ns() ); params.direction = CollectionScanParams::FORWARD; params.tailable = false; // Make a scan and have the runner own it. WorkingSet* ws = new WorkingSet(); PlanStage* ps = new CollectionScan(&_txn, params, ws, NULL); PlanExecutor runner(ws, ps, params.collection); int count = 0; for (BSONObj obj; PlanExecutor::ADVANCED == runner.getNext(&obj, NULL); ) { // Make sure we get the objects in the order we want ASSERT_EQUALS(count, obj["foo"].numberInt()); ++count; } ASSERT_EQUALS(numObj(), count); }
/** * Test hiding of parse() and format() APIs in the Format hierarchy. * We test the entire hierarchy, even though this test is located in * the DateFormat API test. */ void IntlTestDateFormatAPI::TestNameHiding(void) { // N.B.: This test passes if it COMPILES, since it's a test of // compile-time name hiding. UErrorCode status = U_ZERO_ERROR; Formattable dateObj(0, Formattable::kIsDate); Formattable numObj(3.1415926535897932384626433832795); Formattable obj; UnicodeString str; FieldPosition fpos; ParsePosition ppos; // DateFormat calling Format API { logln("DateFormat"); DateFormat *dateFmt = DateFormat::createInstance(); if (dateFmt) { dateFmt->format(dateObj, str, status); dateFmt->format(dateObj, str, fpos, status); delete dateFmt; } else { errln("FAIL: Can't create DateFormat"); } } // SimpleDateFormat calling Format & DateFormat API { logln("SimpleDateFormat"); status = U_ZERO_ERROR; SimpleDateFormat sdf(status); // Format API sdf.format(dateObj, str, status); sdf.format(dateObj, str, fpos, status); // DateFormat API sdf.format((UDate)0, str, fpos); sdf.format((UDate)0, str); sdf.parse(str, status); sdf.parse(str, ppos); } // NumberFormat calling Format API { logln("NumberFormat"); status = U_ZERO_ERROR; NumberFormat *fmt = NumberFormat::createInstance(status); if (fmt) { fmt->format(numObj, str, status); fmt->format(numObj, str, fpos, status); delete fmt; } else { errln("FAIL: Can't create NumberFormat()"); } } // DecimalFormat calling Format & NumberFormat API { logln("DecimalFormat"); status = U_ZERO_ERROR; DecimalFormat fmt(status); if(U_SUCCESS(status)) { // Format API fmt.format(numObj, str, status); fmt.format(numObj, str, fpos, status); // NumberFormat API fmt.format(2.71828, str); fmt.format((int32_t)1234567, str); fmt.format(1.41421, str, fpos); fmt.format((int32_t)9876543, str, fpos); fmt.parse(str, obj, ppos); fmt.parse(str, obj, status); } else { errln("FAIL: Couldn't instantiate DecimalFormat, error %s. Quitting test", u_errorName(status)); } } // ChoiceFormat calling Format & NumberFormat API { logln("ChoiceFormat"); status = U_ZERO_ERROR; ChoiceFormat fmt("0#foo|1#foos|2#foos", status); // Format API fmt.format(numObj, str, status); fmt.format(numObj, str, fpos, status); // NumberFormat API fmt.format(2.71828, str); fmt.format((int32_t)1234567, str); fmt.format(1.41421, str, fpos); fmt.format((int32_t)9876543, str, fpos); fmt.parse(str, obj, ppos); fmt.parse(str, obj, status); } // MessageFormat calling Format API { logln("MessageFormat"); status = U_ZERO_ERROR; MessageFormat fmt("", status); // Format API // We use dateObj, which MessageFormat should reject. // We're testing name hiding, not the format method. fmt.format(dateObj, str, status); fmt.format(dateObj, str, fpos, status); } }
void run() { Client::WriteContext ctx(ns()); fillData(); // The data we're going to later invalidate. set<DiskLoc> locs; getLocs(&locs); // Build the mock stage which feeds the data. WorkingSet ws; auto_ptr<MockStage> ms(new MockStage(&ws)); insertVarietyOfObjects(ms.get()); SortStageParams params; params.pattern = BSON("foo" << 1); auto_ptr<SortStage> ss(new SortStage(params, &ws, ms.get())); const int firstRead = 10; // Have sort read in data from the mock stage. for (int i = 0; i < firstRead; ++i) { WorkingSetID id; PlanStage::StageState status = ss->work(&id); ASSERT_NOT_EQUALS(PlanStage::ADVANCED, status); } // We should have read in the first 'firstRead' locs. Invalidate the first. ss->prepareToYield(); set<DiskLoc>::iterator it = locs.begin(); ss->invalidate(*it++); ss->recoverFromYield(); // Read the rest of the data from the mock stage. while (!ms->isEOF()) { WorkingSetID id; ss->work(&id); } // Release to prevent double-deletion. ms.release(); // Let's just invalidate everything now. ss->prepareToYield(); while (it != locs.end()) { ss->invalidate(*it++); } ss->recoverFromYield(); // The sort should still work. int count = 0; while (!ss->isEOF()) { WorkingSetID id; PlanStage::StageState status = ss->work(&id); if (PlanStage::ADVANCED != status) { continue; } WorkingSetMember* member = ws.get(id); ASSERT(member->hasObj()); ASSERT(!member->hasLoc()); ++count; } // We've invalidated everything, but only 2/3 of our data had a DiskLoc to be // invalidated. We get the rest as-is. ASSERT_EQUALS(count, numObj()); }
void run() { Client::WriteContext ctx(&_txn, ns()); Database* db = ctx.ctx().db(); Collection* coll = db->getCollection(&_txn, ns()); if (!coll) { coll = db->createCollection(&_txn, ns()); } fillData(); // The data we're going to later invalidate. set<DiskLoc> locs; getLocs(&locs, coll); // Build the mock scan stage which feeds the data. WorkingSet ws; auto_ptr<MockStage> ms(new MockStage(&ws)); insertVarietyOfObjects(ms.get(), coll); SortStageParams params; params.collection = coll; params.pattern = BSON("foo" << 1); params.limit = limit(); auto_ptr<SortStage> ss(new SortStage(&_txn, params, &ws, ms.get())); const int firstRead = 10; // Have sort read in data from the mock stage. for (int i = 0; i < firstRead; ++i) { WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState status = ss->work(&id); ASSERT_NOT_EQUALS(PlanStage::ADVANCED, status); } // We should have read in the first 'firstRead' locs. Invalidate the first. ss->saveState(); set<DiskLoc>::iterator it = locs.begin(); ss->invalidate(*it++, INVALIDATION_DELETION); ss->restoreState(&_txn); // Read the rest of the data from the mock stage. while (!ms->isEOF()) { WorkingSetID id = WorkingSet::INVALID_ID; ss->work(&id); } // Release to prevent double-deletion. ms.release(); // Let's just invalidate everything now. ss->saveState(); while (it != locs.end()) { ss->invalidate(*it++, INVALIDATION_DELETION); } ss->restoreState(&_txn); // Invalidation of data in the sort stage fetches it but passes it through. int count = 0; while (!ss->isEOF()) { WorkingSetID id = WorkingSet::INVALID_ID; PlanStage::StageState status = ss->work(&id); if (PlanStage::ADVANCED != status) { continue; } WorkingSetMember* member = ws.get(id); ASSERT(member->hasObj()); ASSERT(!member->hasLoc()); ++count; } ctx.commit(); // Returns all docs. ASSERT_EQUALS(limit() ? limit() : numObj(), count); }
void run() { ASSERT_EQUALS(numObj(), countResults(CollectionScanParams::BACKWARD, BSONObj())); }
void fillData() { for (int i = 0; i < numObj(); ++i) { insert(BSON("foo" << i)); } }