// expression_parser_leaf_test.cpp
/**
* Copyright (C) 2013 10gen Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*
* As a special exception, the copyright holders give permission to link the
* code of portions of this program with the OpenSSL library under certain
* conditions as described in each individual source file and distribute
* linked combinations including the program with the OpenSSL library. You
* must comply with the GNU Affero General Public License in all respects for
* all of the code used other than as permitted herein. If you modify file(s)
* with this exception, you may extend this exception to your version of the
* file(s), but you are not obligated to do so. If you do not wish to do so,
* delete this exception statement from your version. If you delete this
* exception statement from all source files in the program, then also delete
* it in the license file.
*/
#define MONGO_LOG_DEFAULT_COMPONENT ::mongo::logger::LogComponent::kDefault
#include "mongo/unittest/unittest.h"
#include "mongo/db/matcher/expression_parser.h"
#include "mongo/db/jsobj.h"
#include "mongo/db/json.h"
#include "mongo/db/matcher/expression.h"
#include "mongo/db/matcher/expression_leaf.h"
#include "mongo/util/log.h"
namespace mongo {
using std::endl;
using std::string;
TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
BSONObj query = BSON("x" << BSON("$eq" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleEQUndefined) {
BSONObj query = BSON("x" << BSON("$eq" << BSONUndefined));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, SimpleGT1) {
BSONObj query = BSON("x" << BSON("$gt" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleLT1) {
BSONObj query = BSON("x" << BSON("$lt" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleGTE1) {
BSONObj query = BSON("x" << BSON("$gte" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleLTE1) {
BSONObj query = BSON("x" << BSON("$lte" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleNE1) {
BSONObj query = BSON("x" << BSON("$ne" << 2));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, SimpleModBad1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy1(result.getValue());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3)));
result = MatchExpressionParser::parse(query);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2 << 4)));
result = MatchExpressionParser::parse(query);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON_ARRAY("q" << 2)));
result = MatchExpressionParser::parse(query);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << 3));
result = MatchExpressionParser::parse(query);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON("a" << 1 << "b" << 2)));
result = MatchExpressionParser::parse(query);
ASSERT_TRUE(!result.isOK());
}
TEST(MatchExpressionParserLeafTest, SimpleMod1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 4)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 8)));
}
TEST(MatchExpressionParserLeafTest, SimpleModNotNumber) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(2 << "r")));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 4)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "a")));
}
TEST(MatchExpressionParserLeafTest, SimpleIN1) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(2 << 3)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, INSingleDBRef) {
OID oid = OID::gen();
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db"))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
OID oidx = OID::gen();
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oidx << "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$id" << oid << "$ref"
<< "coll"
<< "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$id" << oid << "$ref"
<< "coll"
<< "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$id" << oid << "$ref"
<< "coll"
<< "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "dbx"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$db"
<< "db"
<< "$ref"
<< "coll"
<< "$id" << oid))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db"))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db")))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db")))));
}
TEST(MatchExpressionParserLeafTest, INMultipleDBRef) {
OID oid = OID::gen();
OID oidy = OID::gen();
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "colly"
<< "$id" << oidy << "$db"
<< "db")
<< BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db"))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
OID oidx = OID::gen();
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oidx << "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$id" << oid << "$ref"
<< "coll"
<< "$db"
<< "db"))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oidy << "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "colly"
<< "$id" << oid << "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$id" << oid << "$ref"
<< "coll"
<< "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "dbx")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$id" << oidy << "$ref"
<< "colly"
<< "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "coll"
<< "$id" << oidx << "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "colly"
<< "$id" << oidx << "$db"
<< "db")))));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "dbx")))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db"))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "colly"
<< "$id" << oidy << "$db"
<< "db"))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db")))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "colly"
<< "$id" << oidy << "$db"
<< "db")))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "coll"
<< "$id" << oid << "$db"
<< "db")))));
ASSERT(result.getValue()->matchesBSON(BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "$db"
<< "db")
<< BSON("$ref"
<< "colly"
<< "$id" << oidy << "$db"
<< "db")))));
}
TEST(MatchExpressionParserLeafTest, INDBRefWithOptionalField1) {
OID oid = OID::gen();
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "foo" << 12345))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
OID oidx = OID::gen();
ASSERT(!result.getValue()->matchesBSON(BSON("x" << BSON("$ref"
<< "coll"
<< "$id" << oidx << "$db"
<< "db"))));
ASSERT(result.getValue()->matchesBSON(
BSON("x" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id" << oid << "foo" << 12345)))));
ASSERT(result.getValue()->matchesBSON(
BSON("x" << BSON_ARRAY(BSON("$ref"
<< "collx"
<< "$id" << oidx << "foo" << 12345)
<< BSON("$ref"
<< "coll"
<< "$id" << oid << "foo" << 12345)))));
}
TEST(MatchExpressionParserLeafTest, INInvalidDBRefs) {
// missing $id
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
result = MatchExpressionParser::parse(query);
// second field is not $id
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$foo" << 1))));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
OID oid = OID::gen();
// missing $ref field
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$id" << oid << "foo" << 3))));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
// missing $id and $ref field
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$db"
<< "test"
<< "foo" << 3))));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INExpressionDocument) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$foo" << 1))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INNotArray) {
BSONObj query = BSON("x" << BSON("$in" << 5));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INUndefined) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSONUndefined)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INNotElemMatch) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$elemMatch" << 1))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INRegexTooLong) {
string tooLargePattern(50 * 1000, 'z');
BSONObjBuilder inArray;
inArray.appendRegex("0", tooLargePattern, "");
BSONObjBuilder operand;
operand.appendArray("$in", inArray.obj());
BSONObj query = BSON("x" << operand.obj());
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INRegexTooLong2) {
string tooLargePattern(50 * 1000, 'z');
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$regex" << tooLargePattern))));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INRegexStuff) {
BSONObjBuilder inArray;
inArray.appendRegex("0", "^a", "");
inArray.appendRegex("1", "B", "i");
inArray.append("2", 4);
BSONObjBuilder operand;
operand.appendArray("$in", inArray.obj());
BSONObj query = BSON("a" << operand.obj());
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
BSONObj matchFirst = BSON("a"
<< "ax");
BSONObj matchFirstRegex = BSONObjBuilder().appendRegex("a", "^a", "").obj();
BSONObj matchSecond = BSON("a"
<< "qqb");
BSONObj matchSecondRegex = BSONObjBuilder().appendRegex("a", "B", "i").obj();
BSONObj matchThird = BSON("a" << 4);
BSONObj notMatch = BSON("a"
<< "l");
BSONObj notMatchRegex = BSONObjBuilder().appendRegex("a", "B", "").obj();
ASSERT(result.getValue()->matchesBSON(matchFirst));
ASSERT(result.getValue()->matchesBSON(matchFirstRegex));
ASSERT(result.getValue()->matchesBSON(matchSecond));
ASSERT(result.getValue()->matchesBSON(matchSecondRegex));
ASSERT(result.getValue()->matchesBSON(matchThird));
ASSERT(!result.getValue()->matchesBSON(notMatch));
ASSERT(!result.getValue()->matchesBSON(notMatchRegex));
}
TEST(MatchExpressionParserLeafTest, SimpleNIN1) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY(2 << 3)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, NINNotArray) {
BSONObj query = BSON("x" << BSON("$nin" << 5));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, Regex1) {
BSONObjBuilder b;
b.appendRegex("x", "abc", "i");
BSONObj query = b.obj();
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "ABC")));
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, Regex2) {
BSONObj query = BSON("x" << BSON("$regex"
<< "abc"
<< "$options"
<< "i"));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "ABC")));
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, Regex3) {
BSONObj query = BSON("x" << BSON("$options"
<< "i"
<< "$regex"
<< "abc"));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
log() << "result: " << result.getStatus() << endl;
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "ABC")));
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, RegexBad) {
BSONObj query = BSON("x" << BSON("$regex"
<< "abc"
<< "$optionas"
<< "i"));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
// $regex does not with numbers
query = BSON("x" << BSON("$regex" << 123));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$regex" << BSON_ARRAY("abc")));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$optionas"
<< "i"));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$options"
<< "i"));
result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, ExistsYes1) {
BSONObjBuilder b;
b.appendBool("$exists", true);
BSONObj query = BSON("x" << b.obj());
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(!result.getValue()->matchesBSON(BSON("y"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, ExistsNO1) {
BSONObjBuilder b;
b.appendBool("$exists", false);
BSONObj query = BSON("x" << b.obj());
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(result.getValue()->matchesBSON(BSON("y"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, Type1) {
BSONObj query = BSON("x" << BSON("$type" << String));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
}
TEST(MatchExpressionParserLeafTest, Type2) {
BSONObj query = BSON("x" << BSON("$type" << (double)NumberDouble));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 5.3)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
}
TEST(MatchExpressionParserLeafTest, TypeDoubleOperator) {
BSONObj query = BSON("x" << BSON("$type" << 1.5));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
}
TEST(MatchExpressionParserLeafTest, TypeNull) {
BSONObj query = BSON("x" << BSON("$type" << jstNULL));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSONObj()));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
BSONObjBuilder b;
b.appendNull("x");
ASSERT(result.getValue()->matchesBSON(b.obj()));
}
TEST(MatchExpressionParserLeafTest, TypeBadType) {
BSONObjBuilder b;
b.append("$type", (JSTypeMax + 1));
BSONObj query = BSON("x" << b.obj());
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_TRUE(result.isOK());
std::unique_ptr destroy(result.getValue());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
}
TEST(MatchExpressionParserLeafTest, TypeBad) {
BSONObj query = BSON("x" << BSON("$type" << BSON("x" << 1)));
StatusWithMatchExpression result = MatchExpressionParser::parse(query);
ASSERT_FALSE(result.isOK());
}
}