this repo has no description
at trunk 900 lines 30 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include <cerrno> 3 4#include "Python.h" 5#include "gmock/gmock-matchers.h" 6#include "gtest/gtest.h" 7 8#include "capi-fixture.h" 9#include "capi-testing.h" 10 11namespace py { 12namespace testing { 13using ErrorsExtensionApiTest = ExtensionApi; 14 15TEST_F(ErrorsExtensionApiTest, CompareErrorMessageOnThread) { 16 ASSERT_EQ(nullptr, PyErr_Occurred()); 17 18 PyErr_SetString(PyExc_Exception, "An exception occured"); 19 ASSERT_EQ(PyExc_Exception, PyErr_Occurred()); 20} 21 22TEST_F(ErrorsExtensionApiTest, SetObjectSetsTypeAndValue) { 23 PyObject* type = nullptr; 24 PyObject* value = nullptr; 25 PyObject* traceback = nullptr; 26 PyErr_Fetch(&type, &value, &traceback); 27 EXPECT_EQ(type, nullptr); 28 EXPECT_EQ(value, nullptr); 29 EXPECT_EQ(traceback, nullptr); 30 31 PyErr_SetObject(PyExc_Exception, Py_True); 32 PyErr_Fetch(&type, &value, &traceback); 33 EXPECT_EQ(type, PyExc_Exception); 34 EXPECT_EQ(value, Py_True); 35 EXPECT_EQ(traceback, nullptr); 36 37 Py_DECREF(type); 38 Py_DECREF(value); 39} 40 41TEST_F(ErrorsExtensionApiTest, SetObjectWithNonExceptionTypeRaisesSystemError) { 42 PyObjectPtr bool_type(PyObject_Type(Py_True)); 43 PyErr_SetObject(bool_type, Py_None); 44 EXPECT_EQ(PyErr_Occurred(), PyExc_SystemError); 45} 46 47TEST_F(ErrorsExtensionApiTest, SetObjectWithNonTypeRaisesSystemError) { 48 PyErr_SetObject(Py_True, Py_None); 49 EXPECT_EQ(PyErr_Occurred(), PyExc_SystemError); 50} 51 52TEST_F(ErrorsExtensionApiTest, SetObjectWithPendingExceptionDoesNotAbort) { 53 ASSERT_EQ(PyErr_Occurred(), nullptr); 54 PyErr_SetObject(PyExc_TypeError, Py_True); 55 PyErr_SetObject(PyExc_UserWarning, Py_False); 56 57 PyObject* type = nullptr; 58 PyObject* value = nullptr; 59 PyObject* traceback = nullptr; 60 PyErr_Fetch(&type, &value, &traceback); 61 EXPECT_EQ(type, PyExc_UserWarning); 62 EXPECT_EQ(value, Py_False); 63 EXPECT_EQ(traceback, nullptr); 64 65 Py_DECREF(type); 66 Py_DECREF(value); 67} 68 69TEST_F(ErrorsExtensionApiTest, ClearClearsExceptionState) { 70 // Set the exception state 71 Py_INCREF(PyExc_Exception); 72 Py_INCREF(Py_True); 73 PyErr_Restore(PyExc_Exception, Py_True, nullptr); 74 75 // Check that an exception is pending 76 EXPECT_EQ(PyErr_Occurred(), PyExc_Exception); 77 78 // Clear the exception 79 PyErr_Clear(); 80 81 // Read the exception state again and check for null 82 PyObject* type = nullptr; 83 PyObject* value = nullptr; 84 PyObject* traceback = nullptr; 85 PyErr_Fetch(&type, &value, &traceback); 86 EXPECT_EQ(type, nullptr); 87 EXPECT_EQ(value, nullptr); 88 EXPECT_EQ(traceback, nullptr); 89} 90 91TEST_F(ErrorsExtensionApiTest, BadArgumentRaisesTypeError) { 92 ASSERT_EQ(PyErr_Occurred(), nullptr); 93 EXPECT_EQ(PyErr_BadArgument(), 0); 94 95 PyObject* type = nullptr; 96 PyObject* value = nullptr; 97 PyObject* traceback = nullptr; 98 PyErr_Fetch(&type, &value, &traceback); 99 EXPECT_EQ(type, PyExc_TypeError); 100 101 PyObjectPtr message( 102 PyUnicode_FromString("bad argument type for built-in operation")); 103 ASSERT_TRUE(PyUnicode_Check(message)); 104 EXPECT_EQ(_PyUnicode_EQ(value, message), 1); 105 106 // TODO(T42241510): Traceback support isn't implemented yet. Once it's ready, 107 // inspect the traceback here. 108 109 Py_DECREF(type); 110 Py_DECREF(value); 111} 112 113TEST_F(ErrorsExtensionApiTest, NewExceptionWithBadNameRaisesSystemError) { 114 EXPECT_EQ(PyErr_NewException("NameWithoutADot", nullptr, nullptr), nullptr); 115 ASSERT_NE(PyErr_Occurred(), nullptr); 116 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 117} 118 119TEST_F(ErrorsExtensionApiTest, NewExceptionWithoutDictOrBaseReturnsType) { 120 PyObjectPtr type(PyErr_NewException("Module.Name", nullptr, nullptr)); 121 ASSERT_EQ(PyErr_Occurred(), nullptr); 122 ASSERT_TRUE(PyType_CheckExact(type)); 123 EXPECT_TRUE( 124 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 125 reinterpret_cast<PyTypeObject*>(PyExc_Exception))); 126 127 PyObjectPtr name(PyObject_GetAttrString(type, "__name__")); 128 ASSERT_TRUE(PyUnicode_CheckExact(name)); 129 EXPECT_TRUE(isUnicodeEqualsCStr(name, "Name")); 130 PyObjectPtr module_name(PyObject_GetAttrString(type, "__module__")); 131 ASSERT_TRUE(PyUnicode_CheckExact(module_name)); 132 EXPECT_TRUE(isUnicodeEqualsCStr(module_name, "Module")); 133} 134 135TEST_F(ErrorsExtensionApiTest, NewExceptionWithSingleBaseCreatesBasesTuple) { 136 PyObjectPtr type( 137 PyErr_NewException("Module.Name", PyExc_ValueError, nullptr)); 138 ASSERT_EQ(PyErr_Occurred(), nullptr); 139 ASSERT_TRUE(PyType_CheckExact(type)); 140 EXPECT_TRUE( 141 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 142 reinterpret_cast<PyTypeObject*>(PyExc_ValueError))); 143 144 PyObjectPtr bases(PyObject_GetAttrString(type, "__bases__")); 145 ASSERT_TRUE(PyTuple_CheckExact(bases)); 146 EXPECT_EQ(PyTuple_GetItem(bases, 0), PyExc_ValueError); 147} 148 149TEST_F(ErrorsExtensionApiTest, NewExceptionWithBaseTupleStoresTuple) { 150 PyObjectPtr bases(PyTuple_New(2)); 151 Py_INCREF(PyExc_SystemError); 152 ASSERT_EQ(PyTuple_SetItem(bases, 0, PyExc_SystemError), 0); 153 Py_INCREF(PyExc_ValueError); 154 ASSERT_EQ(PyTuple_SetItem(bases, 1, PyExc_ValueError), 0); 155 PyObjectPtr type(PyErr_NewException("Module.Name", bases, nullptr)); 156 ASSERT_EQ(PyErr_Occurred(), nullptr); 157 ASSERT_TRUE(PyType_CheckExact(type)); 158 EXPECT_TRUE( 159 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 160 reinterpret_cast<PyTypeObject*>(PyExc_ValueError))); 161 EXPECT_TRUE( 162 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 163 reinterpret_cast<PyTypeObject*>(PyExc_SystemError))); 164 165 PyObjectPtr type_bases(PyObject_GetAttrString(type, "__bases__")); 166 EXPECT_EQ(type_bases, bases); 167} 168 169TEST_F(ErrorsExtensionApiTest, NewExceptionWithEmptyDictAddsModuleName) { 170 PyObjectPtr dict(PyDict_New()); 171 PyObjectPtr type(PyErr_NewException("Module.Name", nullptr, dict)); 172 ASSERT_EQ(PyErr_Occurred(), nullptr); 173 ASSERT_TRUE(PyType_CheckExact(type)); 174 175 PyObjectPtr module_name(PyObject_GetAttrString(type, "__module__")); 176 ASSERT_TRUE(PyUnicode_CheckExact(module_name)); 177 EXPECT_TRUE(isUnicodeEqualsCStr(module_name, "Module")); 178} 179 180TEST_F(ErrorsExtensionApiTest, 181 NewExceptionWithDocWithNullDocReturnsTypeWithNoneDoc) { 182 PyObjectPtr type( 183 PyErr_NewExceptionWithDoc("Module.Name", nullptr, nullptr, nullptr)); 184 ASSERT_EQ(PyErr_Occurred(), nullptr); 185 ASSERT_TRUE(PyType_CheckExact(type)); 186 EXPECT_TRUE( 187 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 188 reinterpret_cast<PyTypeObject*>(PyExc_Exception))); 189 190 PyObjectPtr name(PyObject_GetAttrString(type, "__name__")); 191 PyObjectPtr module_name(PyObject_GetAttrString(type, "__module__")); 192 PyObjectPtr doc_string(PyObject_GetAttrString(type, "__doc__")); 193 EXPECT_TRUE(isUnicodeEqualsCStr(name, "Name")); 194 EXPECT_TRUE(isUnicodeEqualsCStr(module_name, "Module")); 195 EXPECT_EQ(doc_string, Py_None); 196} 197 198TEST_F(ErrorsExtensionApiTest, 199 NewExceptionWithDocWithNonDictRaisesSystemError) { 200 PyObjectPtr not_dict(PyList_New(0)); 201 EXPECT_EQ(PyErr_NewExceptionWithDoc("Module.Name", "DOC", nullptr, not_dict), 202 nullptr); 203 ASSERT_NE(PyErr_Occurred(), nullptr); 204 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 205} 206 207TEST_F(ErrorsExtensionApiTest, NewExceptionWithDocWithStrReturnsType) { 208 PyObjectPtr type( 209 PyErr_NewExceptionWithDoc("Module.Name", "DOC", nullptr, nullptr)); 210 ASSERT_EQ(PyErr_Occurred(), nullptr); 211 ASSERT_TRUE(PyType_CheckExact(type)); 212 EXPECT_TRUE( 213 PyType_IsSubtype(reinterpret_cast<PyTypeObject*>(type.get()), 214 reinterpret_cast<PyTypeObject*>(PyExc_Exception))); 215 216 PyObjectPtr name(PyObject_GetAttrString(type, "__name__")); 217 PyObjectPtr module_name(PyObject_GetAttrString(type, "__module__")); 218 PyObjectPtr doc_string(PyObject_GetAttrString(type, "__doc__")); 219 EXPECT_TRUE(isUnicodeEqualsCStr(name, "Name")); 220 EXPECT_TRUE(isUnicodeEqualsCStr(module_name, "Module")); 221 EXPECT_TRUE(isUnicodeEqualsCStr(doc_string, "DOC")); 222} 223 224TEST_F(ErrorsExtensionApiTest, NoMemoryRaisesMemoryError) { 225 ASSERT_EQ(PyErr_Occurred(), nullptr); 226 EXPECT_EQ(PyErr_NoMemory(), nullptr); 227 228 PyObject* type = nullptr; 229 PyObject* value = nullptr; 230 PyObject* traceback = nullptr; 231 PyErr_Fetch(&type, &value, &traceback); 232 EXPECT_EQ(type, PyExc_MemoryError); 233 EXPECT_EQ(value, nullptr); 234 // TODO(T42241510): Traceback support isn't implemented yet. Once it's ready, 235 // inspect the traceback here. 236 237 Py_DECREF(type); 238} 239 240#pragma push_macro("PyErr_BadInternalCall") 241#undef PyErr_BadInternalCall 242// PyErr_BadInternalCall() has an assert(0) in CPython. 243TEST_F(ErrorsExtensionApiTest, BadInternalCallRaisesSystemErrorPyro) { 244 ASSERT_EQ(PyErr_Occurred(), nullptr); 245 PyErr_BadInternalCall(); 246 247 PyObject* type = nullptr; 248 PyObject* value = nullptr; 249 PyObject* traceback = nullptr; 250 PyErr_Fetch(&type, &value, &traceback); 251 EXPECT_EQ(type, PyExc_SystemError); 252 253 PyObjectPtr message( 254 PyUnicode_FromString("bad argument to internal function")); 255 ASSERT_TRUE(PyUnicode_Check(message)); 256 EXPECT_EQ(_PyUnicode_EQ(value, message), 1); 257 258 // TODO(T42241510): Traceback support isn't implemented yet. Once it's ready, 259 // inspect the traceback here. 260 261 Py_DECREF(type); 262 Py_DECREF(value); 263} 264#pragma pop_macro("PyErr_BadInternalCall") 265 266TEST_F(ErrorsExtensionApiTest, UnderBadInternalCallRaisesSystemError) { 267 ASSERT_EQ(PyErr_Occurred(), nullptr); 268 _PyErr_BadInternalCall("abc", 123); 269 270 PyObject* type = nullptr; 271 PyObject* value = nullptr; 272 PyObject* traceback = nullptr; 273 PyErr_Fetch(&type, &value, &traceback); 274 EXPECT_EQ(type, PyExc_SystemError); 275 276 PyObjectPtr message( 277 PyUnicode_FromString("abc:123: bad argument to internal function")); 278 ASSERT_TRUE(PyUnicode_Check(message)); 279 EXPECT_EQ(_PyUnicode_EQ(value, message), 1); 280 281 // TODO(T42241510): Traceback support isn't implemented yet. Once it's ready, 282 // inspect the traceback here. 283 284 Py_DECREF(type); 285 Py_DECREF(value); 286} 287 288TEST_F(ErrorsExtensionApiTest, ExceptionMatches) { 289 ASSERT_EQ(PyErr_Occurred(), nullptr); 290 PyErr_NoMemory(); 291 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_MemoryError)); 292 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_Exception)); 293 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_BaseException)); 294} 295 296TEST_F(ErrorsExtensionApiTest, Fetch) { 297 PyErr_SetObject(PyExc_Exception, Py_True); 298 299 PyObject* type = nullptr; 300 PyObject* value = nullptr; 301 PyObject* traceback = nullptr; 302 PyErr_Fetch(&type, &value, &traceback); 303 EXPECT_EQ(type, PyExc_Exception); 304 EXPECT_EQ(value, Py_True); 305 EXPECT_EQ(traceback, nullptr); 306 307 Py_DECREF(type); 308 Py_DECREF(value); 309} 310 311TEST_F(ErrorsExtensionApiTest, GetExcInfoWhenNoCaughtException) { 312 PyObject* p_type; 313 PyObject* p_value; 314 PyObject* p_traceback; 315 PyErr_SetExcInfo(nullptr, nullptr, nullptr); 316 PyErr_GetExcInfo(&p_type, &p_value, &p_traceback); 317 EXPECT_EQ(p_type, nullptr); 318 EXPECT_EQ(p_value, nullptr); 319 EXPECT_EQ(p_traceback, nullptr); 320} 321 322TEST_F(ErrorsExtensionApiTest, GetExcInfoWhenCaughtException) { 323 binaryfunc func = [](PyObject*, PyObject*) { 324 PyObject* p_type; 325 PyObject* p_value; 326 PyObject* p_traceback; 327 PyErr_GetExcInfo(&p_type, &p_value, &p_traceback); 328 EXPECT_EQ(p_type, PyExc_Exception); 329 PyObjectPtr args(PyObject_GetAttrString(p_value, "args")); 330 PyObject* first_arg = PyTuple_GetItem(args, 0); 331 EXPECT_TRUE(isUnicodeEqualsCStr(first_arg, "some str")); 332 EXPECT_TRUE(PyTraceBack_Check(p_traceback)); 333 Py_INCREF(Py_None); 334 Py_XDECREF(p_type); 335 Py_XDECREF(p_value); 336 Py_XDECREF(p_traceback); 337 return Py_None; 338 }; 339 PyMethodDef foo_methods[] = {{"noargs", func, METH_NOARGS}, {nullptr}}; 340 static PyModuleDef def; 341 def = { 342 PyModuleDef_HEAD_INIT, "foo", nullptr, 0, foo_methods, 343 }; 344 PyObjectPtr module(PyModule_Create(&def)); 345 moduleSet("__main__", "foo", module); 346 ASSERT_TRUE(PyModule_CheckExact(module)); 347 EXPECT_EQ(PyErr_Occurred(), nullptr); 348 PyRun_SimpleString(R"( 349try: 350 raise Exception('some str') 351except: 352 foo.noargs() 353)"); 354} 355 356TEST_F(ErrorsExtensionApiTest, GivenExceptionMatches) { 357 // An exception matches itself and all of its super types up to and including 358 // BaseException. 359 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, PyExc_MemoryError), 360 1); 361 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, PyExc_Exception), 1); 362 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, PyExc_BaseException), 363 1); 364 365 // An exception should not match a disjoint exception type. 366 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, PyExc_IOError), 0); 367 368 // If the objects are not exceptions or exception classes, the matching falls 369 // back to an identity comparison. 370 EXPECT_TRUE(PyErr_GivenExceptionMatches(Py_True, Py_True)); 371} 372 373TEST_F(ErrorsExtensionApiTest, GivenExceptionMatchesWithNullptr) { 374 // If any argument is a null pointer zero is returned. 375 EXPECT_EQ(PyErr_GivenExceptionMatches(nullptr, nullptr), 0); 376 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_SystemError, nullptr), 0); 377 EXPECT_EQ(PyErr_GivenExceptionMatches(nullptr, PyExc_SystemError), 0); 378} 379 380TEST_F(ErrorsExtensionApiTest, GivenExceptionMatchesWithTuple) { 381 PyObject* exc1 = PyTuple_Pack(1, PyExc_Exception); 382 ASSERT_NE(exc1, nullptr); 383 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, exc1), 1); 384 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_SystemExit, exc1), 0); 385 Py_DECREF(exc1); 386 387 // Linear search 388 PyObject* exc2 = PyTuple_Pack(2, PyExc_Warning, PyExc_Exception); 389 ASSERT_NE(exc2, nullptr); 390 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, exc2), 1); 391 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_SystemExit, exc2), 0); 392 Py_DECREF(exc2); 393 394 // Recursion 395 PyObjectPtr inner(PyTuple_Pack(1, PyExc_Exception)); 396 PyObject* exc3 = PyTuple_Pack(2, inner.get(), PyExc_Warning); 397 ASSERT_NE(exc3, nullptr); 398 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_MemoryError, exc3), 1); 399 EXPECT_EQ(PyErr_GivenExceptionMatches(PyExc_SystemExit, exc3), 0); 400 Py_DECREF(exc3); 401} 402 403TEST_F(ErrorsExtensionApiTest, Restore) { 404 ASSERT_EQ(PyErr_Occurred(), nullptr); 405 Py_INCREF(PyExc_Exception); 406 Py_INCREF(Py_True); 407 PyErr_Restore(PyExc_Exception, Py_True, nullptr); 408 409 PyObject* type = nullptr; 410 PyObject* value = nullptr; 411 PyObject* traceback = nullptr; 412 PyErr_Fetch(&type, &value, &traceback); 413 EXPECT_EQ(type, PyExc_Exception); 414 EXPECT_EQ(value, Py_True); 415 EXPECT_EQ(traceback, nullptr); 416 417 Py_DECREF(type); 418 Py_DECREF(value); 419} 420 421TEST_F(ErrorsExtensionApiTest, ChainExceptionsSetsContext) { 422 // First, set an exception. 423 PyErr_SetString(PyExc_RuntimeError, "whoops"); 424 425 // Next, attempt to restore a different exception. It should be chained to the 426 // existing RuntimeError. 427 PyObject* exc = PyExc_TypeError; 428 Py_INCREF(exc); 429 PyObject* val = Py_None; 430 Py_INCREF(val); 431 PyObject* tb = Py_None; 432 Py_INCREF(tb); 433 _PyErr_ChainExceptions(exc, val, tb); 434 ASSERT_NE(PyErr_Occurred(), nullptr); 435 436 // Make sure the RuntimeError has the new TypeError as its context attribute. 437 PyErr_Fetch(&exc, &val, &tb); 438 ASSERT_EQ(PyErr_GivenExceptionMatches(exc, PyExc_RuntimeError), 1); 439 ASSERT_EQ(PyErr_GivenExceptionMatches(val, PyExc_RuntimeError), 1); 440 441 PyObjectPtr ctx(PyException_GetContext(val)); 442 EXPECT_EQ(PyErr_GivenExceptionMatches(ctx, PyExc_TypeError), 1); 443 444 EXPECT_EQ(tb, nullptr); 445 446 Py_DECREF(exc); 447 Py_DECREF(val); 448} 449 450TEST_F(ErrorsExtensionApiTest, NormalizeCreatesException) { 451 PyObject* exc = PyExc_RuntimeError; 452 PyObject* val = PyUnicode_FromString("something went wrong!"); 453 PyObjectPtr val_orig(val); 454 Py_INCREF(val_orig); 455 PyObject* tb = nullptr; 456 PyErr_NormalizeException(&exc, &val, &tb); 457 ASSERT_EQ(PyErr_Occurred(), nullptr); 458 EXPECT_TRUE(PyErr_GivenExceptionMatches(exc, PyExc_RuntimeError)); 459 ASSERT_TRUE(PyErr_GivenExceptionMatches(val, PyExc_RuntimeError)); 460 PyObjectPtr args(PyObject_GetAttrString(val, "args")); 461 ASSERT_TRUE(PyTuple_CheckExact(args)); 462 ASSERT_EQ(PyTuple_Size(args), 1); 463 EXPECT_EQ(PyTuple_GetItem(args, 0), val_orig); 464 465 Py_DECREF(val); 466} 467 468TEST_F(ErrorsExtensionApiTest, NormalizeWithNullTypeDoesNothing) { 469 PyObject* exc = nullptr; 470 PyObject* val = nullptr; 471 PyObject* tb = nullptr; 472 PyErr_NormalizeException(&exc, &val, &tb); 473 EXPECT_EQ(PyErr_Occurred(), nullptr); 474 EXPECT_EQ(exc, nullptr); 475 EXPECT_EQ(val, nullptr); 476 EXPECT_EQ(tb, nullptr); 477} 478 479TEST_F(ErrorsExtensionApiTest, NormalizeWithNullValueUsesNone) { 480 PyObject* exc = PyExc_TypeError; 481 PyObject* val = Py_None; 482 Py_INCREF(val); 483 PyObject* tb = nullptr; 484 PyErr_NormalizeException(&exc, &val, &tb); 485 ASSERT_EQ(PyErr_Occurred(), nullptr); 486 EXPECT_TRUE(PyErr_GivenExceptionMatches(exc, PyExc_TypeError)); 487 ASSERT_TRUE(PyErr_GivenExceptionMatches(val, PyExc_TypeError)); 488 PyObjectPtr args(PyObject_GetAttrString(val, "args")); 489 ASSERT_TRUE(PyTuple_CheckExact(args)); 490 EXPECT_EQ(PyTuple_Size(args), 0); 491 492 Py_DECREF(val); 493} 494 495TEST_F(ErrorsExtensionApiTest, NormalizeWithTupleUsesArgs) { 496 PyObject* exc = PyExc_Exception; 497 PyObject* val = PyTuple_New(2); 498 PyObjectPtr t0(PyLong_FromLong(111)); 499 PyObjectPtr t1(PyUnicode_FromString("hello")); 500 Py_INCREF(t0); 501 PyTuple_SET_ITEM(val, 0, t0); 502 Py_INCREF(t1); 503 PyTuple_SET_ITEM(val, 1, t1); 504 PyObject* tb = nullptr; 505 PyErr_NormalizeException(&exc, &val, &tb); 506 ASSERT_EQ(PyErr_Occurred(), nullptr); 507 EXPECT_TRUE(PyErr_GivenExceptionMatches(exc, PyExc_Exception)); 508 ASSERT_TRUE(PyErr_GivenExceptionMatches(val, PyExc_Exception)); 509 PyObjectPtr args(PyObject_GetAttrString(val, "args")); 510 ASSERT_TRUE(PyTuple_CheckExact(args)); 511 ASSERT_EQ(PyTuple_Size(args), 2); 512 EXPECT_EQ(PyTuple_GetItem(args, 0), t0); 513 EXPECT_EQ(PyTuple_GetItem(args, 1), t1); 514 515 Py_DECREF(val); 516} 517 518TEST_F(ErrorsExtensionApiTest, NormalizeWithNonExceptionDoesNothing) { 519 PyObject *exc = PyLong_FromLong(123), *exc_orig = exc; 520 PyObject *val = PyLong_FromLong(456), *val_orig = val; 521 PyObject* tb = nullptr; 522 PyErr_NormalizeException(&exc, &val, &tb); 523 ASSERT_EQ(PyErr_Occurred(), nullptr); 524 EXPECT_EQ(exc, exc_orig); 525 EXPECT_EQ(val, val_orig); 526 EXPECT_EQ(tb, nullptr); 527 528 Py_DECREF(val); 529 Py_DECREF(exc); 530} 531 532TEST_F(ErrorsExtensionApiTest, NormalizeWithFailingConstructorReturnsNewError) { 533 // TODO(bsimmers): Once we have PyType_FromSpec() (or PyType_Ready() can 534 // handle base classes), add a similar test to ensure that 535 // PyErr_NormalizeException() doesn't loop infinintely when normalization 536 // keeps failing. 537 538 ASSERT_EQ(PyRun_SimpleString(R"( 539class BadException(Exception): 540 def __init__(self, arg): 541 raise RuntimeError(arg) 542)"), 543 0); 544 PyObject* exc = mainModuleGet("BadException"); 545 ASSERT_TRUE(PyType_Check(exc)); 546 547 const char* msg = "couldn't construct BadException"; 548 PyObject* val = PyUnicode_FromString(msg); 549 PyObject* tb = nullptr; 550 PyErr_NormalizeException(&exc, &val, &tb); 551 ASSERT_EQ(PyErr_Occurred(), nullptr); 552 EXPECT_TRUE(PyErr_GivenExceptionMatches(exc, PyExc_RuntimeError)); 553 ASSERT_TRUE(PyErr_GivenExceptionMatches(val, PyExc_RuntimeError)); 554 PyObjectPtr args(PyObject_GetAttrString(val, "args")); 555 ASSERT_TRUE(PyTuple_CheckExact(args)); 556 ASSERT_EQ(PyTuple_Size(args), 1); 557 PyObject* str = PyTuple_GetItem(args, 0); 558 EXPECT_TRUE(isUnicodeEqualsCStr(str, msg)); 559 560 Py_XDECREF(val); 561 Py_XDECREF(exc); 562 Py_XDECREF(tb); 563} 564 565TEST_F(ErrorsExtensionApiTest, ProgramTextObjectWithNullFilenameReturnsNull) { 566 EXPECT_EQ(PyErr_ProgramTextObject(nullptr, 5), nullptr); 567 EXPECT_EQ(PyErr_Occurred(), nullptr); 568} 569 570TEST_F(ErrorsExtensionApiTest, 571 ProgramTextObjectWithNonPositiveLinenoReturnsNull) { 572 PyObjectPtr filename(PyUnicode_FromString("filename")); 573 EXPECT_EQ(PyErr_ProgramTextObject(filename, -5), nullptr); 574 EXPECT_EQ(PyErr_Occurred(), nullptr); 575} 576 577TEST_F(ErrorsExtensionApiTest, 578 ProgramTextObjectWithNonExistentFileReturnsNull) { 579 PyObjectPtr filename(PyUnicode_FromString("foobarbazquux")); 580 EXPECT_EQ(PyErr_ProgramTextObject(filename, 5), nullptr); 581 EXPECT_EQ(PyErr_Occurred(), nullptr); 582} 583 584TEST_F(ErrorsExtensionApiTest, SetExcInfoValuesRetrievedByGetExcInfo) { 585 PyObjectPtr type(PyExc_TypeError); 586 Py_INCREF(type); 587 PyObjectPtr val(PyUnicode_FromString("some str")); 588 PyObject* traceback = nullptr; 589 PyErr_SetExcInfo(type, val, traceback); 590 591 PyObject* p_type; 592 PyObject* p_value; 593 PyObject* p_traceback; 594 PyErr_GetExcInfo(&p_type, &p_value, &p_traceback); 595 EXPECT_EQ(p_type, type); 596 EXPECT_EQ(p_value, val); 597 // TODO(T77866913): EXPECT_EQ(p_traceback, traceback); 598} 599 600TEST_F(ErrorsExtensionApiTest, SetFromErrnoWithZeroSetsError) { 601 errno = 0; 602 ASSERT_EQ(PyErr_SetFromErrno(PyExc_TypeError), nullptr); 603 ASSERT_NE(PyErr_Occurred(), nullptr); 604 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 605} 606 607TEST_F(ErrorsExtensionApiTest, SetFromErrnoWithNonZeroSetsError) { 608 errno = 1; 609 ASSERT_EQ(PyErr_SetFromErrno(PyExc_SystemError), nullptr); 610 ASSERT_NE(PyErr_Occurred(), nullptr); 611 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 612} 613 614TEST_F(ErrorsExtensionApiTest, 615 SetFromErrnoWithInterruptRaisesKeyboardInterrupt) { 616 PyErr_SetInterrupt(); 617 errno = EINTR; 618 ASSERT_EQ(PyErr_SetFromErrno(PyExc_SystemError), nullptr); 619 ASSERT_NE(PyErr_Occurred(), nullptr); 620 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_KeyboardInterrupt)); 621} 622 623TEST_F(ErrorsExtensionApiTest, SetFromErrnoWithFilenameSetsError) { 624 errno = 1; 625 ASSERT_EQ(PyErr_SetFromErrnoWithFilename(PyExc_NameError, "foo"), nullptr); 626 ASSERT_NE(PyErr_Occurred(), nullptr); 627 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_NameError)); 628} 629 630TEST_F(ErrorsExtensionApiTest, SetFromErrnoWithFilenameObjectSetsError) { 631 errno = 1; 632 PyObjectPtr foo(PyUnicode_FromString("foo")); 633 ASSERT_EQ(PyErr_SetFromErrnoWithFilenameObject(PyExc_KeyError, foo), nullptr); 634 ASSERT_NE(PyErr_Occurred(), nullptr); 635 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_KeyError)); 636} 637 638TEST_F(ErrorsExtensionApiTest, SetFromErrnoWithFilenameObjectsSetsError) { 639 errno = 1; 640 PyObjectPtr foo(PyUnicode_FromString("foo")); 641 PyObjectPtr bar(PyUnicode_FromString("bar")); 642 ASSERT_EQ( 643 PyErr_SetFromErrnoWithFilenameObjects(PyExc_ChildProcessError, foo, bar), 644 nullptr); 645 ASSERT_NE(PyErr_Occurred(), nullptr); 646 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ChildProcessError)); 647} 648 649TEST_F(ErrorsExtensionApiTest, SetNoneCreatesExceptionWithNoArgs) { 650 PyErr_SetNone(PyExc_Exception); 651 652 ASSERT_NE(PyErr_Occurred(), nullptr); 653 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_Exception)); 654 PyObject* type = nullptr; 655 PyObject* value = nullptr; 656 PyObject* traceback = nullptr; 657 // Fetch the non-normalized error 658 PyErr_Fetch(&type, &value, &traceback); 659 EXPECT_EQ(type, PyExc_Exception); 660 ASSERT_EQ(value, nullptr); 661 // Normalize the exception 662 PyErr_NormalizeException(&type, &value, &traceback); 663 EXPECT_EQ(type, PyExc_Exception); 664 PyObjectPtr args(PyObject_GetAttrString(value, "args")); 665 ASSERT_TRUE(PyTuple_CheckExact(args)); 666 ASSERT_EQ(PyTuple_Size(args), 0); 667 Py_DECREF(type); 668 Py_DECREF(value); 669} 670 671TEST_F(ErrorsExtensionApiTest, SetStringSetsValue) { 672 PyErr_SetString(PyExc_Exception, "An exception occured"); 673 PyObject* type = nullptr; 674 PyObject* value = nullptr; 675 PyObject* traceback = nullptr; 676 PyErr_Fetch(&type, &value, &traceback); 677 EXPECT_EQ(traceback, nullptr); 678 EXPECT_EQ(type, PyExc_Exception); 679 EXPECT_TRUE(isUnicodeEqualsCStr(value, "An exception occured")); 680 681 Py_DECREF(type); 682 Py_DECREF(value); 683} 684 685TEST_F(ErrorsExtensionApiTest, FormatWithNoArgsSetsAppropriateFields) { 686 ASSERT_EQ(PyErr_Format(PyExc_TypeError, "hello error"), nullptr); 687 PyObject* type = nullptr; 688 PyObject* value = nullptr; 689 PyObject* traceback = nullptr; 690 PyErr_Fetch(&type, &value, &traceback); 691 EXPECT_EQ(type, PyExc_TypeError); 692 EXPECT_TRUE(isUnicodeEqualsCStr(value, "hello error")); 693 EXPECT_EQ(traceback, nullptr); 694 695 Py_DECREF(type); 696 Py_DECREF(value); 697} 698 699TEST_F(ErrorsExtensionApiTest, FormatWithManyArgsSetsAppropriateFields) { 700 ASSERT_EQ(PyErr_Format(PyExc_MemoryError, "h%c%s", 'e', "llo world"), 701 nullptr); 702 PyObject* type = nullptr; 703 PyObject* value = nullptr; 704 PyObject* traceback = nullptr; 705 PyErr_Fetch(&type, &value, &traceback); 706 EXPECT_EQ(type, PyExc_MemoryError); 707 EXPECT_TRUE(isUnicodeEqualsCStr(value, "hello world")); 708 EXPECT_EQ(traceback, nullptr); 709 710 Py_DECREF(type); 711 Py_DECREF(value); 712} 713 714TEST_F(ErrorsExtensionApiTest, FormatFromCauseWithoutExceptionFailsDeathTest) { 715 EXPECT_DEATH(_PyErr_FormatFromCause(PyExc_TypeError, ""), ""); 716} 717 718TEST_F(ErrorsExtensionApiTest, FormatFromCauseSetsCauseAndContext) { 719 ASSERT_EQ(PyErr_Format(PyExc_MemoryError, "%s", "original cause"), nullptr); 720 ASSERT_EQ(_PyErr_FormatFromCause(PyExc_TypeError, "%s", "new error"), 721 nullptr); 722 PyObject* type = nullptr; 723 PyObject* value = nullptr; 724 PyObject* traceback = nullptr; 725 PyErr_Fetch(&type, &value, &traceback); 726 EXPECT_EQ(type, PyExc_TypeError); 727 Py_XDECREF(type); 728 EXPECT_EQ(traceback, nullptr); 729 Py_XDECREF(traceback); 730 PyObjectPtr cause(PyException_GetCause(value)); 731 PyObjectPtr context(PyException_GetContext(value)); 732 EXPECT_TRUE(PyErr_GivenExceptionMatches(cause, PyExc_MemoryError)); 733 EXPECT_TRUE(PyErr_GivenExceptionMatches(context, PyExc_MemoryError)); 734 Py_XDECREF(value); 735} 736 737TEST_F(ErrorsExtensionApiTest, WriteUnraisableClearsException) { 738 PyErr_SetString(PyExc_MemoryError, "original cause"); 739 PyErr_WriteUnraisable(Py_None); 740 EXPECT_EQ(PyErr_Occurred(), nullptr); 741} 742 743TEST_F(ErrorsExtensionApiTest, WriteUnraisableCallsDunderRepr) { 744 PyRun_SimpleString(R"( 745class C: 746 def __repr__(self): 747 return "foo" 748c = C() 749)"); 750 PyObjectPtr c(mainModuleGet("c")); 751 PyErr_SetString(PyExc_MemoryError, "original cause"); 752 CaptureStdStreams streams; 753 PyErr_WriteUnraisable(c); 754 EXPECT_EQ(PyErr_Occurred(), nullptr); 755 EXPECT_THAT(streams.err(), 756 ::testing::StartsWith("Exception ignored in: foo")); 757 EXPECT_EQ(streams.out(), ""); 758} 759 760TEST_F(ErrorsExtensionApiTest, 761 WriteUnraisableDoesNotFailWithNonCallableDunderRepr) { 762 PyRun_SimpleString(R"( 763class C: 764 __repr__ = 5 765c = C() 766)"); 767 PyObjectPtr c(mainModuleGet("c")); 768 PyErr_SetString(PyExc_MemoryError, "original cause"); 769 CaptureStdStreams streams; 770 PyErr_WriteUnraisable(c); 771 EXPECT_EQ(PyErr_Occurred(), nullptr); 772 EXPECT_THAT( 773 streams.err(), 774 ::testing::StartsWith("Exception ignored in: <object repr() failed>")); 775 EXPECT_EQ(streams.out(), ""); 776} 777 778TEST_F(ErrorsExtensionApiTest, 779 WriteUnraisableWithNonStrDunderModuleWritesUnknown) { 780 PyRun_SimpleString(R"( 781class C(BaseException): 782 pass 783C.__module__ = 5 784c = C() 785)"); 786 PyObjectPtr c(mainModuleGet("c")); 787 PyObjectPtr ctype(mainModuleGet("C")); 788 PyErr_SetString(ctype, "original cause"); 789 CaptureStdStreams streams; 790 PyErr_WriteUnraisable(c); 791 EXPECT_EQ(PyErr_Occurred(), nullptr); 792 EXPECT_THAT(streams.err(), 793 ::testing::EndsWith("<unknown>C: original cause\n")); 794 EXPECT_EQ(streams.out(), ""); 795} 796 797TEST_F(ErrorsExtensionApiTest, WriteUnraisableWritesModuleName) { 798 PyRun_SimpleString(R"( 799class C(BaseException): 800 pass 801C.__module__ = "foo" 802c = C() 803)"); 804 PyObjectPtr c(mainModuleGet("c")); 805 PyObjectPtr ctype(mainModuleGet("C")); 806 PyErr_SetString(ctype, "original cause"); 807 CaptureStdStreams streams; 808 PyErr_WriteUnraisable(c); 809 EXPECT_EQ(PyErr_Occurred(), nullptr); 810 EXPECT_THAT(streams.err(), ::testing::EndsWith("foo.C: original cause\n")); 811 EXPECT_EQ(streams.out(), ""); 812} 813 814TEST_F(ErrorsExtensionApiTest, WriteUnraisableCallsDunderStrOnVal) { 815 PyRun_SimpleString(R"( 816class C: 817 def __str__(self): 818 return "bar" 819C.__module__ = "foo" 820c = C() 821)"); 822 PyObjectPtr c(mainModuleGet("c")); 823 PyErr_SetObject(PyExc_MemoryError, c); 824 CaptureStdStreams streams; 825 PyErr_WriteUnraisable(Py_None); 826 EXPECT_EQ(PyErr_Occurred(), nullptr); 827 EXPECT_THAT(streams.err(), ::testing::EndsWith("MemoryError: bar\n")); 828 EXPECT_EQ(streams.out(), ""); 829} 830 831TEST_F(ErrorsExtensionApiTest, 832 WriteUnraisableDoesNotFailWithNonCallableDunderStr) { 833 PyRun_SimpleString(R"( 834class C: 835 __str__ = 5 836C.__module__ = "foo" 837c = C() 838)"); 839 PyObjectPtr c(mainModuleGet("c")); 840 PyErr_SetObject(PyExc_MemoryError, c); 841 CaptureStdStreams streams; 842 PyErr_WriteUnraisable(Py_None); 843 EXPECT_EQ(PyErr_Occurred(), nullptr); 844 EXPECT_THAT(streams.err(), 845 ::testing::EndsWith("MemoryError: <exception str() failed>\n")); 846 EXPECT_EQ(streams.out(), ""); 847} 848 849TEST_F(ErrorsExtensionApiTest, SetObjectWithCaughtExceptionSetsContext) { 850 PyCFunction test_set_object = [](PyObject*, PyObject*) -> PyObject* { 851 PyErr_SetString(PyExc_ValueError, "something went wrong"); 852 return nullptr; 853 }; 854 static PyMethodDef methods[2]; 855 methods[0] = { 856 "test_set_object", 857 test_set_object, 858 METH_NOARGS, 859 "doc", 860 }; 861 methods[1] = {nullptr}; 862 static PyModuleDef mod_def; 863 mod_def = { 864 PyModuleDef_HEAD_INIT, 865 "errors_test", // m_name 866 "doc", // m_doc 867 0, // m_size 868 methods, // m_methods 869 nullptr, // m_slots 870 nullptr, // m_traverse 871 nullptr, // m_clear 872 nullptr, // m_free 873 }; 874 875 PyObjectPtr module(PyModule_Create(&mod_def)); 876 ASSERT_NE(module, nullptr); 877 ASSERT_EQ(moduleSet("__main__", "errors_test", module), 0); 878 ASSERT_EQ(PyRun_SimpleString(R"( 879try: 880 try: 881 raise RuntimeError("blorp") 882 except RuntimeError as exc: 883 inner_exc = exc 884 errors_test.test_set_object() 885except ValueError as exc: 886 outer_exc = exc 887)"), 888 0); 889 890 PyObjectPtr inner_exc(mainModuleGet("inner_exc")); 891 ASSERT_NE(inner_exc, nullptr); 892 PyObjectPtr outer_exc(mainModuleGet("outer_exc")); 893 ASSERT_NE(outer_exc, nullptr); 894 PyObjectPtr outer_ctx(PyException_GetContext(outer_exc)); 895 EXPECT_EQ(outer_ctx, inner_exc); 896 EXPECT_EQ(PyException_GetContext(inner_exc), nullptr); 897} 898 899} // namespace testing 900} // namespace py