1 #include "DataFormatters/FormatterBytecode.h" 2 #include "lldb/Utility/StreamString.h" 3 4 #include "gtest/gtest.h" 5 6 using namespace lldb_private; 7 using namespace lldb; 8 using namespace FormatterBytecode; 9 using llvm::StringRef; 10 11 namespace { 12 class FormatterBytecodeTest : public ::testing::Test {}; 13 14 bool Interpret(std::vector<uint8_t> code, DataStack &data) { 15 auto buf = 16 StringRef(reinterpret_cast<const char *>(code.data()), code.size()); 17 std::vector<ControlStackElement> control({buf}); 18 if (auto error = Interpret(control, data, sel_summary)) { 19 #ifndef NDEBUG 20 llvm::errs() << llvm::toString(std::move(error)) << '\n'; 21 #else 22 llvm::consumeError(std::move(error)); 23 #endif 24 return false; 25 } 26 return true; 27 } 28 29 } // namespace 30 31 TEST_F(FormatterBytecodeTest, StackOps) { 32 { 33 DataStack data; 34 ASSERT_TRUE(Interpret({op_lit_uint, 23, op_dup, op_plus}, data)); 35 ASSERT_EQ(data.Pop<uint64_t>(), 46u); 36 } 37 { 38 DataStack data; 39 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_drop}, data)); 40 ASSERT_EQ(data.size(), 0u); 41 } 42 { 43 for (unsigned char i = 0; i < 3; ++i) { 44 DataStack data; 45 46 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2, 47 op_lit_uint, i, op_pick}, 48 data)); 49 ASSERT_EQ(data.Pop<uint64_t>(), i); 50 } 51 } 52 { 53 DataStack data; 54 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_over}, data)); 55 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 56 } 57 { 58 DataStack data; 59 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_swap}, data)); 60 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 61 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 62 } 63 { 64 DataStack data; 65 ASSERT_TRUE(Interpret( 66 {op_lit_uint, 0, op_lit_uint, 1, op_lit_uint, 2, op_rot}, data)); 67 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 68 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 69 ASSERT_EQ(data.Pop<uint64_t>(), 2u); 70 } 71 } 72 73 TEST_F(FormatterBytecodeTest, ControlOps) { 74 { 75 DataStack data; 76 ASSERT_TRUE( 77 Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42, op_if}, data)); 78 ASSERT_EQ(data.size(), 0u); 79 } 80 { 81 DataStack data; 82 ASSERT_TRUE( 83 Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42, op_if}, data)); 84 ASSERT_EQ(data.Pop<uint64_t>(), 42u); 85 } 86 { 87 DataStack data; 88 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_begin, 2, op_lit_uint, 42, 89 op_begin, 2, op_lit_uint, 23, op_ifelse}, 90 data)); 91 ASSERT_EQ(data.Pop<uint64_t>(), 23u); 92 } 93 { 94 DataStack data; 95 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_begin, 2, op_lit_uint, 42, 96 op_begin, 2, op_lit_uint, 23, op_ifelse}, 97 data)); 98 ASSERT_EQ(data.Pop<uint64_t>(), 42u); 99 } 100 { 101 DataStack data; 102 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_begin, 3, op_lit_uint, 42, 103 op_return, op_if, op_lit_uint, 23}, 104 data)); 105 ASSERT_EQ(data.Pop<uint64_t>(), 42u); 106 } 107 } 108 109 TEST_F(FormatterBytecodeTest, ConversionOps) { 110 { 111 DataStack data(lldb::ValueObjectSP{}); 112 ASSERT_TRUE(Interpret({op_is_null}, data)); 113 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 114 } 115 { 116 DataStack data; 117 ASSERT_TRUE(Interpret({op_lit_uint, 1u, op_as_int}, data)); 118 ASSERT_EQ(data.Pop<int64_t>(), 1); 119 } 120 { 121 DataStack data; 122 ASSERT_TRUE(Interpret({op_lit_int, 126, op_as_uint}, data)); 123 ASSERT_EQ(data.Pop<uint64_t>(), ~1ULL); 124 } 125 } 126 127 TEST_F(FormatterBytecodeTest, ArithOps) { 128 { 129 DataStack data; 130 ASSERT_TRUE(Interpret({op_lit_uint, 2, op_lit_uint, 3, op_plus}, data)); 131 ASSERT_EQ(data.Pop<uint64_t>(), 5u); 132 } 133 { 134 DataStack data; 135 ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_minus}, data)); 136 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 137 } 138 { 139 DataStack data; 140 ASSERT_TRUE(Interpret({op_lit_uint, 3, op_lit_uint, 2, op_mul}, data)); 141 ASSERT_EQ(data.Pop<uint64_t>(), 6u); 142 } 143 { 144 DataStack data; 145 ASSERT_TRUE(Interpret({op_lit_uint, 6, op_lit_uint, 2, op_div}, data)); 146 ASSERT_EQ(data.Pop<uint64_t>(), 3u); 147 } 148 { 149 DataStack data; 150 ASSERT_FALSE(Interpret({op_lit_uint, 23, op_lit_uint, 0, op_div}, data)); 151 } 152 { 153 DataStack data; 154 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 2, op_shl}, data)); 155 ASSERT_EQ(data.Pop<uint64_t>(), 4u); 156 } 157 { 158 DataStack data; 159 unsigned char minus_one = 127; 160 ASSERT_FALSE( 161 Interpret({op_lit_int, minus_one, op_lit_uint, 2, op_shl}, data)); 162 unsigned char minus_two = 126; 163 ASSERT_TRUE( 164 Interpret({op_lit_int, minus_two, op_lit_uint, 1, op_shr}, data)); 165 ASSERT_EQ(data.Pop<int64_t>(), -1); 166 } 167 { 168 DataStack data; 169 ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shl}, data)); 170 ASSERT_FALSE(Interpret({op_lit_uint, 1, op_lit_uint, 65, op_shr}, data)); 171 } 172 { 173 DataStack data; 174 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_and}, data)); 175 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 176 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_and}, data)); 177 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 178 } 179 { 180 DataStack data; 181 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_or}, data)); 182 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 183 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_or}, data)); 184 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 185 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_or}, data)); 186 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 187 } 188 { 189 DataStack data; 190 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_xor}, data)); 191 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 192 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_xor}, data)); 193 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 194 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_xor}, data)); 195 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 196 } 197 { 198 DataStack data; 199 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_not}, data)); 200 ASSERT_EQ(data.Pop<uint64_t>(), 0xffffffffffffffff); 201 } 202 { 203 DataStack data; 204 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_eq}, data)); 205 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 206 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_eq}, data)); 207 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 208 } 209 { 210 DataStack data; 211 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_neq}, data)); 212 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 213 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 0, op_neq}, data)); 214 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 215 } 216 { 217 DataStack data; 218 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_lt}, data)); 219 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 220 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_lt}, data)); 221 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 222 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_lt}, data)); 223 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 224 } 225 { 226 DataStack data; 227 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_gt}, data)); 228 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 229 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_gt}, data)); 230 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 231 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_gt}, data)); 232 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 233 } 234 { 235 DataStack data; 236 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_le}, data)); 237 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 238 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_le}, data)); 239 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 240 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_le}, data)); 241 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 242 } 243 { 244 DataStack data; 245 ASSERT_TRUE(Interpret({op_lit_uint, 0, op_lit_uint, 1, op_ge}, data)); 246 ASSERT_EQ(data.Pop<uint64_t>(), 0u); 247 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 0, op_ge}, data)); 248 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 249 ASSERT_TRUE(Interpret({op_lit_uint, 1, op_lit_uint, 1, op_ge}, data)); 250 ASSERT_EQ(data.Pop<uint64_t>(), 1u); 251 } 252 } 253 254 TEST_F(FormatterBytecodeTest, CallOps) { 255 { 256 DataStack data; 257 data.Push(std::string{"hello"}); 258 ASSERT_TRUE(Interpret({op_lit_selector, sel_strlen, op_call}, data)); 259 ASSERT_EQ(data.Pop<uint64_t>(), 5u); 260 } 261 { 262 DataStack data; 263 data.Push(std::string{"A"}); 264 data.Push(std::string{"B"}); 265 data.Push(std::string{"{1}{0}"}); 266 ASSERT_TRUE(Interpret({op_lit_selector, sel_fmt, op_call}, data)); 267 ASSERT_EQ(data.Pop<std::string>(), "BA"); 268 } 269 { 270 DataStack data; 271 data.Push(std::string{"{0}"}); 272 ASSERT_FALSE(Interpret({op_lit_selector, sel_fmt, op_call}, data)); 273 } 274 } 275