summaryrefslogtreecommitdiff
path: root/src/mongo/db/matcher/expression_leaf_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/matcher/expression_leaf_test.cpp')
-rw-r--r--src/mongo/db/matcher/expression_leaf_test.cpp554
1 files changed, 554 insertions, 0 deletions
diff --git a/src/mongo/db/matcher/expression_leaf_test.cpp b/src/mongo/db/matcher/expression_leaf_test.cpp
index ff3f65efb34..efe64befcd3 100644
--- a/src/mongo/db/matcher/expression_leaf_test.cpp
+++ b/src/mongo/db/matcher/expression_leaf_test.cpp
@@ -1716,4 +1716,558 @@ TEST( InMatchExpression, MatchesIndexKeyArrayValue ) {
"" << BSON_ARRAY( 8 << "ac" ) ), indexSpec ) );
}
*/
+
+std::vector<uint32_t> bsonArrayToBitPositions(const BSONArray& ba) {
+ std::vector<uint32_t> bitPositions;
+
+ // Convert BSONArray of bit positions to int vector
+ for (const auto& elt : ba) {
+ bitPositions.push_back(elt._numberInt());
+ }
+
+ return bitPositions;
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchOther) {
+ std::vector<uint32_t> bitPositions;
+
+ BSONObj notMatch1 = fromjson("{a: {}}"); // Object
+ BSONObj notMatch2 = fromjson("{a: null}"); // Null
+ BSONObj notMatch3 = fromjson("{a: []}"); // Array
+ BSONObj notMatch4 = fromjson("{a: true}"); // Boolean
+ BSONObj notMatch5 = fromjson("{a: ''}"); // String
+ BSONObj notMatch6 = fromjson("{a: 5.5}"); // Non-integral Double
+ BSONObj notMatch7 = fromjson("{a: NaN}"); // NaN
+ BSONObj notMatch8 = fromjson("{a: 1e100}"); // Too-Large Double
+ BSONObj notMatch9 = fromjson("{a: ObjectId('000000000000000000000000')}"); // OID
+ BSONObj notMatch10 = fromjson("{a: Date(54)}"); // Date
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositions));
+ ASSERT_OK(ballc.init("a", bitPositions));
+ ASSERT_OK(banys.init("a", bitPositions));
+ ASSERT_OK(banyc.init("a", bitPositions));
+ ASSERT_EQ((size_t)0, balls.numBitPositions());
+ ASSERT_EQ((size_t)0, ballc.numBitPositions());
+ ASSERT_EQ((size_t)0, banys.numBitPositions());
+ ASSERT_EQ((size_t)0, banyc.numBitPositions());
+ ASSERT(!balls.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch2["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch3["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch4["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch5["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch6["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch7["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch8["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch9["a"]));
+ ASSERT(!balls.matchesSingleElement(notMatch10["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch2["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch3["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch4["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch5["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch6["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch7["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch8["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch9["a"]));
+ ASSERT(!ballc.matchesSingleElement(notMatch10["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch2["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch3["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch4["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch5["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch6["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch7["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch8["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch9["a"]));
+ ASSERT(!banys.matchesSingleElement(notMatch10["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch1["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch2["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch3["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch4["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch5["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch6["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch7["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch8["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch9["a"]));
+ ASSERT(!banyc.matchesSingleElement(notMatch10["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchBinaryWithLongBitMask) {
+ long long bitMask = 54;
+
+ BSONObj match = fromjson("{a: {$binary: 'NgAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitMask));
+ ASSERT_OK(ballc.init("a", bitMask));
+ ASSERT_OK(banys.init("a", bitMask));
+ ASSERT_OK(banyc.init("a", bitMask));
+ std::vector<uint32_t> bitPositions = balls.getBitPositions();
+ ASSERT(balls.matchesSingleElement(match["a"]));
+ ASSERT(!ballc.matchesSingleElement(match["a"]));
+ ASSERT(banys.matchesSingleElement(match["a"]));
+ ASSERT(!banyc.matchesSingleElement(match["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchLongWithBinaryBitMask) {
+ const char* bitMask = "\x36\x00\x00\x00";
+
+ BSONObj match = fromjson("{a: 54}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitMask, 4));
+ ASSERT_OK(ballc.init("a", bitMask, 4));
+ ASSERT_OK(banys.init("a", bitMask, 4));
+ ASSERT_OK(banyc.init("a", bitMask, 4));
+ ASSERT(balls.matchesSingleElement(match["a"]));
+ ASSERT(!ballc.matchesSingleElement(match["a"]));
+ ASSERT(banys.matchesSingleElement(match["a"]));
+ ASSERT(!banyc.matchesSingleElement(match["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesEmpty) {
+ std::vector<uint32_t> bitPositions;
+
+ BSONObj match1 = fromjson("{a: NumberInt(54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(54)}");
+ BSONObj match3 = fromjson("{a: 54.0}");
+ BSONObj match4 = fromjson("{a: {$binary: '2AAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositions));
+ ASSERT_OK(ballc.init("a", bitPositions));
+ ASSERT_OK(banys.init("a", bitPositions));
+ ASSERT_OK(banyc.init("a", bitPositions));
+ ASSERT_EQ((size_t)0, balls.numBitPositions());
+ ASSERT_EQ((size_t)0, ballc.numBitPositions());
+ ASSERT_EQ((size_t)0, banys.numBitPositions());
+ ASSERT_EQ((size_t)0, banyc.numBitPositions());
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(balls.matchesSingleElement(match3["a"]));
+ ASSERT(balls.matchesSingleElement(match4["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match3["a"]));
+ ASSERT(ballc.matchesSingleElement(match4["a"]));
+ ASSERT(!banys.matchesSingleElement(match1["a"]));
+ ASSERT(!banys.matchesSingleElement(match2["a"]));
+ ASSERT(!banys.matchesSingleElement(match3["a"]));
+ ASSERT(!banys.matchesSingleElement(match4["a"]));
+ ASSERT(!banyc.matchesSingleElement(match1["a"]));
+ ASSERT(!banyc.matchesSingleElement(match2["a"]));
+ ASSERT(!banyc.matchesSingleElement(match3["a"]));
+ ASSERT(!banyc.matchesSingleElement(match4["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesInteger) {
+ BSONArray bas = BSON_ARRAY(1 << 2 << 4 << 5);
+ BSONArray bac = BSON_ARRAY(0 << 3 << 600);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: NumberInt(54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(54)}");
+ BSONObj match3 = fromjson("{a: 54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)4, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)4, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(balls.matchesSingleElement(match3["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesNegativeInteger) {
+ BSONArray bas = BSON_ARRAY(1 << 3 << 6 << 7 << 33);
+ BSONArray bac = BSON_ARRAY(0 << 2 << 4 << 5);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: NumberInt(-54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(-54)}");
+ BSONObj match3 = fromjson("{a: -54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)5, balls.numBitPositions());
+ ASSERT_EQ((size_t)4, ballc.numBitPositions());
+ ASSERT_EQ((size_t)5, banys.numBitPositions());
+ ASSERT_EQ((size_t)4, banyc.numBitPositions());
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(balls.matchesSingleElement(match3["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesIntegerWithBitMask) {
+ long long bitMaskSet = 54;
+ long long bitMaskClear = 201;
+
+ BSONObj match1 = fromjson("{a: NumberInt(54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(54)}");
+ BSONObj match3 = fromjson("{a: 54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitMaskSet));
+ ASSERT_OK(ballc.init("a", bitMaskClear));
+ ASSERT_OK(banys.init("a", bitMaskSet));
+ ASSERT_OK(banyc.init("a", bitMaskClear));
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(balls.matchesSingleElement(match3["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesNegativeIntegerWithBitMask) {
+ long long bitMaskSet = 10;
+ long long bitMaskClear = 5;
+
+ BSONObj match1 = fromjson("{a: NumberInt(-54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(-54)}");
+ BSONObj match3 = fromjson("{a: -54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitMaskSet));
+ ASSERT_OK(ballc.init("a", bitMaskClear));
+ ASSERT_OK(banys.init("a", bitMaskSet));
+ ASSERT_OK(banyc.init("a", bitMaskClear));
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(balls.matchesSingleElement(match3["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchInteger) {
+ BSONArray bas = BSON_ARRAY(1 << 2 << 4 << 5 << 6);
+ BSONArray bac = BSON_ARRAY(0 << 3 << 1);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: NumberInt(54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(54)}");
+ BSONObj match3 = fromjson("{a: 54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)5, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)5, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(!balls.matchesSingleElement(match1["a"]));
+ ASSERT(!balls.matchesSingleElement(match2["a"]));
+ ASSERT(!balls.matchesSingleElement(match3["a"]));
+ ASSERT(!ballc.matchesSingleElement(match1["a"]));
+ ASSERT(!ballc.matchesSingleElement(match2["a"]));
+ ASSERT(!ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchIntegerWithBitMask) {
+ long long bitMaskSet = 118;
+ long long bitMaskClear = 11;
+
+ BSONObj match1 = fromjson("{a: NumberInt(54)}");
+ BSONObj match2 = fromjson("{a: NumberLong(54)}");
+ BSONObj match3 = fromjson("{a: 54.0}");
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitMaskSet));
+ ASSERT_OK(ballc.init("a", bitMaskClear));
+ ASSERT_OK(banys.init("a", bitMaskSet));
+ ASSERT_OK(banyc.init("a", bitMaskClear));
+ ASSERT(!balls.matchesSingleElement(match1["a"]));
+ ASSERT(!balls.matchesSingleElement(match2["a"]));
+ ASSERT(!balls.matchesSingleElement(match3["a"]));
+ ASSERT(!ballc.matchesSingleElement(match1["a"]));
+ ASSERT(!ballc.matchesSingleElement(match2["a"]));
+ ASSERT(!ballc.matchesSingleElement(match3["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match3["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match3["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesBinary1) {
+ BSONArray bas = BSON_ARRAY(1 << 2 << 4 << 5);
+ BSONArray bac = BSON_ARRAY(0 << 3 << 600);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: {$binary: 'NgAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00110110...
+ BSONObj match2 = fromjson("{a: {$binary: 'NgAjqwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: 00110110...
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)4, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)4, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesBinary2) {
+ BSONArray bas = BSON_ARRAY(21 << 22 << 8 << 9);
+ BSONArray bac = BSON_ARRAY(20 << 23 << 612);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: {$binary: 'AANgAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00000000 00000011 01100000
+ BSONObj match2 = fromjson("{a: {$binary: 'JANgqwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: ........ 00000011 01100000
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)4, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)4, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
+
+TEST(BitTestMatchExpression, MatchesBinaryWithBitMask) {
+ const char* bas = "\0\x03\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+ const char* bac = "\0\xFC\x9F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
+
+ BSONObj match1 = fromjson("{a: {$binary: 'AANgAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00000000 00000011 01100000
+ BSONObj match2 = fromjson("{a: {$binary: 'JANgAwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: ........ 00000011 01100000
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+ ASSERT_OK(balls.init("a", bas, 21));
+ ASSERT_OK(ballc.init("a", bac, 21));
+ ASSERT_OK(banys.init("a", bas, 21));
+ ASSERT_OK(banyc.init("a", bac, 21));
+ ASSERT(balls.matchesSingleElement(match1["a"]));
+ ASSERT(balls.matchesSingleElement(match2["a"]));
+ ASSERT(ballc.matchesSingleElement(match1["a"]));
+ ASSERT(ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchBinary1) {
+ BSONArray bas = BSON_ARRAY(1 << 2 << 4 << 5 << 6);
+ BSONArray bac = BSON_ARRAY(0 << 3 << 1);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: {$binary: 'NgAAAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00110110...
+ BSONObj match2 = fromjson("{a: {$binary: 'NgAjqwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: 00110110...
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)5, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)5, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(!balls.matchesSingleElement(match1["a"]));
+ ASSERT(!balls.matchesSingleElement(match2["a"]));
+ ASSERT(!ballc.matchesSingleElement(match1["a"]));
+ ASSERT(!ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchBinary2) {
+ BSONArray bas = BSON_ARRAY(21 << 22 << 23 << 24 << 25);
+ BSONArray bac = BSON_ARRAY(20 << 23 << 21);
+ std::vector<uint32_t> bitPositionsSet = bsonArrayToBitPositions(bas);
+ std::vector<uint32_t> bitPositionsClear = bsonArrayToBitPositions(bac);
+
+ BSONObj match1 = fromjson("{a: {$binary: 'AANgAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00000000 00000011 01100000
+ BSONObj match2 = fromjson("{a: {$binary: 'JANgqwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: ........ 00000011 01100000
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+
+ ASSERT_OK(balls.init("a", bitPositionsSet));
+ ASSERT_OK(ballc.init("a", bitPositionsClear));
+ ASSERT_OK(banys.init("a", bitPositionsSet));
+ ASSERT_OK(banyc.init("a", bitPositionsClear));
+ ASSERT_EQ((size_t)5, balls.numBitPositions());
+ ASSERT_EQ((size_t)3, ballc.numBitPositions());
+ ASSERT_EQ((size_t)5, banys.numBitPositions());
+ ASSERT_EQ((size_t)3, banyc.numBitPositions());
+ ASSERT(!balls.matchesSingleElement(match1["a"]));
+ ASSERT(!balls.matchesSingleElement(match2["a"]));
+ ASSERT(!ballc.matchesSingleElement(match1["a"]));
+ ASSERT(!ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
+
+TEST(BitTestMatchExpression, DoesNotMatchBinaryWithBitMask) {
+ const char* bas = "\0\x03\x60\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xFF";
+ const char* bac = "\0\xFD\x9F\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\xFF";
+
+ BSONObj match1 = fromjson("{a: {$binary: 'AANgAAAAAAAAAAAAAAAAAAAAAAAA', $type: '00'}}");
+ // Base64 to Binary: 00000000 00000011 01100000
+ BSONObj match2 = fromjson("{a: {$binary: 'JANgAwetkqwklEWRbWERKKJREtbq', $type: '00'}}");
+ // Base64 to Binary: ........ 00000011 01100000
+
+ BitsAllSetMatchExpression balls;
+ BitsAllClearMatchExpression ballc;
+ BitsAnySetMatchExpression banys;
+ BitsAnyClearMatchExpression banyc;
+ ASSERT_OK(balls.init("a", bas, 22));
+ ASSERT_OK(ballc.init("a", bac, 22));
+ ASSERT_OK(banys.init("a", bas, 22));
+ ASSERT_OK(banyc.init("a", bac, 22));
+ ASSERT(!balls.matchesSingleElement(match1["a"]));
+ ASSERT(!balls.matchesSingleElement(match2["a"]));
+ ASSERT(!ballc.matchesSingleElement(match1["a"]));
+ ASSERT(!ballc.matchesSingleElement(match2["a"]));
+ ASSERT(banys.matchesSingleElement(match1["a"]));
+ ASSERT(banys.matchesSingleElement(match2["a"]));
+ ASSERT(banyc.matchesSingleElement(match1["a"]));
+ ASSERT(banyc.matchesSingleElement(match2["a"]));
+}
}