1 //===-- PythonDataObjectsTests.cpp ----------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "Plugins/ScriptInterpreter/Python/lldb-python.h" 10 #include "gtest/gtest.h" 11 12 #include "Plugins/ScriptInterpreter/Python/PythonDataObjects.h" 13 #include "Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.h" 14 #include "lldb/Host/File.h" 15 #include "lldb/Host/FileSystem.h" 16 #include "lldb/Host/HostInfo.h" 17 #include "lldb/lldb-enumerations.h" 18 #include "llvm/Testing/Support/Error.h" 19 20 #include "PythonTestSuite.h" 21 22 using namespace lldb_private; 23 using namespace lldb_private::python; 24 using llvm::Error; 25 using llvm::Expected; 26 27 class PythonDataObjectsTest : public PythonTestSuite { 28 public: 29 void SetUp() override { 30 PythonTestSuite::SetUp(); 31 32 m_sys_module = unwrapIgnoringErrors(PythonModule::Import("sys")); 33 m_main_module = PythonModule::MainModule(); 34 m_builtins_module = PythonModule::BuiltinsModule(); 35 } 36 37 void TearDown() override { 38 m_sys_module.Reset(); 39 m_main_module.Reset(); 40 m_builtins_module.Reset(); 41 42 PythonTestSuite::TearDown(); 43 } 44 45 protected: 46 PythonModule m_sys_module; 47 PythonModule m_main_module; 48 PythonModule m_builtins_module; 49 }; 50 51 TEST_F(PythonDataObjectsTest, TestOwnedReferences) { 52 // After creating a new object, the refcount should be >= 1 53 PyObject *obj = PyLong_FromLong(3); 54 Py_ssize_t original_refcnt = obj->ob_refcnt; 55 EXPECT_LE(1, original_refcnt); 56 57 // If we take an owned reference, the refcount should be the same 58 PythonObject owned_long(PyRefType::Owned, obj); 59 EXPECT_EQ(original_refcnt, owned_long.get()->ob_refcnt); 60 61 // Take another reference and verify that the refcount increases by 1 62 PythonObject strong_ref(owned_long); 63 EXPECT_EQ(original_refcnt + 1, strong_ref.get()->ob_refcnt); 64 65 // If we reset the first one, the refcount should be the original value. 66 owned_long.Reset(); 67 EXPECT_EQ(original_refcnt, strong_ref.get()->ob_refcnt); 68 } 69 70 TEST_F(PythonDataObjectsTest, TestResetting) { 71 PythonDictionary dict(PyInitialValue::Empty); 72 73 PyObject *new_dict = PyDict_New(); 74 dict = Take<PythonDictionary>(new_dict); 75 EXPECT_EQ(new_dict, dict.get()); 76 77 dict = Take<PythonDictionary>(PyDict_New()); 78 EXPECT_NE(nullptr, dict.get()); 79 dict.Reset(); 80 EXPECT_EQ(nullptr, dict.get()); 81 } 82 83 TEST_F(PythonDataObjectsTest, TestBorrowedReferences) { 84 PythonInteger long_value(PyRefType::Owned, PyLong_FromLong(3)); 85 Py_ssize_t original_refcnt = long_value.get()->ob_refcnt; 86 EXPECT_LE(1, original_refcnt); 87 88 PythonInteger borrowed_long(PyRefType::Borrowed, long_value.get()); 89 EXPECT_EQ(original_refcnt + 1, borrowed_long.get()->ob_refcnt); 90 } 91 92 TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionNoDot) { 93 PythonObject sys_module = m_main_module.ResolveName("sys"); 94 EXPECT_EQ(m_sys_module.get(), sys_module.get()); 95 EXPECT_TRUE(sys_module.IsAllocated()); 96 EXPECT_TRUE(PythonModule::Check(sys_module.get())); 97 } 98 99 TEST_F(PythonDataObjectsTest, TestModuleNameResolutionNoDot) { 100 PythonObject sys_path = m_sys_module.ResolveName("path"); 101 PythonObject sys_version_info = m_sys_module.ResolveName("version_info"); 102 EXPECT_TRUE(sys_path.IsAllocated()); 103 EXPECT_TRUE(sys_version_info.IsAllocated()); 104 105 EXPECT_TRUE(PythonList::Check(sys_path.get())); 106 } 107 108 TEST_F(PythonDataObjectsTest, TestTypeNameResolutionNoDot) { 109 PythonObject sys_version_info = m_sys_module.ResolveName("version_info"); 110 111 PythonObject version_info_type(PyRefType::Owned, 112 PyObject_Type(sys_version_info.get())); 113 EXPECT_TRUE(version_info_type.IsAllocated()); 114 PythonObject major_version_field = version_info_type.ResolveName("major"); 115 EXPECT_TRUE(major_version_field.IsAllocated()); 116 } 117 118 TEST_F(PythonDataObjectsTest, TestInstanceNameResolutionNoDot) { 119 PythonObject sys_version_info = m_sys_module.ResolveName("version_info"); 120 PythonObject major_version_field = sys_version_info.ResolveName("major"); 121 PythonObject minor_version_field = sys_version_info.ResolveName("minor"); 122 123 EXPECT_TRUE(major_version_field.IsAllocated()); 124 EXPECT_TRUE(minor_version_field.IsAllocated()); 125 126 auto major_version_value = As<long long>(major_version_field); 127 auto minor_version_value = As<long long>(minor_version_field); 128 129 EXPECT_THAT_EXPECTED(major_version_value, llvm::HasValue(PY_MAJOR_VERSION)); 130 EXPECT_THAT_EXPECTED(minor_version_value, llvm::HasValue(PY_MINOR_VERSION)); 131 } 132 133 TEST_F(PythonDataObjectsTest, TestGlobalNameResolutionWithDot) { 134 PythonObject sys_path = m_main_module.ResolveName("sys.path"); 135 EXPECT_TRUE(sys_path.IsAllocated()); 136 EXPECT_TRUE(PythonList::Check(sys_path.get())); 137 138 auto version_major = 139 As<long long>(m_main_module.ResolveName("sys.version_info.major")); 140 141 auto version_minor = 142 As<long long>(m_main_module.ResolveName("sys.version_info.minor")); 143 144 EXPECT_THAT_EXPECTED(version_major, llvm::HasValue(PY_MAJOR_VERSION)); 145 EXPECT_THAT_EXPECTED(version_minor, llvm::HasValue(PY_MINOR_VERSION)); 146 } 147 148 TEST_F(PythonDataObjectsTest, TestDictionaryResolutionWithDot) { 149 // Make up a custom dictionary with "sys" pointing to the `sys` module. 150 PythonDictionary dict(PyInitialValue::Empty); 151 dict.SetItemForKey(PythonString("sys"), m_sys_module); 152 153 // Now use that dictionary to resolve `sys.version_info.major` 154 auto version_major = As<long long>( 155 PythonObject::ResolveNameWithDictionary("sys.version_info.major", dict)); 156 157 auto version_minor = As<long long>( 158 PythonObject::ResolveNameWithDictionary("sys.version_info.minor", dict)); 159 160 EXPECT_THAT_EXPECTED(version_major, llvm::HasValue(PY_MAJOR_VERSION)); 161 EXPECT_THAT_EXPECTED(version_minor, llvm::HasValue(PY_MINOR_VERSION)); 162 } 163 164 TEST_F(PythonDataObjectsTest, TestPythonInteger) { 165 // Test that integers behave correctly when wrapped by a PythonInteger. 166 167 // Verify that `PythonInteger` works correctly when given a PyLong object. 168 PyObject *py_long = PyLong_FromLong(12); 169 EXPECT_TRUE(PythonInteger::Check(py_long)); 170 PythonInteger python_long(PyRefType::Owned, py_long); 171 EXPECT_EQ(PyObjectType::Integer, python_long.GetObjectType()); 172 173 // Verify that you can reset the value and that it is reflected properly. 174 python_long.SetInteger(40); 175 auto e = As<long long>(python_long); 176 EXPECT_THAT_EXPECTED(e, llvm::HasValue(40)); 177 178 // Test that creating a `PythonInteger` object works correctly with the 179 // int constructor. 180 PythonInteger constructed_int(7); 181 auto value = As<long long>(constructed_int); 182 EXPECT_THAT_EXPECTED(value, llvm::HasValue(7)); 183 } 184 185 TEST_F(PythonDataObjectsTest, TestPythonBoolean) { 186 // Test PythonBoolean constructed from Py_True 187 EXPECT_TRUE(PythonBoolean::Check(Py_True)); 188 PythonBoolean python_true(PyRefType::Owned, Py_True); 189 EXPECT_EQ(PyObjectType::Boolean, python_true.GetObjectType()); 190 191 // Test PythonBoolean constructed from Py_False 192 EXPECT_TRUE(PythonBoolean::Check(Py_False)); 193 PythonBoolean python_false(PyRefType::Owned, Py_False); 194 EXPECT_EQ(PyObjectType::Boolean, python_false.GetObjectType()); 195 196 auto test_from_long = [](long value) { 197 PyObject *py_bool = PyBool_FromLong(value); 198 EXPECT_TRUE(PythonBoolean::Check(py_bool)); 199 PythonBoolean python_boolean(PyRefType::Owned, py_bool); 200 EXPECT_EQ(PyObjectType::Boolean, python_boolean.GetObjectType()); 201 EXPECT_EQ(bool(value), python_boolean.GetValue()); 202 }; 203 204 // Test PythonBoolean constructed from long integer values. 205 test_from_long(0); // Test 'false' value. 206 test_from_long(1); // Test 'true' value. 207 test_from_long(~0); // Any value != 0 is 'true'. 208 } 209 210 TEST_F(PythonDataObjectsTest, TestPythonBytes) { 211 static const char *test_bytes = "PythonDataObjectsTest::TestPythonBytes"; 212 PyObject *py_bytes = PyBytes_FromString(test_bytes); 213 EXPECT_TRUE(PythonBytes::Check(py_bytes)); 214 PythonBytes python_bytes(PyRefType::Owned, py_bytes); 215 216 EXPECT_FALSE(PythonString::Check(py_bytes)); 217 EXPECT_EQ(PyObjectType::Bytes, python_bytes.GetObjectType()); 218 219 llvm::ArrayRef<uint8_t> bytes = python_bytes.GetBytes(); 220 EXPECT_EQ(bytes.size(), strlen(test_bytes)); 221 EXPECT_EQ(0, ::memcmp(bytes.data(), test_bytes, bytes.size())); 222 } 223 224 TEST_F(PythonDataObjectsTest, TestPythonByteArray) { 225 static const char *test_bytes = "PythonDataObjectsTest::TestPythonByteArray"; 226 llvm::StringRef orig_bytes(test_bytes); 227 PyObject *py_bytes = 228 PyByteArray_FromStringAndSize(test_bytes, orig_bytes.size()); 229 EXPECT_TRUE(PythonByteArray::Check(py_bytes)); 230 PythonByteArray python_bytes(PyRefType::Owned, py_bytes); 231 EXPECT_EQ(PyObjectType::ByteArray, python_bytes.GetObjectType()); 232 233 llvm::ArrayRef<uint8_t> after_bytes = python_bytes.GetBytes(); 234 EXPECT_EQ(after_bytes.size(), orig_bytes.size()); 235 EXPECT_EQ(0, ::memcmp(orig_bytes.data(), test_bytes, orig_bytes.size())); 236 } 237 238 TEST_F(PythonDataObjectsTest, TestPythonString) { 239 // Test that strings behave correctly when wrapped by a PythonString. 240 241 static const char *test_string = "PythonDataObjectsTest::TestPythonString1"; 242 static const char *test_string2 = "PythonDataObjectsTest::TestPythonString2"; 243 244 // Verify that `PythonString` works correctly when given a PyUnicode object. 245 PyObject *py_unicode = PyUnicode_FromString(test_string); 246 EXPECT_TRUE(PythonString::Check(py_unicode)); 247 PythonString python_unicode(PyRefType::Owned, py_unicode); 248 EXPECT_EQ(PyObjectType::String, python_unicode.GetObjectType()); 249 EXPECT_STREQ(test_string, python_unicode.GetString().data()); 250 251 // Test that creating a `PythonString` object works correctly with the 252 // string constructor 253 PythonString constructed_string(test_string2); 254 EXPECT_EQ(test_string2, constructed_string.GetString()); 255 } 256 257 TEST_F(PythonDataObjectsTest, TestPythonStringToStr) { 258 const char *GetString = "PythonDataObjectsTest::TestPythonStringToStr"; 259 260 PythonString str(GetString); 261 EXPECT_EQ(GetString, str.GetString()); 262 263 PythonString str_str = str.Str(); 264 EXPECT_EQ(GetString, str_str.GetString()); 265 } 266 267 TEST_F(PythonDataObjectsTest, TestPythonIntegerToStr) {} 268 269 TEST_F(PythonDataObjectsTest, TestPythonIntegerToStructuredInteger) { 270 PythonInteger integer(7); 271 auto int_sp = integer.CreateStructuredInteger(); 272 EXPECT_EQ(7U, int_sp->GetValue()); 273 } 274 275 TEST_F(PythonDataObjectsTest, TestPythonStringToStructuredString) { 276 static const char *test_string = 277 "PythonDataObjectsTest::TestPythonStringToStructuredString"; 278 PythonString constructed_string(test_string); 279 auto string_sp = constructed_string.CreateStructuredString(); 280 EXPECT_EQ(test_string, string_sp->GetStringValue()); 281 } 282 283 TEST_F(PythonDataObjectsTest, TestPythonListValueEquality) { 284 // Test that a list which is built through the native 285 // Python API behaves correctly when wrapped by a PythonList. 286 static const unsigned list_size = 2; 287 static const long long_value0 = 5; 288 static const char *const string_value1 = "String Index 1"; 289 290 PyObject *py_list = PyList_New(2); 291 EXPECT_TRUE(PythonList::Check(py_list)); 292 PythonList list(PyRefType::Owned, py_list); 293 294 PythonObject list_items[list_size]; 295 list_items[0] = PythonInteger(long_value0); 296 list_items[1] = PythonString(string_value1); 297 298 for (unsigned i = 0; i < list_size; ++i) 299 list.SetItemAtIndex(i, list_items[i]); 300 301 EXPECT_EQ(list_size, list.GetSize()); 302 EXPECT_EQ(PyObjectType::List, list.GetObjectType()); 303 304 // Verify that the values match 305 PythonObject chk_value1 = list.GetItemAtIndex(0); 306 PythonObject chk_value2 = list.GetItemAtIndex(1); 307 EXPECT_TRUE(PythonInteger::Check(chk_value1.get())); 308 EXPECT_TRUE(PythonString::Check(chk_value2.get())); 309 310 PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get()); 311 PythonString chk_str(PyRefType::Borrowed, chk_value2.get()); 312 313 auto chkint = As<long long>(chk_value1); 314 ASSERT_THAT_EXPECTED(chkint, llvm::HasValue(long_value0)); 315 EXPECT_EQ(string_value1, chk_str.GetString()); 316 } 317 318 TEST_F(PythonDataObjectsTest, TestPythonListManipulation) { 319 // Test that manipulation of a PythonList behaves correctly when 320 // wrapped by a PythonDictionary. 321 322 static const long long_value0 = 5; 323 static const char *const string_value1 = "String Index 1"; 324 325 PythonList list(PyInitialValue::Empty); 326 PythonInteger integer(long_value0); 327 PythonString string(string_value1); 328 329 list.AppendItem(integer); 330 list.AppendItem(string); 331 EXPECT_EQ(2U, list.GetSize()); 332 333 // Verify that the values match 334 PythonObject chk_value1 = list.GetItemAtIndex(0); 335 PythonObject chk_value2 = list.GetItemAtIndex(1); 336 EXPECT_TRUE(PythonInteger::Check(chk_value1.get())); 337 EXPECT_TRUE(PythonString::Check(chk_value2.get())); 338 339 PythonInteger chk_int(PyRefType::Borrowed, chk_value1.get()); 340 PythonString chk_str(PyRefType::Borrowed, chk_value2.get()); 341 342 auto e = As<long long>(chk_int); 343 EXPECT_THAT_EXPECTED(e, llvm::HasValue(long_value0)); 344 EXPECT_EQ(string_value1, chk_str.GetString()); 345 } 346 347 TEST_F(PythonDataObjectsTest, TestPythonListToStructuredList) { 348 static const long long_value0 = 5; 349 static const char *const string_value1 = "String Index 1"; 350 351 PythonList list(PyInitialValue::Empty); 352 list.AppendItem(PythonInteger(long_value0)); 353 list.AppendItem(PythonString(string_value1)); 354 355 auto array_sp = list.CreateStructuredArray(); 356 EXPECT_EQ(lldb::eStructuredDataTypeInteger, 357 array_sp->GetItemAtIndex(0)->GetType()); 358 EXPECT_EQ(lldb::eStructuredDataTypeString, 359 array_sp->GetItemAtIndex(1)->GetType()); 360 361 auto int_sp = array_sp->GetItemAtIndex(0)->GetAsInteger(); 362 auto string_sp = array_sp->GetItemAtIndex(1)->GetAsString(); 363 364 EXPECT_EQ(long_value0, long(int_sp->GetValue())); 365 EXPECT_EQ(string_value1, string_sp->GetValue()); 366 } 367 368 TEST_F(PythonDataObjectsTest, TestPythonTupleSize) { 369 PythonTuple tuple(PyInitialValue::Empty); 370 EXPECT_EQ(0U, tuple.GetSize()); 371 372 tuple = PythonTuple(3); 373 EXPECT_EQ(3U, tuple.GetSize()); 374 } 375 376 TEST_F(PythonDataObjectsTest, TestPythonTupleValues) { 377 PythonTuple tuple(3); 378 379 PythonInteger int_value(1); 380 PythonString string_value("Test"); 381 PythonObject none_value(PyRefType::Borrowed, Py_None); 382 383 tuple.SetItemAtIndex(0, int_value); 384 tuple.SetItemAtIndex(1, string_value); 385 tuple.SetItemAtIndex(2, none_value); 386 387 EXPECT_EQ(tuple.GetItemAtIndex(0).get(), int_value.get()); 388 EXPECT_EQ(tuple.GetItemAtIndex(1).get(), string_value.get()); 389 EXPECT_EQ(tuple.GetItemAtIndex(2).get(), none_value.get()); 390 } 391 392 TEST_F(PythonDataObjectsTest, TestPythonTupleInitializerList) { 393 PythonInteger int_value(1); 394 PythonString string_value("Test"); 395 PythonObject none_value(PyRefType::Borrowed, Py_None); 396 PythonTuple tuple{int_value, string_value, none_value}; 397 EXPECT_EQ(3U, tuple.GetSize()); 398 399 EXPECT_EQ(tuple.GetItemAtIndex(0).get(), int_value.get()); 400 EXPECT_EQ(tuple.GetItemAtIndex(1).get(), string_value.get()); 401 EXPECT_EQ(tuple.GetItemAtIndex(2).get(), none_value.get()); 402 } 403 404 TEST_F(PythonDataObjectsTest, TestPythonTupleInitializerList2) { 405 PythonInteger int_value(1); 406 PythonString string_value("Test"); 407 PythonObject none_value(PyRefType::Borrowed, Py_None); 408 409 PythonTuple tuple{int_value.get(), string_value.get(), none_value.get()}; 410 EXPECT_EQ(3U, tuple.GetSize()); 411 412 EXPECT_EQ(tuple.GetItemAtIndex(0).get(), int_value.get()); 413 EXPECT_EQ(tuple.GetItemAtIndex(1).get(), string_value.get()); 414 EXPECT_EQ(tuple.GetItemAtIndex(2).get(), none_value.get()); 415 } 416 417 TEST_F(PythonDataObjectsTest, TestPythonTupleToStructuredList) { 418 PythonInteger int_value(1); 419 PythonString string_value("Test"); 420 421 PythonTuple tuple{int_value.get(), string_value.get()}; 422 423 auto array_sp = tuple.CreateStructuredArray(); 424 EXPECT_EQ(tuple.GetSize(), array_sp->GetSize()); 425 EXPECT_EQ(lldb::eStructuredDataTypeInteger, 426 array_sp->GetItemAtIndex(0)->GetType()); 427 EXPECT_EQ(lldb::eStructuredDataTypeString, 428 array_sp->GetItemAtIndex(1)->GetType()); 429 } 430 431 TEST_F(PythonDataObjectsTest, TestPythonDictionaryValueEquality) { 432 // Test that a dictionary which is built through the native 433 // Python API behaves correctly when wrapped by a PythonDictionary. 434 static const unsigned dict_entries = 2; 435 const char *key_0 = "Key 0"; 436 int key_1 = 1; 437 const int value_0 = 0; 438 const char *value_1 = "Value 1"; 439 440 PythonObject py_keys[dict_entries]; 441 PythonObject py_values[dict_entries]; 442 443 py_keys[0] = PythonString(key_0); 444 py_keys[1] = PythonInteger(key_1); 445 py_values[0] = PythonInteger(value_0); 446 py_values[1] = PythonString(value_1); 447 448 PyObject *py_dict = PyDict_New(); 449 EXPECT_TRUE(PythonDictionary::Check(py_dict)); 450 PythonDictionary dict(PyRefType::Owned, py_dict); 451 452 for (unsigned i = 0; i < dict_entries; ++i) 453 PyDict_SetItem(py_dict, py_keys[i].get(), py_values[i].get()); 454 EXPECT_EQ(dict.GetSize(), dict_entries); 455 EXPECT_EQ(PyObjectType::Dictionary, dict.GetObjectType()); 456 457 // Verify that the values match 458 PythonObject chk_value1 = dict.GetItemForKey(py_keys[0]); 459 PythonObject chk_value2 = dict.GetItemForKey(py_keys[1]); 460 EXPECT_TRUE(PythonInteger::Check(chk_value1.get())); 461 EXPECT_TRUE(PythonString::Check(chk_value2.get())); 462 463 PythonString chk_str(PyRefType::Borrowed, chk_value2.get()); 464 auto chkint = As<long long>(chk_value1); 465 466 EXPECT_THAT_EXPECTED(chkint, llvm::HasValue(value_0)); 467 EXPECT_EQ(value_1, chk_str.GetString()); 468 } 469 470 TEST_F(PythonDataObjectsTest, TestPythonDictionaryManipulation) { 471 // Test that manipulation of a dictionary behaves correctly when wrapped 472 // by a PythonDictionary. 473 static const unsigned dict_entries = 2; 474 475 const char *const key_0 = "Key 0"; 476 const char *const key_1 = "Key 1"; 477 const long value_0 = 1; 478 const char *const value_1 = "Value 1"; 479 480 PythonString keys[dict_entries]; 481 PythonObject values[dict_entries]; 482 483 keys[0] = PythonString(key_0); 484 keys[1] = PythonString(key_1); 485 values[0] = PythonInteger(value_0); 486 values[1] = PythonString(value_1); 487 488 PythonDictionary dict(PyInitialValue::Empty); 489 for (int i = 0; i < 2; ++i) 490 dict.SetItemForKey(keys[i], values[i]); 491 492 EXPECT_EQ(dict_entries, dict.GetSize()); 493 494 // Verify that the keys and values match 495 PythonObject chk_value1 = dict.GetItemForKey(keys[0]); 496 PythonObject chk_value2 = dict.GetItemForKey(keys[1]); 497 EXPECT_TRUE(PythonInteger::Check(chk_value1.get())); 498 EXPECT_TRUE(PythonString::Check(chk_value2.get())); 499 500 auto chkint = As<long long>(chk_value1); 501 PythonString chk_str(PyRefType::Borrowed, chk_value2.get()); 502 503 EXPECT_THAT_EXPECTED(chkint, llvm::HasValue(value_0)); 504 EXPECT_EQ(value_1, chk_str.GetString()); 505 } 506 507 TEST_F(PythonDataObjectsTest, TestPythonDictionaryToStructuredDictionary) { 508 static const char *const string_key0 = "String Key 0"; 509 static const char *const string_key1 = "String Key 1"; 510 511 static const char *const string_value0 = "String Value 0"; 512 static const long int_value1 = 7; 513 514 PythonDictionary dict(PyInitialValue::Empty); 515 dict.SetItemForKey(PythonString(string_key0), PythonString(string_value0)); 516 dict.SetItemForKey(PythonString(string_key1), PythonInteger(int_value1)); 517 518 auto dict_sp = dict.CreateStructuredDictionary(); 519 EXPECT_EQ(2U, dict_sp->GetSize()); 520 521 EXPECT_TRUE(dict_sp->HasKey(string_key0)); 522 EXPECT_TRUE(dict_sp->HasKey(string_key1)); 523 524 auto string_sp = dict_sp->GetValueForKey(string_key0)->GetAsString(); 525 auto int_sp = dict_sp->GetValueForKey(string_key1)->GetAsInteger(); 526 527 EXPECT_EQ(string_value0, string_sp->GetValue()); 528 EXPECT_EQ(int_value1, long(int_sp->GetValue())); 529 } 530 531 TEST_F(PythonDataObjectsTest, TestPythonCallableCheck) { 532 PythonObject sys_exc_info = m_sys_module.ResolveName("exc_info"); 533 PythonObject none(PyRefType::Borrowed, Py_None); 534 535 EXPECT_TRUE(PythonCallable::Check(sys_exc_info.get())); 536 EXPECT_FALSE(PythonCallable::Check(none.get())); 537 } 538 539 TEST_F(PythonDataObjectsTest, TestPythonCallableInvoke) { 540 auto list = m_builtins_module.ResolveName("list").AsType<PythonCallable>(); 541 PythonInteger one(1); 542 PythonString two("two"); 543 PythonTuple three = {one, two}; 544 545 PythonTuple tuple_to_convert = {one, two, three}; 546 PythonObject result = list({tuple_to_convert}); 547 548 EXPECT_TRUE(PythonList::Check(result.get())); 549 auto list_result = result.AsType<PythonList>(); 550 EXPECT_EQ(3U, list_result.GetSize()); 551 EXPECT_EQ(one.get(), list_result.GetItemAtIndex(0).get()); 552 EXPECT_EQ(two.get(), list_result.GetItemAtIndex(1).get()); 553 EXPECT_EQ(three.get(), list_result.GetItemAtIndex(2).get()); 554 } 555 556 TEST_F(PythonDataObjectsTest, TestPythonFile) { 557 auto file = FileSystem::Instance().Open(FileSpec(FileSystem::DEV_NULL), 558 File::eOpenOptionReadOnly); 559 ASSERT_THAT_EXPECTED(file, llvm::Succeeded()); 560 auto py_file = PythonFile::FromFile(*file.get(), "r"); 561 ASSERT_THAT_EXPECTED(py_file, llvm::Succeeded()); 562 EXPECT_TRUE(PythonFile::Check(py_file.get().get())); 563 } 564 565 TEST_F(PythonDataObjectsTest, TestObjectAttributes) { 566 PythonInteger py_int(42); 567 EXPECT_TRUE(py_int.HasAttribute("numerator")); 568 EXPECT_FALSE(py_int.HasAttribute("this_should_not_exist")); 569 570 auto numerator_attr = As<long long>(py_int.GetAttributeValue("numerator")); 571 572 EXPECT_THAT_EXPECTED(numerator_attr, llvm::HasValue(42)); 573 } 574 575 TEST_F(PythonDataObjectsTest, TestExtractingUInt64ThroughStructuredData) { 576 // Make up a custom dictionary with "sys" pointing to the `sys` module. 577 const char *key_name = "addr"; 578 const uint64_t value = 0xf000000000000000ull; 579 PythonDictionary python_dict(PyInitialValue::Empty); 580 PythonInteger python_ull_value(PyRefType::Owned, 581 PyLong_FromUnsignedLongLong(value)); 582 python_dict.SetItemForKey(PythonString(key_name), python_ull_value); 583 StructuredData::ObjectSP structured_data_sp = 584 python_dict.CreateStructuredObject(); 585 EXPECT_TRUE((bool)structured_data_sp); 586 if (structured_data_sp) { 587 StructuredData::Dictionary *structured_dict_ptr = 588 structured_data_sp->GetAsDictionary(); 589 EXPECT_TRUE(structured_dict_ptr != nullptr); 590 if (structured_dict_ptr) { 591 StructuredData::ObjectSP structured_addr_value_sp = 592 structured_dict_ptr->GetValueForKey(key_name); 593 EXPECT_TRUE((bool)structured_addr_value_sp); 594 const uint64_t extracted_value = 595 structured_addr_value_sp->GetIntegerValue(123); 596 EXPECT_TRUE(extracted_value == value); 597 } 598 } 599 } 600 601 TEST_F(PythonDataObjectsTest, TestCallable) { 602 603 PythonDictionary globals(PyInitialValue::Empty); 604 auto builtins = PythonModule::BuiltinsModule(); 605 llvm::Error error = globals.SetItem("__builtins__", builtins); 606 ASSERT_FALSE(error); 607 608 { 609 PyObject *o = PyRun_String("lambda x : x", Py_eval_input, globals.get(), 610 globals.get()); 611 ASSERT_FALSE(o == NULL); 612 auto lambda = Take<PythonCallable>(o); 613 auto arginfo = lambda.GetArgInfo(); 614 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 615 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 616 } 617 618 { 619 PyObject *o = PyRun_String("lambda x,y=0: x", Py_eval_input, globals.get(), 620 globals.get()); 621 ASSERT_FALSE(o == NULL); 622 auto lambda = Take<PythonCallable>(o); 623 auto arginfo = lambda.GetArgInfo(); 624 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 625 EXPECT_EQ(arginfo.get().max_positional_args, 2u); 626 } 627 628 { 629 PyObject *o = PyRun_String("lambda x,y=0, **kw: x", Py_eval_input, 630 globals.get(), globals.get()); 631 ASSERT_FALSE(o == NULL); 632 auto lambda = Take<PythonCallable>(o); 633 auto arginfo = lambda.GetArgInfo(); 634 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 635 EXPECT_EQ(arginfo.get().max_positional_args, 2u); 636 } 637 638 { 639 PyObject *o = PyRun_String("lambda x,y,*a: x", Py_eval_input, globals.get(), 640 globals.get()); 641 ASSERT_FALSE(o == NULL); 642 auto lambda = Take<PythonCallable>(o); 643 auto arginfo = lambda.GetArgInfo(); 644 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 645 EXPECT_EQ(arginfo.get().max_positional_args, 646 PythonCallable::ArgInfo::UNBOUNDED); 647 } 648 649 { 650 PyObject *o = PyRun_String("lambda x,y,*a,**kw: x", Py_eval_input, 651 globals.get(), globals.get()); 652 ASSERT_FALSE(o == NULL); 653 auto lambda = Take<PythonCallable>(o); 654 auto arginfo = lambda.GetArgInfo(); 655 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 656 EXPECT_EQ(arginfo.get().max_positional_args, 657 PythonCallable::ArgInfo::UNBOUNDED); 658 } 659 660 { 661 const char *script = R"( 662 class Foo: 663 def bar(self, x): 664 return x 665 @classmethod 666 def classbar(cls, x): 667 return x 668 @staticmethod 669 def staticbar(x): 670 return x 671 def __call__(self, x): 672 return x 673 obj = Foo() 674 bar_bound = Foo().bar 675 bar_class = Foo().classbar 676 bar_static = Foo().staticbar 677 bar_unbound = Foo.bar 678 679 680 class OldStyle: 681 def __init__(self, one, two, three): 682 pass 683 684 class NewStyle(object): 685 def __init__(self, one, two, three): 686 pass 687 688 )"; 689 PyObject *o = 690 PyRun_String(script, Py_file_input, globals.get(), globals.get()); 691 ASSERT_FALSE(o == NULL); 692 Take<PythonObject>(o); 693 694 auto bar_bound = As<PythonCallable>(globals.GetItem("bar_bound")); 695 ASSERT_THAT_EXPECTED(bar_bound, llvm::Succeeded()); 696 auto arginfo = bar_bound.get().GetArgInfo(); 697 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 698 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 699 700 auto bar_unbound = As<PythonCallable>(globals.GetItem("bar_unbound")); 701 ASSERT_THAT_EXPECTED(bar_unbound, llvm::Succeeded()); 702 arginfo = bar_unbound.get().GetArgInfo(); 703 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 704 EXPECT_EQ(arginfo.get().max_positional_args, 2u); 705 706 auto bar_class = As<PythonCallable>(globals.GetItem("bar_class")); 707 ASSERT_THAT_EXPECTED(bar_class, llvm::Succeeded()); 708 arginfo = bar_class.get().GetArgInfo(); 709 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 710 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 711 712 auto bar_static = As<PythonCallable>(globals.GetItem("bar_static")); 713 ASSERT_THAT_EXPECTED(bar_static, llvm::Succeeded()); 714 arginfo = bar_static.get().GetArgInfo(); 715 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 716 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 717 718 auto obj = As<PythonCallable>(globals.GetItem("obj")); 719 ASSERT_THAT_EXPECTED(obj, llvm::Succeeded()); 720 arginfo = obj.get().GetArgInfo(); 721 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 722 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 723 724 auto oldstyle = As<PythonCallable>(globals.GetItem("OldStyle")); 725 ASSERT_THAT_EXPECTED(oldstyle, llvm::Succeeded()); 726 arginfo = oldstyle.get().GetArgInfo(); 727 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 728 EXPECT_EQ(arginfo.get().max_positional_args, 3u); 729 730 auto newstyle = As<PythonCallable>(globals.GetItem("NewStyle")); 731 ASSERT_THAT_EXPECTED(newstyle, llvm::Succeeded()); 732 arginfo = newstyle.get().GetArgInfo(); 733 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 734 EXPECT_EQ(arginfo.get().max_positional_args, 3u); 735 } 736 737 #if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3 738 739 // the old implementation of GetArgInfo just doesn't work on builtins. 740 741 { 742 auto builtins = PythonModule::BuiltinsModule(); 743 auto hex = As<PythonCallable>(builtins.GetAttribute("hex")); 744 ASSERT_THAT_EXPECTED(hex, llvm::Succeeded()); 745 auto arginfo = hex.get().GetArgInfo(); 746 ASSERT_THAT_EXPECTED(arginfo, llvm::Succeeded()); 747 EXPECT_EQ(arginfo.get().max_positional_args, 1u); 748 } 749 750 #endif 751 } 752 753 TEST_F(PythonDataObjectsTest, TestScript) { 754 755 static const char script[] = R"( 756 def factorial(n): 757 if n > 1: 758 return n * factorial(n-1) 759 else: 760 return 1; 761 main = factorial 762 )"; 763 764 PythonScript factorial(script); 765 766 EXPECT_THAT_EXPECTED(As<long long>(factorial(5ll)), llvm::HasValue(120)); 767 } 768 769 TEST_F(PythonDataObjectsTest, TestExceptions) { 770 771 static const char script[] = R"( 772 def foo(): 773 return bar() 774 def bar(): 775 return baz() 776 def baz(): 777 return 1 / 0 778 main = foo 779 )"; 780 781 PythonScript foo(script); 782 783 EXPECT_THAT_EXPECTED( 784 foo(), llvm::Failed<PythonException>(testing::Property( 785 &PythonException::ReadBacktrace, 786 testing::AllOf(testing::ContainsRegex("line 3, in foo"), 787 testing::ContainsRegex("line 5, in bar"), 788 testing::ContainsRegex("line 7, in baz"), 789 testing::ContainsRegex("ZeroDivisionError"))))); 790 791 static const char script2[] = R"( 792 class MyError(Exception): 793 def __str__(self): 794 return self.my_message 795 796 def main(): 797 raise MyError("lol") 798 799 )"; 800 801 PythonScript lol(script2); 802 803 EXPECT_THAT_EXPECTED(lol(), 804 llvm::Failed<PythonException>(testing::Property( 805 &PythonException::ReadBacktrace, 806 testing::ContainsRegex("unprintable MyError")))); 807 } 808 809 TEST_F(PythonDataObjectsTest, TestRun) { 810 811 PythonDictionary globals(PyInitialValue::Empty); 812 813 auto x = As<long long>(runStringOneLine("40 + 2", globals, globals)); 814 ASSERT_THAT_EXPECTED(x, llvm::Succeeded()); 815 EXPECT_EQ(x.get(), 42l); 816 817 Expected<PythonObject> r = runStringOneLine("n = 42", globals, globals); 818 ASSERT_THAT_EXPECTED(r, llvm::Succeeded()); 819 auto y = As<long long>(globals.GetItem("n")); 820 ASSERT_THAT_EXPECTED(y, llvm::Succeeded()); 821 EXPECT_EQ(y.get(), 42l); 822 823 const char script[] = R"( 824 def foobar(): 825 return "foo" + "bar" + "baz" 826 g = foobar() 827 )"; 828 829 r = runStringMultiLine(script, globals, globals); 830 ASSERT_THAT_EXPECTED(r, llvm::Succeeded()); 831 auto g = As<std::string>(globals.GetItem("g")); 832 ASSERT_THAT_EXPECTED(g, llvm::HasValue("foobarbaz")); 833 } 834