summaryrefslogtreecommitdiff
path: root/src/mongo/db/exec/sbe/sbe_test.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/db/exec/sbe/sbe_test.cpp')
-rw-r--r--src/mongo/db/exec/sbe/sbe_test.cpp80
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'.
*