diff options
Diffstat (limited to 'src/mongo/db/matcher/expression_leaf_test.cpp')
-rw-r--r-- | src/mongo/db/matcher/expression_leaf_test.cpp | 554 |
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"])); +} } |