diff options
Diffstat (limited to 'src/mongo/db/exec/sbe/sbe_test.cpp')
-rw-r--r-- | src/mongo/db/exec/sbe/sbe_test.cpp | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/mongo/db/exec/sbe/sbe_test.cpp b/src/mongo/db/exec/sbe/sbe_test.cpp index 323368a5334..5a577f02462 100644 --- a/src/mongo/db/exec/sbe/sbe_test.cpp +++ b/src/mongo/db/exec/sbe/sbe_test.cpp @@ -31,6 +31,7 @@ #include "mongo/db/exec/sbe/values/value.h" #include "mongo/db/exec/sbe/vm/vm.h" #include "mongo/unittest/unittest.h" +#include "mongo/util/pcre.h" namespace mongo::sbe { @@ -421,6 +422,85 @@ TEST(SBEVM, ConvertBinDataToBsonObj) { namespace { +// The hex representation of memory addresses in the output of CodeFragment::toString() differs on +// Linux and Windows machines so 'addrPattern' is used to cover both cases. +static const std::string kLinuxAddrPattern{"(0x[a-f0-9]+)"}; +static const std::string kWindowsAddrPattern{"([A-F0-9]+)"}; +static const std::string kAddrPattern{"(" + kLinuxAddrPattern + "|" + kWindowsAddrPattern + ")"}; + +// The beginning of the output from CodeFragment::toString() gives a range of the addresses that +// 'pcPointer' will traverse. +static const std::string kPcPointerRangePattern{"(\\[" + kAddrPattern + ")-(" + kAddrPattern + + ")\\])"}; + +/** + * Creates a pcre pattern to match the instructions in the output of CodeFragment::toString(). Any + * arguments must be passed in a single comma separated string, and no arguments can be represented + * using an empty string. + */ +std::string instrPattern(std::string op, std::string args) { + return "(" + kAddrPattern + ": " + op + "\\(" + args + "\\); )"; +} +} // namespace + +TEST(SBEVM, CodeFragmentToString) { + { + vm::CodeFragment code; + std::string toStringPattern{kPcPointerRangePattern + "( )"}; + + code.appendDiv(); + toStringPattern += instrPattern("div", ""); + code.appendMul(); + toStringPattern += instrPattern("mul", ""); + code.appendAdd(); + toStringPattern += instrPattern("add", ""); + + std::string instrs = code.toString(); + + static const pcre::Regex validToStringOutput{toStringPattern}; + + ASSERT_TRUE(!!validToStringOutput.matchView(instrs)); + } +} + +TEST(SBEVM, CodeFragmentToStringArgs) { + { + vm::CodeFragment code; + std::string toStringPattern{kAddrPattern}; + + code.appendFillEmpty(vm::Instruction::True); + toStringPattern += instrPattern("fillEmptyConst", "k: True"); + code.appendFillEmpty(vm::Instruction::Null); + toStringPattern += instrPattern("fillEmptyConst", "k: Null"); + code.appendFillEmpty(vm::Instruction::False); + toStringPattern += instrPattern("fillEmptyConst", "k: False"); + + code.appendTraverseP(0xAA); + auto offsetP = 0xAA - code.instrs().size(); + toStringPattern += instrPattern("traversePConst", "offset: " + std::to_string(offsetP)); + code.appendTraverseF(0xBB, vm::Instruction::True); + auto offsetF = 0xBB - code.instrs().size(); + toStringPattern += + instrPattern("traverseFConst", "k: True, offset: " + std::to_string(offsetF)); + + auto [tag, val] = value::makeNewString("Hello world!"); + value::ValueGuard guard{tag, val}; + code.appendGetField(tag, val); + toStringPattern += instrPattern("getFieldConst", "value: \"Hello world!\""); + + code.appendAdd(); + toStringPattern += instrPattern("add", ""); + + std::string instrs = code.toString(); + + static const pcre::Regex validToStringOutput{toStringPattern}; + + ASSERT_TRUE(!!validToStringOutput.matchView(instrs)); + } +} + +namespace { + /** * Fills bytes after the null terminator in the string with 'pattern'. * |