this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "Python.h"
3#include "gtest/gtest.h"
4
5#include "capi-fixture.h"
6#include "capi-testing.h"
7
8namespace py {
9namespace testing {
10
11using SetExtensionApiTest = ExtensionApi;
12
13TEST_F(SetExtensionApiTest, AddWithNonSetReturnsNegative) {
14 PyObjectPtr dict(PyDict_New());
15 PyObjectPtr key(PyLong_FromLong(1));
16
17 EXPECT_EQ(PySet_Add(dict, key), -1);
18 ASSERT_NE(PyErr_Occurred(), nullptr);
19 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
20}
21
22TEST_F(SetExtensionApiTest, AnySetCheckWithNonSetReturnsFalse) {
23 PyObjectPtr set(PyDict_New());
24 EXPECT_FALSE(PyAnySet_Check(set));
25}
26
27TEST_F(SetExtensionApiTest, AnySetCheckWithAnySetSubclassReturnsTrue) {
28 PyRun_SimpleString(R"(
29class FrozenSub(frozenset):
30 pass
31class SetSub(set):
32 pass
33frozen_instance = FrozenSub()
34set_instance = SetSub()
35)");
36 PyObjectPtr frozen(mainModuleGet("frozen_instance"));
37 PyObjectPtr set(mainModuleGet("set_instance"));
38 EXPECT_TRUE(PyAnySet_Check(frozen));
39 EXPECT_TRUE(PyAnySet_Check(set));
40}
41
42TEST_F(SetExtensionApiTest, AnySetCheckWithAnySetReturnsTrue) {
43 PyObjectPtr frozenset(PyFrozenSet_New(nullptr));
44 PyObjectPtr set(PySet_New(nullptr));
45 EXPECT_TRUE(PyAnySet_Check(frozenset));
46 EXPECT_TRUE(PyAnySet_Check(set));
47}
48
49TEST_F(SetExtensionApiTest, AnySetCheckExactWithNonSetReturnsFalse) {
50 PyObjectPtr set(PyDict_New());
51 EXPECT_FALSE(PyAnySet_CheckExact(set));
52}
53
54TEST_F(SetExtensionApiTest, AnySetCheckExactWithAnySetSubclassReturnsFalse) {
55 PyRun_SimpleString(R"(
56class FrozenSub(frozenset):
57 pass
58class SetSub(set):
59 pass
60frozen_instance = FrozenSub()
61set_instance = SetSub()
62)");
63 PyObjectPtr frozen(mainModuleGet("frozen_instance"));
64 PyObjectPtr set(mainModuleGet("set_instance"));
65 EXPECT_FALSE(PyAnySet_CheckExact(frozen));
66 EXPECT_FALSE(PyAnySet_CheckExact(set));
67}
68
69TEST_F(SetExtensionApiTest, AnySetCheckExactWithAnySetReturnsTrue) {
70 PyObjectPtr frozenset(PyFrozenSet_New(nullptr));
71 PyObjectPtr set(PySet_New(nullptr));
72 EXPECT_TRUE(PyAnySet_CheckExact(frozenset));
73 EXPECT_TRUE(PyAnySet_CheckExact(set));
74}
75
76TEST_F(SetExtensionApiTest, FrozenSetCheckWithSetReturnsFalse) {
77 PyObjectPtr set(PySet_New(nullptr));
78 EXPECT_FALSE(PyFrozenSet_Check(set));
79}
80
81TEST_F(SetExtensionApiTest, FrozenSetCheckWithFrozenSetSubclassReturnsTrue) {
82 PyRun_SimpleString(R"(
83class C(frozenset):
84 pass
85c = C()
86)");
87 PyObjectPtr c(mainModuleGet("c"));
88 EXPECT_TRUE(PyFrozenSet_Check(c));
89}
90
91TEST_F(SetExtensionApiTest, FrozenSetCheckWithFrozenSetReturnsTrue) {
92 PyObjectPtr set(PyFrozenSet_New(nullptr));
93 EXPECT_TRUE(PyFrozenSet_Check(set));
94}
95
96TEST_F(SetExtensionApiTest, FrozenSetCheckExactWithSetReturnsFalse) {
97 PyObjectPtr set(PySet_New(nullptr));
98 EXPECT_FALSE(PyFrozenSet_CheckExact(set));
99}
100
101TEST_F(SetExtensionApiTest,
102 FrozenSetCheckExactWithFrozenSetSubclassReturnsFalse) {
103 PyRun_SimpleString(R"(
104class C(frozenset):
105 pass
106c = C()
107)");
108 PyObjectPtr c(mainModuleGet("c"));
109 EXPECT_FALSE(PyFrozenSet_CheckExact(c));
110}
111
112TEST_F(SetExtensionApiTest, FrozenSetCheckExactWithFrozenSetReturnsTrue) {
113 PyObjectPtr set(PyFrozenSet_New(nullptr));
114 EXPECT_TRUE(PyFrozenSet_CheckExact(set));
115}
116
117TEST_F(SetExtensionApiTest, SetCheckWithFrozenSetReturnsFalse) {
118 PyObjectPtr set(PyFrozenSet_New(nullptr));
119 EXPECT_FALSE(PySet_Check(set));
120}
121
122TEST_F(SetExtensionApiTest, SetCheckWithSetSubclassReturnsTrue) {
123 PyRun_SimpleString(R"(
124class C(set):
125 pass
126c = C()
127)");
128 PyObjectPtr c(mainModuleGet("c"));
129 EXPECT_TRUE(PySet_Check(c));
130}
131
132TEST_F(SetExtensionApiTest, SetCheckWithSetReturnsTrue) {
133 PyObjectPtr set(PySet_New(nullptr));
134 EXPECT_TRUE(PySet_Check(set));
135}
136
137TEST_F(SetExtensionApiTest, ContainsReturnsPositiveAfterAdd) {
138 PyObjectPtr set(PySet_New(nullptr));
139 PyObjectPtr key(PyLong_FromLong(1));
140
141 ASSERT_EQ(PySet_Contains(set, key), 0);
142 ASSERT_EQ(PySet_Add(set, key), 0);
143 EXPECT_EQ(PySet_Contains(set, key), 1);
144}
145
146TEST_F(SetExtensionApiTest, ContainsWithEmptySetReturnsFalse) {
147 PyObjectPtr set(PySet_New(nullptr));
148 PyObjectPtr key(PyLong_FromLong(1));
149
150 EXPECT_EQ(PySet_Contains(set, key), 0);
151}
152
153TEST_F(SetExtensionApiTest, ContainsWithNonSetReturnsNegative) {
154 PyObjectPtr dict(PyDict_New());
155 PyObjectPtr key(PyLong_FromLong(1));
156
157 EXPECT_EQ(PySet_Contains(dict, key), -1);
158 ASSERT_NE(PyErr_Occurred(), nullptr);
159 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
160}
161
162TEST_F(SetExtensionApiTest, NewWithDictCopiesKeys) {
163 PyObjectPtr dict(PyDict_New());
164 PyObjectPtr key1(PyLong_FromLong(1));
165 PyObjectPtr key2(PyLong_FromLong(2));
166 PyObjectPtr key3(PyLong_FromLong(3));
167 PyObjectPtr value(PyLong_FromLong(4));
168
169 PyDict_SetItem(dict, key1, value);
170 PyDict_SetItem(dict, key2, value);
171 PyDict_SetItem(dict, key3, value);
172
173 PyObjectPtr set(PySet_New(dict));
174
175 EXPECT_EQ(PySet_Contains(set, key1), 1);
176 EXPECT_EQ(PySet_Contains(set, key2), 1);
177 EXPECT_EQ(PySet_Contains(set, key3), 1);
178}
179
180TEST_F(SetExtensionApiTest, NewFromSet) {
181 PyObjectPtr set(PySet_New(nullptr));
182 PyObjectPtr one(PyLong_FromLong(1));
183 PyObjectPtr two(PyLong_FromLong(2));
184
185 ASSERT_EQ(PySet_Add(set, one), 0);
186 ASSERT_EQ(PySet_Add(set, two), 0);
187
188 PyObjectPtr set_copy(PySet_New(set));
189
190 EXPECT_EQ(PySet_Contains(set_copy, one), 1);
191 EXPECT_EQ(PySet_Contains(set_copy, two), 1);
192 EXPECT_EQ(PySet_Size(set_copy), 2);
193}
194
195TEST_F(SetExtensionApiTest, NewWithList) {
196 PyObjectPtr one(PyLong_FromLong(1));
197 PyObjectPtr two(PyLong_FromLong(2));
198 PyObjectPtr list(PyList_New(0));
199
200 PyList_Append(list, one);
201 PyList_Append(list, two);
202 PyList_Append(list, one);
203
204 PyObjectPtr set(PySet_New(list));
205 EXPECT_EQ(PySet_Contains(set, one), 1);
206 EXPECT_EQ(PySet_Contains(set, two), 1);
207 EXPECT_EQ(PySet_Size(set), 2);
208}
209
210TEST_F(SetExtensionApiTest, NewWithNonIterableReturnsNull) {
211 PyObjectPtr num(PyLong_FromLong(1));
212
213 EXPECT_EQ(PySet_New(num), nullptr);
214 ASSERT_NE(PyErr_Occurred(), nullptr);
215 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
216}
217
218TEST_F(SetExtensionApiTest, NewWithNullReturnsEmpty) {
219 PyObjectPtr set(PySet_New(nullptr));
220 ASSERT_NE(set, nullptr);
221 EXPECT_EQ(PySet_Size(set), 0);
222}
223
224TEST_F(SetExtensionApiTest, NextEntryWithNonSetRaisesSystemError) {
225 PyObject* key = nullptr;
226 Py_hash_t hash = 0;
227 Py_ssize_t pos = 0;
228 PyObjectPtr nonset(PyDict_New());
229 EXPECT_EQ(_PySet_NextEntry(nonset, &pos, &key, &hash), -1);
230 ASSERT_NE(PyErr_Occurred(), nullptr);
231 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
232}
233
234TEST_F(SetExtensionApiTest, NextEntryWithEmptySetReturnsFalse) {
235 PyObject* key = nullptr;
236 Py_hash_t hash = 0;
237 Py_ssize_t pos = 0;
238 PyObjectPtr set(PySet_New(nullptr));
239 EXPECT_EQ(_PySet_NextEntry(set, &pos, &key, &hash), 0);
240 ASSERT_EQ(PyErr_Occurred(), nullptr);
241}
242
243TEST_F(SetExtensionApiTest, NextEntryWithNonEmptySetReturnsKeysAndHashes) {
244 PyObjectPtr set(PySet_New(nullptr));
245 PyObjectPtr one(PyLong_FromLong(1));
246 ASSERT_EQ(PySet_Add(set, one), 0);
247 PyObjectPtr two(PyLong_FromLong(2));
248 ASSERT_EQ(PySet_Add(set, two), 0);
249
250 Py_ssize_t pos = 0;
251 PyObject* key = nullptr;
252 Py_hash_t hash = -1;
253 ASSERT_EQ(_PySet_NextEntry(set, &pos, &key, &hash), 1);
254 ASSERT_EQ(PyErr_Occurred(), nullptr);
255 EXPECT_EQ(key, one);
256 EXPECT_EQ(hash, PyObject_Hash(one));
257
258 ASSERT_EQ(_PySet_NextEntry(set, &pos, &key, &hash), 1);
259 ASSERT_EQ(PyErr_Occurred(), nullptr);
260 EXPECT_EQ(key, two);
261 EXPECT_EQ(hash, PyObject_Hash(two));
262
263 ASSERT_EQ(_PySet_NextEntry(set, &pos, &key, &hash), 0);
264 ASSERT_EQ(PyErr_Occurred(), nullptr);
265}
266
267TEST_F(SetExtensionApiTest, SizeIncreasesAfterAdd) {
268 PyObjectPtr set(PySet_New(nullptr));
269 PyObjectPtr one(PyLong_FromLong(1));
270 PyObjectPtr two(PyLong_FromLong(2));
271
272 EXPECT_EQ(PySet_Size(set), 0);
273 ASSERT_EQ(PySet_Add(set, one), 0);
274 EXPECT_EQ(PySet_Size(set), 1);
275 ASSERT_EQ(PySet_Add(set, one), 0);
276 EXPECT_EQ(PySet_Size(set), 1);
277 ASSERT_EQ(PySet_Add(set, two), 0);
278 EXPECT_EQ(PySet_Size(set), 2);
279}
280
281TEST_F(SetExtensionApiTest, SizeOfNonSetReturnsNegative) {
282 PyObjectPtr list(PyList_New(2));
283
284 EXPECT_EQ(PySet_Size(list), -1);
285 ASSERT_NE(PyErr_Occurred(), nullptr);
286 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
287}
288
289TEST_F(SetExtensionApiTest, FrozenSetNewWithDictCopiesKeys) {
290 PyObjectPtr dict(PyDict_New());
291 PyObjectPtr value(PyLong_FromLong(4));
292 PyObjectPtr key1(PyLong_FromLong(1));
293 PyDict_SetItem(dict, key1, value);
294 PyObjectPtr key2(PyLong_FromLong(2));
295 PyDict_SetItem(dict, key2, value);
296 PyObjectPtr key3(PyLong_FromLong(3));
297 PyDict_SetItem(dict, key3, value);
298
299 PyObjectPtr set(PyFrozenSet_New(dict));
300 ASSERT_EQ(PyErr_Occurred(), nullptr);
301 EXPECT_EQ(PySet_Contains(set, key1), 1);
302 EXPECT_EQ(PySet_Contains(set, key2), 1);
303 EXPECT_EQ(PySet_Contains(set, key3), 1);
304}
305
306TEST_F(SetExtensionApiTest, FrozenSetNewFromSetContainsElementsOfSet) {
307 PyObjectPtr set(PySet_New(nullptr));
308 PyObjectPtr one(PyLong_FromLong(1));
309 ASSERT_EQ(PySet_Add(set, one), 0);
310 PyObjectPtr two(PyLong_FromLong(2));
311 ASSERT_EQ(PySet_Add(set, two), 0);
312
313 PyObjectPtr set_copy(PyFrozenSet_New(set));
314 ASSERT_EQ(PyErr_Occurred(), nullptr);
315 EXPECT_EQ(PySet_Contains(set_copy, one), 1);
316 EXPECT_EQ(PySet_Contains(set_copy, two), 1);
317 EXPECT_EQ(PySet_Size(set_copy), 2);
318}
319
320TEST_F(SetExtensionApiTest, FrozenSetNewWithListContainsElementsOfList) {
321 PyObjectPtr list(PyList_New(0));
322 PyObjectPtr one(PyLong_FromLong(1));
323 PyList_Append(list, one);
324 PyObjectPtr two(PyLong_FromLong(2));
325 PyList_Append(list, two);
326
327 PyObjectPtr set(PyFrozenSet_New(list));
328 ASSERT_EQ(PyErr_Occurred(), nullptr);
329 EXPECT_EQ(PySet_Contains(set, one), 1);
330 EXPECT_EQ(PySet_Contains(set, two), 1);
331 EXPECT_EQ(PySet_Size(set), 2);
332}
333
334TEST_F(SetExtensionApiTest, FrozenSetNewWithNonIterableRaisesTypeError) {
335 PyObjectPtr num(PyLong_FromLong(1));
336 EXPECT_EQ(PyFrozenSet_New(num), nullptr);
337 ASSERT_NE(PyErr_Occurred(), nullptr);
338 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError));
339}
340
341TEST_F(SetExtensionApiTest, FrozenSetNewWithNullReturnsEmpty) {
342 PyObjectPtr set(PyFrozenSet_New(nullptr));
343 ASSERT_NE(set, nullptr);
344 EXPECT_EQ(PySet_Size(set), 0);
345}
346
347TEST_F(SetExtensionApiTest, ContainsWithFrozenSetDoesNotRaiseSystemError) {
348 PyObjectPtr set(PyFrozenSet_New(nullptr));
349 EXPECT_EQ(PySet_Contains(set, Py_None), 0);
350 EXPECT_EQ(PyErr_Occurred(), nullptr);
351}
352
353TEST_F(SetExtensionApiTest, SizeWithFrozenSetDoesNotRaiseSystemError) {
354 PyObjectPtr set(PyFrozenSet_New(nullptr));
355 EXPECT_EQ(PySet_Size(set), 0);
356 EXPECT_EQ(PyErr_Occurred(), nullptr);
357}
358
359TEST_F(SetExtensionApiTest, ClearWithNonSetRaisesSystemError) {
360 ASSERT_EQ(PySet_Clear(Py_None), -1);
361 ASSERT_NE(PyErr_Occurred(), nullptr);
362 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
363}
364
365TEST_F(SetExtensionApiTest, ClearRemovesAllItems) {
366 PyObjectPtr set(PySet_New(nullptr));
367 PyObjectPtr one(PyLong_FromLong(1));
368 PySet_Add(set, one);
369 PyObjectPtr two(PyLong_FromLong(2));
370 PySet_Add(set, two);
371 PyObjectPtr three(PyLong_FromLong(3));
372 PySet_Add(set, three);
373
374 ASSERT_EQ(PySet_Clear(set), 0);
375 ASSERT_EQ(PyErr_Occurred(), nullptr);
376 EXPECT_EQ(PySet_Size(set), 0);
377}
378
379TEST_F(SetExtensionApiTest, PopWithNonSetRaisesSystemError) {
380 ASSERT_EQ(PySet_Pop(Py_None), nullptr);
381 ASSERT_NE(PyErr_Occurred(), nullptr);
382 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
383}
384
385TEST_F(SetExtensionApiTest, PopWithEmptySetRaisesKeyError) {
386 PyObjectPtr set(PySet_New(nullptr));
387 ASSERT_EQ(PySet_Pop(set), nullptr);
388 ASSERT_NE(PyErr_Occurred(), nullptr);
389 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_KeyError));
390}
391
392TEST_F(SetExtensionApiTest, PopWithNonEmptySetRemovesItem) {
393 PyObjectPtr set(PySet_New(nullptr));
394 PyObjectPtr elt(PyLong_FromLong(5));
395 ASSERT_EQ(PySet_Add(set, elt), 0);
396 ASSERT_EQ(PySet_Size(set), 1);
397 PyObjectPtr result(PySet_Pop(set));
398 ASSERT_EQ(result, elt);
399 EXPECT_EQ(PySet_Size(set), 0);
400}
401
402TEST_F(SetExtensionApiTest, PopWithSetContainingErrorsRemovesItem) {
403 PyObjectPtr set(PySet_New(nullptr));
404 PyObjectPtr elt(PyExc_KeyError);
405 ASSERT_EQ(PySet_Add(set, elt), 0);
406 ASSERT_EQ(PySet_Size(set), 1);
407 ASSERT_EQ(PySet_Pop(set), elt);
408 EXPECT_EQ(PySet_Size(set), 0);
409}
410
411TEST_F(SetExtensionApiTest, DiscardWithNonSetRaisesSystemError) {
412 ASSERT_EQ(PySet_Discard(Py_None, Py_None), -1);
413 ASSERT_NE(PyErr_Occurred(), nullptr);
414 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError));
415}
416
417TEST_F(SetExtensionApiTest, DiscardWithSetRemovesItem) {
418 PyObjectPtr set(PySet_New(nullptr));
419 PyObjectPtr elt(PyLong_FromLong(5));
420 ASSERT_EQ(PySet_Add(set, elt), 0);
421 ASSERT_EQ(PySet_Size(set), 1);
422 ASSERT_EQ(PySet_Discard(set, elt), 1);
423 ASSERT_EQ(PyErr_Occurred(), nullptr);
424 EXPECT_EQ(PySet_Size(set), 0);
425}
426
427} // namespace testing
428} // namespace py