this repo has no description
at trunk 308 lines 9.9 kB view raw
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 TupleExtensionApiTest = ExtensionApi; 12 13TEST_F(TupleExtensionApiTest, CheckWithTupleSubclassReturnsTrue) { 14 PyRun_SimpleString(R"( 15class Foo(tuple): pass 16obj = Foo((1, 2)); 17)"); 18 PyObjectPtr obj(mainModuleGet("obj")); 19 EXPECT_TRUE(PyTuple_Check(obj)); 20} 21 22TEST_F(TupleExtensionApiTest, CheckExactWithTupleSubclassReturnsFalse) { 23 PyRun_SimpleString(R"( 24class Foo(tuple): pass 25obj = Foo((1, 2)); 26)"); 27 PyObjectPtr obj(mainModuleGet("obj")); 28 EXPECT_FALSE(PyTuple_CheckExact(obj)); 29} 30 31TEST_F(TupleExtensionApiTest, NewAndSize) { 32 Py_ssize_t length = 5; 33 PyObjectPtr pytuple(PyTuple_New(length)); 34 Py_ssize_t result = PyTuple_Size(pytuple); 35 EXPECT_EQ(result, length); 36} 37 38TEST_F(TupleExtensionApiTest, SetItemWithNonTupleReturnsNegative) { 39 Py_INCREF(Py_None); 40 int result = PyTuple_SetItem(Py_True, 0, Py_None); 41 EXPECT_EQ(result, -1); 42 43 ASSERT_NE(PyErr_Occurred(), nullptr); 44 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 45} 46 47TEST_F(TupleExtensionApiTest, SetItemWithInvalidIndexReturnsNegative) { 48 PyObjectPtr pytuple(PyTuple_New(1)); 49 Py_INCREF(Py_None); 50 int result = PyTuple_SetItem(pytuple, 2, Py_None); 51 EXPECT_EQ(result, -1); 52 53 ASSERT_NE(PyErr_Occurred(), nullptr); 54 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError)); 55} 56 57TEST_F(TupleExtensionApiTest, SetItemReturnsZero) { 58 PyObjectPtr pytuple(PyTuple_New(1)); 59 Py_INCREF(Py_None); 60 int result = PyTuple_SetItem(pytuple, 0, Py_None); 61 EXPECT_EQ(result, 0); 62} 63 64TEST_F(TupleExtensionApiTest, SetItemWithTupleSubclassReturnsZero) { 65 PyRun_SimpleString(R"( 66class Foo(tuple): pass 67obj = Foo((1, 2)); 68)"); 69 PyObjectPtr pytuple(mainModuleGet("obj")); 70 // PyTuple_SetItem() wants the tuple's reference count to be 1, so remove the 71 // reference from __main__. 72 moduleSet("__main__", "obj", Py_None); 73 Py_INCREF(Py_None); 74 int result = PyTuple_SetItem(pytuple, 0, Py_None); 75 ASSERT_EQ(PyErr_Occurred(), nullptr); 76 EXPECT_EQ(result, 0); 77 EXPECT_EQ(PyTuple_GetItem(pytuple, 0), Py_None); 78} 79 80TEST_F(TupleExtensionApiTest, GetItemFromNonTupleReturnsNull) { 81 PyObject* pytuple = PyTuple_GetItem(Py_None, 0); 82 EXPECT_EQ(nullptr, pytuple); 83} 84 85TEST_F(TupleExtensionApiTest, GetItemOutOfBoundsRaisesIndexError) { 86 Py_ssize_t length = 5; 87 PyObjectPtr pytuple(PyTuple_New(length)); 88 89 // Get item out of bounds 90 PyObject* pyresult = PyTuple_GetItem(pytuple, -1); 91 EXPECT_EQ(nullptr, pyresult); 92 ASSERT_NE(PyErr_Occurred(), nullptr); 93 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError)); 94 95 PyErr_Clear(); 96 pyresult = PyTuple_GetItem(pytuple, length); 97 EXPECT_EQ(nullptr, pyresult); 98 ASSERT_NE(PyErr_Occurred(), nullptr); 99 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_IndexError)); 100} 101 102TEST_F(TupleExtensionApiTest, GetItemReturnsSameItem) { 103 Py_ssize_t length = 5; 104 Py_ssize_t pos = 3; 105 Py_ssize_t int_value = 10; 106 PyObjectPtr pytuple(PyTuple_New(length)); 107 PyObject* pyitem = PyLong_FromLong(int_value); 108 ASSERT_EQ(PyTuple_SetItem(pytuple, pos, pyitem), 0); 109 110 // Get item 111 PyObject* pyresult = PyTuple_GetItem(pytuple, pos); 112 EXPECT_NE(nullptr, pyresult); 113 EXPECT_EQ(PyLong_AsLong(pyresult), int_value); 114} 115 116TEST_F(TupleExtensionApiTest, GetItemReturnsBorrowedReference) { 117 Py_ssize_t length = 5; 118 Py_ssize_t pos = 3; 119 PyObjectPtr pytuple(PyTuple_New(length)); 120 PyObjectPtr pyitem(PyLong_FromLong(0)); 121 Py_INCREF(pyitem); // keep an extra reference for checking below SetItem 122 ASSERT_EQ(PyTuple_SetItem(pytuple, pos, pyitem), 0); 123 124 long refcnt = Py_REFCNT(pyitem); 125 PyObject* pyresult = PyTuple_GetItem(pytuple, pos); 126 // PyTuple_GetItem "borrows" a reference for the return value. Verify the 127 // reference count did not change. 128 EXPECT_EQ(Py_REFCNT(pyresult), refcnt); 129} 130 131TEST_F(TupleExtensionApiTest, GetItemWithTupleSubclassReturnsValue) { 132 PyRun_SimpleString(R"( 133class Foo(tuple): pass 134obj = Foo((1, 2)); 135)"); 136 PyObjectPtr obj(mainModuleGet("obj")); 137 PyObject* first = PyTuple_GetItem(obj, 0); 138 PyObject* second = PyTuple_GetItem(obj, 1); 139 EXPECT_EQ(PyLong_AsLong(first), 1); 140 EXPECT_EQ(PyLong_AsLong(second), 2); 141} 142 143TEST_F(TupleExtensionApiTest, PackZeroReturnsEmptyTuple) { 144 PyObjectPtr pytuple(PyTuple_Pack(0)); 145 Py_ssize_t result = PyTuple_Size(pytuple); 146 EXPECT_EQ(result, 0); 147} 148 149TEST_F(TupleExtensionApiTest, PackOneValue) { 150 Py_ssize_t length = 1; 151 const int int_value = 5; 152 PyObjectPtr pylong(PyLong_FromLong(int_value)); 153 PyObjectPtr pytuple(PyTuple_Pack(length, pylong.get())); 154 155 PyObject* pyresult = PyTuple_GetItem(pytuple, 0); 156 EXPECT_EQ(PyLong_AsLong(pyresult), int_value); 157} 158 159TEST_F(TupleExtensionApiTest, PackTwoValues) { 160 Py_ssize_t length = 2; 161 const int int_value1 = 5; 162 const int int_value2 = 12; 163 PyObjectPtr pylong1(PyLong_FromLong(int_value1)); 164 PyObjectPtr pylong2(PyLong_FromLong(int_value2)); 165 PyObjectPtr pytuple(PyTuple_Pack(length, pylong1.get(), pylong2.get())); 166 167 PyObject* pyresult1 = PyTuple_GetItem(pytuple, 0); 168 PyObject* pyresult2 = PyTuple_GetItem(pytuple, 1); 169 EXPECT_EQ(PyLong_AsLong(pyresult1), int_value1); 170 EXPECT_EQ(PyLong_AsLong(pyresult2), int_value2); 171} 172 173TEST_F(TupleExtensionApiTest, GetSliceWithNullRaisesSystemError) { 174 ASSERT_EQ(PyTuple_GetSlice(nullptr, 0, 0), nullptr); 175 ASSERT_NE(PyErr_Occurred(), nullptr); 176 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 177} 178 179TEST_F(TupleExtensionApiTest, GetSliceWithNonTupleRaisesSystemError) { 180 ASSERT_EQ(PyTuple_GetSlice(Py_None, 0, 0), nullptr); 181 ASSERT_NE(PyErr_Occurred(), nullptr); 182 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 183} 184 185TEST_F(TupleExtensionApiTest, GetSliceWithLowSmallerThanZeroStartsAtZero) { 186 PyObjectPtr tuple(PyTuple_New(3)); 187 PyObjectPtr zero(PyLong_FromLong(0)); 188 // The calls to Py_INCREF in this function exist because SetItem steals 189 // references and these items need to be kept alive for later checking. 190 Py_INCREF(zero); 191 PyTuple_SetItem(tuple, 0, zero); 192 PyObjectPtr one(PyLong_FromLong(1)); 193 Py_INCREF(one); 194 PyTuple_SetItem(tuple, 1, one); 195 PyObjectPtr two(PyLong_FromLong(2)); 196 Py_INCREF(two); 197 PyTuple_SetItem(tuple, 2, two); 198 199 PyObjectPtr result(PyTuple_GetSlice(tuple, -5, 3)); 200 ASSERT_NE(result, nullptr); 201 ASSERT_EQ(PyErr_Occurred(), nullptr); 202 ASSERT_TRUE(PyTuple_CheckExact(result)); 203 EXPECT_EQ(tuple, result); 204 EXPECT_EQ(PyTuple_Size(result), 3); 205 EXPECT_EQ(PyTuple_GetItem(result, 0), zero); 206 EXPECT_EQ(PyTuple_GetItem(result, 1), one); 207 EXPECT_EQ(PyTuple_GetItem(result, 2), two); 208} 209 210TEST_F(TupleExtensionApiTest, 211 GetSliceWithLowLargerThanLengthReturnsEmptyTuple) { 212 PyObjectPtr tuple(PyTuple_New(3)); 213 PyTuple_SetItem(tuple, 0, PyLong_FromLong(0)); 214 PyTuple_SetItem(tuple, 1, PyLong_FromLong(1)); 215 PyTuple_SetItem(tuple, 2, PyLong_FromLong(2)); 216 217 PyObjectPtr result(PyTuple_GetSlice(tuple, 15, 3)); 218 ASSERT_NE(result, nullptr); 219 ASSERT_EQ(PyErr_Occurred(), nullptr); 220 ASSERT_TRUE(PyTuple_CheckExact(result)); 221 EXPECT_NE(tuple, result); 222 EXPECT_EQ(PyTuple_Size(result), 0); 223} 224 225TEST_F(TupleExtensionApiTest, 226 GetSliceWithOutOfBoundsHighStartsAtLowAndReturnsEmptyTuple) { 227 PyObjectPtr tuple(PyTuple_New(3)); 228 PyTuple_SetItem(tuple, 0, PyLong_FromLong(0)); 229 PyTuple_SetItem(tuple, 1, PyLong_FromLong(1)); 230 PyTuple_SetItem(tuple, 2, PyLong_FromLong(2)); 231 232 PyObjectPtr result(PyTuple_GetSlice(tuple, 1, 0)); 233 ASSERT_NE(result, nullptr); 234 ASSERT_EQ(PyErr_Occurred(), nullptr); 235 ASSERT_TRUE(PyTuple_CheckExact(result)); 236 EXPECT_NE(tuple, result); 237 EXPECT_EQ(PyTuple_Size(result), 0); 238} 239 240TEST_F(TupleExtensionApiTest, GetSliceWithHighLargerThanLengthEndsAtLength) { 241 PyObjectPtr tuple(PyTuple_New(3)); 242 PyObjectPtr zero(PyLong_FromLong(0)); 243 Py_INCREF(zero); 244 PyTuple_SetItem(tuple, 0, zero); 245 PyObjectPtr one(PyLong_FromLong(1)); 246 Py_INCREF(one); 247 PyTuple_SetItem(tuple, 1, one); 248 PyObjectPtr two(PyLong_FromLong(2)); 249 Py_INCREF(two); 250 PyTuple_SetItem(tuple, 2, two); 251 252 PyObjectPtr result(PyTuple_GetSlice(tuple, 0, 20)); 253 ASSERT_NE(result, nullptr); 254 ASSERT_EQ(PyErr_Occurred(), nullptr); 255 ASSERT_TRUE(PyTuple_CheckExact(result)); 256 EXPECT_EQ(tuple, result); 257 EXPECT_EQ(PyTuple_Size(result), 3); 258 EXPECT_EQ(PyTuple_GetItem(result, 0), zero); 259 EXPECT_EQ(PyTuple_GetItem(result, 1), one); 260 EXPECT_EQ(PyTuple_GetItem(result, 2), two); 261} 262 263TEST_F(TupleExtensionApiTest, 264 GetSliceWithZeroLowAndLengthHighReturnsOriginalTuple) { 265 PyObjectPtr tuple(PyTuple_New(3)); 266 PyObjectPtr zero(PyLong_FromLong(0)); 267 Py_INCREF(zero); 268 PyTuple_SetItem(tuple, 0, zero); 269 PyObjectPtr one(PyLong_FromLong(1)); 270 Py_INCREF(one); 271 PyTuple_SetItem(tuple, 1, one); 272 PyObjectPtr two(PyLong_FromLong(2)); 273 Py_INCREF(two); 274 PyTuple_SetItem(tuple, 2, two); 275 276 PyObjectPtr result(PyTuple_GetSlice(tuple, 0, 3)); 277 ASSERT_NE(result, nullptr); 278 ASSERT_EQ(PyErr_Occurred(), nullptr); 279 ASSERT_TRUE(PyTuple_CheckExact(result)); 280 EXPECT_EQ(tuple, result); 281 EXPECT_EQ(PyTuple_Size(result), 3); 282 EXPECT_EQ(PyTuple_GetItem(result, 0), zero); 283 EXPECT_EQ(PyTuple_GetItem(result, 1), one); 284 EXPECT_EQ(PyTuple_GetItem(result, 2), two); 285} 286 287TEST_F(TupleExtensionApiTest, GetSliceReturnsSmallerTuple) { 288 PyObjectPtr tuple(PyTuple_New(4)); 289 PyTuple_SetItem(tuple, 0, PyLong_FromLong(0)); 290 PyObjectPtr one(PyLong_FromLong(1)); 291 Py_INCREF(one); 292 PyTuple_SetItem(tuple, 1, one); 293 PyObjectPtr two(PyLong_FromLong(2)); 294 Py_INCREF(two); 295 PyTuple_SetItem(tuple, 2, two); 296 PyTuple_SetItem(tuple, 3, PyLong_FromLong(3)); 297 298 PyObjectPtr result(PyTuple_GetSlice(tuple, 1, 3)); 299 ASSERT_NE(result, nullptr); 300 ASSERT_EQ(PyErr_Occurred(), nullptr); 301 ASSERT_TRUE(PyTuple_CheckExact(result)); 302 EXPECT_EQ(PyTuple_Size(result), 2); 303 EXPECT_EQ(PyTuple_GetItem(result, 0), one); 304 EXPECT_EQ(PyTuple_GetItem(result, 1), two); 305} 306 307} // namespace testing 308} // namespace py