this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include <climits>
3#include <cstring>
4
5#include "Python.h"
6#include "gtest/gtest.h"
7
8#include "capi-fixture.h"
9#include "capi-testing.h"
10
11namespace py {
12namespace testing {
13
14using AbstractExtensionApiTest = ExtensionApi;
15
16// Buffer Protocol
17
18TEST_F(AbstractExtensionApiTest, PyBufferFillInfoSimpleFillsInfo) {
19 Py_buffer buffer;
20 char buf[13];
21 PyObjectPtr pyobj(PyTuple_New(1));
22 long prev_refcount = Py_REFCNT(pyobj);
23 int readonly = 1;
24 int result = PyBuffer_FillInfo(&buffer, pyobj, buf, sizeof(buf), readonly,
25 PyBUF_SIMPLE);
26 EXPECT_EQ(result, 0);
27 EXPECT_EQ(Py_REFCNT(pyobj), prev_refcount + 1);
28 EXPECT_EQ(buffer.obj, pyobj);
29 EXPECT_EQ(buffer.buf, buf);
30 EXPECT_EQ(buffer.len, (Py_ssize_t)sizeof(buf));
31 EXPECT_EQ(buffer.readonly, 1);
32 EXPECT_EQ(buffer.itemsize, 1);
33 EXPECT_EQ(buffer.format, nullptr);
34 EXPECT_EQ(buffer.ndim, 1);
35 EXPECT_EQ(buffer.shape, nullptr);
36 EXPECT_EQ(buffer.strides, nullptr);
37 EXPECT_EQ(buffer.suboffsets, nullptr);
38 EXPECT_EQ(buffer.internal, nullptr);
39}
40
41TEST_F(AbstractExtensionApiTest,
42 PyBufferFillInfoWithWritableFormatNdStridesFillsInfo) {
43 Py_buffer buffer;
44 char buf[7];
45 PyObjectPtr pyobj(PyTuple_New(1));
46 long prev_refcount = Py_REFCNT(pyobj);
47 int readonly = 0;
48 int result = PyBuffer_FillInfo(
49 &buffer, pyobj, buf, sizeof(buf), readonly,
50 PyBUF_WRITABLE | PyBUF_FORMAT | PyBUF_ND | PyBUF_STRIDES);
51 EXPECT_EQ(result, 0);
52 EXPECT_EQ(Py_REFCNT(pyobj), prev_refcount + 1);
53 EXPECT_EQ(buffer.obj, pyobj);
54 EXPECT_EQ(buffer.buf, buf);
55 EXPECT_EQ(buffer.len, (Py_ssize_t)sizeof(buf));
56 EXPECT_EQ(buffer.readonly, 0);
57 EXPECT_EQ(buffer.itemsize, 1);
58 EXPECT_EQ(strcmp(buffer.format, "B"), 0);
59 EXPECT_EQ(buffer.ndim, 1);
60 EXPECT_EQ(buffer.shape, &buffer.len);
61 EXPECT_EQ(buffer.strides, &buffer.itemsize);
62 EXPECT_EQ(buffer.suboffsets, nullptr);
63 EXPECT_EQ(buffer.internal, nullptr);
64}
65
66TEST_F(AbstractExtensionApiTest, PyBufferFillInfoWithNullptrRaisesBufferError) {
67 int result = PyBuffer_FillInfo(nullptr, Py_None, nullptr, 0, 1, PyBUF_SIMPLE);
68 EXPECT_EQ(result, -1);
69 ASSERT_NE(PyErr_Occurred(), nullptr);
70 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_BufferError));
71}
72
73TEST_F(AbstractExtensionApiTest,
74 PyBufferFillInfoWithWritableFlagAndReadonlyRaisesBufferError) {
75 Py_buffer buffer;
76 int result =
77 PyBuffer_FillInfo(&buffer, Py_None, nullptr, 0, 1, PyBUF_WRITABLE);
78 EXPECT_EQ(result, -1);
79 ASSERT_NE(PyErr_Occurred(), nullptr);
80 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_BufferError));
81}
82
83TEST_F(AbstractExtensionApiTest,
84 PyBufferIsContiguousWithInvalidOrderReturnsFalse) {
85 Py_buffer buffer;
86 char data[1];
87 ASSERT_EQ(PyBuffer_FillInfo(&buffer, Py_None, data, /*len=*/1,
88 /*readonly=*/1, PyBUF_SIMPLE),
89 0);
90 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, '%'));
91}
92
93TEST_F(AbstractExtensionApiTest,
94 PyBufferIsContiguousWithSubOffsetsReturnsFalse) {
95 Py_buffer buffer;
96 char data[1];
97 ASSERT_EQ(PyBuffer_FillInfo(&buffer, Py_None, data, /*len=*/1,
98 /*readonly=*/1, PyBUF_SIMPLE),
99 0);
100 static Py_ssize_t suboffsets[] = {13};
101 buffer.suboffsets = suboffsets;
102 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, 'C'));
103 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, 'F'));
104 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, 'A'));
105}
106
107TEST_F(AbstractExtensionApiTest, PyBufferIsContiguousReturnsTrue) {
108 Py_buffer buffer;
109 char data[1];
110 ASSERT_EQ(PyBuffer_FillInfo(&buffer, Py_None, data, /*len=*/1,
111 /*readonly=*/1, PyBUF_SIMPLE),
112 0);
113 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'C'));
114 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'F'));
115 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'A'));
116}
117
118TEST_F(AbstractExtensionApiTest, PyBufferIsContiguousWithRowMajorBuffer) {
119 Py_buffer buffer;
120 char data[300];
121 ASSERT_EQ(PyBuffer_FillInfo(&buffer, Py_None, data, /*len=*/100,
122 /*readonly=*/1, PyBUF_STRIDES),
123 0);
124 buffer.itemsize = 2;
125 buffer.format = const_cast<char*>("h");
126 buffer.ndim = 3;
127 Py_ssize_t shape[3] = {10, 3, 5};
128 buffer.shape = shape;
129 Py_ssize_t strides[3] = {30, 10, 2};
130 buffer.strides = strides;
131 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'C'));
132 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, 'F'));
133 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'A'));
134}
135
136TEST_F(AbstractExtensionApiTest, PyBufferIsContiguousWithColumnMajorBuffer) {
137 Py_buffer buffer;
138 char data[420];
139 ASSERT_EQ(PyBuffer_FillInfo(&buffer, Py_None, data, /*len=*/100,
140 /*readonly=*/1, PyBUF_STRIDES),
141 0);
142 buffer.itemsize = 4;
143 buffer.format = const_cast<char*>("L");
144 buffer.ndim = 3;
145 Py_ssize_t shape[3] = {7, 3, 5};
146 buffer.shape = shape;
147 Py_ssize_t strides[3] = {4, 28, 84};
148 buffer.strides = strides;
149 EXPECT_FALSE(PyBuffer_IsContiguous(&buffer, 'C'));
150 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'F'));
151 EXPECT_TRUE(PyBuffer_IsContiguous(&buffer, 'A'));
152}
153
154TEST_F(AbstractExtensionApiTest, PyEvalCallFunctionCalls) {
155 PyRun_SimpleString(R"(
156def func(*args):
157 return f"{args!r}"
158)");
159 PyObjectPtr func(mainModuleGet("func"));
160 PyObjectPtr result(PyEval_CallFunction(func, "(iI)s#i", 3, 7, "aaaa", 3, 99));
161 EXPECT_TRUE(isUnicodeEqualsCStr(result, "((3, 7), 'aaa', 99)"));
162}
163
164TEST_F(AbstractExtensionApiTest, PyEvalCallMethodCalls) {
165 PyRun_SimpleString(R"(
166class C:
167 x = 42
168 def func(self, *args):
169 return f"{self.x}{args!r}"
170c = C()
171)");
172 PyObjectPtr c(mainModuleGet("c"));
173 PyObjectPtr result(PyEval_CallMethod(c, "func", "s#(i)", "ccc", 1, 7));
174 EXPECT_TRUE(isUnicodeEqualsCStr(result, "42('c', (7,))"));
175}
176
177// PyIndex_Check
178
179TEST_F(AbstractExtensionApiTest, PyIndexCheckWithIntReturnsTrue) {
180 PyObjectPtr int_num(PyLong_FromLong(1));
181 EXPECT_TRUE(PyIndex_Check(int_num.get()));
182 ASSERT_EQ(PyErr_Occurred(), nullptr);
183}
184
185TEST_F(AbstractExtensionApiTest, PyIndexCheckWithFloatReturnsFalse) {
186 PyObjectPtr float_num(PyFloat_FromDouble(1.1));
187 EXPECT_FALSE(PyIndex_Check(float_num.get()));
188 ASSERT_EQ(PyErr_Occurred(), nullptr);
189}
190
191TEST_F(AbstractExtensionApiTest,
192 PyIndexCheckWithUncallableDunderIndexReturnsTrue) {
193 PyRun_SimpleString(R"(
194class C:
195 __index__ = None
196idx = C()
197 )");
198 PyObjectPtr idx(mainModuleGet("idx"));
199 EXPECT_TRUE(PyIndex_Check(idx.get()));
200 ASSERT_EQ(PyErr_Occurred(), nullptr);
201}
202
203TEST_F(AbstractExtensionApiTest, PyIndexCheckWithDunderIndexReturnsTrue) {
204 PyRun_SimpleString(R"(
205class C:
206 def __index__(self):
207 return 1
208idx = C()
209 )");
210 PyObjectPtr idx(mainModuleGet("idx"));
211 EXPECT_TRUE(PyIndex_Check(idx.get()));
212 ASSERT_EQ(PyErr_Occurred(), nullptr);
213}
214
215TEST_F(AbstractExtensionApiTest,
216 PyIndexCheckWithDunderIndexDescriptorThatRaisesReturnsTrue) {
217 PyRun_SimpleString(R"(
218class Desc:
219 def __get__(self, obj, type):
220 raise UserWarning("foo")
221class C:
222 __index__ = Desc()
223c = C()
224)");
225 PyObjectPtr c(mainModuleGet("c"));
226 EXPECT_EQ(PyIndex_Check(c.get()), 1);
227 ASSERT_EQ(PyErr_Occurred(), nullptr);
228}
229
230// PyIter_Next
231
232TEST_F(AbstractExtensionApiTest, PyIterNextReturnsNext) {
233 PyObjectPtr one(PyLong_FromLong(1));
234 PyObjectPtr two(PyLong_FromLong(2));
235 PyObjectPtr three(PyLong_FromLong(3));
236 PyObjectPtr tuple(PyTuple_Pack(3, one.get(), two.get(), three.get()));
237 PyObjectPtr iter(PyObject_GetIter(tuple));
238 ASSERT_NE(iter, nullptr);
239 PyObjectPtr next(PyIter_Next(iter));
240 ASSERT_NE(next, nullptr);
241 EXPECT_EQ(PyErr_Occurred(), nullptr);
242 EXPECT_EQ(PyLong_AsLong(next), 1);
243 next = PyIter_Next(iter);
244 ASSERT_NE(next, nullptr);
245 EXPECT_EQ(PyErr_Occurred(), nullptr);
246 EXPECT_EQ(PyLong_AsLong(next), 2);
247 next = PyIter_Next(iter);
248 ASSERT_NE(next, nullptr);
249 EXPECT_EQ(PyErr_Occurred(), nullptr);
250 EXPECT_EQ(PyLong_AsLong(next), 3);
251 next = PyIter_Next(iter);
252 ASSERT_EQ(next, nullptr);
253 EXPECT_EQ(PyErr_Occurred(), nullptr);
254}
255
256TEST_F(AbstractExtensionApiTest, PyIterNextOnNonIterRaises) {
257 ASSERT_EQ(PyObject_GetIter(Py_None), nullptr);
258 ASSERT_NE(PyErr_Occurred(), nullptr);
259 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
260}
261
262TEST_F(AbstractExtensionApiTest, PyIterNextPropagatesException) {
263 PyRun_SimpleString(R"(
264class C:
265 def __iter__(self):
266 return self
267 def __next__(self):
268 raise ValueError("hi")
269
270c = C()
271)");
272 PyObjectPtr c(mainModuleGet("c"));
273 PyObjectPtr iter(PyObject_GetIter(c));
274 ASSERT_NE(iter, nullptr);
275 PyObjectPtr next(PyIter_Next(iter));
276 ASSERT_EQ(next, nullptr);
277 ASSERT_NE(PyErr_Occurred(), nullptr);
278 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
279}
280
281// Mapping Protocol
282
283TEST_F(AbstractExtensionApiTest, PyMappingCheckWithoutGetItemReturnsFalse) {
284 PyRun_SimpleString(R"(
285class ClassWithoutDunderGetItem: pass
286
287obj = ClassWithoutDunderGetItem()
288 )");
289
290 PyObjectPtr obj(mainModuleGet("obj"));
291 EXPECT_FALSE(PyMapping_Check(obj));
292}
293
294TEST_F(AbstractExtensionApiTest,
295 PyMappingCheckWithoutGetItemOnClassReturnsFalse) {
296 PyRun_SimpleString(R"(
297class ClassWithoutDunderGetItem: pass
298
299obj = ClassWithoutDunderGetItem()
300obj.__getitem__ = lambda self, key: 1
301 )");
302
303 PyObjectPtr obj(mainModuleGet("obj"));
304 EXPECT_FALSE(PyMapping_Check(obj));
305}
306
307TEST_F(AbstractExtensionApiTest, PyMappingCheckWithNumericReturnsFalse) {
308 PyObjectPtr num(PyLong_FromLong(4));
309 EXPECT_FALSE(PyMapping_Check(num));
310}
311
312TEST_F(AbstractExtensionApiTest, PyMappingCheckWithSetReturnsFalse) {
313 PyObjectPtr set(PySet_New(nullptr));
314 EXPECT_FALSE(PyMapping_Check(set));
315}
316
317TEST_F(AbstractExtensionApiTest, PyMappingCheckWithBooleanReturnsFalse) {
318 EXPECT_FALSE(PyMapping_Check(Py_False));
319}
320
321TEST_F(AbstractExtensionApiTest, PyMappingCheckWithGetItemMethodReturnsTrue) {
322 PyRun_SimpleString(R"(
323class ClassWithDunderGetItemMethod:
324 def __getitem__(self, key):
325 return None
326
327obj = ClassWithDunderGetItemMethod()
328 )");
329
330 PyObjectPtr obj(mainModuleGet("obj"));
331 EXPECT_TRUE(PyMapping_Check(obj));
332}
333
334TEST_F(AbstractExtensionApiTest, PyMappingCheckWithGetItemAttrReturnsTrue) {
335 PyRun_SimpleString(R"(
336class ClassWithDunderGetItemAttr:
337 __getitem__ = 42
338
339obj = ClassWithDunderGetItemAttr()
340 )");
341
342 PyObjectPtr obj(mainModuleGet("obj"));
343 EXPECT_TRUE(PyMapping_Check(obj));
344}
345
346TEST_F(AbstractExtensionApiTest, PyMappingCheckWithStringReturnsTrue) {
347 PyObjectPtr str(PyUnicode_FromString("foo"));
348 EXPECT_TRUE(PyMapping_Check(str));
349}
350
351TEST_F(AbstractExtensionApiTest, PyMappingCheckWithListReturnsTrue) {
352 PyObjectPtr list(PyList_New(3));
353 EXPECT_TRUE(PyMapping_Check(list));
354}
355
356TEST_F(AbstractExtensionApiTest, PyMappingCheckWithDictReturnsTrue) {
357 PyObjectPtr dict(PyDict_New());
358 EXPECT_TRUE(PyMapping_Check(dict));
359}
360
361TEST_F(AbstractExtensionApiTest, PyMappingLengthOnNullRaisesSystemError) {
362 EXPECT_EQ(PyMapping_Length(nullptr), -1);
363 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
364}
365
366TEST_F(AbstractExtensionApiTest, PyMappingLengthWithNonMappingReturnsLen) {
367 PyRun_SimpleString(R"(
368class Foo:
369 def __len__(self):
370 return 1
371obj = Foo()
372 )");
373
374 PyObjectPtr obj(mainModuleGet("obj"));
375 EXPECT_EQ(PyMapping_Length(obj), 1);
376 EXPECT_EQ(PyErr_Occurred(), nullptr);
377}
378
379TEST_F(AbstractExtensionApiTest, PyMappingSizeOnNullRaisesSystemError) {
380 EXPECT_EQ(PyMapping_Size(nullptr), -1);
381 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
382}
383
384// Number Protocol
385
386TEST_F(AbstractExtensionApiTest, PyNumberAbsoluteWithNullRaisesSystemError) {
387 ASSERT_EQ(PyNumber_Absolute(nullptr), nullptr);
388 ASSERT_NE(PyErr_Occurred(), nullptr);
389 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
390}
391
392TEST_F(AbstractExtensionApiTest,
393 PyNumberAbsoluteWithNoDunderAbsRaisesTypeError) {
394 PyRun_SimpleString(R"(
395class C:
396 pass
397c = C()
398)");
399 PyObjectPtr c(mainModuleGet("c"));
400 ASSERT_EQ(PyNumber_Absolute(c), nullptr);
401 ASSERT_NE(PyErr_Occurred(), nullptr);
402 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
403}
404
405TEST_F(AbstractExtensionApiTest, PyNumberAbsoluteCallsDunderAbs) {
406 PyObjectPtr negative(PyLong_FromLong(-10));
407 PyObjectPtr positive(PyLong_FromLong(10));
408 PyObjectPtr result(PyNumber_Absolute(negative));
409 EXPECT_EQ(result, positive);
410 EXPECT_EQ(PyErr_Occurred(), nullptr);
411}
412
413TEST_F(AbstractExtensionApiTest, PyNumberAddWithNoDunderAddRaisesTypeError) {
414 PyRun_SimpleString(R"(
415class C:
416 pass
417c = C()
418)");
419 PyObjectPtr c(mainModuleGet("c"));
420 ASSERT_EQ(PyNumber_Add(c, c), nullptr);
421 ASSERT_NE(PyErr_Occurred(), nullptr);
422 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
423}
424
425TEST_F(AbstractExtensionApiTest, PyNumberAddCallsDunderAdd) {
426 PyRun_SimpleString(R"(
427class ClassWithDunderAdd:
428 def __add__(self, other):
429 return "hello";
430
431x = ClassWithDunderAdd()
432 )");
433 PyObjectPtr x(mainModuleGet("x"));
434 PyObjectPtr y(PyLong_FromLong(7));
435 PyObjectPtr result(PyNumber_Add(x, y));
436 EXPECT_TRUE(isUnicodeEqualsCStr(result, "hello"));
437}
438
439TEST_F(AbstractExtensionApiTest, PyNumberAddWithIntsReturnsSum) {
440 PyObjectPtr x(PyLong_FromLong(7));
441 PyObjectPtr y(PyLong_FromLong(10));
442 PyObjectPtr result(PyNumber_Add(x, y));
443 ASSERT_TRUE(PyLong_CheckExact(result));
444 EXPECT_EQ(PyLong_AsLong(result), 17);
445}
446
447TEST_F(AbstractExtensionApiTest, PyNumberAddWithUnicodeReturnsConcat) {
448 PyObjectPtr x(PyUnicode_FromString("foo"));
449 PyObjectPtr y(PyUnicode_FromString("bar"));
450 PyObjectPtr result(PyNumber_Add(x, y));
451 EXPECT_TRUE(isUnicodeEqualsCStr(result, "foobar"));
452}
453
454TEST_F(AbstractExtensionApiTest, PyNumberAndWithNonIntRaisesTypeError) {
455 PyObjectPtr x(PyUnicode_FromString("foo"));
456 PyObjectPtr y(PyLong_FromLong(2));
457 ASSERT_EQ(PyNumber_And(x, y), nullptr);
458 ASSERT_NE(PyErr_Occurred(), nullptr);
459 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
460}
461
462TEST_F(AbstractExtensionApiTest, PyNumberAndWithIntsReturnsBitwiseAnd) {
463 PyObjectPtr x(PyLong_FromLong(5)); // 0b0101
464 PyObjectPtr y(PyLong_FromLong(3)); // 0b0011
465 PyObjectPtr result(PyNumber_And(x, y));
466 ASSERT_TRUE(PyLong_CheckExact(result));
467 EXPECT_EQ(PyLong_AsLong(result), 1); // 0b0001
468}
469
470TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithNullRaisesSystemError) {
471 ASSERT_EQ(PyNumber_AsSsize_t(nullptr, PyExc_TypeError), -1);
472 ASSERT_NE(PyErr_Occurred(), nullptr);
473 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
474}
475
476TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithStringRaisesTypeError) {
477 PyObjectPtr str(PyUnicode_FromString("foo"));
478 ASSERT_EQ(PyNumber_AsSsize_t(str, nullptr), -1);
479 ASSERT_NE(PyErr_Occurred(), nullptr);
480 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
481}
482
483TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithIntReturnsInt) {
484 PyObjectPtr num(PyLong_FromLong(10));
485 Py_ssize_t result = PyNumber_AsSsize_t(num, nullptr);
486 ASSERT_EQ(PyErr_Occurred(), nullptr);
487 EXPECT_EQ(result, 10);
488}
489
490TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithIntSubclassReturnsInt) {
491 PyRun_SimpleString(R"(
492class C(int):
493 def __index__(self): return 10
494obj = C(42);
495)");
496 PyObjectPtr obj(mainModuleGet("obj"));
497 Py_ssize_t result = PyNumber_AsSsize_t(obj, nullptr);
498 EXPECT_EQ(PyErr_Occurred(), nullptr);
499 EXPECT_EQ(result, 42);
500}
501
502TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithDunderIndexReturnsInt) {
503 PyRun_SimpleString(R"(
504class C:
505 def __index__(self): return 42
506obj = C();
507)");
508 PyObjectPtr obj(mainModuleGet("obj"));
509 Py_ssize_t result = PyNumber_AsSsize_t(obj, nullptr);
510 EXPECT_EQ(PyErr_Occurred(), nullptr);
511 EXPECT_EQ(result, 42);
512}
513
514TEST_F(AbstractExtensionApiTest,
515 PyNumberAsSsizeTWithNegativeOneReturnsNegativeOne) {
516 PyObjectPtr num(PyLong_FromLong(-1));
517 Py_ssize_t result = PyNumber_AsSsize_t(num, nullptr);
518 ASSERT_EQ(PyErr_Occurred(), nullptr);
519 EXPECT_EQ(result, -1);
520}
521
522TEST_F(AbstractExtensionApiTest,
523 PyNumberAsSsizeTWithOverflowAndNullClearsError) {
524 const unsigned char bytes[] = {0x01, 0x00, 0x00, 0x00, 0x00,
525 0x00, 0x00, 0x00, 0x00};
526 PyObjectPtr num(_PyLong_FromByteArray(bytes, sizeof(bytes), false, true));
527 Py_ssize_t result = PyNumber_AsSsize_t(num, nullptr);
528 ASSERT_EQ(PyErr_Occurred(), nullptr);
529 EXPECT_EQ(result, 0x7fffffffffffffff);
530}
531
532TEST_F(AbstractExtensionApiTest,
533 PyNumberAsSsizeTWithUnderflowAndNullClearsError) {
534 const unsigned char bytes[] = {0xff, 0x00, 0x00, 0x00, 0x00,
535 0x00, 0x00, 0x00, 0x00};
536 PyObjectPtr num(_PyLong_FromByteArray(bytes, sizeof(bytes), false, true));
537 Py_ssize_t result = PyNumber_AsSsize_t(num, nullptr);
538 ASSERT_EQ(PyErr_Occurred(), nullptr);
539 EXPECT_EQ(result, INT64_MIN);
540}
541
542TEST_F(AbstractExtensionApiTest, PyNumberAsSsizeTWithOverflowSetsGivenError) {
543 const unsigned char bytes[] = {0x01, 0x00, 0x00, 0x00, 0x00,
544 0x00, 0x00, 0x00, 0x00};
545 PyObjectPtr num(_PyLong_FromByteArray(bytes, sizeof(bytes), false, true));
546 ASSERT_EQ(PyNumber_AsSsize_t(num, PyExc_ModuleNotFoundError), -1);
547 ASSERT_NE(PyErr_Occurred(), nullptr);
548 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ModuleNotFoundError));
549}
550
551TEST_F(AbstractExtensionApiTest, PyNumberCheckWithFloatReturnsTrue) {
552 PyObjectPtr float_num(PyFloat_FromDouble(1.1));
553 EXPECT_EQ(PyNumber_Check(float_num), 1);
554 ASSERT_EQ(PyErr_Occurred(), nullptr);
555}
556
557TEST_F(AbstractExtensionApiTest, PyNumberCheckWithIntReturnsTrue) {
558 PyObjectPtr int_num(PyLong_FromLong(1));
559 EXPECT_EQ(PyNumber_Check(int_num), 1);
560 ASSERT_EQ(PyErr_Occurred(), nullptr);
561}
562
563TEST_F(AbstractExtensionApiTest, PyNumberCheckWithFloatSubclassReturnsTrue) {
564 PyRun_SimpleString(R"(
565class SubFloat(float):
566 pass
567sub = SubFloat()
568 )");
569 PyObjectPtr sub(mainModuleGet("sub"));
570 EXPECT_EQ(PyNumber_Check(sub), 1);
571 ASSERT_EQ(PyErr_Occurred(), nullptr);
572}
573
574TEST_F(AbstractExtensionApiTest, PyNumberCheckWithDunderIntClassReturnsTrue) {
575 PyRun_SimpleString(R"(
576class DunderIntClass():
577 def __int__(self):
578 return 5
579i = DunderIntClass()
580 )");
581 PyObjectPtr i(mainModuleGet("i"));
582 EXPECT_EQ(PyNumber_Check(i), 1);
583 ASSERT_EQ(PyErr_Occurred(), nullptr);
584}
585
586TEST_F(AbstractExtensionApiTest, PyNumberCheckWithDunderFloatClassReturnsTrue) {
587 PyRun_SimpleString(R"(
588class DunderFloatClass():
589 def __float__(self):
590 return 5.0
591f = DunderFloatClass()
592 )");
593 PyObjectPtr f(mainModuleGet("f"));
594 EXPECT_EQ(PyNumber_Check(f), 1);
595 ASSERT_EQ(PyErr_Occurred(), nullptr);
596}
597
598TEST_F(AbstractExtensionApiTest, PyNumberCheckWithNonNumberReturnsFalse) {
599 PyObjectPtr str(PyUnicode_FromString(""));
600 EXPECT_EQ(PyNumber_Check(str), 0);
601 ASSERT_EQ(PyErr_Occurred(), nullptr);
602}
603
604TEST_F(AbstractExtensionApiTest,
605 PyNumberCheckWithDunderIntDescriptorThatRaisesReturnsTrue) {
606 PyRun_SimpleString(R"(
607class Desc:
608 def __get__(self, obj, type):
609 raise UserWarning("foo")
610class C:
611 __int__ = Desc()
612c = C()
613)");
614 PyObjectPtr c(mainModuleGet("c"));
615 EXPECT_EQ(PyNumber_Check(c), 1);
616 ASSERT_EQ(PyErr_Occurred(), nullptr);
617}
618
619TEST_F(AbstractExtensionApiTest,
620 PyNumberCheckWithDunderFloatDescriptorThatRaisesReturnsTrue) {
621 PyRun_SimpleString(R"(
622class Desc:
623 def __get__(self, obj, type):
624 raise UserWarning("foo")
625class C:
626 __float__ = Desc()
627c = C()
628)");
629 PyObjectPtr c(mainModuleGet("c"));
630 EXPECT_EQ(PyNumber_Check(c), 1);
631 ASSERT_EQ(PyErr_Occurred(), nullptr);
632}
633
634TEST_F(AbstractExtensionApiTest, PyNumberCheckWithNullReturnsFalse) {
635 EXPECT_EQ(PyNumber_Check(nullptr), 0);
636 ASSERT_EQ(PyErr_Occurred(), nullptr);
637}
638
639TEST_F(AbstractExtensionApiTest, PyNumberFloatWithNullRaisesSystemError) {
640 EXPECT_EQ(PyNumber_Float(nullptr), nullptr);
641 ASSERT_NE(PyErr_Occurred(), nullptr);
642 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
643}
644
645TEST_F(AbstractExtensionApiTest, PyNumberFloatWithStringReturnsFloat) {
646 PyObjectPtr str(PyUnicode_FromString("4.2"));
647 PyObjectPtr flt(PyNumber_Float(str));
648 EXPECT_EQ(PyErr_Occurred(), nullptr);
649 ASSERT_TRUE(PyFloat_CheckExact(flt));
650 EXPECT_EQ(PyFloat_AsDouble(flt), 4.2);
651}
652
653TEST_F(AbstractExtensionApiTest, PyNumberFloatWithIntReturnsFloat) {
654 PyObjectPtr num(PyLong_FromLong(42));
655 PyObjectPtr flt(PyNumber_Float(num));
656 EXPECT_EQ(PyErr_Occurred(), nullptr);
657 ASSERT_TRUE(PyFloat_CheckExact(flt));
658 EXPECT_EQ(PyFloat_AsDouble(flt), 42.0);
659}
660
661TEST_F(AbstractExtensionApiTest, PyNumberFloatWithFloatReturnsSameFloat) {
662 PyObjectPtr num(PyFloat_FromDouble(4.2));
663 Py_ssize_t refcnt = Py_REFCNT(num);
664 PyObjectPtr flt(PyNumber_Float(num));
665 EXPECT_EQ(PyErr_Occurred(), nullptr);
666 EXPECT_EQ(num, flt);
667 EXPECT_EQ(Py_REFCNT(num), refcnt + 1);
668}
669
670TEST_F(AbstractExtensionApiTest, PyNumberFloatWithFloatSubclassReturnsFloat) {
671 PyRun_SimpleString(R"(
672class C(float):
673 pass
674x = C(4.2)
675)");
676 PyObjectPtr x(mainModuleGet("x"));
677 PyObjectPtr flt(PyNumber_Float(x));
678 EXPECT_EQ(PyErr_Occurred(), nullptr);
679 ASSERT_TRUE(PyFloat_CheckExact(flt));
680 EXPECT_EQ(PyFloat_AsDouble(flt), 4.2);
681}
682
683TEST_F(AbstractExtensionApiTest,
684 PyNumberFloatWithDescriptorThatRaisesPropagatesException) {
685 PyRun_SimpleString(R"(
686class Desc:
687 def __get__(self, obj, type):
688 raise UserWarning("foo")
689class C:
690 __float__ = Desc()
691c = C()
692)");
693 PyObjectPtr c(mainModuleGet("c"));
694 EXPECT_EQ(PyNumber_Float(c), nullptr);
695 ASSERT_NE(PyErr_Occurred(), nullptr);
696 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
697}
698
699TEST_F(AbstractExtensionApiTest, PyNumberFloorDivideWithNonIntRaisesTypeError) {
700 PyObjectPtr x(PyUnicode_FromString("foo"));
701 PyObjectPtr y(PyLong_FromLong(2));
702 ASSERT_EQ(PyNumber_FloorDivide(x, y), nullptr);
703 ASSERT_NE(PyErr_Occurred(), nullptr);
704 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
705}
706
707TEST_F(AbstractExtensionApiTest, PyNumberFloorDivideWithIntsReturnsInt) {
708 PyObjectPtr x(PyLong_FromLong(42));
709 PyObjectPtr y(PyLong_FromLong(5));
710 PyObjectPtr result(PyNumber_FloorDivide(x, y));
711 ASSERT_TRUE(PyLong_CheckExact(result));
712 EXPECT_EQ(PyLong_AsLong(result), 8);
713}
714
715TEST_F(AbstractExtensionApiTest, PyNumberIndexOnIntReturnsSelf) {
716 PyObjectPtr pylong(PyLong_FromLong(666));
717 PyObjectPtr index(PyNumber_Index(pylong));
718 EXPECT_EQ(index, pylong);
719}
720
721TEST_F(AbstractExtensionApiTest, PyNumberIndexOnIntSubclassReturnsSelf) {
722 PyRun_SimpleString(R"(
723class C(int): pass
724obj = C(42);
725)");
726 PyObjectPtr obj(mainModuleGet("obj"));
727 PyObjectPtr index(PyNumber_Index(obj));
728 EXPECT_EQ(index, obj);
729}
730
731TEST_F(AbstractExtensionApiTest, PyNumberIndexCallsDunderIndex) {
732 PyRun_SimpleString(R"(
733class IntLikeClass:
734 def __index__(self):
735 return 42;
736
737i = IntLikeClass();
738 )");
739 PyObjectPtr i(mainModuleGet("i"));
740 PyObjectPtr index(PyNumber_Index(i));
741 ASSERT_TRUE(PyLong_CheckExact(index));
742 EXPECT_EQ(PyLong_AsLong(index), 42);
743}
744
745TEST_F(AbstractExtensionApiTest, PyNumberIndexOnNullRaisesSystemError) {
746 ASSERT_EQ(PyNumber_Index(nullptr), nullptr);
747 ASSERT_NE(PyErr_Occurred(), nullptr);
748 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
749}
750
751TEST_F(AbstractExtensionApiTest, PyNumberIndexOnNonIntRaisesTypeError) {
752 PyObjectPtr str(PyUnicode_FromString("not an int"));
753 ASSERT_EQ(PyNumber_Index(str), nullptr);
754 ASSERT_NE(PyErr_Occurred(), nullptr);
755 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
756}
757
758TEST_F(AbstractExtensionApiTest,
759 PyNumberIndexWithMistypedDunderIndexRaisesTypeError) {
760 PyRun_SimpleString(R"(
761class IntLikeClass:
762 def __index__(self):
763 return "not an int";
764
765i = IntLikeClass();
766 )");
767 PyObjectPtr i(mainModuleGet("i"));
768 ASSERT_EQ(PyNumber_Index(i), nullptr);
769 ASSERT_NE(PyErr_Occurred(), nullptr);
770 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
771}
772
773TEST_F(AbstractExtensionApiTest,
774 PyNumberInPlaceAddWithNonNumberRaisesTypeError) {
775 PyObjectPtr x(PyUnicode_FromString("foo"));
776 PyObjectPtr y(PyLong_FromLong(2));
777 ASSERT_EQ(PyNumber_InPlaceAdd(x, y), nullptr);
778 ASSERT_NE(PyErr_Occurred(), nullptr);
779 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
780}
781
782TEST_F(AbstractExtensionApiTest, PyNumberInPlaceAddWithIntsReturnsInt) {
783 PyObjectPtr x(PyLong_FromLong(4));
784 PyObjectPtr y(PyLong_FromLong(2));
785 PyObjectPtr result(PyNumber_InPlaceAdd(x, y));
786 ASSERT_TRUE(PyLong_CheckExact(result));
787 EXPECT_EQ(PyLong_AsLong(result), 6);
788 EXPECT_EQ(PyLong_AsLong(x), 4);
789}
790
791TEST_F(AbstractExtensionApiTest,
792 PyNumberInPlaceAndWithNonNumberRaisesTypeError) {
793 PyObjectPtr x(PyUnicode_FromString("foo"));
794 PyObjectPtr y(PyLong_FromLong(2));
795 ASSERT_EQ(PyNumber_InPlaceAnd(x, y), nullptr);
796 ASSERT_NE(PyErr_Occurred(), nullptr);
797 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
798}
799
800TEST_F(AbstractExtensionApiTest, PyNumberInPlaceAndWithIntsReturnsInt) {
801 PyObjectPtr x(PyLong_FromLong(5)); // 0b0101
802 PyObjectPtr y(PyLong_FromLong(3)); // 0b0011
803 PyObjectPtr result(PyNumber_InPlaceAnd(x, y));
804 ASSERT_TRUE(PyLong_CheckExact(result));
805 EXPECT_EQ(PyLong_AsLong(result), 1); // 0b0001
806 EXPECT_EQ(PyLong_AsLong(x), 5);
807}
808
809TEST_F(AbstractExtensionApiTest,
810 PyNumberInPlaceFloorDivideWithNonNumberRaisesTypeError) {
811 PyObjectPtr x(PyUnicode_FromString("foo"));
812 PyObjectPtr y(PyLong_FromLong(2));
813 ASSERT_EQ(PyNumber_InPlaceFloorDivide(x, y), nullptr);
814 ASSERT_NE(PyErr_Occurred(), nullptr);
815 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
816}
817
818TEST_F(AbstractExtensionApiTest, PyNumberInPlaceFloorDivideWithIntsReturnsInt) {
819 PyObjectPtr x(PyLong_FromLong(42));
820 PyObjectPtr y(PyLong_FromLong(5));
821 PyObjectPtr result(PyNumber_InPlaceFloorDivide(x, y));
822 ASSERT_TRUE(PyLong_CheckExact(result));
823 EXPECT_EQ(PyLong_AsLong(result), 8);
824 EXPECT_EQ(PyLong_AsLong(x), 42);
825}
826
827TEST_F(AbstractExtensionApiTest,
828 PyNumberInPlaceLshiftWithNonNumberRaisesTypeError) {
829 PyObjectPtr x(PyUnicode_FromString("foo"));
830 PyObjectPtr y(PyLong_FromLong(2));
831 ASSERT_EQ(PyNumber_InPlaceLshift(x, y), nullptr);
832 ASSERT_NE(PyErr_Occurred(), nullptr);
833 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
834}
835
836TEST_F(AbstractExtensionApiTest, PyNumberInPlaceLshiftIntsReturnsInt) {
837 PyObjectPtr x(PyLong_FromLong(5));
838 PyObjectPtr y(PyLong_FromLong(3));
839 PyObjectPtr result(PyNumber_InPlaceLshift(x, y));
840 ASSERT_TRUE(PyLong_CheckExact(result));
841 EXPECT_EQ(PyLong_AsLong(result), 40);
842 EXPECT_EQ(PyLong_AsLong(x), 5);
843}
844
845TEST_F(AbstractExtensionApiTest,
846 PyNumberInPlaceMatrixMultiplyWithNonNumberRaisesTypeError) {
847 PyObjectPtr x(PyUnicode_FromString("foo"));
848 PyObjectPtr y(PyLong_FromLong(2));
849 ASSERT_EQ(PyNumber_InPlaceMatrixMultiply(x, y), nullptr);
850 ASSERT_NE(PyErr_Occurred(), nullptr);
851 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
852}
853
854TEST_F(AbstractExtensionApiTest,
855 PyNumberInPlaceMatrixMultiplyCallsDunderImatmul) {
856 PyRun_SimpleString(R"(
857class C:
858 def __init__(self):
859 self.called = False
860 def __imatmul__(self, other):
861 self.called = True
862 return 1
863x = C()
864)");
865 PyObjectPtr x(mainModuleGet("x"));
866 PyObjectPtr y(PyLong_FromLong(3));
867 PyObjectPtr called1(PyObject_GetAttrString(x, "called"));
868 EXPECT_EQ(called1, Py_False);
869 PyObjectPtr result(PyNumber_InPlaceMatrixMultiply(x, y));
870 ASSERT_TRUE(PyLong_CheckExact(result));
871 EXPECT_EQ(PyLong_AsLong(result), 1);
872 PyObjectPtr called2(PyObject_GetAttrString(x, "called"));
873 EXPECT_EQ(called2, Py_True);
874}
875
876TEST_F(AbstractExtensionApiTest,
877 PyNumberInPlaceMultiplyWithNonNumberRaisesTypeError) {
878 PyObjectPtr x(PyLong_FromLong(2));
879 ASSERT_EQ(PyNumber_InPlaceMultiply(x, Py_None), nullptr);
880 ASSERT_NE(PyErr_Occurred(), nullptr);
881 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
882}
883
884TEST_F(AbstractExtensionApiTest, PyNumberInPlaceMultiplyWithIntsReturnsInt) {
885 PyObjectPtr x(PyLong_FromLong(3));
886 PyObjectPtr y(PyLong_FromLong(2));
887 PyObjectPtr result(PyNumber_InPlaceMultiply(x, y));
888 ASSERT_TRUE(PyLong_CheckExact(result));
889 EXPECT_EQ(PyLong_AsLong(result), 6);
890}
891
892TEST_F(AbstractExtensionApiTest,
893 PyNumberInPlaceOrWithNonNumberRaisesTypeError) {
894 PyObjectPtr x(PyUnicode_FromString("foo"));
895 PyObjectPtr y(PyLong_FromLong(2));
896 ASSERT_EQ(PyNumber_InPlaceOr(x, y), nullptr);
897 ASSERT_NE(PyErr_Occurred(), nullptr);
898 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
899}
900
901TEST_F(AbstractExtensionApiTest, PyNumberInPlaceOrWithIntsReturnsInt) {
902 PyObjectPtr x(PyLong_FromLong(5)); // 0b0101
903 PyObjectPtr y(PyLong_FromLong(3)); // 0b0011
904 PyObjectPtr result(PyNumber_InPlaceOr(x, y));
905 ASSERT_TRUE(PyLong_CheckExact(result));
906 EXPECT_EQ(PyLong_AsLong(result), 7); // 0b0111
907 EXPECT_EQ(PyLong_AsLong(x), 5);
908}
909
910TEST_F(AbstractExtensionApiTest,
911 PyNumberInPlacePowerWithNonNumberRaisesTypeError) {
912 PyObjectPtr x(PyUnicode_FromString("foo"));
913 PyObjectPtr y(PyLong_FromLong(2));
914 ASSERT_EQ(PyNumber_InPlacePower(x, y, Py_None), nullptr);
915 ASSERT_NE(PyErr_Occurred(), nullptr);
916 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
917}
918
919TEST_F(AbstractExtensionApiTest, PyNumberInPlacePowerCallsDunderIpow) {
920 PyRun_SimpleString(R"(
921class C:
922 def __init__(self):
923 self.called = False
924 def __ipow__(self, other):
925 self.called = True
926 return 1
927x = C()
928)");
929 PyObjectPtr x(mainModuleGet("x"));
930 PyObjectPtr y(PyLong_FromLong(3));
931 PyObjectPtr called1(PyObject_GetAttrString(x, "called"));
932 EXPECT_EQ(called1, Py_False);
933 PyObjectPtr result(PyNumber_InPlacePower(x, y, Py_None));
934 ASSERT_TRUE(PyLong_CheckExact(result));
935 EXPECT_EQ(PyLong_AsLong(result), 1);
936 PyObjectPtr called2(PyObject_GetAttrString(x, "called"));
937 EXPECT_EQ(called2, Py_True);
938}
939
940TEST_F(AbstractExtensionApiTest,
941 PyNumberInPlaceRemainderWithNonNumberRaisesTypeError) {
942 PyObjectPtr x(PyList_New(0));
943 PyObjectPtr y(PyLong_FromLong(2));
944 ASSERT_EQ(PyNumber_InPlaceRemainder(x, y), nullptr);
945 ASSERT_NE(PyErr_Occurred(), nullptr);
946 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
947}
948
949TEST_F(AbstractExtensionApiTest, PyNumberInPlaceRemainderWithIntsReturnsInt) {
950 PyObjectPtr x(PyLong_FromLong(42));
951 PyObjectPtr y(PyLong_FromLong(5));
952 PyObjectPtr result(PyNumber_InPlaceRemainder(x, y));
953 ASSERT_TRUE(PyLong_CheckExact(result));
954 EXPECT_EQ(PyLong_AsLong(result), 2);
955}
956
957TEST_F(AbstractExtensionApiTest,
958 PyNumberInPlaceRshiftWithNonNumberRaisesTypeError) {
959 PyObjectPtr x(PyUnicode_FromString("foo"));
960 PyObjectPtr y(PyLong_FromLong(2));
961 ASSERT_EQ(PyNumber_InPlaceRshift(x, y), nullptr);
962 ASSERT_NE(PyErr_Occurred(), nullptr);
963 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
964}
965
966TEST_F(AbstractExtensionApiTest, PyNumberInPlaceRshiftIntsReturnsInt) {
967 PyObjectPtr x(PyLong_FromLong(42));
968 PyObjectPtr y(PyLong_FromLong(3));
969 PyObjectPtr result(PyNumber_InPlaceRshift(x, y));
970 ASSERT_TRUE(PyLong_CheckExact(result));
971 EXPECT_EQ(PyLong_AsLong(result), 5);
972 EXPECT_EQ(PyLong_AsLong(x), 42);
973}
974
975TEST_F(AbstractExtensionApiTest,
976 PyNumberInPlaceSubtractWithNonNumberRaisesTypeError) {
977 PyObjectPtr x(PyUnicode_FromString("foo"));
978 PyObjectPtr y(PyLong_FromLong(2));
979 ASSERT_EQ(PyNumber_InPlaceSubtract(x, y), nullptr);
980 ASSERT_NE(PyErr_Occurred(), nullptr);
981 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
982}
983
984TEST_F(AbstractExtensionApiTest, PyNumberInPlaceSubtractIntsReturnsInt) {
985 PyObjectPtr x(PyLong_FromLong(5));
986 PyObjectPtr y(PyLong_FromLong(3));
987 PyObjectPtr result(PyNumber_InPlaceSubtract(x, y));
988 ASSERT_TRUE(PyLong_CheckExact(result));
989 EXPECT_EQ(PyLong_AsLong(result), 2);
990 EXPECT_EQ(PyLong_AsLong(x), 5);
991}
992
993TEST_F(AbstractExtensionApiTest,
994 PyNumberInPlaceTrueDivideWithNonNumberRaisesTypeError) {
995 PyObjectPtr x(PyUnicode_FromString("foo"));
996 PyObjectPtr y(PyLong_FromLong(2));
997 ASSERT_EQ(PyNumber_InPlaceTrueDivide(x, y), nullptr);
998 ASSERT_NE(PyErr_Occurred(), nullptr);
999 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1000}
1001
1002TEST_F(AbstractExtensionApiTest,
1003 PyNumberInPlaceTrueDivideWithFloatsReturnsFloat) {
1004 PyObjectPtr x(PyLong_FromLong(42.0));
1005 PyObjectPtr y(PyLong_FromLong(5));
1006 PyObjectPtr result(PyNumber_InPlaceTrueDivide(x, y));
1007 ASSERT_TRUE(PyFloat_CheckExact(result));
1008 EXPECT_EQ(PyFloat_AsDouble(result), 8.4);
1009 EXPECT_EQ(PyFloat_AsDouble(x), 42.0);
1010}
1011
1012TEST_F(AbstractExtensionApiTest,
1013 PyNumberInPlaceXorWithNonNumberRaisesTypeError) {
1014 PyObjectPtr x(PyUnicode_FromString("foo"));
1015 PyObjectPtr y(PyLong_FromLong(2));
1016 ASSERT_EQ(PyNumber_InPlaceXor(x, y), nullptr);
1017 ASSERT_NE(PyErr_Occurred(), nullptr);
1018 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1019}
1020
1021TEST_F(AbstractExtensionApiTest, PyNumberInPlaceXorWithIntsReturnsInt) {
1022 PyObjectPtr x(PyLong_FromLong(5)); // 0b0101
1023 PyObjectPtr y(PyLong_FromLong(3)); // 0b0011
1024 PyObjectPtr result(PyNumber_InPlaceXor(x, y));
1025 ASSERT_TRUE(PyLong_CheckExact(result));
1026 EXPECT_EQ(PyLong_AsLong(result), 6); // 0b0110
1027 EXPECT_EQ(PyLong_AsLong(x), 5);
1028}
1029
1030TEST_F(AbstractExtensionApiTest, PyNumberInvertWithIntReturnsInt) {
1031 PyObjectPtr num(PyLong_FromLong(7));
1032 PyObjectPtr result(PyNumber_Invert(num));
1033 EXPECT_EQ(PyLong_AsLong(result), -8);
1034}
1035
1036TEST_F(AbstractExtensionApiTest,
1037 PyNumberInvertWithCustomClassCallsDunderInvert) {
1038 PyRun_SimpleString(R"(
1039class C:
1040 def __invert__(self):
1041 return "custom invert"
1042c = C()
1043)");
1044 PyObjectPtr c(mainModuleGet("c"));
1045 PyObjectPtr result(PyNumber_Invert(c));
1046 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "custom invert"), 0);
1047}
1048
1049TEST_F(AbstractExtensionApiTest, PyNumberInvertWithNullRaisesSystemError) {
1050 ASSERT_EQ(PyNumber_Invert(nullptr), nullptr);
1051 ASSERT_NE(PyErr_Occurred(), nullptr);
1052 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1053}
1054
1055TEST_F(AbstractExtensionApiTest, PyNumberInvertWithNonNumberRaisesTypeError) {
1056 ASSERT_EQ(PyNumber_Positive(Py_None), nullptr);
1057 ASSERT_NE(PyErr_Occurred(), nullptr);
1058 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1059}
1060
1061TEST_F(AbstractExtensionApiTest, PyNumberInvertPropagatesException) {
1062 PyRun_SimpleString(R"(
1063class C:
1064 def __invert__(self):
1065 raise UserWarning()
1066c = C()
1067)");
1068 PyObjectPtr c(mainModuleGet("c"));
1069 PyObjectPtr result(PyNumber_Invert(c));
1070 ASSERT_EQ(result, nullptr);
1071 ASSERT_NE(PyErr_Occurred(), nullptr);
1072 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1073}
1074
1075TEST_F(AbstractExtensionApiTest, PyNumberLongWithNullRaisesSystemError) {
1076 EXPECT_EQ(PyNumber_Long(nullptr), nullptr);
1077 ASSERT_NE(PyErr_Occurred(), nullptr);
1078 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1079}
1080
1081TEST_F(AbstractExtensionApiTest, PyNumberLongWithIntReturnsInt) {
1082 PyObjectPtr intobj(PyLong_FromLong(PY_SSIZE_T_MAX));
1083 Py_ssize_t refcnt = Py_REFCNT(intobj);
1084 PyObjectPtr result(PyNumber_Long(intobj));
1085 ASSERT_NE(result, nullptr);
1086 EXPECT_EQ(result, intobj);
1087 EXPECT_EQ(Py_REFCNT(result), refcnt + 1);
1088 EXPECT_EQ(PyErr_Occurred(), nullptr);
1089}
1090
1091TEST_F(AbstractExtensionApiTest,
1092 PyNumberLongDunderLongReturnsNonIntRaisesTypeError) {
1093 PyRun_SimpleString(R"(
1094class C:
1095 def __int__(self):
1096 return "foo"
1097c = C()
1098)");
1099 PyObjectPtr c(mainModuleGet("c"));
1100 EXPECT_EQ(PyNumber_Long(c), nullptr);
1101 ASSERT_NE(PyErr_Occurred(), nullptr);
1102 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1103}
1104
1105TEST_F(AbstractExtensionApiTest, PyNumberLongCallsDunderTrunc) {
1106 PyRun_SimpleString(R"(
1107class C:
1108 def __trunc__(self):
1109 return 7
1110c = C()
1111)");
1112 PyObjectPtr c(mainModuleGet("c"));
1113 PyObjectPtr result(PyNumber_Long(c));
1114 ASSERT_NE(result, nullptr);
1115 EXPECT_EQ(PyLong_AsLong(result), 7);
1116 EXPECT_EQ(PyErr_Occurred(), nullptr);
1117}
1118
1119TEST_F(AbstractExtensionApiTest, PyNumberLongCallsDunderTruncAndDunderInt) {
1120 PyRun_SimpleString(R"(
1121class D:
1122 def __int__(self):
1123 return 8
1124
1125class C:
1126 def __trunc__(self):
1127 return D()
1128
1129c = C()
1130)");
1131 PyObjectPtr c(mainModuleGet("c"));
1132 PyObjectPtr result(PyNumber_Long(c));
1133 ASSERT_NE(result, nullptr);
1134 EXPECT_EQ(PyLong_AsLong(result), 8);
1135 EXPECT_EQ(PyErr_Occurred(), nullptr);
1136}
1137
1138TEST_F(AbstractExtensionApiTest, PyNumberLongWithStringReturnsInt) {
1139 PyObjectPtr str(PyUnicode_FromString("7"));
1140 PyObjectPtr result(PyNumber_Long(str));
1141 ASSERT_NE(result, nullptr);
1142 EXPECT_EQ(PyLong_AsLong(result), 7);
1143 EXPECT_EQ(PyErr_Occurred(), nullptr);
1144}
1145
1146TEST_F(AbstractExtensionApiTest,
1147 PyNumberLongWithUnsupportedTypeRaisesTypeError) {
1148 PyRun_SimpleString(R"(
1149class C:
1150 pass
1151c = C()
1152)");
1153 PyObjectPtr c(mainModuleGet("c"));
1154 EXPECT_EQ(PyNumber_Long(c), nullptr);
1155 ASSERT_NE(PyErr_Occurred(), nullptr);
1156 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1157}
1158
1159TEST_F(AbstractExtensionApiTest, PyNumberLshiftWithNonIntSelfRaisesTypeError) {
1160 PyObjectPtr x(PyFloat_FromDouble(5.0));
1161 PyObjectPtr y(PyLong_FromLong(2));
1162 ASSERT_EQ(PyNumber_Lshift(x, y), nullptr);
1163 ASSERT_NE(PyErr_Occurred(), nullptr);
1164 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1165}
1166
1167TEST_F(AbstractExtensionApiTest, PyNumberLshiftWithNonIntOtherRaisesTypeError) {
1168 PyObjectPtr x(PyLong_FromLong(5));
1169 PyObjectPtr y(PyFloat_FromDouble(2.0));
1170 ASSERT_EQ(PyNumber_Lshift(x, y), nullptr);
1171 ASSERT_NE(PyErr_Occurred(), nullptr);
1172 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1173}
1174
1175TEST_F(AbstractExtensionApiTest, PyNumberLshiftWithIntsShiftBitsLeft) {
1176 PyObjectPtr x(PyLong_FromLong(0x13));
1177 PyObjectPtr y(PyLong_FromLong(2));
1178 PyObjectPtr result(PyNumber_Lshift(x, y));
1179 ASSERT_TRUE(PyLong_CheckExact(result));
1180 EXPECT_EQ(PyLong_AsLong(result), 0x4C);
1181}
1182
1183TEST_F(AbstractExtensionApiTest,
1184 PyNumberMatrixMultiplyWithoutDunderMatmulRaisesTypeError) {
1185 PyObjectPtr x(PyFloat_FromDouble(5.0));
1186 PyObjectPtr y(PyLong_FromLong(2));
1187 ASSERT_EQ(PyNumber_MatrixMultiply(x, y), nullptr);
1188 ASSERT_NE(PyErr_Occurred(), nullptr);
1189 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1190}
1191
1192TEST_F(AbstractExtensionApiTest, PyNumberMatrixMultiplyCallsDunderMatmul) {
1193 PyRun_SimpleString(R"(
1194class C:
1195 def __matmul__(self, other):
1196 return other
1197c = C()
1198)");
1199 PyObjectPtr c(mainModuleGet("c"));
1200 PyObjectPtr x(PyLong_FromLong(42));
1201 PyObjectPtr result(PyNumber_MatrixMultiply(c, x));
1202 ASSERT_TRUE(PyLong_CheckExact(result));
1203 ASSERT_EQ(PyLong_AsLong(result), 42);
1204}
1205
1206TEST_F(AbstractExtensionApiTest, PyNumberMultiplyWithIntsReturnsInt) {
1207 PyObjectPtr x(PyLong_FromLong(5));
1208 PyObjectPtr y(PyLong_FromLong(2));
1209 PyObjectPtr result(PyNumber_Multiply(x, y));
1210 ASSERT_TRUE(PyLong_CheckExact(result));
1211 EXPECT_EQ(PyLong_AsLong(result), 10);
1212}
1213
1214TEST_F(AbstractExtensionApiTest, PyNumberMultiplyWithFloatReturnsFloat) {
1215 PyObjectPtr x(PyFloat_FromDouble(5.0));
1216 PyObjectPtr y(PyLong_FromLong(2));
1217 PyObjectPtr result(PyNumber_Multiply(x, y));
1218 ASSERT_TRUE(PyFloat_CheckExact(result));
1219 ASSERT_EQ(PyFloat_AsDouble(result), 10.0);
1220}
1221
1222TEST_F(AbstractExtensionApiTest, PyNumberMultiplyCallsDunderMul) {
1223 PyRun_SimpleString(R"(
1224class C:
1225 def __mul__(self, other):
1226 return other
1227c = C()
1228)");
1229 PyObjectPtr c(mainModuleGet("c"));
1230 PyObjectPtr x(PyLong_FromLong(42));
1231 PyObjectPtr result(PyNumber_Multiply(c, x));
1232 ASSERT_TRUE(PyLong_CheckExact(result));
1233 ASSERT_EQ(PyLong_AsLong(result), 42);
1234}
1235
1236TEST_F(AbstractExtensionApiTest, PyNumberNegativeWithIntReturnsInt) {
1237 PyObjectPtr num(PyLong_FromLong(-22));
1238 PyObjectPtr result(PyNumber_Negative(num));
1239 EXPECT_EQ(PyLong_AsLong(result), 22);
1240}
1241
1242TEST_F(AbstractExtensionApiTest,
1243 PyNumberNegativeWithCustomClassCallsDunderNeg) {
1244 PyRun_SimpleString(R"(
1245class C:
1246 def __neg__(self):
1247 return "custom neg"
1248c = C()
1249)");
1250 PyObjectPtr c(mainModuleGet("c"));
1251 PyObjectPtr result(PyNumber_Negative(c));
1252 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "custom neg"), 0);
1253}
1254
1255TEST_F(AbstractExtensionApiTest, PyNumberNegativeWithNullRaisesSystemError) {
1256 EXPECT_EQ(PyNumber_Negative(nullptr), nullptr);
1257 ASSERT_NE(PyErr_Occurred(), nullptr);
1258 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1259}
1260
1261TEST_F(AbstractExtensionApiTest, PyNumberNegativeWithNonNumberRaisesTypeError) {
1262 EXPECT_EQ(PyNumber_Negative(Py_None), nullptr);
1263 ASSERT_NE(PyErr_Occurred(), nullptr);
1264 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1265}
1266
1267TEST_F(AbstractExtensionApiTest, PyNumberNegativePropagatesException) {
1268 PyRun_SimpleString(R"(
1269class C:
1270 def __neg__(self):
1271 raise UserWarning()
1272c = C()
1273)");
1274 PyObjectPtr c(mainModuleGet("c"));
1275 PyObjectPtr result(PyNumber_Negative(c));
1276 EXPECT_EQ(result, nullptr);
1277 ASSERT_NE(PyErr_Occurred(), nullptr);
1278 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1279}
1280
1281TEST_F(AbstractExtensionApiTest, PyNumberOrWithNonIntRaisesTypeError) {
1282 PyObjectPtr x(PyLong_FromLong(10));
1283 PyObjectPtr y(PyFloat_FromDouble(2.0));
1284 ASSERT_EQ(PyNumber_Or(x, y), nullptr);
1285 ASSERT_NE(PyErr_Occurred(), nullptr);
1286 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1287}
1288
1289TEST_F(AbstractExtensionApiTest, PyNumberOrWithIntsReturnsBitwiseOr) {
1290 PyObjectPtr x(PyLong_FromLong(5)); // 0b0101
1291 PyObjectPtr y(PyLong_FromLong(3)); // 0b0011
1292 PyObjectPtr result(PyNumber_Or(x, y));
1293 ASSERT_TRUE(PyLong_CheckExact(result));
1294 EXPECT_EQ(PyLong_AsLong(result), 7); // 0b0111
1295}
1296
1297TEST_F(AbstractExtensionApiTest, PyNumberPositiveWithIntReturnsInt) {
1298 PyObjectPtr num(PyLong_FromLong(-13));
1299 PyObjectPtr result(PyNumber_Positive(num));
1300 EXPECT_EQ(PyLong_AsLong(result), -13);
1301}
1302
1303TEST_F(AbstractExtensionApiTest,
1304 PyNumberPositiveWithCustomClassCallsDunderPos) {
1305 PyRun_SimpleString(R"(
1306class C:
1307 def __pos__(self):
1308 return "custom pos"
1309c = C()
1310)");
1311 PyObjectPtr c(mainModuleGet("c"));
1312 PyObjectPtr result(PyNumber_Positive(c));
1313 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "custom pos"), 0);
1314}
1315
1316TEST_F(AbstractExtensionApiTest, PyNumberPositiveWithNullRaisesSystemError) {
1317 ASSERT_EQ(PyNumber_Positive(nullptr), nullptr);
1318 ASSERT_NE(PyErr_Occurred(), nullptr);
1319 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1320}
1321
1322TEST_F(AbstractExtensionApiTest, PyNumberPositiveWithNonNumberRaisesTypeError) {
1323 ASSERT_EQ(PyNumber_Positive(Py_None), nullptr);
1324 ASSERT_NE(PyErr_Occurred(), nullptr);
1325 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1326}
1327
1328TEST_F(AbstractExtensionApiTest, PyNumberPositivePropagatesException) {
1329 PyRun_SimpleString(R"(
1330class C:
1331 def __pos__(self):
1332 raise UserWarning()
1333c = C()
1334)");
1335 PyObjectPtr c(mainModuleGet("c"));
1336 PyObjectPtr result(PyNumber_Positive(c));
1337 EXPECT_EQ(result, nullptr);
1338 ASSERT_NE(PyErr_Occurred(), nullptr);
1339 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1340}
1341
1342TEST_F(AbstractExtensionApiTest, PyNumberPowerWithNonNumberRaisesTypeError) {
1343 PyObjectPtr x(PyUnicode_FromString("foo"));
1344 PyObjectPtr y(PyLong_FromLong(2));
1345 ASSERT_EQ(PyNumber_Power(x, y, Py_None), nullptr);
1346 ASSERT_NE(PyErr_Occurred(), nullptr);
1347 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1348}
1349
1350TEST_F(AbstractExtensionApiTest, PyNumberPowerWithFloatReturnsFloat) {
1351 PyObjectPtr x(PyFloat_FromDouble(2.0));
1352 PyObjectPtr y(PyLong_FromLong(3));
1353 PyObjectPtr result(PyNumber_Power(x, y, Py_None));
1354 ASSERT_TRUE(PyFloat_CheckExact(result));
1355 EXPECT_EQ(PyFloat_AsDouble(result), 8.0);
1356}
1357
1358TEST_F(AbstractExtensionApiTest, PyNumberRemainderWithNonIntRaisesTypeError) {
1359 PyObjectPtr x(PyLong_FromLong(10));
1360 ASSERT_EQ(PyNumber_Remainder(x, Py_None), nullptr);
1361 ASSERT_NE(PyErr_Occurred(), nullptr);
1362 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1363}
1364
1365TEST_F(AbstractExtensionApiTest, PyNumberRemainderWithIntsReturnsInt) {
1366 PyObjectPtr x(PyLong_FromLong(10));
1367 PyObjectPtr y(PyLong_FromLong(3));
1368 PyObjectPtr result(PyNumber_Remainder(x, y));
1369 ASSERT_TRUE(PyLong_CheckExact(result));
1370 EXPECT_EQ(PyLong_AsLong(result), 1);
1371}
1372
1373TEST_F(AbstractExtensionApiTest, PyNumberRshiftWithNonIntSelfRaisesTypeError) {
1374 PyObjectPtr x(PyFloat_FromDouble(5.0));
1375 PyObjectPtr y(PyLong_FromLong(2));
1376 ASSERT_EQ(PyNumber_Rshift(x, y), nullptr);
1377 ASSERT_NE(PyErr_Occurred(), nullptr);
1378 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1379}
1380
1381TEST_F(AbstractExtensionApiTest, PyNumberRshiftWithNonIntOtherRaisesTypeError) {
1382 PyObjectPtr x(PyLong_FromLong(5));
1383 PyObjectPtr y(PyFloat_FromDouble(2.0));
1384 ASSERT_EQ(PyNumber_Rshift(x, y), nullptr);
1385 ASSERT_NE(PyErr_Occurred(), nullptr);
1386 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1387}
1388
1389TEST_F(AbstractExtensionApiTest, PyNumberRshiftWithIntsShiftBitsRight) {
1390 PyObjectPtr x(PyLong_FromLong(0x4C));
1391 PyObjectPtr y(PyLong_FromLong(2));
1392 PyObjectPtr result(PyNumber_Rshift(x, y));
1393 ASSERT_TRUE(PyLong_CheckExact(result));
1394 EXPECT_EQ(PyLong_AsLong(result), 0x13);
1395}
1396
1397TEST_F(AbstractExtensionApiTest,
1398 PyNumberSubtractWithoutDunderSubtractRaisesTypeError) {
1399 PyObjectPtr x(PyUnicode_FromString("foo"));
1400 PyObjectPtr y(PyLong_FromLong(2));
1401 ASSERT_EQ(PyNumber_Subtract(x, y), nullptr);
1402 ASSERT_NE(PyErr_Occurred(), nullptr);
1403 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1404}
1405
1406TEST_F(AbstractExtensionApiTest, PyNumberSubtractCallsDunderSub) {
1407 PyRun_SimpleString(R"(
1408class C:
1409 def __sub__(self, other):
1410 return other
1411c = C()
1412)");
1413 PyObjectPtr c(mainModuleGet("c"));
1414 PyObjectPtr x(PyLong_FromLong(42));
1415 PyObjectPtr result(PyNumber_Subtract(c, x));
1416 ASSERT_TRUE(PyLong_CheckExact(result));
1417 EXPECT_EQ(PyLong_AsLong(result), 42);
1418}
1419
1420TEST_F(AbstractExtensionApiTest, PyNumberSubtractWithFloatReturnsFloat) {
1421 PyObjectPtr x(PyLong_FromLong(10));
1422 PyObjectPtr y(PyFloat_FromDouble(2.0));
1423 PyObjectPtr result(PyNumber_Subtract(x, y));
1424 ASSERT_TRUE(PyFloat_CheckExact(result));
1425 EXPECT_EQ(PyFloat_AsDouble(result), 8.0);
1426
1427 PyObjectPtr result2(PyNumber_Subtract(y, x));
1428 ASSERT_TRUE(PyFloat_CheckExact(result2));
1429 EXPECT_EQ(PyFloat_AsDouble(result2), -8.0);
1430}
1431
1432TEST_F(AbstractExtensionApiTest, PyNumberSubtractWithIntsReturnsInt) {
1433 PyObjectPtr x(PyLong_FromLong(10));
1434 PyObjectPtr y(PyLong_FromLong(2));
1435 PyObjectPtr result(PyNumber_Subtract(x, y));
1436 ASSERT_TRUE(PyLong_CheckExact(result));
1437 EXPECT_EQ(PyLong_AsLong(result), 8);
1438}
1439
1440TEST_F(AbstractExtensionApiTest, PyNumberToBaseWithBinaryFormatsAsBinary) {
1441 PyObjectPtr x(PyLong_FromLong(10)); // 0b1010
1442 PyObjectPtr result(PyNumber_ToBase(x, 2));
1443 EXPECT_EQ(PyErr_Occurred(), nullptr);
1444 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "0b1010"), 0);
1445}
1446
1447TEST_F(AbstractExtensionApiTest, PyNumberToBaseWithOctalFormatsAsOctal) {
1448 PyObjectPtr x(PyLong_FromLong(520)); // 0o1010
1449 PyObjectPtr result(PyNumber_ToBase(x, 8));
1450 EXPECT_EQ(PyErr_Occurred(), nullptr);
1451 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "0o1010"), 0);
1452}
1453
1454TEST_F(AbstractExtensionApiTest, PyNumberToBaseWithDecimalFormatsAsDecimal) {
1455 PyObjectPtr x(PyLong_FromLong(12345));
1456 PyObjectPtr result(PyNumber_ToBase(x, 10));
1457 EXPECT_EQ(PyErr_Occurred(), nullptr);
1458 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "12345"), 0);
1459}
1460
1461TEST_F(AbstractExtensionApiTest, PyNumberToBaseWithHexFormatsAsHex) {
1462 PyObjectPtr x(PyLong_FromLong(0xdeadbeef));
1463 PyObjectPtr result(PyNumber_ToBase(x, 16));
1464 EXPECT_EQ(PyErr_Occurred(), nullptr);
1465 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "0xdeadbeef"), 0);
1466}
1467
1468TEST_F(AbstractExtensionApiTest, PyNumberToBaseSupportsIndex) {
1469 PyRun_SimpleString(R"(
1470class C:
1471 def __index__(self):
1472 return 42
1473c = C()
1474)");
1475 PyObjectPtr c(mainModuleGet("c"));
1476 PyObjectPtr result(PyNumber_ToBase(c, 8));
1477 EXPECT_EQ(PyErr_Occurred(), nullptr);
1478 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "0o52"), 0);
1479}
1480
1481TEST_F(AbstractExtensionApiTest, PyNumberToBasePropagatesIndexException) {
1482 PyRun_SimpleString(R"(
1483class C:
1484 def __index__(self):
1485 raise ValueError
1486c = C()
1487)");
1488 PyObjectPtr c(mainModuleGet("c"));
1489 PyObjectPtr result(PyNumber_ToBase(c, 8));
1490 ASSERT_NE(PyErr_Occurred(), nullptr);
1491 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
1492 EXPECT_EQ(result, nullptr);
1493}
1494
1495TEST_F(AbstractExtensionApiTest, PyNumberToBaseSupportsIntSubclass) {
1496 PyRun_SimpleString(R"(
1497class C(int):
1498 pass
1499c = C(33)
1500)");
1501 PyObjectPtr c(mainModuleGet("c"));
1502 PyObjectPtr result(PyNumber_ToBase(c, 16));
1503 EXPECT_EQ(PyErr_Occurred(), nullptr);
1504 EXPECT_EQ(PyUnicode_CompareWithASCIIString(result, "0x21"), 0);
1505}
1506
1507TEST_F(AbstractExtensionApiTest, PyNumberToBaseWithInvalidBaseRaises) {
1508 PyObjectPtr x(PyLong_FromLong(0xdeadbeef));
1509 PyObjectPtr result(PyNumber_ToBase(x, 15));
1510 ASSERT_NE(PyErr_Occurred(), nullptr);
1511 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1512 EXPECT_EQ(result, nullptr);
1513}
1514
1515TEST_F(AbstractExtensionApiTest, PyNumberTrueDivideWithNonIntRaisesTypeError) {
1516 PyObjectPtr x(PyUnicode_FromString("foo"));
1517 PyObjectPtr y(PyLong_FromLong(2));
1518 ASSERT_EQ(PyNumber_TrueDivide(x, y), nullptr);
1519 ASSERT_NE(PyErr_Occurred(), nullptr);
1520 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1521}
1522
1523TEST_F(AbstractExtensionApiTest, PyNumberTrueDivideCallsDunderTruediv) {
1524 PyRun_SimpleString(R"(
1525class C:
1526 def __truediv__(self, other):
1527 return other
1528c = C()
1529)");
1530 PyObjectPtr c(mainModuleGet("c"));
1531 PyObjectPtr x(PyLong_FromLong(42));
1532 PyObjectPtr result(PyNumber_TrueDivide(c, x));
1533 ASSERT_TRUE(PyLong_CheckExact(result));
1534 EXPECT_EQ(PyLong_AsLong(result), 42);
1535}
1536
1537TEST_F(AbstractExtensionApiTest, PyNumberTrueDivideWithIntsReturnsFloat) {
1538 PyObjectPtr x(PyLong_FromLong(42));
1539 PyObjectPtr y(PyLong_FromLong(5));
1540 PyObjectPtr result(PyNumber_TrueDivide(x, y));
1541 ASSERT_TRUE(PyFloat_CheckExact(result));
1542 EXPECT_EQ(PyFloat_AsDouble(result), 8.4);
1543}
1544
1545TEST_F(AbstractExtensionApiTest, PyNumberTrueDivideWithFloatReturnsFloat) {
1546 PyObjectPtr a(PyFloat_FromDouble(42.0));
1547 PyObjectPtr b(PyLong_FromLong(5));
1548 PyObjectPtr result1(PyNumber_TrueDivide(a, b));
1549 ASSERT_TRUE(PyFloat_CheckExact(result1));
1550 EXPECT_EQ(PyFloat_AsDouble(result1), 8.4);
1551
1552 PyObjectPtr x(PyLong_FromLong(42));
1553 PyObjectPtr y(PyFloat_FromDouble(5.0));
1554 PyObjectPtr result2(PyNumber_TrueDivide(x, y));
1555 ASSERT_TRUE(PyFloat_CheckExact(result2));
1556 EXPECT_EQ(PyFloat_AsDouble(result2), 8.4);
1557}
1558
1559TEST_F(AbstractExtensionApiTest, PyNumberXorWithNonIntRaisesTypeError) {
1560 PyObjectPtr x(PyFloat_FromDouble(5.0));
1561 PyObjectPtr y(PyLong_FromLong(3));
1562 ASSERT_EQ(PyNumber_Xor(x, y), nullptr);
1563 ASSERT_NE(PyErr_Occurred(), nullptr);
1564 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1565}
1566
1567TEST_F(AbstractExtensionApiTest, PyNumberXorWithIntsReturnsBitwiseOr) {
1568 PyObjectPtr v(PyLong_FromLong(5)); // 0b0101
1569 PyObjectPtr w(PyLong_FromLong(3)); // 0b0011
1570 PyObjectPtr result(PyNumber_Xor(v, w));
1571 ASSERT_TRUE(PyLong_CheckExact(result));
1572 EXPECT_EQ(PyLong_AsLong(result), 6); // 0b0110
1573}
1574
1575// Object Protocol
1576
1577TEST_F(AbstractExtensionApiTest, PyObjectCallWithArgsCalls) {
1578 PyRun_SimpleString(R"(
1579def func(*args, **kwargs):
1580 return f"{args!r}{kwargs!r}"
1581)");
1582 PyObjectPtr func(mainModuleGet("func"));
1583 PyObjectPtr tup0(PyUnicode_FromString("one"));
1584 PyObjectPtr tup1(PyLong_FromLong(2));
1585 PyObjectPtr tup2(PyLong_FromLong(3));
1586 PyObjectPtr args(PyTuple_Pack(3, tup0.get(), tup1.get(), tup2.get()));
1587 PyObjectPtr result(PyObject_Call(func, args, nullptr));
1588 EXPECT_TRUE(isUnicodeEqualsCStr(result, "('one', 2, 3){}"));
1589}
1590
1591TEST_F(AbstractExtensionApiTest, PyObjectCallWithArgsAndKwargsCalls) {
1592 PyRun_SimpleString(R"(
1593def func(*args, **kwargs):
1594 return f"{args!r}{kwargs!r}"
1595)");
1596 PyObjectPtr func(mainModuleGet("func"));
1597 PyObjectPtr tup0(PyLong_FromLong(1));
1598 PyObjectPtr tup1(PyLong_FromLong(2));
1599 PyObjectPtr tup2(PyUnicode_FromString("three"));
1600 PyObjectPtr args(PyTuple_Pack(3, tup0.get(), tup1.get(), tup2.get()));
1601 PyObjectPtr kwargs(PyDict_New());
1602 PyObjectPtr kwarg_name(PyUnicode_FromString("kwarg"));
1603 PyObjectPtr kwarg_val(PyLong_FromLong(4));
1604 PyDict_SetItem(kwargs, kwarg_name, kwarg_val);
1605 PyObjectPtr result(PyObject_Call(func, args, kwargs));
1606 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(1, 2, 'three'){'kwarg': 4}"));
1607}
1608
1609TEST_F(AbstractExtensionApiTest, PyObjectCallPropagatesException) {
1610 PyRun_SimpleString(R"(
1611def func(*args, **kwargs):
1612 raise UserWarning()
1613)");
1614 PyObjectPtr func(mainModuleGet("func"));
1615 PyObjectPtr args(PyTuple_New(0));
1616 PyObjectPtr result(PyObject_Call(func, args, nullptr));
1617 EXPECT_EQ(result, nullptr);
1618 ASSERT_NE(PyErr_Occurred(), nullptr);
1619 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1620}
1621
1622TEST_F(AbstractExtensionApiTest, PyObjectCallWithCallableOfNativeType) {
1623 ternaryfunc meth = [](PyObject*, PyObject*, PyObject*) {
1624 return PyUnicode_FromString("from_tp_call");
1625 };
1626 static const PyType_Slot slots[] = {
1627 {Py_tp_call, reinterpret_cast<void*>(meth)},
1628 {0, nullptr},
1629 };
1630 static PyType_Spec spec = {
1631 "__main__.Bar",
1632 0,
1633 0,
1634 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
1635 const_cast<PyType_Slot*>(slots),
1636 };
1637 PyObjectPtr type(PyType_FromSpec(&spec));
1638 moduleSet("__main__", "Bar", type);
1639
1640 PyRun_SimpleString(R"(
1641b = Bar()
1642)");
1643
1644 PyObjectPtr func(mainModuleGet("b"));
1645 PyObjectPtr args(PyTuple_New(0));
1646 PyObjectPtr result(PyObject_Call(func, args, nullptr));
1647 EXPECT_TRUE(isUnicodeEqualsCStr(result, "from_tp_call"));
1648}
1649
1650TEST_F(AbstractExtensionApiTest, PyObjectCallFunctionCalls) {
1651 PyRun_SimpleString(R"(
1652def func(*args):
1653 return f"{args!r}"
1654)");
1655 PyObjectPtr func(mainModuleGet("func"));
1656 PyObjectPtr result(
1657 PyObject_CallFunction(func, "(iI)s#i", 3, 7, "aaaa", 3, 99));
1658 EXPECT_TRUE(isUnicodeEqualsCStr(result, "((3, 7), 'aaa', 99)"));
1659}
1660
1661TEST_F(AbstractExtensionApiTest, PyObjectCallFunctionWithTypeAndTupleCalls) {
1662 PyObjectPtr result(
1663 PyObject_CallFunction(reinterpret_cast<PyObject*>(&PyList_Type),
1664 "((ss#i))", "bce", "aaaa", 3, 99));
1665 EXPECT_TRUE(PyList_CheckExact(result));
1666 EXPECT_EQ(PyList_Size(result), 3);
1667 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "bce"));
1668 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "aaa"));
1669 EXPECT_TRUE(isLongEqualsLong(PyList_GetItem(result, 2), 99));
1670}
1671
1672TEST_F(AbstractExtensionApiTest, PyObjectCallFunctionWithTypeAndListCalls) {
1673 PyObjectPtr result(
1674 PyObject_CallFunction(reinterpret_cast<PyObject*>(&PyList_Type), "[ss#i]",
1675 "bce", "aaaa", 3, 99));
1676 EXPECT_TRUE(PyList_CheckExact(result));
1677 EXPECT_EQ(PyList_Size(result), 3);
1678 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "bce"));
1679 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "aaa"));
1680 EXPECT_TRUE(isLongEqualsLong(PyList_GetItem(result, 2), 99));
1681}
1682
1683TEST_F(AbstractExtensionApiTest,
1684 PyObjectCallFunctionWithNonCallableRaisesTypeError) {
1685 PyObjectPtr result(PyObject_CallFunction(Py_None, nullptr));
1686 EXPECT_EQ(result, nullptr);
1687 ASSERT_NE(PyErr_Occurred(), nullptr);
1688 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1689}
1690
1691TEST_F(AbstractExtensionApiTest, PyObjectCallFunctionPropagatesException) {
1692 PyRun_SimpleString(R"(
1693def func():
1694 raise UserWarning()
1695)");
1696 PyObjectPtr func(mainModuleGet("func"));
1697 PyObjectPtr result(PyObject_CallFunction(func, nullptr));
1698 EXPECT_EQ(result, nullptr);
1699 ASSERT_NE(PyErr_Occurred(), nullptr);
1700 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1701}
1702
1703TEST_F(AbstractExtensionApiTest, PyObjectCallFunctionSizeTCalls) {
1704 PyRun_SimpleString(R"(
1705def func(*args):
1706 return f"{args!r}"
1707)");
1708 PyObjectPtr func(mainModuleGet("func"));
1709 PyObjectPtr result(
1710 PyObject_CallFunction(func, "is#i", 7, "bbb", Py_ssize_t{2}, 14));
1711 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(7, 'bb', 14)"));
1712}
1713
1714TEST_F(AbstractExtensionApiTest, PyObjectCallMethodWithEmptyTuplePassesNoArgs) {
1715 PyRun_SimpleString(R"(
1716class C:
1717 def func(self, *arg):
1718 return f"{self.__class__.__name__} {arg}"
1719instance = C()
1720)");
1721 PyObjectPtr instance(mainModuleGet("instance"));
1722 PyObjectPtr result(PyObject_CallMethod(instance, "func", "()"));
1723 EXPECT_TRUE(isUnicodeEqualsCStr(result, "C ()"));
1724}
1725
1726TEST_F(AbstractExtensionApiTest, PyObjectCallMethodWithIntTuplePassesTwoInts) {
1727 PyRun_SimpleString(R"(
1728class C:
1729 def func(self, *arg):
1730 return f"{self.__class__.__name__} {arg}"
1731instance = C()
1732)");
1733 PyObjectPtr instance(mainModuleGet("instance"));
1734 PyObjectPtr result(PyObject_CallMethod(instance, "func", "(ii)", 5, 10));
1735 EXPECT_TRUE(isUnicodeEqualsCStr(result, "C (5, 10)"));
1736}
1737
1738TEST_F(AbstractExtensionApiTest,
1739 PyObjectCallMethodWithTupleAndIntPassesTwoArgs) {
1740 PyRun_SimpleString(R"(
1741class C:
1742 def func(self, *arg):
1743 return f"{self.__class__.__name__} {arg}"
1744instance = C()
1745)");
1746 PyObjectPtr instance(mainModuleGet("instance"));
1747 PyObjectPtr result(PyObject_CallMethod(instance, "func", "()i", 10));
1748 EXPECT_TRUE(isUnicodeEqualsCStr(result, "C ((), 10)"));
1749}
1750
1751TEST_F(AbstractExtensionApiTest, PyObjectCallMethodCalls) {
1752 PyRun_SimpleString(R"(
1753class C:
1754 x = 42
1755 def func(self, *args):
1756 return f"{self.x}{args!r}"
1757c = C()
1758)");
1759 PyObjectPtr c(mainModuleGet("c"));
1760 PyObjectPtr result(PyObject_CallMethod(c, "func", "s#(i)", "ccc", 1, 7));
1761 EXPECT_TRUE(isUnicodeEqualsCStr(result, "42('c', (7,))"));
1762}
1763
1764TEST_F(AbstractExtensionApiTest,
1765 PyObjectCallMethodWithNonExistentMemberRaisesAttributeError) {
1766 PyObjectPtr result(PyObject_CallMethod(Py_None, "foo", nullptr));
1767 EXPECT_EQ(result, nullptr);
1768 ASSERT_NE(PyErr_Occurred(), nullptr);
1769 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError));
1770}
1771
1772TEST_F(AbstractExtensionApiTest, PyObjectCallMethodPropagatesException) {
1773 PyRun_SimpleString(R"(
1774class C:
1775 def func(self):
1776 raise UserWarning()
1777c = C()
1778)");
1779 PyObjectPtr c(mainModuleGet("c"));
1780 PyObjectPtr result(PyObject_CallMethod(c, "func", nullptr));
1781 EXPECT_EQ(result, nullptr);
1782 ASSERT_NE(PyErr_Occurred(), nullptr);
1783 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
1784}
1785
1786TEST_F(AbstractExtensionApiTest, PyObjectCallMethodObjArgsCalls) {
1787 PyRun_SimpleString(R"(
1788class C:
1789 x = 23
1790 def func(self, *args):
1791 return f"{self.x}{args!r}"
1792c = C()
1793)");
1794 PyObjectPtr c(mainModuleGet("c"));
1795 PyObjectPtr name(PyUnicode_FromString("func"));
1796 PyObjectPtr arg0(PyLong_FromLong(-13));
1797 PyObjectPtr arg1(PyUnicode_FromString("zzz"));
1798 PyObjectPtr result(
1799 PyObject_CallMethodObjArgs(c, name, arg0.get(), arg1.get(), nullptr));
1800 EXPECT_TRUE(isUnicodeEqualsCStr(result, "23(-13, 'zzz')"));
1801}
1802
1803TEST_F(AbstractExtensionApiTest,
1804 PyObjectCallMethodObjArgsWithNullObjectRaisesSystemError) {
1805 PyObjectPtr name(PyUnicode_FromString("func"));
1806 PyObjectPtr result(PyObject_CallMethodObjArgs(nullptr, name));
1807 ASSERT_EQ(result, nullptr);
1808 ASSERT_NE(PyErr_Occurred(), nullptr);
1809 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1810}
1811
1812TEST_F(AbstractExtensionApiTest,
1813 PyObjectCallMethodObjArgsWithNullMethodNameRaisesSystemError) {
1814 PyObjectPtr result(PyObject_CallMethodObjArgs(Py_None, nullptr));
1815 ASSERT_EQ(result, nullptr);
1816 ASSERT_NE(PyErr_Occurred(), nullptr);
1817 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1818}
1819
1820TEST_F(AbstractExtensionApiTest, PyObjectCallMethodSizeTCalls) {
1821 PyRun_SimpleString(R"(
1822class C:
1823 x = -5
1824 def func(self, *args):
1825 return f"{self.x}{args!r}"
1826c = C()
1827)");
1828 PyObjectPtr c(mainModuleGet("c"));
1829 PyObjectPtr result(_PyObject_CallMethod_SizeT(c, "func", "is#i", 9, "ddd",
1830 Py_ssize_t{2}, 8));
1831 EXPECT_TRUE(isUnicodeEqualsCStr(result, "-5(9, 'dd', 8)"));
1832}
1833
1834TEST_F(AbstractExtensionApiTest, PyObjectCallObjectCalls) {
1835 PyRun_SimpleString(R"(
1836class C:
1837 x = 9
1838 def __call__(self, *args):
1839 return f"{self.x}{args!r}"
1840c = C()
1841)");
1842 PyObjectPtr c(mainModuleGet("c"));
1843 PyObjectPtr one(PyLong_FromLong(1));
1844 PyObjectPtr two(PyUnicode_FromString("two"));
1845 PyObjectPtr three(PyLong_FromLong(3));
1846 PyObjectPtr args(PyTuple_Pack(3, one.get(), two.get(), three.get()));
1847 PyObjectPtr result(PyObject_CallObject(c, args));
1848 EXPECT_TRUE(isUnicodeEqualsCStr(result, "9(1, 'two', 3)"));
1849}
1850
1851TEST_F(AbstractExtensionApiTest, PyObjectCallObjectWithArgsNullptrCalls) {
1852 PyRun_SimpleString(R"(
1853def func(*args, **kwargs):
1854 return f"{args!r}{kwargs!r}"
1855)");
1856 PyObjectPtr func(mainModuleGet("func"));
1857 PyObjectPtr result(PyObject_CallObject(func, nullptr));
1858 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(){}"));
1859}
1860
1861TEST_F(AbstractExtensionApiTest, PyObjCallFunctionObjArgsWithNullReturnsNull) {
1862 testing::PyObjectPtr test(PyObject_CallFunctionObjArgs(nullptr, nullptr));
1863 EXPECT_EQ(nullptr, test);
1864 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
1865}
1866
1867TEST_F(AbstractExtensionApiTest,
1868 PyObjCallFunctionObjArgsWithNonFunctionReturnsNull) {
1869 testing::PyObjectPtr non_func(PyTuple_New(0));
1870 testing::PyObjectPtr test(PyObject_CallFunctionObjArgs(non_func, nullptr));
1871 EXPECT_EQ(test, nullptr);
1872 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
1873}
1874
1875TEST_F(AbstractExtensionApiTest, PyObjectGetBufferWithBytesReturnsBuffer) {
1876 Py_buffer buffer;
1877 PyObjectPtr bytes(PyBytes_FromStringAndSize("hello\0world", 11));
1878 Py_ssize_t old_refcnt = Py_REFCNT(bytes);
1879 int result = PyObject_GetBuffer(bytes, &buffer, 0);
1880 EXPECT_EQ(Py_REFCNT(bytes), old_refcnt + 1);
1881 ASSERT_EQ(buffer.len, 11);
1882 EXPECT_EQ(std::memcmp(buffer.buf, "hello\0world", 11), 0);
1883 ASSERT_EQ(result, 0);
1884 PyBuffer_Release(&buffer);
1885 EXPECT_EQ(PyErr_Occurred(), nullptr);
1886 EXPECT_EQ(buffer.obj, nullptr);
1887 EXPECT_EQ(Py_REFCNT(bytes), old_refcnt);
1888}
1889
1890TEST_F(AbstractExtensionApiTest, PyObjectGetBufferWithByteArrayReturnsBuffer) {
1891 Py_buffer buffer;
1892 PyObjectPtr bytearray(PyByteArray_FromStringAndSize("hello\0world", 11));
1893 Py_ssize_t old_refcnt = Py_REFCNT(bytearray);
1894 int result = PyObject_GetBuffer(bytearray, &buffer, 0);
1895 EXPECT_EQ(Py_REFCNT(bytearray), old_refcnt + 1);
1896 ASSERT_EQ(buffer.len, 11);
1897 EXPECT_EQ(std::memcmp(buffer.buf, "hello\0world", 11), 0);
1898 ASSERT_EQ(result, 0);
1899 PyBuffer_Release(&buffer);
1900 EXPECT_EQ(PyErr_Occurred(), nullptr);
1901 EXPECT_EQ(buffer.obj, nullptr);
1902 EXPECT_EQ(Py_REFCNT(bytearray), old_refcnt);
1903}
1904
1905TEST_F(AbstractExtensionApiTest,
1906 PyObjectGetBufferWithBufferProtocolObjectReturnsBuffer) {
1907 static char contents[] = "hello world";
1908 static Py_ssize_t contents_len = std::strlen(contents);
1909 getbufferproc getbuffer_func = [](PyObject* obj, Py_buffer* view, int flags) {
1910 return PyBuffer_FillInfo(view, obj, strdup(contents), contents_len,
1911 /*readonly=*/1, flags);
1912 };
1913 releasebufferproc releasebuffer_func = [](PyObject*, Py_buffer* view) {
1914 std::free(view->buf);
1915 view->obj = nullptr;
1916 };
1917 PyType_Slot slots[] = {
1918 {Py_bf_getbuffer, reinterpret_cast<void*>(getbuffer_func)},
1919 {Py_bf_releasebuffer, reinterpret_cast<void*>(releasebuffer_func)},
1920 {0, nullptr},
1921 };
1922 static PyType_Spec spec;
1923 spec = {
1924 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots,
1925 };
1926 PyObjectPtr type(PyType_FromSpec(&spec));
1927 PyObjectPtr instance(PyObject_CallFunction(type, nullptr));
1928
1929 Py_buffer buffer;
1930 Py_ssize_t old_refcnt = Py_REFCNT(instance);
1931 int result = PyObject_GetBuffer(instance, &buffer, 0);
1932 EXPECT_EQ(Py_REFCNT(instance), old_refcnt + 1);
1933 ASSERT_EQ(buffer.len, contents_len);
1934 EXPECT_NE(buffer.buf, contents);
1935 EXPECT_EQ(std::memcmp(buffer.buf, contents, contents_len), 0);
1936 ASSERT_EQ(result, 0);
1937 PyBuffer_Release(&buffer);
1938 EXPECT_EQ(PyErr_Occurred(), nullptr);
1939 EXPECT_EQ(buffer.obj, nullptr);
1940 EXPECT_EQ(Py_REFCNT(instance), old_refcnt);
1941}
1942
1943TEST_F(AbstractExtensionApiTest,
1944 PyObjectGetBufferWithBytesMemoryViewReturnsBuffer) {
1945 Py_buffer buffer;
1946 PyObjectPtr bytes(PyBytes_FromStringAndSize("hello\0world", 11));
1947 PyObjectPtr memoryview(PyMemoryView_FromObject(bytes));
1948 Py_ssize_t old_memoryview_refcnt = Py_REFCNT(memoryview);
1949 Py_ssize_t old_bytes_refcnt = Py_REFCNT(bytes);
1950
1951 ASSERT_EQ(PyObject_GetBuffer(memoryview, &buffer, 0), 0);
1952
1953 // Getting the underlying buffer increments references to the underlying
1954 // buffer, not the memoryview object itself.
1955 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt + 1);
1956 EXPECT_EQ(Py_REFCNT(bytes), old_bytes_refcnt);
1957 ASSERT_EQ(buffer.len, 11);
1958 EXPECT_EQ(std::memcmp(buffer.buf, "hello\0world", 11), 0);
1959
1960 PyBuffer_Release(&buffer);
1961 EXPECT_EQ(PyErr_Occurred(), nullptr);
1962 EXPECT_EQ(buffer.obj, nullptr);
1963 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt);
1964 EXPECT_EQ(Py_REFCNT(bytes), old_bytes_refcnt);
1965}
1966
1967TEST_F(AbstractExtensionApiTest,
1968 PyObjectGetBufferWithBytearrayMemoryViewReturnsBuffer) {
1969 Py_buffer buffer;
1970 PyObjectPtr bytearray(PyByteArray_FromStringAndSize("hello\0world", 11));
1971 PyObjectPtr memoryview_unsliced(PyMemoryView_FromObject(bytearray));
1972 PyObjectPtr memoryview(PySequence_GetSlice(memoryview_unsliced, 0, 10));
1973 Py_ssize_t old_memoryview_refcnt = Py_REFCNT(memoryview);
1974 Py_ssize_t old_bytearray_refcnt = Py_REFCNT(bytearray);
1975
1976 ASSERT_EQ(PyObject_GetBuffer(memoryview, &buffer, 0), 0);
1977
1978 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt + 1);
1979 EXPECT_EQ(Py_REFCNT(bytearray), old_bytearray_refcnt);
1980 ASSERT_EQ(buffer.len, 10);
1981 EXPECT_EQ(std::memcmp(buffer.buf, "hello\0worl", 10), 0);
1982
1983 PyBuffer_Release(&buffer);
1984 EXPECT_EQ(PyErr_Occurred(), nullptr);
1985 EXPECT_EQ(buffer.obj, nullptr);
1986 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt);
1987 EXPECT_EQ(Py_REFCNT(bytearray), old_bytearray_refcnt);
1988}
1989
1990TEST_F(AbstractExtensionApiTest,
1991 PyObjectGetBufferWithFromMemoryMemoryViewReturnsBuffer) {
1992 char memory[6] = "hello";
1993 PyObjectPtr memoryview(
1994 PyMemoryView_FromMemory(reinterpret_cast<char*>(memory), 6, PyBUF_READ));
1995 Py_ssize_t old_memoryview_refcnt = Py_REFCNT(memoryview);
1996 Py_buffer buffer;
1997 EXPECT_EQ(PyObject_GetBuffer(memoryview, &buffer, 0), 0);
1998
1999 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt + 1);
2000 ASSERT_EQ(buffer.len, 6);
2001 EXPECT_EQ(std::memcmp(buffer.buf, "hello", 6), 0);
2002
2003 PyBuffer_Release(&buffer);
2004 EXPECT_EQ(PyErr_Occurred(), nullptr);
2005 EXPECT_EQ(buffer.obj, nullptr);
2006 EXPECT_EQ(Py_REFCNT(memoryview), old_memoryview_refcnt);
2007}
2008
2009TEST_F(AbstractExtensionApiTest,
2010 PyObjectGetBufferWithByteFormattedArrayReturnsBuffer) {
2011 PyRun_SimpleString(R"(
2012import array
2013result = array.array('b', b'hello')
2014)");
2015 PyObjectPtr array(mainModuleGet("result"));
2016 Py_ssize_t old_array_refcnt = Py_REFCNT(array);
2017
2018 Py_buffer buffer;
2019 EXPECT_EQ(PyObject_GetBuffer(array, &buffer, 0), 0);
2020
2021 EXPECT_EQ(Py_REFCNT(array), old_array_refcnt + 1);
2022 ASSERT_EQ(buffer.len, 5);
2023 EXPECT_EQ(std::memcmp(buffer.buf, "hello", 5), 0);
2024
2025 PyBuffer_Release(&buffer);
2026 EXPECT_EQ(buffer.obj, nullptr);
2027 EXPECT_EQ(Py_REFCNT(array), old_array_refcnt);
2028}
2029
2030TEST_F(AbstractExtensionApiTest, PyObjectGetBufferWithQuadArrayReturnsBuffer) {
2031 PyRun_SimpleString(R"(
2032import array
2033result = array.array('Q')
2034result.append(0xdeadbeef12345678)
2035)");
2036 PyObjectPtr array(mainModuleGet("result"));
2037 Py_ssize_t old_array_refcnt = Py_REFCNT(array);
2038
2039 Py_buffer buffer;
2040 EXPECT_EQ(PyObject_GetBuffer(array, &buffer, 0), 0);
2041
2042 EXPECT_EQ(Py_REFCNT(array), old_array_refcnt + 1);
2043 char* underlying_buffer = reinterpret_cast<char*>(buffer.buf);
2044 ASSERT_EQ(buffer.len, 8);
2045 EXPECT_EQ(underlying_buffer[0], '\x78');
2046 EXPECT_EQ(underlying_buffer[1], '\x56');
2047 EXPECT_EQ(underlying_buffer[2], '\x34');
2048 EXPECT_EQ(underlying_buffer[3], '\x12');
2049 EXPECT_EQ(underlying_buffer[4], '\xef');
2050 EXPECT_EQ(underlying_buffer[5], '\xbe');
2051 EXPECT_EQ(underlying_buffer[6], '\xad');
2052 EXPECT_EQ(underlying_buffer[7], '\xde');
2053
2054 PyBuffer_Release(&buffer);
2055 EXPECT_EQ(buffer.obj, nullptr);
2056 EXPECT_EQ(Py_REFCNT(array), old_array_refcnt);
2057}
2058
2059TEST_F(AbstractExtensionApiTest,
2060 PyObjectGetBufferWithNonBufferExtensionObjectRaisesTypeError) {
2061 PyType_Slot slots[] = {
2062 {0, nullptr},
2063 };
2064 static PyType_Spec spec;
2065 spec = {
2066 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots,
2067 };
2068 PyObjectPtr type(PyType_FromSpec(&spec));
2069 PyObjectPtr instance(PyObject_CallFunction(type, nullptr));
2070 Py_buffer buffer;
2071 EXPECT_EQ(PyObject_GetBuffer(instance, &buffer, 0), -1);
2072 EXPECT_NE(PyErr_Occurred(), nullptr);
2073 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2074}
2075
2076TEST_F(AbstractExtensionApiTest,
2077 PyObjectGetBufferWithNonBufferManagedObjectRaisesTypeError) {
2078 PyRun_SimpleString(R"(
2079class C:
2080 pass
2081instance = C()
2082)");
2083 Py_buffer buffer;
2084 PyObjectPtr instance(mainModuleGet("instance"));
2085 EXPECT_EQ(PyObject_GetBuffer(instance, &buffer, 0), -1);
2086 EXPECT_NE(PyErr_Occurred(), nullptr);
2087 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2088}
2089
2090TEST_F(AbstractExtensionApiTest,
2091 PyObjectGetBufferWithNonBufferBuiltinTypeRaisesTypeError) {
2092 Py_buffer buffer;
2093 PyObjectPtr instance(PyLong_FromLong(42));
2094 EXPECT_EQ(PyObject_GetBuffer(instance, &buffer, 0), -1);
2095 EXPECT_NE(PyErr_Occurred(), nullptr);
2096 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2097}
2098
2099TEST_F(AbstractExtensionApiTest, CallFunctionObjArgsWithNoArgsReturnsValue) {
2100 PyRun_SimpleString(R"(
2101def func():
2102 return 5
2103 )");
2104
2105 testing::PyObjectPtr func(testing::mainModuleGet("func"));
2106 testing::PyObjectPtr func_result(PyObject_CallFunctionObjArgs(func, nullptr));
2107 EXPECT_EQ(PyLong_AsLong(func_result), 5);
2108 EXPECT_EQ(PyErr_Occurred(), nullptr);
2109}
2110
2111TEST_F(AbstractExtensionApiTest,
2112 CallFunctionObjArgsWithCallableClassReturnsValue) {
2113 PyRun_SimpleString(R"(
2114class Foo():
2115 def __call__(self):
2116 return 5
2117f = Foo()
2118 )");
2119
2120 testing::PyObjectPtr f(testing::mainModuleGet("f"));
2121 testing::PyObjectPtr f_result(PyObject_CallFunctionObjArgs(f, nullptr));
2122 EXPECT_EQ(PyLong_AsLong(f_result), 5);
2123 EXPECT_EQ(PyErr_Occurred(), nullptr);
2124}
2125
2126TEST_F(AbstractExtensionApiTest,
2127 CallFunctionObjArgsWithManyArgumentsReturnsValue) {
2128 PyRun_SimpleString(R"(
2129def func(a, b, c, d, e, f):
2130 return a + b + c + d + e + f
2131 )");
2132
2133 testing::PyObjectPtr func(testing::mainModuleGet("func"));
2134 PyObject* one = PyLong_FromLong(1);
2135 PyObject* two = PyLong_FromLong(2);
2136 testing::PyObjectPtr func_result(PyObject_CallFunctionObjArgs(
2137 func, one, one, two, two, one, two, nullptr));
2138 Py_DECREF(one);
2139 Py_DECREF(two);
2140 EXPECT_EQ(PyLong_AsLong(func_result), 9);
2141 EXPECT_EQ(PyErr_Occurred(), nullptr);
2142}
2143
2144TEST_F(AbstractExtensionApiTest, PyObjectCheckBufferWithBytesReturnsTrue) {
2145 PyObjectPtr obj(PyBytes_FromString("foo"));
2146 EXPECT_TRUE(PyObject_CheckBuffer(obj.get()));
2147}
2148
2149TEST_F(AbstractExtensionApiTest, PyObjectCheckBufferWithBytearrayReturnsTrue) {
2150 PyObjectPtr obj(PyByteArray_FromStringAndSize("foo", 3));
2151 EXPECT_TRUE(PyObject_CheckBuffer(obj.get()));
2152}
2153
2154TEST_F(AbstractExtensionApiTest,
2155 PyObjectCheckBufferWithBufferObjectReturnsTrue) {
2156 static char contents[] = "hello world";
2157 static Py_ssize_t contents_len = std::strlen(contents);
2158 getbufferproc getbuffer_func = [](PyObject* obj, Py_buffer* view, int flags) {
2159 return PyBuffer_FillInfo(view, obj, strdup(contents), contents_len,
2160 /*readonly=*/1, flags);
2161 };
2162 releasebufferproc releasebuffer_func = [](PyObject*, Py_buffer* view) {
2163 std::free(view->buf);
2164 view->obj = nullptr;
2165 };
2166 PyType_Slot slots[] = {
2167 {Py_bf_getbuffer, reinterpret_cast<void*>(getbuffer_func)},
2168 {Py_bf_releasebuffer, reinterpret_cast<void*>(releasebuffer_func)},
2169 {0, nullptr},
2170 };
2171 static PyType_Spec spec;
2172 spec = {
2173 "foo.Bar", 0, 0, Py_TPFLAGS_DEFAULT, slots,
2174 };
2175 PyObjectPtr type(PyType_FromSpec(&spec));
2176 PyObjectPtr obj(PyObject_CallFunction(type, nullptr));
2177 EXPECT_TRUE(PyObject_CheckBuffer(obj.get()));
2178}
2179
2180TEST_F(AbstractExtensionApiTest,
2181 PyObjectCheckBufferWithNonByteslikeReturnsFalse) {
2182 PyObjectPtr obj(PyLong_FromLong(2));
2183 EXPECT_FALSE(PyObject_CheckBuffer(obj.get()));
2184}
2185
2186TEST_F(AbstractExtensionApiTest,
2187 PyObjectFastCallDictWithPositionalsAndKeywordArgsCalls) {
2188 PyRun_SimpleString(R"(
2189def func(*args, **kwargs):
2190 return f"{args!r}{kwargs!r}"
2191)");
2192 PyObjectPtr func(mainModuleGet("func"));
2193 PyObject* args[] = {
2194 PyLong_FromLong(3),
2195 PyUnicode_FromString("lll"),
2196 PyLong_FromLong(2),
2197 };
2198 size_t n_args = Py_ARRAY_LENGTH(args);
2199 PyObjectPtr kwargs(PyDict_New());
2200 PyObjectPtr kwarg_name(PyUnicode_FromString("kwarg"));
2201 PyObjectPtr kwarg_value(PyLong_FromLong(7));
2202 PyDict_SetItem(kwargs, kwarg_name, kwarg_value);
2203 PyObjectPtr result(_PyObject_FastCallDict(func, args, n_args, kwargs));
2204 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(3, 'lll', 2){'kwarg': 7}"));
2205 for (size_t i = 0; i < n_args; i++) {
2206 Py_DECREF(args[i]);
2207 }
2208}
2209
2210TEST_F(AbstractExtensionApiTest, PyObjectFastCallDictWithNoArgsCalls) {
2211 PyRun_SimpleString(R"(
2212def func(*args, **kwargs):
2213 return f"{args!r}{kwargs!r}"
2214)");
2215 PyObjectPtr func(mainModuleGet("func"));
2216 PyObjectPtr result(_PyObject_FastCallDict(func, nullptr, 0, nullptr));
2217 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(){}"));
2218}
2219
2220TEST_F(AbstractExtensionApiTest, PyObjectFastCallDictWithoutKeywordArgsCalls) {
2221 PyRun_SimpleString(R"(
2222def func(*args, **kwargs):
2223 return f"{args!r}{kwargs!r}"
2224)");
2225 PyObjectPtr func(mainModuleGet("func"));
2226 PyObject* args[] = {
2227 PyLong_FromLong(7),
2228 PyUnicode_FromString("xxx"),
2229 PyLong_FromLong(16),
2230 };
2231 size_t n_args = Py_ARRAY_LENGTH(args);
2232 PyObjectPtr result(_PyObject_FastCallDict(func, args, n_args, nullptr));
2233 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(7, 'xxx', 16){}"));
2234 for (size_t i = 0; i < n_args; i++) {
2235 Py_DECREF(args[i]);
2236 }
2237}
2238
2239TEST_F(AbstractExtensionApiTest,
2240 PyObjectFastCallDictWithZeroPositionalsAndKeywordArgsCalls) {
2241 PyRun_SimpleString(R"(
2242def func(*args, **kwargs):
2243 return f"{args!r}{kwargs!r}"
2244)");
2245 PyObjectPtr func(mainModuleGet("func"));
2246 PyObjectPtr kwargs(PyDict_New());
2247 PyObjectPtr kwarg_name(PyUnicode_FromString("kwarg"));
2248 PyObjectPtr kwarg_value(PyLong_FromLong(2));
2249 PyDict_SetItem(kwargs, kwarg_name, kwarg_value);
2250 PyObjectPtr result(_PyObject_FastCallDict(func, nullptr, 0, kwargs));
2251 EXPECT_TRUE(isUnicodeEqualsCStr(result, "(){'kwarg': 2}"));
2252}
2253
2254TEST_F(AbstractExtensionApiTest,
2255 PyObjectFastCallDictWithPositionalsAndKeywordArgsPropagatesException) {
2256 PyRun_SimpleString(R"(
2257def func(*args, **kwargs):
2258 raise UserWarning()
2259)");
2260 PyObjectPtr func(mainModuleGet("func"));
2261 PyObject* args[] = {
2262 PyLong_FromLong(8),
2263 };
2264 size_t n_args = Py_ARRAY_LENGTH(args);
2265 PyObjectPtr kwargs(PyDict_New());
2266 PyObjectPtr kwarg_name(PyUnicode_FromString("kwarg"));
2267 PyObjectPtr kwarg_value(PyLong_FromLong(7));
2268 PyDict_SetItem(kwargs, kwarg_name, kwarg_value);
2269 PyObjectPtr result(_PyObject_FastCallDict(func, args, n_args, kwargs));
2270 for (size_t i = 0; i < n_args; i++) {
2271 Py_DECREF(args[i]);
2272 }
2273 ASSERT_EQ(result, nullptr);
2274 ASSERT_NE(PyErr_Occurred(), nullptr);
2275 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
2276}
2277
2278TEST_F(AbstractExtensionApiTest,
2279 PyObjectFastCallDictWithoutKeywordArgsPropagatesException) {
2280 PyRun_SimpleString(R"(
2281def func(*args, **kwargs):
2282 raise UserWarning()
2283)");
2284 PyObjectPtr func(mainModuleGet("func"));
2285 PyObject* args[] = {
2286 PyUnicode_FromString(""),
2287 };
2288 size_t n_args = Py_ARRAY_LENGTH(args);
2289 PyObjectPtr result(_PyObject_FastCallDict(func, args, n_args, nullptr));
2290 for (size_t i = 0; i < n_args; i++) {
2291 Py_DECREF(args[i]);
2292 }
2293 ASSERT_EQ(result, nullptr);
2294 ASSERT_NE(PyErr_Occurred(), nullptr);
2295 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_UserWarning));
2296}
2297
2298TEST_F(AbstractExtensionApiTest, GetIterWithNoDunderIterRaises) {
2299 PyRun_SimpleString(R"(
2300class C:
2301 pass
2302c = C()
2303)");
2304 PyObjectPtr c(mainModuleGet("c"));
2305 ASSERT_EQ(PyObject_GetIter(c), nullptr);
2306 ASSERT_NE(PyErr_Occurred(), nullptr);
2307 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2308}
2309
2310TEST_F(AbstractExtensionApiTest, GetIterWithNonCallableDunderIterRaises) {
2311 PyRun_SimpleString(R"(
2312class C:
2313 __iter__ = 4
2314c = C()
2315)");
2316 PyObjectPtr c(mainModuleGet("c"));
2317 ASSERT_EQ(PyObject_GetIter(c), nullptr);
2318 ASSERT_NE(PyErr_Occurred(), nullptr);
2319 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2320}
2321
2322TEST_F(AbstractExtensionApiTest, GetIterWithDunderIterReturningNonIterRaises) {
2323 PyRun_SimpleString(R"(
2324class C:
2325 def __iter__(self):
2326 return 4
2327c = C()
2328)");
2329 PyObjectPtr c(mainModuleGet("c"));
2330 ASSERT_EQ(PyObject_GetIter(c), nullptr);
2331 ASSERT_NE(PyErr_Occurred(), nullptr);
2332 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2333}
2334
2335TEST_F(AbstractExtensionApiTest, GetIterPropagatesException) {
2336 PyRun_SimpleString(R"(
2337class C:
2338 def __iter__(self):
2339 raise ValueError("hi")
2340c = C()
2341)");
2342 PyObjectPtr c(mainModuleGet("c"));
2343 ASSERT_EQ(PyObject_GetIter(c), nullptr);
2344 ASSERT_NE(PyErr_Occurred(), nullptr);
2345 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2346}
2347
2348TEST_F(AbstractExtensionApiTest, PyObjectIsInstanceWithNonTypeRaisesTypeError) {
2349 PyObjectPtr obj(PyLong_FromLong(1));
2350 PyObjectPtr cls(PyList_New(0));
2351 EXPECT_EQ(PyObject_IsInstance(obj, cls), -1);
2352 ASSERT_NE(PyErr_Occurred(), nullptr);
2353 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2354}
2355
2356TEST_F(AbstractExtensionApiTest, PyObjectIsInstanceWithTypeReturnsTrue) {
2357 PyObjectPtr obj(PyList_New(0));
2358 PyObjectPtr cls(PyObject_Type(obj));
2359 EXPECT_EQ(PyObject_IsInstance(obj, cls), 1);
2360 EXPECT_EQ(PyErr_Occurred(), nullptr);
2361}
2362
2363TEST_F(AbstractExtensionApiTest, PyObjectIsInstanceWithSupertypeReturnsTrue) {
2364 PyObjectPtr obj(PyLong_FromLong(0));
2365 PyObjectPtr cls(PyObject_Type(obj));
2366 EXPECT_EQ(PyObject_IsInstance(Py_True, cls), 1);
2367 EXPECT_EQ(PyErr_Occurred(), nullptr);
2368}
2369
2370TEST_F(AbstractExtensionApiTest, PyObjectIsInstanceWithSubtypeReturnsFalse) {
2371 PyObjectPtr obj(PyLong_FromLong(0));
2372 PyObjectPtr cls(PyObject_Type(Py_True));
2373 EXPECT_EQ(PyObject_IsInstance(obj, cls), 0);
2374 EXPECT_EQ(PyErr_Occurred(), nullptr);
2375}
2376
2377TEST_F(AbstractExtensionApiTest, PyObjectIsInstanceWithTupleChecksTypes) {
2378 PyObjectPtr obj1(PyList_New(0));
2379 PyObjectPtr obj2(PyLong_FromLong(10));
2380 PyObjectPtr cls(PyTuple_New(3));
2381 PyTuple_SetItem(cls, 0, PyObject_Type(obj1));
2382 PyTuple_SetItem(cls, 1, PyObject_Type(obj2));
2383 PyTuple_SetItem(cls, 2, PySet_New(nullptr));
2384 EXPECT_EQ(PyObject_IsInstance(Py_True, cls), 1);
2385 EXPECT_EQ(PyErr_Occurred(), nullptr);
2386}
2387
2388TEST_F(AbstractExtensionApiTest, PyObjectIsSubclassWithNonTypeRaisesTypeError) {
2389 PyObjectPtr obj(PyLong_FromLong(2));
2390 PyObjectPtr subclass(PyObject_Type(obj));
2391 PyObjectPtr superclass(PyList_New(0));
2392 EXPECT_EQ(PyObject_IsSubclass(subclass, superclass), -1);
2393 ASSERT_NE(PyErr_Occurred(), nullptr);
2394 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2395}
2396
2397TEST_F(AbstractExtensionApiTest, PyObjectIsSubclassWithSameTypesReturnsTrue) {
2398 PyObjectPtr obj1(PyLong_FromLong(2));
2399 PyObjectPtr obj2(PyLong_FromLong(10));
2400 PyObjectPtr subclass(PyObject_Type(obj1));
2401 PyObjectPtr superclass(PyObject_Type(obj2));
2402 EXPECT_EQ(PyObject_IsSubclass(subclass, superclass), 1);
2403 EXPECT_EQ(PyErr_Occurred(), nullptr);
2404}
2405
2406TEST_F(AbstractExtensionApiTest, PyObjectIsSubclassWithSubtypeReturnsTrue) {
2407 PyObjectPtr obj(PyLong_FromLong(10));
2408 PyObjectPtr subclass(PyObject_Type(Py_True));
2409 PyObjectPtr superclass(PyObject_Type(obj));
2410 EXPECT_EQ(PyObject_IsSubclass(subclass, superclass), 1);
2411 EXPECT_EQ(PyErr_Occurred(), nullptr);
2412}
2413
2414TEST_F(AbstractExtensionApiTest, PyObjectIsSubclassWithSupertypeReturnsFalse) {
2415 PyObjectPtr obj(PyLong_FromLong(10));
2416 PyObjectPtr subclass(PyObject_Type(obj));
2417 PyObjectPtr superclass(PyObject_Type(Py_True));
2418 EXPECT_EQ(PyObject_IsSubclass(subclass, superclass), 0);
2419 EXPECT_EQ(PyErr_Occurred(), nullptr);
2420}
2421
2422TEST_F(AbstractExtensionApiTest, PyObjectIsSubclassWithTupleChecksTypes) {
2423 PyObjectPtr obj1(PyList_New(0));
2424 PyObjectPtr obj2(PyLong_FromLong(10));
2425 PyObjectPtr subclass(PyObject_Type(Py_True));
2426 PyObjectPtr superclass(PyTuple_New(3));
2427 PyTuple_SetItem(superclass, 0, PyObject_Type(obj1));
2428 PyTuple_SetItem(superclass, 1, PyObject_Type(obj2));
2429 PyTuple_SetItem(superclass, 2, PySet_New(nullptr));
2430 EXPECT_EQ(PyObject_IsSubclass(subclass, superclass), 1);
2431 EXPECT_EQ(PyErr_Occurred(), nullptr);
2432}
2433
2434TEST_F(AbstractExtensionApiTest, PyObjectLengthOnNullRaisesSystemError) {
2435 EXPECT_EQ(PyObject_Length(nullptr), -1);
2436 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2437}
2438
2439TEST_F(AbstractExtensionApiTest,
2440 PyObjectLengthWithoutDunderLenRaisesTypeError) {
2441 PyObjectPtr num(PyLong_FromLong(3));
2442 ASSERT_EQ(PyObject_Length(num), -1);
2443 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2444}
2445
2446TEST_F(AbstractExtensionApiTest,
2447 PyObjectLengthHintWithDunderLengthReturnsValueOfDunderLength) {
2448 PyRun_SimpleString(R"(
2449class Bar:
2450 def __len__(self): return 1
2451 def __length_hint__(self): return 500
2452obj = Bar()
2453 )");
2454 PyObjectPtr obj(mainModuleGet("obj"));
2455 EXPECT_EQ(PyObject_LengthHint(obj, 234), 1);
2456 EXPECT_EQ(PyErr_Occurred(), nullptr);
2457}
2458
2459TEST_F(AbstractExtensionApiTest,
2460 PyObjectLengthHintWithDunderLengthRaisingNonTypeErrorRaisesError) {
2461 PyRun_SimpleString(R"(
2462class Bar:
2463 def __len__(self): raise ValueError
2464 def __length_hint__(self): return 500
2465obj = Bar()
2466 )");
2467 PyObjectPtr obj(mainModuleGet("obj"));
2468 EXPECT_EQ(PyObject_LengthHint(obj, 234), -1);
2469 ASSERT_NE(PyErr_Occurred(), nullptr);
2470 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2471}
2472
2473TEST_F(
2474 AbstractExtensionApiTest,
2475 PyObjectLengthHintWithDunderLengthRaisingTypeErrorReturnsDunderLengthHintValue) {
2476 PyRun_SimpleString(R"(
2477class Bar:
2478 def __len__(self): raise TypeError
2479 def __length_hint__(self): return 500
2480obj = Bar()
2481 )");
2482 PyObjectPtr obj(mainModuleGet("obj"));
2483 EXPECT_EQ(PyObject_LengthHint(obj, 234), 500);
2484 EXPECT_EQ(PyErr_Occurred(), nullptr);
2485}
2486
2487TEST_F(
2488 AbstractExtensionApiTest,
2489 PyObjectLengthHintWithoutDunderLengthAndDunderLengthHintReturnsDefaultValue) {
2490 PyRun_SimpleString(R"(
2491class Bar: pass
2492
2493obj = Bar()
2494 )");
2495 PyObjectPtr obj(mainModuleGet("obj"));
2496 EXPECT_EQ(PyObject_LengthHint(obj, 234), 234);
2497 EXPECT_EQ(PyErr_Occurred(), nullptr);
2498}
2499
2500TEST_F(
2501 AbstractExtensionApiTest,
2502 PyObjectLengthHintWithNotImplementedDunderLengthHintReturnsDefaultValue) {
2503 PyRun_SimpleString(R"(
2504class Bar:
2505 def __length_hint__(self): return NotImplemented
2506
2507obj = Bar()
2508 )");
2509 PyObjectPtr obj(mainModuleGet("obj"));
2510 EXPECT_EQ(PyObject_LengthHint(obj, 234), 234);
2511 EXPECT_EQ(PyErr_Occurred(), nullptr);
2512}
2513
2514TEST_F(
2515 AbstractExtensionApiTest,
2516 PyObjectLengthHintWithDunderLengthHintRaisingExceptionReturnsNegativeValue) {
2517 PyRun_SimpleString(R"(
2518class Bar:
2519 def __length_hint__(self): raise ValueError
2520
2521obj = Bar()
2522 )");
2523 PyObjectPtr obj(mainModuleGet("obj"));
2524 EXPECT_EQ(PyObject_LengthHint(obj, 234), -1);
2525 ASSERT_NE(PyErr_Occurred(), nullptr);
2526 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2527}
2528
2529TEST_F(AbstractExtensionApiTest,
2530 PyObjectLengthHintWithDunderLengthHintReturningNonIntRaisesTypeError) {
2531 PyRun_SimpleString(R"(
2532class Bar:
2533 def __length_hint__(self): return "not int"
2534
2535obj = Bar()
2536 )");
2537 PyObjectPtr obj(mainModuleGet("obj"));
2538 EXPECT_EQ(PyObject_LengthHint(obj, 234), -1);
2539 ASSERT_NE(PyErr_Occurred(), nullptr);
2540 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2541}
2542
2543TEST_F(
2544 AbstractExtensionApiTest,
2545 PyObjectLengthHintWithDunderLengthHintReturningLargeIntNotFitInWordRaisesOverflowError) {
2546 PyRun_SimpleString(R"(
2547class Bar:
2548 def __length_hint__(self): return 13843149871348971349871398471389473
2549
2550obj = Bar()
2551 )");
2552 PyObjectPtr obj(mainModuleGet("obj"));
2553 EXPECT_EQ(PyObject_LengthHint(obj, 234), -1);
2554 ASSERT_NE(PyErr_Occurred(), nullptr);
2555 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_OverflowError));
2556}
2557
2558TEST_F(
2559 AbstractExtensionApiTest,
2560 PyObjectLengthHintWithDunderLengthHintReturningNegativeNumberRaisesValueError) {
2561 PyRun_SimpleString(R"(
2562class Bar:
2563 def __length_hint__(self): return -1
2564
2565obj = Bar()
2566 )");
2567 PyObjectPtr obj(mainModuleGet("obj"));
2568 EXPECT_EQ(PyObject_LengthHint(obj, 234), -1);
2569 ASSERT_NE(PyErr_Occurred(), nullptr);
2570 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2571}
2572
2573TEST_F(AbstractExtensionApiTest, PyObjectLengthWithNonIntLenRaisesTypeError) {
2574 PyRun_SimpleString(R"(
2575class Foo:
2576 def __len__(self):
2577 return "foo"
2578obj = Foo()
2579 )");
2580
2581 PyObjectPtr obj(mainModuleGet("obj"));
2582 ASSERT_EQ(PyObject_Length(obj), -1);
2583 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2584}
2585
2586TEST_F(AbstractExtensionApiTest, PyObjectLengthWithoutIndexRaisesTypeError) {
2587 PyRun_SimpleString(R"(
2588class Foo: pass
2589class Bar:
2590 def __len__(self): return Foo()
2591obj = Bar()
2592 )");
2593
2594 PyObjectPtr obj(mainModuleGet("obj"));
2595 ASSERT_EQ(PyObject_Length(obj), -1);
2596 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2597}
2598
2599TEST_F(AbstractExtensionApiTest, PyObjectLengthWithNonIntIndexRaisesTypeError) {
2600 PyRun_SimpleString(R"(
2601class Foo:
2602 def __index__(self): return None
2603class Bar:
2604 def __len__(self): return Foo()
2605obj = Bar()
2606 )");
2607
2608 PyObjectPtr obj(mainModuleGet("obj"));
2609 ASSERT_EQ(PyObject_Length(obj), -1);
2610 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2611}
2612
2613TEST_F(AbstractExtensionApiTest,
2614 PyObjectLengthWithIntSubclassLargeRaisesOverflowError) {
2615 PyRun_SimpleString(R"(
2616class Foo(int): pass
2617class Bar:
2618 def __len__(self): return Foo(2**63)
2619obj = Bar()
2620)");
2621
2622 PyObjectPtr obj(mainModuleGet("obj"));
2623 ASSERT_EQ(PyObject_Length(obj), -1);
2624 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_OverflowError));
2625}
2626
2627TEST_F(AbstractExtensionApiTest, PyObjectLengthWithIntSubclassReturnsValue) {
2628 PyRun_SimpleString(R"(
2629class Foo(int): pass
2630class Bar:
2631 def __len__(self): return Foo(5)
2632obj = Bar()
2633)");
2634
2635 PyObjectPtr obj(mainModuleGet("obj"));
2636 EXPECT_EQ(PyObject_Length(obj), 5);
2637 EXPECT_EQ(PyErr_Occurred(), nullptr);
2638}
2639
2640TEST_F(AbstractExtensionApiTest, PyObjectLengthWithIndexReturnsValue) {
2641 PyRun_SimpleString(R"(
2642class Foo:
2643 def __index__(self): return 1
2644class Bar:
2645 def __len__(self): return Foo()
2646obj = Bar()
2647 )");
2648
2649 PyObjectPtr obj(mainModuleGet("obj"));
2650 EXPECT_EQ(PyObject_Length(obj), 1);
2651 EXPECT_EQ(PyErr_Occurred(), nullptr);
2652}
2653
2654TEST_F(AbstractExtensionApiTest,
2655 PyObjectLengthWithNegativeLenRaisesValueError) {
2656 PyRun_SimpleString(R"(
2657class Foo:
2658 def __len__(self):
2659 return -5
2660obj = Foo()
2661 )");
2662
2663 PyObjectPtr obj(mainModuleGet("obj"));
2664 ASSERT_EQ(PyObject_Length(obj), -1);
2665 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2666}
2667
2668TEST_F(AbstractExtensionApiTest,
2669 PyObjectLengthWithOverflowRaisesOverflowError) {
2670 PyRun_SimpleString(R"(
2671class Foo:
2672 def __len__(self):
2673 return 0x8000000000000000
2674obj = Foo()
2675 )");
2676
2677 PyObjectPtr obj(mainModuleGet("obj"));
2678 ASSERT_EQ(PyObject_Length(obj), -1);
2679 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_OverflowError));
2680}
2681
2682TEST_F(AbstractExtensionApiTest, PyObjectLengthWithUnderflowRaisesValueError) {
2683 PyRun_SimpleString(R"(
2684class Foo:
2685 def __len__(self):
2686 return -0x8000000000000001
2687obj = Foo()
2688 )");
2689
2690 PyObjectPtr obj(mainModuleGet("obj"));
2691 ASSERT_EQ(PyObject_Length(obj), -1);
2692 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
2693}
2694
2695TEST_F(AbstractExtensionApiTest, PyObjectLengthWithEmptyDictReturnsZero) {
2696 PyObjectPtr dict(PyDict_New());
2697 EXPECT_EQ(PyObject_Length(dict), 0);
2698 EXPECT_EQ(PyErr_Occurred(), nullptr);
2699}
2700
2701TEST_F(AbstractExtensionApiTest, PyObjectLengthWithEmptyListReturnsZero) {
2702 PyObjectPtr list(PyList_New(0));
2703 EXPECT_EQ(PyObject_Length(list), 0);
2704 EXPECT_EQ(PyErr_Occurred(), nullptr);
2705}
2706
2707TEST_F(AbstractExtensionApiTest, PyObjectLengthWithEmptyStringReturnsZero) {
2708 PyObjectPtr str(PyUnicode_FromString(""));
2709 EXPECT_EQ(PyObject_Length(str), 0);
2710 EXPECT_EQ(PyErr_Occurred(), nullptr);
2711}
2712
2713TEST_F(AbstractExtensionApiTest, PyObjectLengthWithNonEmptyDictReturnsValue) {
2714 PyObjectPtr dict(PyDict_New());
2715
2716 {
2717 PyObjectPtr value(PyLong_FromLong(3));
2718
2719 PyObjectPtr key1(PyLong_FromLong(1));
2720 PyDict_SetItem(dict, key1, value);
2721
2722 PyObjectPtr key2(PyLong_FromLong(2));
2723 PyDict_SetItem(dict, key2, value);
2724 }
2725
2726 EXPECT_EQ(PyObject_Length(dict), 2);
2727 EXPECT_EQ(PyErr_Occurred(), nullptr);
2728}
2729
2730TEST_F(AbstractExtensionApiTest, PyObjectLengthWithNonEmptyListReturnsValue) {
2731 PyObjectPtr list(PyList_New(3));
2732 EXPECT_EQ(PyObject_Length(list), 3);
2733 EXPECT_EQ(PyErr_Occurred(), nullptr);
2734}
2735
2736TEST_F(AbstractExtensionApiTest, PyObjectLengthWithNonEmptyStringReturnsValue) {
2737 PyObjectPtr str(PyUnicode_FromString("foo"));
2738 EXPECT_EQ(PyObject_Length(str), 3);
2739 EXPECT_EQ(PyErr_Occurred(), nullptr);
2740}
2741
2742TEST_F(AbstractExtensionApiTest, PyObjectSizeOnNullRaisesSystemError) {
2743 EXPECT_EQ(PyObject_Size(nullptr), -1);
2744 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2745}
2746
2747TEST_F(AbstractExtensionApiTest, PyObjectTypeOnNullRaisesSystemError) {
2748 EXPECT_EQ(PyObject_Type(nullptr), nullptr);
2749 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2750}
2751
2752TEST_F(AbstractExtensionApiTest, PyObjectTypeReturnsType) {
2753 PyObjectPtr num(PyLong_FromLong(4));
2754 PyObjectPtr type(PyObject_Type(num));
2755 EXPECT_TRUE(PyType_Check(type));
2756}
2757
2758TEST_F(AbstractExtensionApiTest, PyObjectTypeReturnsSameTypeForSmallAndLarge) {
2759 PyObjectPtr str1(PyUnicode_FromString("short"));
2760 PyObjectPtr str2(PyUnicode_FromString("This is a longer string."));
2761 PyObjectPtr type1(PyObject_Type(str1));
2762 PyObjectPtr type2(PyObject_Type(str2));
2763 EXPECT_EQ(type1, type2);
2764}
2765
2766#ifndef Py_SET_TYPE
2767#define Py_SET_TYPE(obj, type) ((Py_TYPE(obj) = (type)), (void)0)
2768#endif
2769
2770TEST_F(AbstractExtensionApiTest, PySETTYPEWithObjectSetsType) {
2771 PyRun_SimpleString(R"(
2772class C:
2773 pass
2774class D:
2775 pass
2776instance = C()
2777)");
2778 PyObjectPtr class_c(mainModuleGet("C"));
2779 PyObjectPtr class_d(mainModuleGet("D"));
2780 PyObjectPtr instance(mainModuleGet("instance"));
2781 EXPECT_TRUE(PyObject_IsInstance(instance, class_c));
2782 // The instance must have an owned reference to D
2783 Py_INCREF(class_d);
2784 Py_SET_TYPE(instance.get(), class_d.asTypeObject());
2785 EXPECT_TRUE(PyObject_IsInstance(instance, class_d));
2786}
2787
2788TEST_F(AbstractExtensionApiTest, PySETTYPEWithTypeObjectSetsMetaclass) {
2789 PyRun_SimpleString(R"(
2790class M(type):
2791 pass
2792class C(metaclass=M):
2793 pass
2794class D(type):
2795 pass
2796)");
2797 PyObjectPtr class_m(mainModuleGet("M"));
2798 PyObjectPtr class_c(mainModuleGet("C"));
2799 PyObjectPtr class_d(mainModuleGet("D"));
2800 EXPECT_TRUE(PyObject_IsInstance(class_c, class_m));
2801 // The instance must have an owned reference to D
2802 Py_INCREF(class_d);
2803 Py_SET_TYPE(class_c.get(), class_d.asTypeObject());
2804 EXPECT_TRUE(PyObject_IsInstance(class_c, class_d));
2805}
2806
2807// Sequence Protocol
2808
2809TEST_F(AbstractExtensionApiTest,
2810 PySequenceBytesToCharpArrayWithNonSequenceRaisesTypeError) {
2811 PyObjectPtr obj(PyLong_FromLong(1));
2812 EXPECT_EQ(_PySequence_BytesToCharpArray(obj), nullptr);
2813 ASSERT_NE(PyErr_Occurred(), nullptr);
2814 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2815}
2816
2817TEST_F(AbstractExtensionApiTest,
2818 PySequenceBytesToCharpArrayWithEmptyListReturnsArray) {
2819 PyObjectPtr obj(PyList_New(0));
2820 char* const* array = _PySequence_BytesToCharpArray(obj);
2821 EXPECT_EQ(PyErr_Occurred(), nullptr);
2822 ASSERT_NE(array, nullptr);
2823 EXPECT_EQ(array[0], nullptr);
2824 _Py_FreeCharPArray(array);
2825}
2826
2827TEST_F(AbstractExtensionApiTest,
2828 PySequenceBytesToCharpArrayWithNonBytesItemRaisesTypeError) {
2829 PyObjectPtr obj(PyTuple_New(1));
2830 PyTuple_SetItem(obj, 0, PyByteArray_FromStringAndSize("foo", 3));
2831 EXPECT_EQ(_PySequence_BytesToCharpArray(obj), nullptr);
2832 ASSERT_NE(PyErr_Occurred(), nullptr);
2833 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
2834}
2835
2836TEST_F(AbstractExtensionApiTest,
2837 PySequenceBytesToCharpArrayWithBytesSequenceReturnsArray) {
2838 PyObjectPtr obj(PyTuple_New(3));
2839 PyTuple_SetItem(obj, 0, PyBytes_FromString("foo"));
2840 PyTuple_SetItem(obj, 1, PyBytes_FromString("bar"));
2841 PyTuple_SetItem(obj, 2, PyBytes_FromString("baz"));
2842 char* const* array = _PySequence_BytesToCharpArray(obj);
2843 EXPECT_EQ(PyErr_Occurred(), nullptr);
2844 ASSERT_NE(array, nullptr);
2845 EXPECT_STREQ(array[0], "foo");
2846 EXPECT_STREQ(array[1], "bar");
2847 EXPECT_STREQ(array[2], "baz");
2848 EXPECT_EQ(array[3], nullptr);
2849 _Py_FreeCharPArray(array);
2850}
2851
2852TEST_F(AbstractExtensionApiTest, PySequenceCheckWithoutGetItemReturnsFalse) {
2853 PyRun_SimpleString(R"(
2854class ClassWithoutDunderGetItem: pass
2855
2856obj = ClassWithoutDunderGetItem()
2857)");
2858
2859 PyObjectPtr obj(mainModuleGet("obj"));
2860 EXPECT_FALSE(PySequence_Check(obj));
2861}
2862
2863TEST_F(AbstractExtensionApiTest,
2864 PySequenceCheckWithoutGetItemOnClassReturnsFalse) {
2865 PyRun_SimpleString(R"(
2866class ClassWithoutDunderGetItem: pass
2867
2868obj = ClassWithoutDunderGetItem()
2869obj.__getitem__ = lambda self, key : 1
2870)");
2871
2872 PyObjectPtr obj(mainModuleGet("obj"));
2873 EXPECT_FALSE(PySequence_Check(obj));
2874}
2875
2876TEST_F(AbstractExtensionApiTest, PySequenceCheckWithNumericReturnsFalse) {
2877 PyObjectPtr num(PyLong_FromLong(3));
2878 EXPECT_FALSE(PySequence_Check(num));
2879}
2880
2881TEST_F(AbstractExtensionApiTest, PySequenceCheckWithSetReturnsFalse) {
2882 PyObjectPtr set(PySet_New(nullptr));
2883 EXPECT_FALSE(PySequence_Check(set));
2884}
2885
2886TEST_F(AbstractExtensionApiTest, PySequenceCheckWithDictReturnsFalse) {
2887 PyObjectPtr dict(PyDict_New());
2888 EXPECT_FALSE(PySequence_Check(dict));
2889}
2890
2891TEST_F(AbstractExtensionApiTest, PySequenceCheckWithDictSubclassReturnsFalse) {
2892 PyRun_SimpleString(R"(
2893class Subclass(dict): pass
2894
2895obj = Subclass()
2896)");
2897
2898 PyObjectPtr obj(mainModuleGet("obj"));
2899 EXPECT_FALSE(PySequence_Check(obj));
2900}
2901
2902TEST_F(AbstractExtensionApiTest, PySequenceCheckWithNoneReturnsFalse) {
2903 EXPECT_FALSE(PySequence_Check(Py_None));
2904}
2905
2906TEST_F(AbstractExtensionApiTest, PySequenceCheckWithGetItemMethodReturnsTrue) {
2907 PyRun_SimpleString(R"(
2908class ClassWithDunderGetItemMethod:
2909 def __getitem__(self, key):
2910 return None
2911
2912obj = ClassWithDunderGetItemMethod()
2913)");
2914
2915 PyObjectPtr obj(mainModuleGet("obj"));
2916 EXPECT_TRUE(PySequence_Check(obj));
2917}
2918
2919TEST_F(AbstractExtensionApiTest, PySequenceCheckWithGetItemAttrReturnsTrue) {
2920 PyRun_SimpleString(R"(
2921class ClassWithDunderGetItemAttr:
2922 __getitem__ = 42
2923
2924obj = ClassWithDunderGetItemAttr()
2925)");
2926
2927 PyObjectPtr obj(mainModuleGet("obj"));
2928 EXPECT_TRUE(PySequence_Check(obj));
2929}
2930
2931TEST_F(AbstractExtensionApiTest, PySequenceCheckWithStringReturnsTrue) {
2932 PyObjectPtr str(PyUnicode_FromString("foo"));
2933 EXPECT_TRUE(PySequence_Check(str));
2934}
2935
2936TEST_F(AbstractExtensionApiTest, PySequenceCheckWithListReturnsTrue) {
2937 PyObjectPtr list(PyList_New(3));
2938 EXPECT_TRUE(PySequence_Check(list));
2939}
2940
2941TEST_F(AbstractExtensionApiTest, PySequenceConcatWithNullLeftRaises) {
2942 PyObjectPtr tuple(PyTuple_New(0));
2943 PyObjectPtr result(PySequence_Concat(nullptr, tuple));
2944 ASSERT_EQ(result, nullptr);
2945 ASSERT_NE(PyErr_Occurred(), nullptr);
2946 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2947}
2948
2949TEST_F(AbstractExtensionApiTest, PySequenceConcatWithNullRightRaises) {
2950 PyObjectPtr tuple(PyTuple_New(0));
2951 PyObjectPtr result(PySequence_Concat(tuple, nullptr));
2952 ASSERT_EQ(result, nullptr);
2953 ASSERT_NE(PyErr_Occurred(), nullptr);
2954 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2955}
2956
2957TEST_F(AbstractExtensionApiTest, PySequenceConcatCallsDunderAdd) {
2958 PyObjectPtr one(PyLong_FromLong(1));
2959 PyObjectPtr two(PyLong_FromLong(2));
2960 PyObjectPtr three(PyLong_FromLong(3));
2961 PyObjectPtr four(PyLong_FromLong(4));
2962 PyObjectPtr left(PyTuple_Pack(2, one.get(), two.get()));
2963 PyObjectPtr right(PyTuple_Pack(2, three.get(), four.get()));
2964 PyObjectPtr result(PySequence_Concat(left, right));
2965 ASSERT_NE(result, nullptr);
2966 ASSERT_TRUE(PyTuple_CheckExact(result));
2967 ASSERT_EQ(PyTuple_Size(result), 4);
2968 EXPECT_EQ(PyTuple_GetItem(result, 0), PyTuple_GetItem(left, 0));
2969 EXPECT_EQ(PyTuple_GetItem(result, 1), PyTuple_GetItem(left, 1));
2970 EXPECT_EQ(PyTuple_GetItem(result, 2), PyTuple_GetItem(right, 0));
2971 EXPECT_EQ(PyTuple_GetItem(result, 3), PyTuple_GetItem(right, 1));
2972}
2973
2974TEST_F(AbstractExtensionApiTest, PySequenceRepeatWithNullSeqRaises) {
2975 PyObjectPtr result(PySequence_Repeat(nullptr, 5));
2976 ASSERT_EQ(result, nullptr);
2977 ASSERT_NE(PyErr_Occurred(), nullptr);
2978 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
2979}
2980
2981TEST_F(AbstractExtensionApiTest, PySequenceRepeatCallsDunderMul) {
2982 PyObjectPtr one(PyLong_FromLong(1));
2983 PyObjectPtr two(PyLong_FromLong(2));
2984 PyObjectPtr seq(PyTuple_Pack(2, one.get(), two.get()));
2985 PyObjectPtr result(PySequence_Repeat(seq, 2));
2986 ASSERT_NE(result, nullptr);
2987 ASSERT_EQ(PyErr_Occurred(), nullptr);
2988 ASSERT_EQ(PyTuple_Size(result), 4);
2989 EXPECT_EQ(PyTuple_GetItem(result, 0), PyTuple_GetItem(seq, 0));
2990 EXPECT_EQ(PyTuple_GetItem(result, 1), PyTuple_GetItem(seq, 1));
2991 EXPECT_EQ(PyTuple_GetItem(result, 2), PyTuple_GetItem(seq, 0));
2992 EXPECT_EQ(PyTuple_GetItem(result, 3), PyTuple_GetItem(seq, 1));
2993}
2994
2995TEST_F(AbstractExtensionApiTest, PySequenceCountWithNullSeqRaises) {
2996 PyObjectPtr obj(PyLong_FromLong(1));
2997 EXPECT_EQ(PySequence_Count(nullptr, obj), -1);
2998 ASSERT_NE(PyErr_Occurred(), nullptr);
2999 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3000}
3001
3002TEST_F(AbstractExtensionApiTest, PySequenceCountWithNullObjRaises) {
3003 PyObjectPtr one(PyLong_FromLong(1));
3004 PyObjectPtr two(PyLong_FromLong(2));
3005 PyObjectPtr tuple(PyTuple_Pack(2, one.get(), two.get()));
3006 EXPECT_EQ(PySequence_Count(tuple, nullptr), -1);
3007 ASSERT_NE(PyErr_Occurred(), nullptr);
3008 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3009}
3010
3011TEST_F(AbstractExtensionApiTest, PySequenceCountCountsOccurrences) {
3012 PyObjectPtr obj(PyLong_FromLong(2));
3013 PyObjectPtr one(PyLong_FromLong(1));
3014 PyObjectPtr two1(PyLong_FromLong(2));
3015 PyObjectPtr two2(PyLong_FromLong(2));
3016 PyObjectPtr tuple(PyTuple_Pack(3, one.get(), two1.get(), two2.get()));
3017 EXPECT_EQ(PySequence_Count(tuple, obj), 2);
3018 EXPECT_EQ(PyErr_Occurred(), nullptr);
3019}
3020
3021TEST_F(AbstractExtensionApiTest, PySequenceGetItemCallsDunderGetItem) {
3022 PyRun_SimpleString(R"(
3023class C:
3024 def __getitem__(self, key):
3025 return 7
3026c = C()
3027)");
3028 PyObjectPtr c(mainModuleGet("c"));
3029 PyObjectPtr result(PySequence_GetItem(c, 0));
3030 ASSERT_NE(result, nullptr);
3031 ASSERT_EQ(PyErr_Occurred(), nullptr);
3032 EXPECT_EQ(PyLong_AsLong(result), 7);
3033}
3034
3035TEST_F(AbstractExtensionApiTest, PySequenceItemCallsDunderGetItem) {
3036 PyRun_SimpleString(R"(
3037class C:
3038 def __getitem__(self, key):
3039 return 7
3040c = C()
3041)");
3042 PyObjectPtr c(mainModuleGet("c"));
3043 PyObjectPtr result(PySequence_ITEM(c, 0));
3044 ASSERT_NE(result, nullptr);
3045 ASSERT_EQ(PyErr_Occurred(), nullptr);
3046 EXPECT_EQ(PyLong_AsLong(result), 7);
3047}
3048
3049TEST_F(AbstractExtensionApiTest, PySequenceItemDunderGetItemRaises) {
3050 PyRun_SimpleString(R"(
3051class C:
3052 def __getitem__(self, key):
3053 raise Exception("foo")
3054c = C()
3055)");
3056 PyObjectPtr c(mainModuleGet("c"));
3057 PyObjectPtr result(PySequence_ITEM(c, 0));
3058 ASSERT_EQ(result, nullptr);
3059 ASSERT_NE(PyErr_Occurred(), nullptr);
3060}
3061
3062TEST_F(AbstractExtensionApiTest, PySequenceSetItemWithNullValCallsDelItem) {
3063 PyRun_SimpleString(R"(
3064sideeffect = 0
3065class C:
3066 def __delitem__(self, key):
3067 global sideeffect
3068 sideeffect = 10
3069c = C()
3070)");
3071 PyObjectPtr c(mainModuleGet("c"));
3072 ASSERT_EQ(PySequence_SetItem(c, 0, nullptr), 0);
3073 ASSERT_EQ(PyErr_Occurred(), nullptr);
3074 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3075 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3076}
3077
3078TEST_F(AbstractExtensionApiTest, PySequenceSetItemCallsDunderSetItem) {
3079 PyRun_SimpleString(R"(
3080sideeffect = 0
3081class C:
3082 def __setitem__(self, key, val):
3083 global sideeffect
3084 sideeffect = 10
3085c = C()
3086)");
3087 PyObjectPtr c(mainModuleGet("c"));
3088 PyObjectPtr val(PyLong_FromLong(4));
3089 ASSERT_EQ(PySequence_SetItem(c, 0, val), 0);
3090 ASSERT_EQ(PyErr_Occurred(), nullptr);
3091 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3092 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3093}
3094
3095TEST_F(AbstractExtensionApiTest,
3096 PySequenceGetItemWithTupleReturnsTupleElement) {
3097 PyObjectPtr tuple(PyTuple_New(2));
3098 ASSERT_EQ(PyTuple_SetItem(tuple, 0, PyUnicode_FromString("first")), 0);
3099 ASSERT_EQ(PyTuple_SetItem(tuple, 1, PyUnicode_FromString("second")), 0);
3100
3101 PyObjectPtr result(PySequence_GetItem(tuple, 0));
3102 EXPECT_TRUE(isUnicodeEqualsCStr(result, "first"));
3103
3104 result = PySequence_GetItem(tuple, 1);
3105 EXPECT_TRUE(isUnicodeEqualsCStr(result, "second"));
3106}
3107
3108TEST_F(AbstractExtensionApiTest, PySequenceGetItemWithListReturnsListElement) {
3109 PyObjectPtr list(PyList_New(2));
3110 ASSERT_EQ(PyList_SetItem(list, 0, PyUnicode_FromString("first")), 0);
3111 ASSERT_EQ(PyList_SetItem(list, 1, PyUnicode_FromString("second")), 0);
3112
3113 PyObjectPtr result(PySequence_GetItem(list, 0));
3114 EXPECT_TRUE(isUnicodeEqualsCStr(result, "first"));
3115
3116 result = PySequence_GetItem(list, 1);
3117 EXPECT_TRUE(isUnicodeEqualsCStr(result, "second"));
3118}
3119
3120TEST_F(AbstractExtensionApiTest, PySequenceDelItemCallsDunderDelItem) {
3121 PyRun_SimpleString(R"(
3122sideeffect = 0
3123class C:
3124 def __delitem__(self, key):
3125 global sideeffect
3126 sideeffect = 10
3127c = C()
3128)");
3129 PyObjectPtr c(mainModuleGet("c"));
3130 ASSERT_EQ(PySequence_DelItem(c, 0), 0);
3131 ASSERT_EQ(PyErr_Occurred(), nullptr);
3132 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3133 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3134}
3135
3136TEST_F(AbstractExtensionApiTest, PySequenceContainsCallsDunderContains) {
3137 PyRun_SimpleString(R"(
3138class C:
3139 def __getitem__(self, key):
3140 pass
3141 def __contains__(self, key):
3142 return True
3143c = C()
3144)");
3145 PyObjectPtr c(mainModuleGet("c"));
3146 PyObjectPtr key(PyLong_FromLong(3));
3147 ASSERT_EQ(PySequence_Contains(c, key), 1);
3148 ASSERT_EQ(PyErr_Occurred(), nullptr);
3149}
3150
3151TEST_F(AbstractExtensionApiTest, PySequenceContainsPropagatesException) {
3152 PyRun_SimpleString(R"(
3153class C:
3154 def __getitem__(self, key):
3155 pass
3156 def __contains__(self, key):
3157 raise ValueError
3158c = C()
3159)");
3160 PyObjectPtr c(mainModuleGet("c"));
3161 PyObjectPtr key(PyLong_FromLong(3));
3162 ASSERT_EQ(PySequence_Contains(c, key), -1);
3163 ASSERT_NE(PyErr_Occurred(), nullptr);
3164 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_ValueError));
3165}
3166
3167TEST_F(AbstractExtensionApiTest, PySequenceContainsFallsBackToIterSearch) {
3168 PyRun_SimpleString(R"(
3169class C:
3170 def __getitem__(self, key):
3171 pass
3172 def __iter__(self):
3173 return [1,2,3].__iter__()
3174c = C()
3175)");
3176 PyObjectPtr c(mainModuleGet("c"));
3177 PyObjectPtr key(PyLong_FromLong(4));
3178 ASSERT_EQ(PySequence_Contains(c, key), 0);
3179 ASSERT_EQ(PyErr_Occurred(), nullptr);
3180}
3181
3182TEST_F(AbstractExtensionApiTest, PySequenceIndexWithNullObjRaises) {
3183 PyObjectPtr one(PyLong_FromLong(1));
3184 PyObjectPtr two(PyLong_FromLong(2));
3185 PyObjectPtr tuple(PyTuple_Pack(2, one.get(), two.get()));
3186 EXPECT_EQ(PySequence_Index(tuple, nullptr), -1);
3187 ASSERT_NE(PyErr_Occurred(), nullptr);
3188 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3189}
3190
3191TEST_F(AbstractExtensionApiTest, PySequenceIndexFindsFirstOccurrence) {
3192 PyObjectPtr one(PyLong_FromLong(1));
3193 PyObjectPtr two(PyLong_FromLong(2));
3194 PyObjectPtr tuple(PyTuple_Pack(3, one.get(), two.get(), two.get()));
3195 EXPECT_EQ(PySequence_Index(tuple, two), 1);
3196 EXPECT_EQ(PyErr_Occurred(), nullptr);
3197}
3198
3199TEST_F(AbstractExtensionApiTest, PySequenceFastWithNullObjRaisesSystemError) {
3200 EXPECT_EQ(PySequence_Fast(nullptr, "msg"), nullptr);
3201 ASSERT_NE(PyErr_Occurred(), nullptr);
3202 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3203}
3204
3205TEST_F(AbstractExtensionApiTest, PySequenceFastWithTupleReturnsSameObject) {
3206 PyObjectPtr tuple(PyTuple_New(3));
3207 PyObjectPtr result(PySequence_Fast(tuple, "msg"));
3208 ASSERT_EQ(PyErr_Occurred(), nullptr);
3209 EXPECT_EQ(tuple, result);
3210}
3211
3212TEST_F(AbstractExtensionApiTest, PySequenceFastWithListReturnsSameObject) {
3213 PyObjectPtr list(PyList_New(3));
3214 PyObjectPtr result(PySequence_Fast(list, "msg"));
3215 ASSERT_EQ(PyErr_Occurred(), nullptr);
3216 EXPECT_EQ(list, result);
3217}
3218
3219TEST_F(AbstractExtensionApiTest, PySequenceFastWithNonIterableRaisesTypeError) {
3220 ASSERT_EQ(PySequence_Fast(Py_None, "msg"), nullptr);
3221 ASSERT_NE(PyErr_Occurred(), nullptr);
3222 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3223}
3224
3225TEST_F(AbstractExtensionApiTest, PySequenceFastGetSizeWithTupleReturnsSize) {
3226 PyObjectPtr tuple(PyTuple_Pack(3, Py_None, Py_None, Py_None));
3227 PyObjectPtr fast_seq(PySequence_Fast(tuple, ""));
3228 EXPECT_EQ(PySequence_Fast_GET_SIZE(fast_seq.get()), 3);
3229}
3230
3231TEST_F(AbstractExtensionApiTest, PySequenceFastGetSizeWithListReturnsSize) {
3232 PyObjectPtr list(PyList_New(0));
3233 for (int i = 0; i < 11; i++) {
3234 PyList_Append(list, Py_None);
3235 }
3236 PyObjectPtr fast_seq(PySequence_Fast(list, ""));
3237 EXPECT_EQ(PySequence_Fast_GET_SIZE(fast_seq.get()), 11);
3238}
3239
3240TEST_F(AbstractExtensionApiTest, PySequenceFastGetItemWithTupleReturnsItem) {
3241 PyObjectPtr number(PyLong_FromLong(42));
3242 PyObjectPtr tuple(PyTuple_Pack(3, Py_None, Py_None, number.get()));
3243 PyObjectPtr fast_seq(PySequence_Fast(tuple, ""));
3244 EXPECT_TRUE(
3245 isLongEqualsLong(PySequence_Fast_GET_ITEM(fast_seq.get(), 2), 42));
3246}
3247
3248TEST_F(AbstractExtensionApiTest, PySequenceFastGetItemWithListReturnsItem) {
3249 PyObjectPtr list(PyList_New(0));
3250 PyList_Append(list, Py_None);
3251 PyObjectPtr number(PyLong_FromLong(42));
3252 PyList_Append(list, number);
3253 PyList_Append(list, Py_None);
3254 PyObjectPtr fast_seq(PySequence_Fast(list, ""));
3255 EXPECT_TRUE(
3256 isLongEqualsLong(PySequence_Fast_GET_ITEM(fast_seq.get(), 1), 42));
3257}
3258
3259TEST_F(AbstractExtensionApiTest, PySequenceFastWithIterableReturnsList) {
3260 PyRun_SimpleString(R"(
3261class C:
3262 def __iter__(self):
3263 return (1, 2, 3).__iter__()
3264c = C()
3265)");
3266 PyObjectPtr c(mainModuleGet("c"));
3267 PyObjectPtr result(PySequence_Fast(c, "msg"));
3268 ASSERT_NE(result, nullptr);
3269 ASSERT_EQ(PyErr_Occurred(), nullptr);
3270 EXPECT_TRUE(PyList_CheckExact(result));
3271}
3272
3273TEST_F(AbstractExtensionApiTest,
3274 PySequenceInPlaceConcatWithNullLeftRaisesSystemError) {
3275 PyObjectPtr right(PyLong_FromLong(1));
3276 EXPECT_EQ(PySequence_InPlaceConcat(nullptr, right), nullptr);
3277 ASSERT_NE(PyErr_Occurred(), nullptr);
3278 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3279}
3280
3281TEST_F(AbstractExtensionApiTest,
3282 PySequenceInPlaceConcatWithNullRightRaisesSystemError) {
3283 PyObjectPtr left(PyLong_FromLong(1));
3284 EXPECT_EQ(PySequence_InPlaceConcat(left, nullptr), nullptr);
3285 ASSERT_NE(PyErr_Occurred(), nullptr);
3286 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3287}
3288
3289TEST_F(AbstractExtensionApiTest,
3290 PySequenceInPlaceConcatWithByteArrayLeftReturnsByteArray) {
3291 PyObjectPtr left(PyByteArray_FromStringAndSize("foo", 3));
3292 PyObjectPtr right(PyBytes_FromString("bar"));
3293 PyObjectPtr result(PySequence_InPlaceConcat(left, right));
3294 EXPECT_EQ(PyErr_Occurred(), nullptr);
3295 EXPECT_EQ(result, left);
3296 EXPECT_STREQ(PyByteArray_AsString(left), "foobar");
3297}
3298
3299TEST_F(AbstractExtensionApiTest,
3300 PySequenceInPlaceConcatWithoutDunderGetItemRaisesTypeError) {
3301 PyRun_SimpleString(R"(
3302class C: pass
3303left = C()
3304)");
3305 PyObjectPtr left(mainModuleGet("left"));
3306 PyObjectPtr right(PyLong_FromLong(42));
3307 EXPECT_EQ(PySequence_InPlaceConcat(left, right), nullptr);
3308 ASSERT_NE(PyErr_Occurred(), nullptr);
3309 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3310}
3311
3312TEST_F(AbstractExtensionApiTest, PySequenceInPlaceConcatCallsDunderIadd) {
3313 PyRun_SimpleString(R"(
3314class C(list):
3315 def __add__(self, other):
3316 return 1
3317 def __iadd__(self, other):
3318 return 2
3319left = C()
3320right = (1, 2, 3)
3321)");
3322 PyObjectPtr left(mainModuleGet("left"));
3323 PyObjectPtr right(mainModuleGet("right"));
3324 PyObjectPtr result(PySequence_InPlaceConcat(left, right));
3325 EXPECT_EQ(PyErr_Occurred(), nullptr);
3326 ASSERT_TRUE(PyLong_CheckExact(result));
3327 EXPECT_EQ(PyLong_AsLong(result), 2);
3328}
3329
3330TEST_F(AbstractExtensionApiTest, PySequenceInPlaceConcatCallsDunderAdd) {
3331 PyRun_SimpleString(R"(
3332class C(tuple):
3333 def __add__(self, other):
3334 return 1
3335left = C()
3336right = (1, 2, 3)
3337)");
3338 PyObjectPtr left(mainModuleGet("left"));
3339 PyObjectPtr right(mainModuleGet("right"));
3340 PyObjectPtr result(PySequence_InPlaceConcat(left, right));
3341 EXPECT_EQ(PyErr_Occurred(), nullptr);
3342 ASSERT_TRUE(PyLong_CheckExact(result));
3343 EXPECT_EQ(PyLong_AsLong(result), 1);
3344}
3345
3346TEST_F(AbstractExtensionApiTest,
3347 PySequenceInPlaceRepeatWithNullRaisesSystemError) {
3348 EXPECT_EQ(PySequence_InPlaceRepeat(nullptr, 0), nullptr);
3349 ASSERT_NE(PyErr_Occurred(), nullptr);
3350 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3351}
3352
3353TEST_F(AbstractExtensionApiTest,
3354 PySequenceInPlaceRepeatWithoutDunderGetItemRaisesTypeError) {
3355 PyRun_SimpleString(R"(
3356class C: pass
3357obj = C()
3358)");
3359 PyObjectPtr obj(mainModuleGet("obj"));
3360 EXPECT_EQ(PySequence_InPlaceRepeat(obj, 42), nullptr);
3361 ASSERT_NE(PyErr_Occurred(), nullptr);
3362 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3363}
3364
3365TEST_F(AbstractExtensionApiTest, PySequenceInPlaceRepeatWithTupleReturnsTuple) {
3366 PyObjectPtr obj(Py_BuildValue("(ii)", 0, 1));
3367 ASSERT_EQ(PyTuple_Size(obj), 2);
3368 PyObjectPtr result(PySequence_InPlaceRepeat(obj, 3));
3369 EXPECT_EQ(PyErr_Occurred(), nullptr);
3370 EXPECT_EQ(PyTuple_Size(obj), 2);
3371 ASSERT_TRUE(PyTuple_CheckExact(result));
3372 EXPECT_EQ(PyTuple_Size(result), 6);
3373}
3374
3375TEST_F(AbstractExtensionApiTest, PySequenceInPlaceRepeatCallsDunderImul) {
3376 PyRun_SimpleString(R"(
3377class C(list):
3378 def __imul__(self, other):
3379 return 1
3380 def __mul__(self, other):
3381 return 2
3382obj = C()
3383)");
3384 PyObjectPtr obj(mainModuleGet("obj"));
3385 PyObjectPtr result(PySequence_InPlaceRepeat(obj, 0));
3386 EXPECT_EQ(PyErr_Occurred(), nullptr);
3387 ASSERT_TRUE(PyLong_CheckExact(result));
3388 EXPECT_EQ(PyLong_AsLong(result), 1);
3389}
3390
3391TEST_F(AbstractExtensionApiTest, PySequenceInPlaceRepeatCallsDunderMul) {
3392 PyRun_SimpleString(R"(
3393class C(tuple):
3394 def __mul__(self, other):
3395 return 1
3396obj = C()
3397)");
3398 PyObjectPtr obj(mainModuleGet("obj"));
3399 PyObjectPtr result(PySequence_InPlaceRepeat(obj, 0));
3400 EXPECT_EQ(PyErr_Occurred(), nullptr);
3401 ASSERT_TRUE(PyLong_CheckExact(result));
3402 EXPECT_EQ(PyLong_AsLong(result), 1);
3403}
3404
3405TEST_F(AbstractExtensionApiTest, PySequenceLengthOnNull) {
3406 EXPECT_EQ(PySequence_Length(nullptr), -1);
3407 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3408}
3409
3410TEST_F(AbstractExtensionApiTest, PySequenceLengthWithNonSequenceReturnsValue) {
3411 PyRun_SimpleString(R"(
3412class Foo:
3413 def __len__(self):
3414 return 1
3415obj = Foo()
3416)");
3417
3418 PyObjectPtr obj(mainModuleGet("obj"));
3419 EXPECT_EQ(PySequence_Length(obj), 1);
3420 EXPECT_EQ(PyErr_Occurred(), nullptr);
3421}
3422
3423// PySequence_Length fails on `dict` in CPython, but succeeds on subclasses
3424TEST_F(AbstractExtensionApiTest,
3425 PySequenceLengthWithEmptyDictSubclassReturnsZero) {
3426 PyRun_SimpleString(R"(
3427class Foo(dict):
3428 pass
3429obj = Foo()
3430)");
3431
3432 PyObjectPtr obj(mainModuleGet("obj"));
3433 EXPECT_EQ(PySequence_Length(obj), 0);
3434 EXPECT_EQ(PyErr_Occurred(), nullptr);
3435}
3436
3437TEST_F(AbstractExtensionApiTest,
3438 PySequenceLengthWithNonEmptyDictSubclassReturnsValue) {
3439 PyRun_SimpleString(R"(
3440class Foo(dict):
3441 pass
3442obj = Foo()
3443)");
3444
3445 PyObjectPtr obj(mainModuleGet("obj"));
3446 PyObjectPtr one(PyLong_FromLong(1));
3447 PyObjectPtr two(PyLong_FromLong(2));
3448
3449 ASSERT_EQ(PyDict_SetItem(obj, one, two), 0);
3450 ASSERT_EQ(PyDict_SetItem(obj, two, one), 0);
3451
3452 EXPECT_EQ(PySequence_Length(obj), 2);
3453 EXPECT_EQ(PyErr_Occurred(), nullptr);
3454}
3455
3456TEST_F(AbstractExtensionApiTest, PySequenceListWithNullSeqRaisesSystemError) {
3457 ASSERT_EQ(PySequence_List(nullptr), nullptr);
3458 ASSERT_NE(PyErr_Occurred(), nullptr);
3459 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3460}
3461
3462TEST_F(AbstractExtensionApiTest, PySequenceListWithNonIterableRaisesTypeError) {
3463 ASSERT_EQ(PySequence_List(Py_None), nullptr);
3464 ASSERT_NE(PyErr_Occurred(), nullptr);
3465 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3466}
3467
3468TEST_F(AbstractExtensionApiTest, PySequenceListReturnsList) {
3469 PyRun_SimpleString(R"(
3470class C:
3471 def __iter__(self):
3472 return (1, 2, 3).__iter__()
3473c = C()
3474)");
3475 PyObjectPtr c(mainModuleGet("c"));
3476 PyObjectPtr result(PySequence_List(c));
3477 ASSERT_NE(result, nullptr);
3478 ASSERT_EQ(PyErr_Occurred(), nullptr);
3479 EXPECT_TRUE(PyList_CheckExact(result));
3480 EXPECT_EQ(PyList_Size(result), 3);
3481}
3482
3483TEST_F(AbstractExtensionApiTest,
3484 PySequenceGetSliceWithNullSeqRaisesSystemError) {
3485 EXPECT_EQ(PySequence_GetSlice(nullptr, 1, 2), nullptr);
3486 ASSERT_NE(PyErr_Occurred(), nullptr);
3487 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3488}
3489
3490TEST_F(AbstractExtensionApiTest,
3491 PySequenceGetSliceWithNonIterableRaisesTypeError) {
3492 EXPECT_EQ(PySequence_GetSlice(Py_None, 1, 2), nullptr);
3493 ASSERT_NE(PyErr_Occurred(), nullptr);
3494 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3495}
3496
3497TEST_F(AbstractExtensionApiTest, PySequenceGetSliceCallsDunderGetItem) {
3498 PyRun_SimpleString(R"(
3499class C:
3500 def __getitem__(self, key):
3501 return 7
3502c = C()
3503)");
3504 PyObjectPtr c(mainModuleGet("c"));
3505 PyObjectPtr result(PySequence_GetSlice(c, 1, 2));
3506 ASSERT_NE(result, nullptr);
3507 ASSERT_EQ(PyErr_Occurred(), nullptr);
3508 ASSERT_TRUE(PyLong_Check(result));
3509 EXPECT_EQ(PyLong_AsLong(result), 7);
3510}
3511
3512TEST_F(AbstractExtensionApiTest,
3513 PySequenceSetSliceWithNullSeqRaisesSystemError) {
3514 PyObjectPtr obj(PyList_New(0));
3515 EXPECT_EQ(PySequence_SetSlice(nullptr, 1, 2, obj), -1);
3516 ASSERT_NE(PyErr_Occurred(), nullptr);
3517 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3518}
3519
3520TEST_F(AbstractExtensionApiTest,
3521 PySequenceSetSliceWithNonIterableRaisesTypeError) {
3522 PyObjectPtr obj(PyList_New(0));
3523 EXPECT_EQ(PySequence_SetSlice(Py_None, 1, 2, obj), -1);
3524 ASSERT_NE(PyErr_Occurred(), nullptr);
3525 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3526}
3527
3528TEST_F(AbstractExtensionApiTest, PySequenceSetSliceCallsDunderSetItem) {
3529 PyRun_SimpleString(R"(
3530sideeffect = 0
3531class C:
3532 def __setitem__(self, key, value):
3533 global sideeffect
3534 sideeffect = 10
3535c = C()
3536)");
3537 PyObjectPtr c(mainModuleGet("c"));
3538 PyObjectPtr obj(PyList_New(0));
3539 ASSERT_EQ(PySequence_SetSlice(c, 1, 2, obj), 0);
3540 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3541 ASSERT_EQ(PyErr_Occurred(), nullptr);
3542 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3543}
3544
3545TEST_F(AbstractExtensionApiTest,
3546 PySequenceSetSliceWithNullObjCallsDunderDelItem) {
3547 PyRun_SimpleString(R"(
3548sideeffect = 0
3549class C:
3550 def __delitem__(self, key):
3551 global sideeffect
3552 sideeffect = 10
3553c = C()
3554)");
3555 PyObjectPtr c(mainModuleGet("c"));
3556 EXPECT_EQ(PySequence_SetSlice(c, 1, 2, nullptr), 0);
3557 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3558 ASSERT_EQ(PyErr_Occurred(), nullptr);
3559 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3560}
3561
3562TEST_F(AbstractExtensionApiTest,
3563 PySequenceDelSliceWithNullSeqRaisesSystemError) {
3564 EXPECT_EQ(PySequence_DelSlice(nullptr, 1, 2), -1);
3565 ASSERT_NE(PyErr_Occurred(), nullptr);
3566 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3567}
3568
3569TEST_F(AbstractExtensionApiTest,
3570 PySequenceDelSliceWithNonIterableRaisesTypeError) {
3571 EXPECT_EQ(PySequence_DelSlice(Py_None, 1, 2), -1);
3572 ASSERT_NE(PyErr_Occurred(), nullptr);
3573 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3574}
3575
3576TEST_F(AbstractExtensionApiTest, PySequenceDelSliceCallsDunderDelItem) {
3577 PyRun_SimpleString(R"(
3578sideeffect = 0
3579class C:
3580 def __delitem__(self, key):
3581 global sideeffect
3582 sideeffect = 10
3583c = C()
3584)");
3585 PyObjectPtr c(mainModuleGet("c"));
3586 EXPECT_EQ(PySequence_DelSlice(c, 1, 2), 0);
3587 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3588 ASSERT_EQ(PyErr_Occurred(), nullptr);
3589 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3590}
3591
3592TEST_F(AbstractExtensionApiTest, ObjectDelItemWithNullObjRaisesSystemError) {
3593 PyObjectPtr obj(PyLong_FromLong(1));
3594 EXPECT_EQ(PyObject_DelItem(nullptr, obj), -1);
3595 ASSERT_NE(PyErr_Occurred(), nullptr);
3596 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3597}
3598
3599TEST_F(AbstractExtensionApiTest, ObjectDelItemWithNullKeyRaisesSystemError) {
3600 PyObjectPtr obj(PyLong_FromLong(1));
3601 EXPECT_EQ(PyObject_DelItem(obj, nullptr), -1);
3602 ASSERT_NE(PyErr_Occurred(), nullptr);
3603 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3604}
3605
3606TEST_F(AbstractExtensionApiTest, ObjectDelItemCallsDunderDelItem) {
3607 PyRun_SimpleString(R"(
3608sideeffect = 0
3609class C:
3610 def __delitem__(self, key):
3611 global sideeffect
3612 sideeffect = 10
3613
3614c = C()
3615)");
3616 PyObjectPtr c(mainModuleGet("c"));
3617 PyObjectPtr key(PyLong_FromLong(7));
3618 EXPECT_EQ(PyObject_DelItem(c, key), 0);
3619 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3620 EXPECT_EQ(PyErr_Occurred(), nullptr);
3621 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3622}
3623
3624TEST_F(AbstractExtensionApiTest, ObjectDelItemPropagatesDelItemException) {
3625 PyRun_SimpleString(R"(
3626class C:
3627 def __delitem__(self, key):
3628 raise TypeError
3629
3630c = C()
3631)");
3632 PyObjectPtr c(mainModuleGet("c"));
3633 PyObjectPtr key(PyLong_FromLong(7));
3634 EXPECT_EQ(PyObject_DelItem(c, key), -1);
3635 ASSERT_NE(PyErr_Occurred(), nullptr);
3636 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3637}
3638
3639TEST_F(AbstractExtensionApiTest,
3640 ObjectDelItemStringWithNullObjRaisesSystemError) {
3641 EXPECT_EQ(PyObject_DelItemString(nullptr, "hello"), -1);
3642 ASSERT_NE(PyErr_Occurred(), nullptr);
3643 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3644}
3645
3646TEST_F(AbstractExtensionApiTest,
3647 ObjectDelItemStringWithNullKeyRaisesSystemError) {
3648 PyObjectPtr obj(PyLong_FromLong(1));
3649 EXPECT_EQ(PyObject_DelItemString(obj, nullptr), -1);
3650 ASSERT_NE(PyErr_Occurred(), nullptr);
3651 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3652}
3653
3654TEST_F(AbstractExtensionApiTest, ObjectDelItemStringCallsDunderDelItem) {
3655 PyRun_SimpleString(R"(
3656sideeffect = 0
3657class C:
3658 def __delitem__(self, key):
3659 global sideeffect
3660 sideeffect = 10
3661
3662c = C()
3663)");
3664 PyObjectPtr c(mainModuleGet("c"));
3665 EXPECT_EQ(PyObject_DelItemString(c, "hello"), 0);
3666 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3667 EXPECT_EQ(PyErr_Occurred(), nullptr);
3668 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3669}
3670
3671TEST_F(AbstractExtensionApiTest,
3672 ObjectDelItemStringPropagatesDelitemException) {
3673 PyRun_SimpleString(R"(
3674class C:
3675 def __delitem__(self, key):
3676 raise TypeError
3677
3678c = C()
3679)");
3680 PyObjectPtr c(mainModuleGet("c"));
3681 EXPECT_EQ(PyObject_DelItemString(c, "hello"), -1);
3682 ASSERT_NE(PyErr_Occurred(), nullptr);
3683 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3684}
3685
3686TEST_F(AbstractExtensionApiTest, PySequenceSizeWithNullRaisesSystemError) {
3687 EXPECT_EQ(PySequence_Size(nullptr), -1);
3688 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3689}
3690
3691TEST_F(AbstractExtensionApiTest, PySequenceTupleWithNullSeqRaisesSystemError) {
3692 EXPECT_EQ(PySequence_Tuple(nullptr), nullptr);
3693 ASSERT_NE(PyErr_Occurred(), nullptr);
3694 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3695}
3696
3697TEST_F(AbstractExtensionApiTest,
3698 PySequenceTupleWithNonIterableRaisesTypeError) {
3699 EXPECT_EQ(PySequence_Tuple(Py_None), nullptr);
3700 ASSERT_NE(PyErr_Occurred(), nullptr);
3701 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3702}
3703
3704TEST_F(AbstractExtensionApiTest, PySequenceTupleReturnsTuple) {
3705 PyRun_SimpleString(R"(
3706class C:
3707 def __iter__(self):
3708 return [1, 2, 3].__iter__()
3709c = C()
3710)");
3711 PyObjectPtr c(mainModuleGet("c"));
3712 PyObjectPtr result(PySequence_Tuple(c));
3713 ASSERT_NE(result, nullptr);
3714 ASSERT_EQ(PyErr_Occurred(), nullptr);
3715 EXPECT_TRUE(PyTuple_CheckExact(result));
3716 EXPECT_EQ(PyTuple_Size(result), 3);
3717}
3718
3719TEST_F(AbstractExtensionApiTest, ObjectGetItemWithNullObjRaisesSystemError) {
3720 PyObjectPtr obj(PyLong_FromLong(1));
3721 EXPECT_EQ(PyObject_GetItem(nullptr, obj), nullptr);
3722 ASSERT_NE(PyErr_Occurred(), nullptr);
3723 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3724}
3725
3726TEST_F(AbstractExtensionApiTest, ObjectGetItemWithNullKeyRaisesSystemError) {
3727 PyObjectPtr obj(PyLong_FromLong(1));
3728 EXPECT_EQ(PyObject_GetItem(obj, nullptr), nullptr);
3729 ASSERT_NE(PyErr_Occurred(), nullptr);
3730 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3731}
3732
3733TEST_F(AbstractExtensionApiTest,
3734 ObjectGetItemWithNoDunderGetItemRaisesTypeError) {
3735 PyRun_SimpleString(R"(
3736class C:
3737 pass
3738c = C()
3739)");
3740 PyObjectPtr c(mainModuleGet("c"));
3741 PyObjectPtr key(PyLong_FromLong(7));
3742 EXPECT_EQ(PyObject_GetItem(c, key), nullptr);
3743 ASSERT_NE(PyErr_Occurred(), nullptr);
3744 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3745}
3746
3747TEST_F(AbstractExtensionApiTest,
3748 ObjectGetItemWithUncallableDunderGetItemRaisesTypeError) {
3749 PyRun_SimpleString(R"(
3750class C:
3751 __getitem__ = 4
3752c = C()
3753)");
3754 PyObjectPtr c(mainModuleGet("c"));
3755 PyObjectPtr key(PyLong_FromLong(7));
3756 EXPECT_EQ(PyObject_GetItem(c, key), nullptr);
3757 ASSERT_NE(PyErr_Occurred(), nullptr);
3758 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3759}
3760
3761TEST_F(AbstractExtensionApiTest, ObjectGetItemCallsDunderGetItem) {
3762 PyRun_SimpleString(R"(
3763class C:
3764 def __getitem__(self, key):
3765 return key
3766c = C()
3767)");
3768 PyObjectPtr c(mainModuleGet("c"));
3769 PyObjectPtr key(PyLong_FromLong(7));
3770 PyObjectPtr result(PyObject_GetItem(c, key));
3771 EXPECT_EQ(result, key);
3772 EXPECT_EQ(PyErr_Occurred(), nullptr);
3773}
3774
3775TEST_F(AbstractExtensionApiTest, ObjectGetItemPropagatesException) {
3776 PyRun_SimpleString(R"(
3777class C:
3778 def __getitem__(self, key):
3779 raise IndexError
3780c = C()
3781)");
3782 PyObjectPtr c(mainModuleGet("c"));
3783 PyObjectPtr key(PyLong_FromLong(7));
3784 EXPECT_EQ(PyObject_GetItem(c, key), nullptr);
3785 ASSERT_NE(PyErr_Occurred(), nullptr);
3786 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError));
3787}
3788
3789TEST_F(AbstractExtensionApiTest,
3790 MappingGetItemStringWithNullObjRaisesSystemError) {
3791 EXPECT_EQ(PyMapping_GetItemString(nullptr, "hello"), nullptr);
3792 ASSERT_NE(PyErr_Occurred(), nullptr);
3793 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3794}
3795
3796TEST_F(AbstractExtensionApiTest,
3797 MappingGetItemStringWithNullKeyRaisesSystemError) {
3798 PyObjectPtr obj(PyLong_FromLong(1));
3799 EXPECT_EQ(PyMapping_GetItemString(obj, nullptr), nullptr);
3800 ASSERT_NE(PyErr_Occurred(), nullptr);
3801 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
3802}
3803
3804TEST_F(AbstractExtensionApiTest,
3805 MappingGetItemStringWithNoDunderGetItemRaisesTypeError) {
3806 PyRun_SimpleString(R"(
3807class C:
3808 pass
3809c = C()
3810)");
3811 PyObjectPtr c(mainModuleGet("c"));
3812 EXPECT_EQ(PyMapping_GetItemString(c, "hello"), nullptr);
3813 ASSERT_NE(PyErr_Occurred(), nullptr);
3814 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3815}
3816
3817TEST_F(AbstractExtensionApiTest,
3818 MappingGetItemStringWithUncallableDunderGetItemRaisesTypeError) {
3819 PyRun_SimpleString(R"(
3820class C:
3821 __getitem__ = 4
3822c = C()
3823)");
3824 PyObjectPtr c(mainModuleGet("c"));
3825 EXPECT_EQ(PyMapping_GetItemString(c, "hello"), nullptr);
3826 ASSERT_NE(PyErr_Occurred(), nullptr);
3827 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
3828}
3829
3830TEST_F(AbstractExtensionApiTest, MappingGetItemStringCallsDunderGetItem) {
3831 PyRun_SimpleString(R"(
3832class C:
3833 def __getitem__(self, key):
3834 return key
3835c = C()
3836)");
3837 PyObjectPtr c(mainModuleGet("c"));
3838 const char* key = "hello";
3839 PyObjectPtr result(PyMapping_GetItemString(c, key));
3840 EXPECT_EQ(PyErr_Occurred(), nullptr);
3841 EXPECT_TRUE(isUnicodeEqualsCStr(result, key));
3842}
3843
3844TEST_F(AbstractExtensionApiTest, MappingGetItemStringPropagatesException) {
3845 PyRun_SimpleString(R"(
3846class C:
3847 def __getitem__(self, key):
3848 raise IndexError
3849c = C()
3850)");
3851 PyObjectPtr c(mainModuleGet("c"));
3852 EXPECT_EQ(PyMapping_GetItemString(c, "hello"), nullptr);
3853 ASSERT_NE(PyErr_Occurred(), nullptr);
3854 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError));
3855}
3856
3857TEST_F(AbstractExtensionApiTest, MappingHasKeyWithNullObjReturnsFalse) {
3858 PyObjectPtr obj(PyLong_FromLong(7));
3859 EXPECT_EQ(PyMapping_HasKey(nullptr, obj), 0);
3860 EXPECT_EQ(PyErr_Occurred(), nullptr);
3861}
3862
3863TEST_F(AbstractExtensionApiTest, MappingHasKeyWithNullKeyReturnsFalse) {
3864 PyObjectPtr obj(PyLong_FromLong(7));
3865 EXPECT_EQ(PyMapping_HasKey(obj, nullptr), 0);
3866 EXPECT_EQ(PyErr_Occurred(), nullptr);
3867}
3868
3869TEST_F(AbstractExtensionApiTest, MappingHasKeyCallsDunderGetItem) {
3870 PyRun_SimpleString(R"(
3871sideeffect = 0
3872class C:
3873 def __getitem__(self, key):
3874 global sideeffect
3875 sideeffect = 10
3876c = C()
3877)");
3878 PyObjectPtr c(mainModuleGet("c"));
3879 PyObjectPtr key(PyLong_FromLong(7));
3880 ASSERT_EQ(PyMapping_HasKey(c, key), 1);
3881 ASSERT_EQ(PyErr_Occurred(), nullptr);
3882 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3883 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3884}
3885
3886TEST_F(AbstractExtensionApiTest,
3887 MappingHasKeyReturnsFalseWhenExceptionIsRaised) {
3888 PyRun_SimpleString(R"(
3889class C:
3890 def __getitem__(self, key):
3891 raise IndexError
3892c = C()
3893)");
3894 PyObjectPtr c(mainModuleGet("c"));
3895 PyObjectPtr key(PyLong_FromLong(7));
3896 EXPECT_EQ(PyMapping_HasKey(c, key), 0);
3897 EXPECT_EQ(PyErr_Occurred(), nullptr);
3898}
3899
3900TEST_F(AbstractExtensionApiTest, MappingHasKeyStringWithNullObjReturnsFalse) {
3901 EXPECT_EQ(PyMapping_HasKeyString(nullptr, "hello"), 0);
3902 EXPECT_EQ(PyErr_Occurred(), nullptr);
3903}
3904
3905TEST_F(AbstractExtensionApiTest, MappingHasKeyStringWithNullKeyReturnsFalse) {
3906 PyObjectPtr obj(PyLong_FromLong(7));
3907 EXPECT_EQ(PyMapping_HasKeyString(obj, nullptr), 0);
3908 EXPECT_EQ(PyErr_Occurred(), nullptr);
3909}
3910
3911TEST_F(AbstractExtensionApiTest, MappingHasKeyStringCallsDunderGetItem) {
3912 PyRun_SimpleString(R"(
3913sideeffect = 0
3914class C:
3915 def __getitem__(self, key):
3916 global sideeffect
3917 sideeffect = 10
3918c = C()
3919)");
3920 PyObjectPtr c(mainModuleGet("c"));
3921 ASSERT_EQ(PyMapping_HasKeyString(c, "hello"), 1);
3922 ASSERT_EQ(PyErr_Occurred(), nullptr);
3923 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
3924 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
3925}
3926
3927TEST_F(AbstractExtensionApiTest,
3928 MappingHasKeyStringReturnsFalseWhenExceptionIsRaised) {
3929 PyRun_SimpleString(R"(
3930class C:
3931 def __getitem__(self, key):
3932 raise IndexError
3933c = C()
3934)");
3935 PyObjectPtr c(mainModuleGet("c"));
3936 EXPECT_EQ(PyMapping_HasKeyString(c, "hello"), 0);
3937 EXPECT_EQ(PyErr_Occurred(), nullptr);
3938}
3939
3940TEST_F(AbstractExtensionApiTest, MappingKeysWithNoKeysRaisesAttributeError) {
3941 PyRun_SimpleString(R"(
3942class C:
3943 pass
3944c = C()
3945)");
3946 PyObjectPtr c(mainModuleGet("c"));
3947 EXPECT_EQ(PyMapping_Keys(c), nullptr);
3948 ASSERT_NE(PyErr_Occurred(), nullptr);
3949 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError));
3950}
3951
3952TEST_F(AbstractExtensionApiTest, MappingKeysCallsReturnsListOfKeys) {
3953 PyRun_SimpleString(R"(
3954class C:
3955 def keys(self):
3956 return ["hello", "world"]
3957c = C()
3958)");
3959 PyObjectPtr c(mainModuleGet("c"));
3960 PyObjectPtr result(PyMapping_Keys(c));
3961 ASSERT_NE(result, nullptr);
3962 ASSERT_TRUE(PyList_Check(result));
3963 ASSERT_EQ(PyList_Size(result), 2);
3964 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
3965 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
3966}
3967
3968TEST_F(AbstractExtensionApiTest, MappingKeysCallsReturnsListOfKeysSequence) {
3969 PyRun_SimpleString(R"(
3970class C:
3971 def keys(self):
3972 return ("hello", "world").__iter__()
3973c = C()
3974)");
3975 PyObjectPtr c(mainModuleGet("c"));
3976 PyObjectPtr result(PyMapping_Keys(c));
3977 ASSERT_NE(result, nullptr);
3978 ASSERT_TRUE(PyList_Check(result));
3979 ASSERT_EQ(PyList_Size(result), 2);
3980 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
3981 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
3982}
3983
3984TEST_F(AbstractExtensionApiTest, MappingKeysWithDictSubclassCallsKeys) {
3985 PyRun_SimpleString(R"(
3986class C(dict):
3987 def keys(self):
3988 return ("hello", "world").__iter__()
3989c = C()
3990c["a"] = 1
3991c["b"] = 2
3992c["c"] = 3
3993)");
3994 PyObjectPtr c(mainModuleGet("c"));
3995 PyObjectPtr result(PyMapping_Keys(c));
3996 ASSERT_NE(result, nullptr);
3997 ASSERT_TRUE(PyList_Check(result));
3998 ASSERT_EQ(PyList_Size(result), 2);
3999 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4000 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4001}
4002
4003TEST_F(AbstractExtensionApiTest, MappingItemsWithNoItemsRaisesAttributeError) {
4004 PyRun_SimpleString(R"(
4005class C:
4006 pass
4007c = C()
4008)");
4009 PyObjectPtr c(mainModuleGet("c"));
4010 EXPECT_EQ(PyMapping_Items(c), nullptr);
4011 ASSERT_NE(PyErr_Occurred(), nullptr);
4012 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError));
4013}
4014
4015TEST_F(AbstractExtensionApiTest, MappingItemsCallsReturnsListOfItems) {
4016 PyRun_SimpleString(R"(
4017class C:
4018 def items(self):
4019 return ["hello", "world"]
4020c = C()
4021)");
4022 PyObjectPtr c(mainModuleGet("c"));
4023 PyObjectPtr result(PyMapping_Items(c));
4024 ASSERT_NE(result, nullptr);
4025 ASSERT_TRUE(PyList_Check(result));
4026 ASSERT_EQ(PyList_Size(result), 2);
4027 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4028 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4029}
4030
4031TEST_F(AbstractExtensionApiTest, MappingItemsCallsReturnsListOfItemsSequence) {
4032 PyRun_SimpleString(R"(
4033class C:
4034 def items(self):
4035 return ("hello", "world").__iter__()
4036c = C()
4037)");
4038 PyObjectPtr c(mainModuleGet("c"));
4039 PyObjectPtr result(PyMapping_Items(c));
4040 ASSERT_NE(result, nullptr);
4041 ASSERT_TRUE(PyList_Check(result));
4042 ASSERT_EQ(PyList_Size(result), 2);
4043 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4044 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4045}
4046
4047TEST_F(AbstractExtensionApiTest, MappingItemsWithDictSubclassCallsItems) {
4048 PyRun_SimpleString(R"(
4049class C(dict):
4050 def items(self):
4051 return ("hello", "world").__iter__()
4052c = C()
4053c["a"] = 1
4054c["b"] = 2
4055c["c"] = 3
4056)");
4057 PyObjectPtr c(mainModuleGet("c"));
4058 PyObjectPtr result(PyMapping_Items(c));
4059 ASSERT_NE(result, nullptr);
4060 ASSERT_TRUE(PyList_Check(result));
4061 ASSERT_EQ(PyList_Size(result), 2);
4062 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4063 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4064}
4065
4066TEST_F(AbstractExtensionApiTest,
4067 MappingValuesWithNoValuesRaisesAttributeError) {
4068 PyRun_SimpleString(R"(
4069class C:
4070 pass
4071c = C()
4072)");
4073 PyObjectPtr c(mainModuleGet("c"));
4074 EXPECT_EQ(PyMapping_Values(c), nullptr);
4075 ASSERT_NE(PyErr_Occurred(), nullptr);
4076 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError));
4077}
4078
4079TEST_F(AbstractExtensionApiTest, MappingValuesCallsReturnsListOfValues) {
4080 PyRun_SimpleString(R"(
4081class C:
4082 def values(self):
4083 return ["hello", "world"]
4084c = C()
4085)");
4086 PyObjectPtr c(mainModuleGet("c"));
4087 PyObjectPtr result(PyMapping_Values(c));
4088 ASSERT_NE(result, nullptr);
4089 ASSERT_TRUE(PyList_Check(result));
4090 ASSERT_EQ(PyList_Size(result), 2);
4091 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4092 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4093}
4094
4095TEST_F(AbstractExtensionApiTest,
4096 MappingValuesCallsReturnsListOfValuesSequence) {
4097 PyRun_SimpleString(R"(
4098class C:
4099 def values(self):
4100 return ("hello", "world").__iter__()
4101c = C()
4102)");
4103 PyObjectPtr c(mainModuleGet("c"));
4104 PyObjectPtr result(PyMapping_Values(c));
4105 ASSERT_NE(result, nullptr);
4106 ASSERT_TRUE(PyList_Check(result));
4107 ASSERT_EQ(PyList_Size(result), 2);
4108 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4109 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4110}
4111
4112TEST_F(AbstractExtensionApiTest, MappingValuesWithDictSubclassCallsValues) {
4113 PyRun_SimpleString(R"(
4114class C(dict):
4115 def values(self):
4116 return ("hello", "world").__iter__()
4117c = C()
4118c["a"] = 1
4119c["b"] = 2
4120c["c"] = 3
4121)");
4122 PyObjectPtr c(mainModuleGet("c"));
4123 PyObjectPtr result(PyMapping_Values(c));
4124 ASSERT_NE(result, nullptr);
4125 ASSERT_TRUE(PyList_Check(result));
4126 ASSERT_EQ(PyList_Size(result), 2);
4127 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 0), "hello"));
4128 EXPECT_TRUE(isUnicodeEqualsCStr(PyList_GetItem(result, 1), "world"));
4129}
4130
4131TEST_F(AbstractExtensionApiTest, ObjectSetItemWithNullObjRaisesSystemError) {
4132 PyObjectPtr obj(PyLong_FromLong(1));
4133 EXPECT_EQ(PyObject_SetItem(nullptr, obj, obj), -1);
4134 ASSERT_NE(PyErr_Occurred(), nullptr);
4135 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4136}
4137
4138TEST_F(AbstractExtensionApiTest, ObjectSetItemWithNullKeyRaisesSystemError) {
4139 PyObjectPtr obj(PyLong_FromLong(1));
4140 EXPECT_EQ(PyObject_SetItem(obj, nullptr, obj), -1);
4141 ASSERT_NE(PyErr_Occurred(), nullptr);
4142 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4143}
4144
4145TEST_F(AbstractExtensionApiTest, ObjectSetItemWithNullValueRaisesSystemError) {
4146 PyObjectPtr obj(PyLong_FromLong(1));
4147 EXPECT_EQ(PyObject_SetItem(obj, obj, nullptr), -1);
4148 ASSERT_NE(PyErr_Occurred(), nullptr);
4149 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4150}
4151
4152TEST_F(AbstractExtensionApiTest,
4153 ObjectSetItemWithNoDunderSetItemRaisesTypeError) {
4154 PyRun_SimpleString(R"(
4155class C:
4156 pass
4157c = C()
4158)");
4159 PyObjectPtr c(mainModuleGet("c"));
4160 PyObjectPtr obj(PyLong_FromLong(1));
4161 EXPECT_EQ(PyObject_SetItem(c, obj, obj), -1);
4162 ASSERT_NE(PyErr_Occurred(), nullptr);
4163 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4164}
4165
4166TEST_F(AbstractExtensionApiTest,
4167 ObjectSetItemWithUncallableDunderSetItemRaisesTypeError) {
4168 PyRun_SimpleString(R"(
4169class C:
4170 __setitem__ = 4
4171c = C()
4172)");
4173 PyObjectPtr c(mainModuleGet("c"));
4174 PyObjectPtr obj(PyLong_FromLong(1));
4175 EXPECT_EQ(PyObject_SetItem(c, obj, obj), -1);
4176 ASSERT_NE(PyErr_Occurred(), nullptr);
4177 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4178}
4179
4180TEST_F(AbstractExtensionApiTest, ObjectSetItemCallsDunderSetItem) {
4181 PyRun_SimpleString(R"(
4182sideeffect = 0
4183class C:
4184 def __setitem__(self, key, val):
4185 global sideeffect
4186 sideeffect = 10
4187c = C()
4188)");
4189 PyObjectPtr c(mainModuleGet("c"));
4190 PyObjectPtr obj(PyLong_FromLong(1));
4191 ASSERT_EQ(PyObject_SetItem(c, obj, obj), 0);
4192 ASSERT_EQ(PyErr_Occurred(), nullptr);
4193 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
4194 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
4195}
4196
4197TEST_F(AbstractExtensionApiTest, ObjectSetItemPropagatesException) {
4198 PyRun_SimpleString(R"(
4199class C:
4200 def __setitem__(self, key, value):
4201 raise IndexError
4202c = C()
4203)");
4204 PyObjectPtr c(mainModuleGet("c"));
4205 PyObjectPtr obj(PyLong_FromLong(7));
4206 EXPECT_EQ(PyObject_SetItem(c, obj, obj), -1);
4207 ASSERT_NE(PyErr_Occurred(), nullptr);
4208 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError));
4209}
4210
4211TEST_F(AbstractExtensionApiTest,
4212 MappingSetItemStringWithNullObjRaisesSystemError) {
4213 PyObjectPtr obj(PyLong_FromLong(1));
4214 EXPECT_EQ(PyMapping_SetItemString(nullptr, "hello", obj), -1);
4215 ASSERT_NE(PyErr_Occurred(), nullptr);
4216 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4217}
4218
4219TEST_F(AbstractExtensionApiTest,
4220 MappingSetItemStringWithNullKeyRaisesSystemError) {
4221 PyObjectPtr obj(PyLong_FromLong(1));
4222 EXPECT_EQ(PyMapping_SetItemString(obj, nullptr, obj), -1);
4223 ASSERT_NE(PyErr_Occurred(), nullptr);
4224 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4225}
4226
4227TEST_F(AbstractExtensionApiTest,
4228 MappingSetItemStringWithNullValueRaisesSystemError) {
4229 PyObjectPtr obj(PyLong_FromLong(1));
4230 EXPECT_EQ(PyMapping_SetItemString(obj, "hello", nullptr), -1);
4231 ASSERT_NE(PyErr_Occurred(), nullptr);
4232 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
4233}
4234
4235TEST_F(AbstractExtensionApiTest,
4236 MappingSetItemStringWithNoDunderSetItemRaisesTypeError) {
4237 PyRun_SimpleString(R"(
4238class C:
4239 pass
4240c = C()
4241)");
4242 PyObjectPtr c(mainModuleGet("c"));
4243 PyObjectPtr obj(PyLong_FromLong(1));
4244 EXPECT_EQ(PyMapping_SetItemString(c, "hello", obj), -1);
4245 ASSERT_NE(PyErr_Occurred(), nullptr);
4246 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4247}
4248
4249TEST_F(AbstractExtensionApiTest,
4250 MappingSetItemStringWithUncallableDunderSetItemRaisesTypeError) {
4251 PyRun_SimpleString(R"(
4252class C:
4253 __setitem__ = 4
4254c = C()
4255)");
4256 PyObjectPtr c(mainModuleGet("c"));
4257 PyObjectPtr obj(PyLong_FromLong(1));
4258 EXPECT_EQ(PyMapping_SetItemString(c, "hello", obj), -1);
4259 ASSERT_NE(PyErr_Occurred(), nullptr);
4260 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4261}
4262
4263TEST_F(AbstractExtensionApiTest, MappingSetItemStringCallsDunderSetItem) {
4264 PyRun_SimpleString(R"(
4265sideeffect = 0
4266class C:
4267 def __setitem__(self, key, val):
4268 global sideeffect
4269 sideeffect = 10
4270c = C()
4271)");
4272 PyObjectPtr c(mainModuleGet("c"));
4273 PyObjectPtr obj(PyLong_FromLong(1));
4274 ASSERT_EQ(PyMapping_SetItemString(c, "hello", obj), 0);
4275 ASSERT_EQ(PyErr_Occurred(), nullptr);
4276 PyObjectPtr sideeffect(mainModuleGet("sideeffect"));
4277 EXPECT_EQ(PyLong_AsLong(sideeffect), 10);
4278}
4279
4280TEST_F(AbstractExtensionApiTest, MappingSetItemStringPropagatesException) {
4281 PyRun_SimpleString(R"(
4282class C:
4283 def __setitem__(self, key, value):
4284 raise IndexError
4285c = C()
4286)");
4287 PyObjectPtr c(mainModuleGet("c"));
4288 PyObjectPtr obj(PyLong_FromLong(7));
4289 EXPECT_EQ(PyMapping_SetItemString(c, "hello", obj), -1);
4290 ASSERT_NE(PyErr_Occurred(), nullptr);
4291 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError));
4292}
4293
4294TEST_F(AbstractExtensionApiTest,
4295 ObjectFormatWithNonStrFormatSpecRaisesTypeErrorPyro) {
4296 EXPECT_EQ(PyObject_Format(Py_None, Py_None), nullptr);
4297 ASSERT_NE(PyErr_Occurred(), nullptr);
4298 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4299}
4300
4301TEST_F(AbstractExtensionApiTest, ObjectFormatCallsDunderFormat) {
4302 PyRun_SimpleString(R"(
4303last_arguments = None
4304class C:
4305 def __format__(self, format_spec):
4306 global last_arguments
4307 last_arguments = (self, format_spec)
4308 return "foo"
4309c = C()
4310)");
4311 PyObjectPtr c(mainModuleGet("c"));
4312 PyObjectPtr fmt(PyUnicode_FromString("foo"));
4313 PyObjectPtr result(PyObject_Format(c, fmt));
4314 ASSERT_EQ(PyErr_Occurred(), nullptr);
4315 EXPECT_TRUE(isUnicodeEqualsCStr(result, "foo"));
4316 PyObjectPtr last_arguments(mainModuleGet("last_arguments"));
4317 ASSERT_TRUE(PyTuple_Check(last_arguments));
4318 EXPECT_EQ(PyTuple_GetItem(last_arguments, 0), c);
4319 EXPECT_EQ(PyTuple_GetItem(last_arguments, 1), fmt);
4320}
4321
4322TEST_F(AbstractExtensionApiTest,
4323 ObjectFormatWithDunderFormatReturningNonStrRaisesTypeError) {
4324 PyRun_SimpleString(R"(
4325class C:
4326 def __format__(self, format_spec):
4327 return 7
4328c = C()
4329)");
4330 PyObjectPtr c(mainModuleGet("c"));
4331 EXPECT_EQ(PyObject_Format(c, nullptr), nullptr);
4332 ASSERT_NE(PyErr_Occurred(), nullptr);
4333 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
4334}
4335
4336} // namespace testing
4337} // namespace py