// 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/db/matcher/extensions_callback_disallow_extensions.h"
#include "mongo/db/query/collation/collator_interface_mock.h"
#include "mongo/platform/decimal128.h"
#include "mongo/util/log.h"
namespace mongo {
using std::endl;
using std::string;
TEST(MatchExpressionParserLeafTest, NullCollation) {
BSONObj query = BSON("x"
<< "string");
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, Collation) {
BSONObj query = BSON("x"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleEQ2) {
BSONObj query = BSON("x" << BSON("$eq" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, EQNullCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, EQCollation) {
BSONObj query = BSON("x" << BSON("$eq"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleGT1) {
BSONObj query = BSON("x" << BSON("$gt" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, GTNullCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, GTCollation) {
BSONObj query = BSON("x" << BSON("$gt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::GT, result.getValue()->matchType());
GTMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleLT1) {
BSONObj query = BSON("x" << BSON("$lt" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, LTNullCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, LTCollation) {
BSONObj query = BSON("x" << BSON("$lt"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::LT, result.getValue()->matchType());
LTMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleGTE1) {
BSONObj query = BSON("x" << BSON("$gte" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, GTENullCollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, GTECollation) {
BSONObj query = BSON("x" << BSON("$gte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::GTE, result.getValue()->matchType());
GTEMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleLTE1) {
BSONObj query = BSON("x" << BSON("$lte" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, LTENullCollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, LTECollation) {
BSONObj query = BSON("x" << BSON("$lte"
<< "abc"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kReverseString);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::LTE, result.getValue()->matchType());
LTEMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleNE1) {
BSONObj query = BSON("x" << BSON("$ne" << 2));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, NENullCollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::EQ, child->matchType());
EqualityMatchExpression* eqMatch = static_cast(child);
ASSERT_TRUE(eqMatch->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, NECollation) {
BSONObj query = BSON("x" << BSON("$ne"
<< "string"));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::EQ, child->matchType());
EqualityMatchExpression* eqMatch = static_cast(child);
ASSERT_TRUE(eqMatch->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, SimpleModBad1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3)));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2 << 4)));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON_ARRAY("q" << 2)));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << 3));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(!result.isOK());
query = BSON("x" << BSON("$mod" << BSON("a" << 1 << "b" << 2)));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(!result.isOK());
}
TEST(MatchExpressionParserLeafTest, SimpleMod1) {
BSONObj query = BSON("x" << BSON("$mod" << BSON_ARRAY(3 << 2)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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")));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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, IdCollation) {
BSONObj query = BSON("$id"
<< "string");
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, IdNullCollation) {
BSONObj query = BSON("$id"
<< "string");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, RefCollation) {
BSONObj query = BSON("$ref"
<< "coll");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == nullptr);
}
TEST(MatchExpressionParserLeafTest, DbCollation) {
BSONObj query = BSON("$db"
<< "db");
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::EQ, result.getValue()->matchType());
EqualityMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == nullptr);
}
TEST(MatchExpressionParserLeafTest, SimpleIN1) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(2 << 3)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 1)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 2)));
ASSERT(result.getValue()->matchesBSON(BSON("x" << 3)));
}
TEST(MatchExpressionParserLeafTest, INNullCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, INCollation) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::MATCH_IN, result.getValue()->matchType());
InMatchExpression* match = static_cast(result.getValue().get());
ASSERT_TRUE(match->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, INSingleDBRef) {
OID oid = OID::gen();
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$id"
<< oid
<< "$db"
<< "db"))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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"))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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"))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
// second field is not $id
query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$ref"
<< "coll"
<< "$foo"
<< 1))));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
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, ExtensionsCallbackDisallowExtensions(), collator);
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, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INExpressionDocument) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$foo" << 1))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INNotArray) {
BSONObj query = BSON("x" << BSON("$in" << 5));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INUndefined) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSONUndefined)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INNotElemMatch) {
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$elemMatch" << 1))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
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());
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, INRegexTooLong2) {
string tooLargePattern(50 * 1000, 'z');
BSONObj query = BSON("x" << BSON("$in" << BSON_ARRAY(BSON("$regex" << tooLargePattern))));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
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());
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, NINNullCollation) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY("string")));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::MATCH_IN, child->matchType());
InMatchExpression* inMatch = static_cast(child);
ASSERT_TRUE(inMatch->getCollator() == collator);
}
TEST(MatchExpressionParserLeafTest, NINCollation) {
BSONObj query = BSON("x" << BSON("$nin" << BSON_ARRAY("string")));
CollatorInterfaceMock collator(CollatorInterfaceMock::MockType::kAlwaysEqual);
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), &collator);
ASSERT_TRUE(result.isOK());
ASSERT_EQUALS(MatchExpression::NOT, result.getValue()->matchType());
MatchExpression* child = result.getValue()->getChild(0);
ASSERT_EQUALS(MatchExpression::MATCH_IN, child->matchType());
InMatchExpression* inMatch = static_cast(child);
ASSERT_TRUE(inMatch->getCollator() == &collator);
}
TEST(MatchExpressionParserLeafTest, Regex1) {
BSONObjBuilder b;
b.appendRegex("x", "abc", "i");
BSONObj query = b.obj();
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
log() << "result: " << result.getStatus() << endl;
ASSERT_TRUE(result.isOK());
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"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
// $regex does not with numbers
query = BSON("x" << BSON("$regex" << 123));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$regex" << BSON_ARRAY("abc")));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$optionas"
<< "i"));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
query = BSON("x" << BSON("$options"
<< "i"));
result = MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, RegexEmbeddedNULByte) {
BSONObj query = BSON("x" << BSON("$regex"
<< "^a\\x00b"));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
StringData value("a\0b", StringData::LiteralTag());
ASSERT(result.getValue()->matchesBSON(BSON("x" << value)));
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "a")));
}
TEST(MatchExpressionParserLeafTest, ExistsYes1) {
BSONObjBuilder b;
b.appendBool("$exists", true);
BSONObj query = BSON("x" << b.obj());
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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());
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x"
<< "abc")));
ASSERT(result.getValue()->matchesBSON(BSON("y"
<< "AC")));
}
TEST(MatchExpressionParserLeafTest, Type1) {
BSONObj query = BSON("x" << BSON("$type" << String));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5.3)));
ASSERT(!result.getValue()->matchesBSON(BSON("x" << 5)));
}
TEST(MatchExpressionParserLeafTest, TypeDecimalOperator) {
BSONObj query = BSON("x" << BSON("$type" << mongo::NumberDecimal));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
ASSERT_FALSE(result.getValue()->matchesBSON(BSON("x" << 5.3)));
ASSERT_TRUE(result.getValue()->matchesBSON(BSON("x" << mongo::Decimal128("1"))));
}
TEST(MatchExpressionParserLeafTest, TypeNull) {
BSONObj query = BSON("x" << BSON("$type" << jstNULL));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_TRUE(result.isOK());
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());
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_NOT_OK(result.getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeBad) {
BSONObj query = BSON("x" << BSON("$type" << BSON("x" << 1)));
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression result =
MatchExpressionParser::parse(query, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_FALSE(result.isOK());
}
TEST(MatchExpressionParserLeafTest, TypeBadString) {
const CollatorInterface* collator = nullptr;
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: null}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: true}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: {}}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(fromjson("{a: {$type: ObjectId('000000000000000000000000')}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$type: []}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserLeafTest, TypeStringnameDouble) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumberDouble = MatchExpressionParser::parse(
fromjson("{a: {$type: 'double'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeNumberDouble.getStatus());
TypeMatchExpression* tmeNumberDouble =
static_cast(typeNumberDouble.getValue().get());
ASSERT(tmeNumberDouble->getType() == NumberDouble);
ASSERT_TRUE(tmeNumberDouble->matchesBSON(fromjson("{a: 5.4}")));
ASSERT_FALSE(tmeNumberDouble->matchesBSON(fromjson("{a: NumberInt(5)}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringNameNumberDecimal) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumberDecimal = MatchExpressionParser::parse(
fromjson("{a: {$type: 'decimal'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeNumberDecimal.getStatus());
TypeMatchExpression* tmeNumberDecimal =
static_cast(typeNumberDecimal.getValue().get());
ASSERT(tmeNumberDecimal->getType() == NumberDecimal);
ASSERT_TRUE(tmeNumberDecimal->matchesBSON(BSON("a" << mongo::Decimal128("1"))));
ASSERT_FALSE(tmeNumberDecimal->matchesBSON(fromjson("{a: true}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberInt) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumberInt = MatchExpressionParser::parse(
fromjson("{a: {$type: 'int'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeNumberInt.getStatus());
TypeMatchExpression* tmeNumberInt =
static_cast(typeNumberInt.getValue().get());
ASSERT(tmeNumberInt->getType() == NumberInt);
ASSERT_TRUE(tmeNumberInt->matchesBSON(fromjson("{a: NumberInt(5)}")));
ASSERT_FALSE(tmeNumberInt->matchesBSON(fromjson("{a: 5.4}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumberLong) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumberLong = MatchExpressionParser::parse(
fromjson("{a: {$type: 'long'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeNumberLong.getStatus());
TypeMatchExpression* tmeNumberLong =
static_cast(typeNumberLong.getValue().get());
ASSERT(tmeNumberLong->getType() == NumberLong);
ASSERT_TRUE(tmeNumberLong->matchesBSON(BSON("a" << -1LL)));
ASSERT_FALSE(tmeNumberLong->matchesBSON(fromjson("{a: true}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameString) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeString = MatchExpressionParser::parse(
fromjson("{a: {$type: 'string'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeString.getStatus());
TypeMatchExpression* tmeString = static_cast(typeString.getValue().get());
ASSERT(tmeString->getType() == String);
ASSERT_TRUE(tmeString->matchesBSON(fromjson("{a: 'hello world'}")));
ASSERT_FALSE(tmeString->matchesBSON(fromjson("{a: 5.4}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnamejstOID) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typejstOID = MatchExpressionParser::parse(
fromjson("{a: {$type: 'objectId'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typejstOID.getStatus());
TypeMatchExpression* tmejstOID = static_cast(typejstOID.getValue().get());
ASSERT(tmejstOID->getType() == jstOID);
ASSERT_TRUE(tmejstOID->matchesBSON(fromjson("{a: ObjectId('000000000000000000000000')}")));
ASSERT_FALSE(tmejstOID->matchesBSON(fromjson("{a: 'hello world'}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnamejstNULL) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typejstNULL = MatchExpressionParser::parse(
fromjson("{a: {$type: 'null'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typejstNULL.getStatus());
TypeMatchExpression* tmejstNULL =
static_cast(typejstNULL.getValue().get());
ASSERT(tmejstNULL->getType() == jstNULL);
ASSERT_TRUE(tmejstNULL->matchesBSON(fromjson("{a: null}")));
ASSERT_FALSE(tmejstNULL->matchesBSON(fromjson("{a: true}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameBool) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeBool = MatchExpressionParser::parse(
fromjson("{a: {$type: 'bool'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeBool.getStatus());
TypeMatchExpression* tmeBool = static_cast(typeBool.getValue().get());
ASSERT(tmeBool->getType() == Bool);
ASSERT_TRUE(tmeBool->matchesBSON(fromjson("{a: true}")));
ASSERT_FALSE(tmeBool->matchesBSON(fromjson("{a: null}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameObject) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeObject = MatchExpressionParser::parse(
fromjson("{a: {$type: 'object'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeObject.getStatus());
TypeMatchExpression* tmeObject = static_cast(typeObject.getValue().get());
ASSERT(tmeObject->getType() == Object);
ASSERT_TRUE(tmeObject->matchesBSON(fromjson("{a: {}}")));
ASSERT_FALSE(tmeObject->matchesBSON(fromjson("{a: []}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameArray) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeArray = MatchExpressionParser::parse(
fromjson("{a: {$type: 'array'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeArray.getStatus());
TypeMatchExpression* tmeArray = static_cast(typeArray.getValue().get());
ASSERT(tmeArray->getType() == Array);
ASSERT_TRUE(tmeArray->matchesBSON(fromjson("{a: [[]]}")));
ASSERT_FALSE(tmeArray->matchesBSON(fromjson("{a: {}}")));
}
TEST(MatchExpressionParserLeafTest, TypeStringnameNumber) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
fromjson("{a: {$type: 'number'}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(typeNumber.getStatus());
TypeMatchExpression* tmeNumber = static_cast(typeNumber.getValue().get());
ASSERT_TRUE(tmeNumber->matchesBSON(fromjson("{a: 5.4}")));
ASSERT_TRUE(tmeNumber->matchesBSON(fromjson("{a: NumberInt(5)}")));
ASSERT_TRUE(tmeNumber->matchesBSON(BSON("a" << -1LL)));
ASSERT_FALSE(tmeNumber->matchesBSON(fromjson("{a: ''}")));
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeLessThanMinKeyFailsToParse) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
fromjson("{a: {$type: -20}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeGreaterThanMaxKeyFailsToParse) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
fromjson("{a: {$type: 400}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, InvalidTypeCodeUnusedBetweenMinAndMaxFailsToParse) {
const CollatorInterface* collator = nullptr;
StatusWithMatchExpression typeNumber = MatchExpressionParser::parse(
fromjson("{a: {$type: 62}}"), ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_NOT_OK(typeNumber.getStatus());
}
TEST(MatchExpressionParserLeafTest, ValidTypeCodesParseSuccessfully) {
std::vector validTypes{
MinKey, EOO, NumberDouble, String, Object, Array, BinData,
Undefined, jstOID, Bool, Date, jstNULL, RegEx, DBRef,
Code, Symbol, CodeWScope, NumberInt, bsonTimestamp, NumberLong, MaxKey};
for (auto type : validTypes) {
BSONObj predicate = BSON("a" << BSON("$type" << type));
const CollatorInterface* collator = nullptr;
auto expression = MatchExpressionParser::parse(
predicate, ExtensionsCallbackDisallowExtensions(), collator);
ASSERT_OK(expression.getStatus());
auto typeExpression = static_cast(expression.getValue().get());
ASSERT_EQ(type, typeExpression->getType());
}
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidMask) {
const double k2Power53 = scalbn(1, 32);
const CollatorInterface* collator = nullptr;
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << 54)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << k2Power53 - 1)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << 54)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << k2Power53 - 1)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << 54)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << k2Power53 - 1)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << 54)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << k2Power53 - 1)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidArray) {
BSONArray bsonArrayLongLong = BSON_ARRAY(0LL << 1LL << 2LL << 3LL);
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[0].type());
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[1].type());
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[2].type());
ASSERT_EQ(BSONType::NumberLong, bsonArrayLongLong[3].type());
const CollatorInterface* collator = nullptr;
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(0 << 1 << 2 << 3))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << bsonArrayLongLong)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(0 << 1 << 2 << 3))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << bsonArrayLongLong)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(0 << 1 << 2 << 3))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << bsonArrayLongLong)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(0 << 1 << 2 << 3))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << bsonArrayLongLong)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionValidBinData) {
const CollatorInterface* collator = nullptr;
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAllSet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson("{a: {$bitsAnySet: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: {$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskType) {
const CollatorInterface* collator = nullptr;
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: null}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: true}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: {}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ''}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: null}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: true}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: {}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ''}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
fromjson("{a: {$bitsAllClear: ObjectId('000000000000000000000000')}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: null}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: true}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: {}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ''}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
fromjson("{a: {$bitsAnySet: ObjectId('000000000000000000000000')}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: null}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: true}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: {}}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ''}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
fromjson("{a: {$bitsAnyClear: ObjectId('000000000000000000000000')}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidMaskValue) {
const double kLongLongMaxAsDouble = scalbn(1, std::numeric_limits::digits);
const CollatorInterface* collator = nullptr;
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: NaN}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: -54}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllSet" << kLongLongMaxAsDouble)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: 2.5}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: NaN}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: -54}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(BSON("a" << BSON("$bitsAllClear" << kLongLongMaxAsDouble)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: 2.5}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: NaN}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: -54}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnySet" << kLongLongMaxAsDouble)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: 2.5}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: NaN}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: -54}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << std::numeric_limits::max())),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(BSON("a" << BSON("$bitsAnyClear" << kLongLongMaxAsDouble)),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: 2.5}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArray) {
const CollatorInterface* collator = nullptr;
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [null]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [true]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: ['']}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [{}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [[]]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllSet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [null]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [true]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: ['']}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [{}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [[]]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAllClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [null]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [true]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: ['']}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [{}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [[]]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnySet: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [null]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [true]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: ['']}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [{}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [[]]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
fromjson(
"{a: {$bitsAnyClear: [{$binary: 'AAAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
TEST(MatchExpressionParserTest, BitTestMatchExpressionInvalidArrayValue) {
const CollatorInterface* collator = nullptr;
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-54]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [NaN]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllSet: [-1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllSet" << BSON_ARRAY(std::numeric_limits::min()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-54]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [NaN]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAllClear: [-1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAllClear" << BSON_ARRAY(std::numeric_limits::min()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-54]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [NaN]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnySet: [-1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnySet" << BSON_ARRAY(std::numeric_limits::min()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-54]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [NaN]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [2.5]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(MatchExpressionParser::parse(fromjson("{a: {$bitsAnyClear: [-1e100]}}"),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits::max()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
ASSERT_NOT_OK(
MatchExpressionParser::parse(
BSON("a" << BSON("$bitsAnyClear" << BSON_ARRAY(std::numeric_limits::min()))),
ExtensionsCallbackDisallowExtensions(),
collator)
.getStatus());
}
}