this repo has no description
at trunk 775 lines 26 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "Python.h" 3 4#include "capi-fixture.h" 5#include "capi-testing.h" 6 7namespace py { 8namespace testing { 9 10using GetArgsExtensionApiTest = ExtensionApi; 11 12TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsFastFromDict) { 13 PyObjectPtr args(PyTuple_New(0)); 14 PyObjectPtr kwargs(PyDict_New()); 15 PyObjectPtr key(PyUnicode_FromString("first")); 16 PyObjectPtr value(PyLong_FromLong(42)); 17 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 18 19 const char* const keywords[] = {"first", nullptr}; 20 static _PyArg_Parser parser = {"O:ParseTupleAndKeywordsFastFromDict", 21 keywords}; 22 PyObject* out = Py_None; 23 24 EXPECT_EQ(_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &parser, &out), 1); 25 EXPECT_EQ(PyLong_AsLong(out), 42); 26} 27 28TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsFastFromTuple) { 29 PyObjectPtr args(PyTuple_New(1)); 30 ASSERT_NE(-1, PyTuple_SetItem(args, 0, PyLong_FromLong(43))); 31 PyObjectPtr kwargs(PyDict_New()); 32 33 const char* const keywords[] = {"first", nullptr}; 34 static _PyArg_Parser parser = {"O:ParseTupleAndKeywordsFastFromTuple", 35 keywords}; 36 PyObject* out = Py_None; 37 38 EXPECT_EQ(_PyArg_ParseTupleAndKeywordsFast(args, kwargs, &parser, &out), 1); 39 EXPECT_EQ(PyLong_AsLong(out), 43); 40} 41 42TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsFastFromTupleAndDict) { 43 PyObjectPtr args(PyTuple_New(1)); 44 ASSERT_NE(-1, PyTuple_SetItem(args, 0, PyLong_FromLong(44))); 45 PyObjectPtr kwargs(PyDict_New()); 46 PyObjectPtr key(PyUnicode_FromString("second")); 47 PyObjectPtr value(PyLong_FromLong(45)); 48 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 49 50 const char* const keywords[] = {"first", "second", nullptr}; 51 static _PyArg_Parser parser = {"ii:ParseTupleAndKeywordsFastFromTupleAndDict", 52 keywords}; 53 int out1 = -1, out2 = -1; 54 EXPECT_EQ( 55 _PyArg_ParseTupleAndKeywordsFast(args, kwargs, &parser, &out1, &out2), 1); 56 EXPECT_EQ(out1, 44); 57 EXPECT_EQ(out2, 45); 58} 59 60TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsFastWithOptionals) { 61 PyObjectPtr args(PyTuple_New(0)); 62 PyObjectPtr kwargs(PyDict_New()); 63 PyObjectPtr key(PyUnicode_FromString("second")); 64 PyObjectPtr value(PyLong_FromLong(42)); 65 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 66 67 const char* const keywords[] = {"first", "second", nullptr}; 68 static _PyArg_Parser parser = {"|ii:ParseTupleAndKeywordsFastWithOptionals", 69 keywords}; 70 int out1 = -1, out2 = -1; 71 EXPECT_EQ( 72 _PyArg_ParseTupleAndKeywordsFast(args, kwargs, &parser, &out1, &out2), 1); 73 EXPECT_EQ(out1, -1); 74 EXPECT_EQ(out2, 42); 75} 76 77TEST_F(GetArgsExtensionApiTest, ParseStackMaintainsRefcount) { 78 PyObjectPtr str(PyUnicode_FromString("hello world")); 79 Py_ssize_t old_refcnt = Py_REFCNT(str); 80 PyObject* args[] = {str}; 81 PyObject* out = nullptr; 82 EXPECT_EQ(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "O", &out), 1); 83 EXPECT_EQ(PyErr_Occurred(), nullptr); 84 EXPECT_EQ(out, str.get()); 85 EXPECT_EQ(Py_REFCNT(out), old_refcnt); 86 _PyArg_Fini(); 87} 88 89TEST_F(GetArgsExtensionApiTest, ParseStackOneObject) { 90 PyObjectPtr str(PyUnicode_FromString("hello world")); 91 PyObject* args[] = {str}; 92 PyObject* out = nullptr; 93 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "O:xyz", &out)); 94 EXPECT_EQ(PyErr_Occurred(), nullptr); 95 EXPECT_EQ(out, str.get()); 96} 97 98TEST_F(GetArgsExtensionApiTest, ParseStackMultipleObjects) { 99 PyObjectPtr long111(PyLong_FromLong(111)); 100 PyObjectPtr long333(PyLong_FromLong(333)); 101 PyObject* args[] = {long111, Py_None, long333}; 102 PyObject* out1 = nullptr; 103 PyObject* out2 = nullptr; 104 PyObject* out3 = nullptr; 105 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "OOO:xyz", &out1, 106 &out2, &out3)); 107 EXPECT_EQ(PyErr_Occurred(), nullptr); 108 EXPECT_EQ(out1, long111.get()); 109 EXPECT_EQ(out2, Py_None); 110 EXPECT_EQ(out3, long333.get()); 111} 112 113TEST_F(GetArgsExtensionApiTest, ParseStackUnicodeObject) { 114 PyObjectPtr str(PyUnicode_FromString("hello world")); 115 PyObject* args[] = {str}; 116 PyObject* out = nullptr; 117 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "U:xyz", &out)); 118 EXPECT_EQ(PyErr_Occurred(), nullptr); 119 EXPECT_EQ(out, str); 120} 121 122TEST_F(GetArgsExtensionApiTest, ParseStackWithWrongTypeRaisesTypeError) { 123 PyObjectPtr non_str(PyLong_FromLong(10)); 124 PyObject* args[] = {non_str}; 125 PyObject* out = nullptr; 126 EXPECT_FALSE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "U:xyz", &out)); 127 ASSERT_NE(PyErr_Occurred(), nullptr); 128 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 129 EXPECT_EQ(out, nullptr); 130} 131 132TEST_F(GetArgsExtensionApiTest, ParseStackWithFormatsSAndZ) { 133 PyObjectPtr str1(PyUnicode_FromString("hello")); 134 PyObjectPtr str2(PyUnicode_FromString("world")); 135 PyObject* args[] = {str1, str2}; 136 char* out1 = nullptr; 137 char* out2 = nullptr; 138 EXPECT_TRUE( 139 _PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "sz", &out1, &out2)); 140 EXPECT_EQ(PyErr_Occurred(), nullptr); 141 EXPECT_STREQ("hello", out1); 142 EXPECT_STREQ("world", out2); 143} 144 145TEST_F(GetArgsExtensionApiTest, ParseStackWithStringAndNone) { 146 PyObject* args[] = {Py_None, Py_None}; 147 char* out1 = nullptr; 148 char* out2 = nullptr; 149 int size = 123; 150 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "zz#", &out1, 151 &out2, &size)); 152 EXPECT_EQ(PyErr_Occurred(), nullptr); 153 EXPECT_EQ(nullptr, out1); 154 EXPECT_EQ(nullptr, out2); 155 EXPECT_EQ(0, size); 156} 157 158TEST_F(GetArgsExtensionApiTest, ParseStackWithStringAndSize) { 159 PyObjectPtr str1(PyUnicode_FromString("hello")); 160 PyObjectPtr str2(PyUnicode_FromString("cpython")); 161 PyObject* args[] = {str1, str2}; 162 char* out1 = nullptr; 163 char* out2 = nullptr; 164 int size1 = 123; 165 int size2 = 456; 166 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "s#z#", &out1, 167 &size1, &out2, &size2)); 168 EXPECT_EQ(PyErr_Occurred(), nullptr); 169 EXPECT_STREQ("hello", out1); 170 EXPECT_EQ(5, size1); 171 EXPECT_STREQ("cpython", out2); 172 EXPECT_EQ(7, size2); 173} 174 175TEST_F(GetArgsExtensionApiTest, ParseStackNumbers) { 176 const int k_ints = 11; 177 PyObject* args[k_ints]; 178 for (int i = 0; i < k_ints; i++) { 179 args[i] = PyLong_FromLong(123 + i); 180 } 181 182 unsigned char nb; 183 unsigned char n_b; 184 short int nh; 185 unsigned short int n_h; 186 int ni; 187 unsigned int n_i; 188 long int nl; 189 unsigned long nk; 190 long long n_l; 191 unsigned long long n_k; 192 Py_ssize_t nn; 193 194 EXPECT_TRUE(_PyArg_ParseStack(args, k_ints, "bBhHiIlkLKn", &nb, &n_b, &nh, 195 &n_h, &ni, &n_i, &nl, &nk, &n_l, &n_k, &nn)); 196 EXPECT_EQ(PyErr_Occurred(), nullptr); 197 EXPECT_EQ(123, nb); 198 EXPECT_EQ(124, n_b); 199 EXPECT_EQ(125, nh); 200 EXPECT_EQ(126, n_h); 201 EXPECT_EQ(127, ni); 202 EXPECT_EQ(128U, n_i); 203 EXPECT_EQ(129, nl); 204 EXPECT_EQ(130UL, nk); 205 EXPECT_EQ(131, n_l); 206 EXPECT_EQ(132ULL, n_k); 207 EXPECT_EQ(133, nn); 208 209 for (int i = 0; i < k_ints; i++) { 210 Py_DECREF(args[i]); 211 } 212} 213 214TEST_F(GetArgsExtensionApiTest, ParseStackOptionalPresent) { 215 PyObjectPtr obj(PyLong_FromLong(111)); 216 PyObject* args[] = {obj}; 217 218 PyObject* out = reinterpret_cast<PyObject*>(0xdeadbeef); 219 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "|O", &out)); 220 EXPECT_EQ(PyErr_Occurred(), nullptr); 221 EXPECT_EQ(out, obj.get()); 222} 223 224TEST_F(GetArgsExtensionApiTest, ParseStackOptionalNotPresent) { 225 PyObject* out = reinterpret_cast<PyObject*>(0xdeadbeef); 226 EXPECT_TRUE(_PyArg_ParseStack(nullptr, 0, "|O", &out)); 227 EXPECT_EQ(PyErr_Occurred(), nullptr); 228 ASSERT_EQ(out, reinterpret_cast<PyObject*>(0xdeadbeef)); 229} 230 231TEST_F(GetArgsExtensionApiTest, ParseStackObjectWithCorrectType) { 232 PyObjectPtr obj(PyLong_FromLong(111)); 233 PyObject* args[] = {obj}; 234 235 PyObject* out = reinterpret_cast<PyObject*>(0xdeadbeef); 236 EXPECT_TRUE( 237 _PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "O!", &PyLong_Type, &out)); 238 EXPECT_EQ(PyErr_Occurred(), nullptr); 239 EXPECT_EQ(out, obj.get()); 240} 241 242TEST_F(GetArgsExtensionApiTest, ParseStackObjectWithIncorrectType) { 243 PyObjectPtr obj(PyLong_FromLong(111)); 244 PyObject* args[] = {obj}; 245 246 PyObject* out = reinterpret_cast<PyObject*>(0xdeadbeef); 247 EXPECT_FALSE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "O!", 248 &PyTuple_Type, &out)); 249 ASSERT_NE(PyErr_Occurred(), nullptr); 250 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 251 EXPECT_EQ(out, reinterpret_cast<PyObject*>(0xdeadbeef)); 252} 253 254TEST_F(GetArgsExtensionApiTest, ParseStackObjectWithConverter) { 255 using converter_func = void (*)(PyObject*, void*); 256 converter_func converter = [](PyObject* ptr, void* out) { 257 *static_cast<int*>(out) = 1 + PyLong_AsLong(ptr); 258 }; 259 260 PyObjectPtr obj(PyLong_FromLong(111)); 261 PyObject* args[] = {obj}; 262 263 int out = 0; 264 EXPECT_TRUE(_PyArg_ParseStack(args, Py_ARRAY_LENGTH(args), "O&", converter, 265 static_cast<void*>(&out))); 266 EXPECT_EQ(out, 112); 267} 268 269TEST_F(GetArgsExtensionApiTest, ParseStackAndKeywordsOneObject) { 270 PyObjectPtr long10(PyLong_FromLong(10)); 271 PyObject* args[] = {long10}; 272 int nargs = Py_ARRAY_LENGTH(args); 273 274 const char* const keywords[] = {"first", nullptr}; 275 static _PyArg_Parser parser = {"O:ParseStackOneObject", keywords}; 276 277 PyObject* kwnames = nullptr; 278 PyObject* out = nullptr; 279 280 EXPECT_EQ(_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out), 281 1); 282 EXPECT_EQ(PyLong_AsLong(out), 10); 283 _PyArg_Fini(); 284} 285 286TEST_F(GetArgsExtensionApiTest, 287 ParseStackAndKeywordsWithLongKWNamesRaisesTypeError) { 288 PyObjectPtr long10(PyLong_FromLong(10)); 289 PyObject* args[] = {long10}; 290 int nargs = Py_ARRAY_LENGTH(args); 291 292 PyObjectPtr kwnames(PyTuple_New(1)); 293 PyObject* in1 = PyLong_FromLong(37); 294 ASSERT_NE(-1, PyTuple_SetItem(kwnames, 0, in1)); 295 296 const char* const keywords[] = {"first", "second", nullptr}; 297 static _PyArg_Parser parser = {"OO:ParseStackWithLongKWNamesRaisesTypeError", 298 keywords}; 299 PyObject* out1 = nullptr; 300 301 EXPECT_EQ(_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out1), 302 0); 303 ASSERT_NE(PyErr_Occurred(), nullptr); 304 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 305 EXPECT_EQ(PyLong_AsLong(out1), 10); 306 _PyArg_Fini(); 307} 308 309TEST_F(GetArgsExtensionApiTest, ParseStackAndKeywordsMultipleObjects) { 310 PyObjectPtr long10(PyLong_FromLong(10)); 311 PyObjectPtr long33(PyLong_FromLong(33)); 312 PyObjectPtr test_str(PyUnicode_FromString("test_str")); 313 PyObject* args[] = {long10, long33, test_str}; 314 int nargs = Py_ARRAY_LENGTH(args); 315 316 const char* const keywords[] = {"first", "second", "third", nullptr}; 317 static _PyArg_Parser parser = {"OOU:ParseStackMultipleObjects", keywords}; 318 319 PyObject* kwnames = nullptr; 320 PyObject* out1 = nullptr; 321 PyObject* out2 = nullptr; 322 PyObject* out3 = nullptr; 323 324 EXPECT_EQ(_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out1, 325 &out2, &out3), 326 1); 327 EXPECT_EQ(PyLong_AsLong(out1), 10); 328 EXPECT_EQ(PyLong_AsLong(out2), 33); 329 EXPECT_EQ(out3, test_str); 330 _PyArg_Fini(); 331} 332 333TEST_F(GetArgsExtensionApiTest, ParseStackAndKeywordsUnicode) { 334 PyObjectPtr hello(PyUnicode_FromString("hello")); 335 PyObjectPtr world(PyUnicode_FromString("world")); 336 PyObject* args[] = {hello, world}; 337 int nargs = Py_ARRAY_LENGTH(args); 338 339 const char* const keywords[] = {"first", "second", nullptr}; 340 static _PyArg_Parser parser = {"UU:ParseStackUnicode", keywords}; 341 342 PyObject* kwnames = nullptr; 343 PyObject* out1 = nullptr; 344 PyObject* out2 = nullptr; 345 EXPECT_EQ( 346 _PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out1, &out2), 347 1); 348 EXPECT_EQ(hello, out1); 349 EXPECT_EQ(world, out2); 350 _PyArg_Fini(); 351} 352 353TEST_F(GetArgsExtensionApiTest, 354 ParseStackAndKeywordsWithWrongTypeRaisesTypeError) { 355 PyObjectPtr long100(PyLong_FromLong(100)); 356 PyObject* args[] = {long100}; 357 int nargs = Py_ARRAY_LENGTH(args); 358 359 const char* const keywords[] = {"first", nullptr}; 360 _PyArg_Parser parser = {"U:ParseStackWithWrongTypeRaisesTypeError", keywords}; 361 362 PyObject* kwnames = nullptr; 363 PyObject* out1 = nullptr; 364 EXPECT_EQ(_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out1), 365 0); 366 ASSERT_NE(PyErr_Occurred(), nullptr); 367 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 368 EXPECT_EQ(out1, nullptr); 369 _PyArg_Fini(); 370} 371 372TEST_F(GetArgsExtensionApiTest, ParseStackAndKeywordsString) { 373 PyObjectPtr hello(PyUnicode_FromString("hello")); 374 PyObjectPtr world(PyUnicode_FromString("world")); 375 PyObject* args[] = {hello, world}; 376 int nargs = Py_ARRAY_LENGTH(args); 377 378 const char* const keywords[] = {"first", "second", nullptr}; 379 _PyArg_Parser parser = {"sz:ParseStackString", keywords}; 380 381 PyObject* kwnames = nullptr; 382 char* out1 = nullptr; 383 char* out2 = nullptr; 384 EXPECT_EQ( 385 _PyArg_ParseStackAndKeywords(args, nargs, kwnames, &parser, &out1, &out2), 386 1); 387 EXPECT_STREQ("hello", out1); 388 EXPECT_STREQ("world", out2); 389 _PyArg_Fini(); 390} 391 392TEST_F(GetArgsExtensionApiTest, ParseTupleOneObject) { 393 PyObjectPtr pytuple(PyTuple_New(1)); 394 PyObject* in = PyUnicode_FromString("hello world"); 395 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in)); 396 397 long refcnt = Py_REFCNT(in); 398 PyObject* out; 399 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "O:xyz", &out)); 400 // This returns a borrowed reference, verify ref count did not change 401 EXPECT_EQ(Py_REFCNT(out), refcnt); 402 EXPECT_TRUE(_PyUnicode_EqualToASCIIString(out, "hello world")); 403} 404 405TEST_F(GetArgsExtensionApiTest, ParseTupleMultipleObjects) { 406 PyObjectPtr pytuple(PyTuple_New(3)); 407 PyObject* in1 = PyLong_FromLong(111); 408 PyObject* in2 = Py_None; 409 Py_INCREF(in2); 410 PyObject* in3 = PyLong_FromLong(333); 411 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in1)); 412 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 1, in2)); 413 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 2, in3)); 414 415 PyObject* out1; 416 PyObject* out2; 417 PyObject* out3; 418 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "OOO:xyz", &out1, &out2, &out3)); 419 EXPECT_EQ(111, PyLong_AsLong(out1)); 420 EXPECT_EQ(Py_None, out2); 421 EXPECT_EQ(333, PyLong_AsLong(out3)); 422} 423 424TEST_F(GetArgsExtensionApiTest, ParseTupleUnicodeObject) { 425 PyObjectPtr pytuple(PyTuple_New(1)); 426 PyObject* in1 = PyUnicode_FromString("pyro"); 427 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in1)); 428 429 PyObject* out1; 430 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "U:is_frozen", &out1)); 431 EXPECT_EQ(in1, out1); 432} 433 434TEST_F(GetArgsExtensionApiTest, ParseTupleWithWrongType) { 435 PyObjectPtr pytuple(PyTuple_New(1)); 436 PyObject* in = PyLong_FromLong(42); 437 ASSERT_NE(in, nullptr); 438 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in)); 439 440 PyObject* out1 = nullptr; 441 EXPECT_FALSE(PyArg_ParseTuple(pytuple, "U:is_frozen", &out1)); 442 EXPECT_NE(PyErr_Occurred(), nullptr); 443 EXPECT_EQ(out1, nullptr); 444} 445 446TEST_F(GetArgsExtensionApiTest, ParseTupleString) { 447 PyObjectPtr pytuple(PyTuple_New(2)); 448 PyObject* in1 = PyUnicode_FromString("hello"); 449 PyObject* in2 = PyUnicode_FromString("world"); 450 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in1)); 451 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 1, in2)); 452 453 char *out1, *out2; 454 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "sz", &out1, &out2)); 455 EXPECT_STREQ("hello", out1); 456 EXPECT_STREQ("world", out2); 457} 458 459TEST_F(GetArgsExtensionApiTest, ParseTupleStringFromNone) { 460 PyObjectPtr pytuple(PyTuple_New(2)); 461 Py_INCREF(Py_None); 462 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, Py_None)); 463 Py_INCREF(Py_None); 464 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 1, Py_None)); 465 466 char *out1, *out2; 467 int size = 123; 468 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "zz#", &out1, &out2, &size)); 469 EXPECT_EQ(nullptr, out1); 470 EXPECT_EQ(nullptr, out2); 471 EXPECT_EQ(0, size); 472} 473 474TEST_F(GetArgsExtensionApiTest, ParseTupleStringWithSize) { 475 PyObjectPtr pytuple(PyTuple_New(2)); 476 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, PyUnicode_FromString("hello"))); 477 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 1, PyUnicode_FromString("cpython"))); 478 479 char *out1, *out2; 480 int size1, size2; 481 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "s#z#", &out1, &size1, &out2, &size2)); 482 EXPECT_STREQ("hello", out1); 483 EXPECT_EQ(5, size1); 484 EXPECT_STREQ("cpython", out2); 485 EXPECT_EQ(7, size2); 486} 487 488TEST_F(GetArgsExtensionApiTest, ParseTupleNumbers) { 489 const int k_ints = 11; 490 PyObjectPtr pytuple(PyTuple_New(k_ints)); 491 for (int i = 0; i < k_ints; i++) { 492 ASSERT_EQ(0, PyTuple_SetItem(pytuple, i, PyLong_FromLong(123 + i))); 493 } 494 495 unsigned char nb, n_b; 496 short int nh; 497 unsigned short int n_h; 498 int ni; 499 unsigned int n_i; 500 long int nl; 501 unsigned long nk; 502 long long n_l; 503 unsigned long long n_k; 504 Py_ssize_t nn; 505 506 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "bBhHiIlkLKn", &nb, &n_b, &nh, &n_h, 507 &ni, &n_i, &nl, &nk, &n_l, &n_k, &nn)); 508 EXPECT_EQ(123, nb); 509 EXPECT_EQ(124, n_b); 510 EXPECT_EQ(125, nh); 511 EXPECT_EQ(126, n_h); 512 EXPECT_EQ(127, ni); 513 EXPECT_EQ(128U, n_i); 514 EXPECT_EQ(129, nl); 515 EXPECT_EQ(130UL, nk); 516 EXPECT_EQ(131, n_l); 517 EXPECT_EQ(132ULL, n_k); 518 EXPECT_EQ(133, nn); 519} 520 521TEST_F(GetArgsExtensionApiTest, ParseTupleOptionalPresent) { 522 PyObjectPtr pytuple(PyTuple_New(1)); 523 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, PyLong_FromLong(111))); 524 525 PyObject* out = nullptr; 526 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "|O", &out)); 527 ASSERT_NE(out, nullptr); 528 EXPECT_EQ(111, PyLong_AsLong(out)); 529} 530 531TEST_F(GetArgsExtensionApiTest, ParseTupleOptionalNotPresent) { 532 PyObjectPtr pytuple(PyTuple_New(0)); 533 534 PyObject* out = nullptr; 535 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "|O", &out)); 536 ASSERT_EQ(out, nullptr); 537} 538 539TEST_F(GetArgsExtensionApiTest, ParseTupleObjectWithCorrectType) { 540 PyObjectPtr pytuple(PyTuple_New(1)); 541 PyObject* in = PyLong_FromLong(111); 542 PyTypeObject* type = Py_TYPE(in); 543 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in)); 544 545 PyObject* out = nullptr; 546 EXPECT_TRUE(PyArg_ParseTuple(pytuple, "O!", type, &out)); 547 548 EXPECT_EQ(PyErr_Occurred(), nullptr); 549 EXPECT_EQ(111, PyLong_AsLong(out)); 550} 551 552TEST_F(GetArgsExtensionApiTest, ParseTupleObjectWithIncorrectType) { 553 PyObjectPtr pytuple(PyTuple_New(1)); 554 PyObject* in = PyLong_FromLong(111); 555 PyTypeObject* type = Py_TYPE(pytuple); 556 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, in)); 557 558 PyObject* out = nullptr; 559 EXPECT_FALSE(PyArg_ParseTuple(pytuple, "O!", type, &out)); 560 561 EXPECT_NE(PyErr_Occurred(), nullptr); 562 EXPECT_EQ(out, nullptr); 563} 564 565TEST_F(GetArgsExtensionApiTest, ParseTupleObjectWithConverter) { 566 using converter_func = void (*)(PyObject*, void*); 567 converter_func converter = [](PyObject* ptr, void* out) { 568 *static_cast<int*>(out) = 1 + PyLong_AsLong(ptr); 569 }; 570 571 PyObjectPtr pytuple(PyTuple_New(1)); 572 ASSERT_NE(-1, PyTuple_SetItem(pytuple, 0, PyLong_FromLong(111))); 573 574 int out = 0; 575 EXPECT_TRUE( 576 PyArg_ParseTuple(pytuple, "O&", converter, static_cast<void*>(&out))); 577 EXPECT_EQ(out, 112); 578} 579 580TEST_F(GetArgsExtensionApiTest, OldStyleParseWithInt) { 581 PyObjectPtr pylong(PyLong_FromLong(666)); 582 int n = 0; 583 EXPECT_TRUE(PyArg_Parse(pylong, "i", &n)); 584 EXPECT_EQ(n, 666); 585} 586 587TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsParseFromDict) { 588 PyObjectPtr args(PyTuple_New(0)); 589 PyObjectPtr kwargs(PyDict_New()); 590 PyObjectPtr key(PyUnicode_FromString("first")); 591 PyObjectPtr value(PyLong_FromLong(42)); 592 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 593 594 const char* kwnames[] = {"first", nullptr}; 595 int out = -1; 596 EXPECT_TRUE(PyArg_ParseTupleAndKeywords(args, kwargs, "i", 597 const_cast<char**>(kwnames), &out)); 598 EXPECT_EQ(out, 42); 599} 600 601TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsParseFromTuple) { 602 PyObjectPtr args(PyTuple_New(1)); 603 ASSERT_NE(-1, PyTuple_SetItem(args, 0, PyLong_FromLong(43))); 604 PyObjectPtr kwargs(PyDict_New()); 605 606 const char* kwnames[] = {"first", nullptr}; 607 int out = -1; 608 EXPECT_TRUE(PyArg_ParseTupleAndKeywords(args, kwargs, "i", 609 const_cast<char**>(kwnames), &out)); 610 EXPECT_EQ(out, 43); 611} 612 613TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsParseFromTupleAndDict) { 614 PyObjectPtr args(PyTuple_New(1)); 615 ASSERT_NE(-1, PyTuple_SetItem(args, 0, PyLong_FromLong(44))); 616 PyObjectPtr kwargs(PyDict_New()); 617 PyObjectPtr key(PyUnicode_FromString("second")); 618 PyObjectPtr value(PyLong_FromLong(45)); 619 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 620 621 const char* kwnames[] = {"first", "second", nullptr}; 622 int out1 = -1, out2 = -1; 623 EXPECT_TRUE(PyArg_ParseTupleAndKeywords( 624 args, kwargs, "ii", const_cast<char**>(kwnames), &out1, &out2)); 625 EXPECT_EQ(out1, 44); 626 EXPECT_EQ(out2, 45); 627} 628 629TEST_F(GetArgsExtensionApiTest, ParseTupleAndKeywordsWithOptionals) { 630 PyObjectPtr args(PyTuple_New(0)); 631 PyObjectPtr kwargs(PyDict_New()); 632 PyObjectPtr key(PyUnicode_FromString("second")); 633 PyObjectPtr value(PyLong_FromLong(42)); 634 ASSERT_EQ(PyDict_SetItem(kwargs, key, value), 0); 635 636 const char* kwnames[] = {"first", "second", nullptr}; 637 int out1 = -1, out2 = -1; 638 EXPECT_TRUE(PyArg_ParseTupleAndKeywords( 639 args, kwargs, "|ii", const_cast<char**>(kwnames), &out1, &out2)); 640 EXPECT_EQ(out1, -1); 641 EXPECT_EQ(out2, 42); 642} 643 644#pragma push_macro("_PyArg_NoKeywords") 645#undef _PyArg_NoKeywords 646TEST_F(GetArgsExtensionApiTest, NoKeywordsWithNullptrReturnsTrue) { 647 EXPECT_EQ(_PyArg_NoKeywords("", nullptr), 1); 648} 649#pragma pop_macro("_PyArg_NoKeywords") 650 651#pragma push_macro("_PyArg_NoKeywords") 652#undef _PyArg_NoKeywords 653TEST_F(GetArgsExtensionApiTest, NoKeywordsWithEmptyDictReturnsTrue) { 654 PyObjectPtr empty_dict(PyDict_New()); 655 EXPECT_EQ(_PyArg_NoKeywords("", empty_dict), 1); 656} 657#pragma pop_macro("_PyArg_NoKeywords") 658 659#pragma push_macro("_PyArg_NoKeywords") 660#undef _PyArg_NoKeywords 661TEST_F(GetArgsExtensionApiTest, NoKeywordsWithNonDictRaisesSystemError) { 662 PyObjectPtr not_a_dict(PyTuple_New(10)); 663 EXPECT_EQ(_PyArg_NoKeywords("", not_a_dict), 0); 664 ASSERT_NE(PyErr_Occurred(), nullptr); 665 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 666} 667#pragma pop_macro("_PyArg_NoKeywords") 668 669#pragma push_macro("_PyArg_NoKeywords") 670#undef _PyArg_NoKeywords 671TEST_F(GetArgsExtensionApiTest, NoKeywordsWithNonEmptyDictRaisesTypeError) { 672 PyObjectPtr non_empty_dict(PyDict_New()); 673 PyObjectPtr tuple(PyTuple_New(0)); 674 PyDict_SetItemString(non_empty_dict, "my key", tuple); 675 EXPECT_EQ(_PyArg_NoKeywords("", non_empty_dict.get()), 0); 676 ASSERT_NE(PyErr_Occurred(), nullptr); 677 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 678} 679#pragma pop_macro("_PyArg_NoKeywords") 680 681#pragma push_macro("_PyArg_NoPositional") 682#undef _PyArg_NoPositional 683TEST_F(GetArgsExtensionApiTest, NoPositionalWithNullptrReturnsTrue) { 684 EXPECT_EQ(_PyArg_NoPositional("", nullptr), 1); 685} 686#pragma pop_macro("_PyArg_NoPositional") 687 688#pragma push_macro("_PyArg_NoPositional") 689#undef _PyArg_NoPositional 690TEST_F(GetArgsExtensionApiTest, NoPositionalWitEmptyTupleReturnsTrue) { 691 PyObjectPtr empty_tuple(PyTuple_New(0)); 692 EXPECT_EQ(_PyArg_NoPositional("", empty_tuple), 1); 693} 694#pragma pop_macro("_PyArg_NoPositional") 695 696#pragma push_macro("_PyArg_NoPositional") 697#undef _PyArg_NoPositional 698TEST_F(GetArgsExtensionApiTest, NoPositionalWithNonTupleRaisesSystemError) { 699 PyObjectPtr not_a_tuple(PyLong_FromLong(1)); 700 EXPECT_EQ(_PyArg_NoPositional("", not_a_tuple), 0); 701 EXPECT_NE(PyErr_Occurred(), nullptr); 702 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 703} 704#pragma pop_macro("_PyArg_NoPositional") 705 706#pragma push_macro("_PyArg_NoPositional") 707#undef _PyArg_NoPositional 708TEST_F(GetArgsExtensionApiTest, NoPositionalWithNonEmptyTupleRaisesTypeError) { 709 PyObjectPtr non_empty_tuple(PyTuple_New(10)); 710 EXPECT_EQ(_PyArg_NoPositional("", non_empty_tuple), 0); 711 ASSERT_NE(PyErr_Occurred(), nullptr); 712 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 713} 714#pragma pop_macro("_PyArg_NoPositional") 715 716TEST_F(GetArgsExtensionApiTest, 717 UnpackStackWithNullNameAndNargsLessThanMinRaisesTypeError) { 718 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/nullptr, /*nargs=*/1, /*name=*/nullptr, 719 /*min=*/2, /*max=*/3), 720 0); 721 ASSERT_NE(PyErr_Occurred(), nullptr); 722 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 723} 724 725TEST_F(GetArgsExtensionApiTest, 726 UnpackStackWithNonNullNameAndNargsLessThanMinRaisesTypeError) { 727 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/nullptr, /*nargs=*/1, /*name=*/"foo", 728 /*min=*/2, /*max=*/3), 729 0); 730 ASSERT_NE(PyErr_Occurred(), nullptr); 731 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 732} 733 734TEST_F(GetArgsExtensionApiTest, UnpackStackWithNargsEqualsZeroReturnsOne) { 735 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/nullptr, /*nargs=*/0, /*name=*/"foo", 736 /*min=*/0, /*max=*/3), 737 1); 738 EXPECT_EQ(PyErr_Occurred(), nullptr); 739} 740 741TEST_F(GetArgsExtensionApiTest, 742 UnpackStackWithNullNameAndNargsGreaterThanMaxRaisesTypeError) { 743 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/nullptr, /*nargs=*/2, /*name=*/nullptr, 744 /*min=*/0, /*max=*/1), 745 0); 746 ASSERT_NE(PyErr_Occurred(), nullptr); 747 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 748} 749 750TEST_F(GetArgsExtensionApiTest, 751 UnpackStackWithNonNullNameAndNargsGreaterThanMaxRaisesTypeError) { 752 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/nullptr, /*nargs=*/2, /*name=*/"foo", 753 /*min=*/0, /*max=*/1), 754 0); 755 ASSERT_NE(PyErr_Occurred(), nullptr); 756 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 757} 758 759TEST_F(GetArgsExtensionApiTest, UnpackStackUnpacksArrayIntoVarargs) { 760 PyObjectPtr long10(PyLong_FromLong(10)); 761 PyObjectPtr long33(PyLong_FromLong(33)); 762 PyObjectPtr test_str(PyUnicode_FromString("test_str")); 763 PyObject* args[] = {long10, long33, test_str}; 764 PyObject *arg0 = nullptr, *arg1 = nullptr, *arg2 = nullptr; 765 EXPECT_EQ(_PyArg_UnpackStack(/*args=*/args, /*nargs=*/3, /*name=*/nullptr, 766 /*min=*/0, /*max=*/3, &arg0, &arg1, &arg2), 767 1); 768 EXPECT_EQ(PyErr_Occurred(), nullptr); 769 EXPECT_EQ(arg0, long10.get()); 770 EXPECT_EQ(arg1, long33.get()); 771 EXPECT_EQ(arg2, test_str.get()); 772} 773 774} // namespace testing 775} // namespace py