this repo has no description
at trunk 274 lines 8.1 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 ClassExtensionApiTest = ExtensionApi; 12 13TEST_F(ClassExtensionApiTest, InstanceMethodNewReturnsInstanceMethod) { 14 PyRun_SimpleString(R"( 15def foo(): 16 pass 17)"); 18 PyObjectPtr foo(mainModuleGet("foo")); 19 PyObjectPtr method(PyInstanceMethod_New(foo)); 20 EXPECT_NE(method, nullptr); 21 EXPECT_TRUE(PyInstanceMethod_Check(method.get())); 22 EXPECT_NE(method, foo); 23} 24 25TEST_F(ClassExtensionApiTest, InstanceMethodGETFUNCTIONReturnsFunction) { 26 PyRun_SimpleString(R"( 27def foo(): 28 pass 29)"); 30 PyObjectPtr foo(mainModuleGet("foo")); 31 PyObjectPtr method(PyInstanceMethod_New(foo)); 32 EXPECT_NE(method, nullptr); 33 EXPECT_EQ(PyInstanceMethod_GET_FUNCTION(method.get()), foo); 34} 35 36TEST_F(ClassExtensionApiTest, CallWithInstanceMethodCallsFunction) { 37 PyRun_SimpleString(R"( 38def foo(): 39 return 123 40)"); 41 PyObjectPtr foo(mainModuleGet("foo")); 42 PyObjectPtr method(PyInstanceMethod_New(foo)); 43 EXPECT_NE(method, nullptr); 44 PyObjectPtr result(PyObject_CallFunctionObjArgs(method, nullptr)); 45 EXPECT_EQ(PyErr_Occurred(), nullptr); 46 EXPECT_TRUE(isLongEqualsLong(result, 123)); 47} 48 49TEST_F(ClassExtensionApiTest, 50 InstanceMethodDunderGetWithNoneObjectReturnsFunction) { 51 PyRun_SimpleString(R"( 52def foo(): 53 return 123 54)"); 55 PyObjectPtr foo(mainModuleGet("foo")); 56 PyObjectPtr method(PyInstanceMethod_New(foo)); 57 EXPECT_NE(method, nullptr); 58 PyObjectPtr none((Borrowed(Py_None))); 59 PyObjectPtr non_none(PyLong_FromLong(123)); 60 PyObjectPtr result( 61 PyObject_CallMethod(method, "__get__", "OO", none.get(), non_none.get())); 62 ASSERT_EQ(PyErr_Occurred(), nullptr); 63 EXPECT_NE(result, nullptr); 64 EXPECT_EQ(result, foo); 65} 66 67TEST_F(ClassExtensionApiTest, 68 InstanceMethodDunderGetAttrWithNonExistentAttrRaisesAttributeError) { 69 PyRun_SimpleString(R"( 70def foo(): 71 pass 72)"); 73 PyObjectPtr foo(mainModuleGet("foo")); 74 PyObjectPtr method(PyInstanceMethod_New(foo)); 75 ASSERT_NE(method, nullptr); 76 // Call the "__getattr__" method of the instancemethod, check 77 // behavior for requesting a non-existent attribute. 78 PyObjectPtr result(PyObject_GetAttrString(method, "bar")); 79 EXPECT_EQ(result, nullptr); 80 ASSERT_NE(PyErr_Occurred(), nullptr); 81 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_AttributeError)); 82} 83 84TEST_F(ClassExtensionApiTest, 85 InstanceMethodDunderGetAttrReturnsAttributeOfUnderlyingFunction) { 86 PyRun_SimpleString(R"( 87def foo(): 88 pass 89foo.bar = 123 90)"); 91 PyObjectPtr foo(mainModuleGet("foo")); 92 PyObjectPtr method(PyInstanceMethod_New(foo)); 93 ASSERT_NE(method, nullptr); 94 // Call the "__getattr__" method of the instancemethod, check 95 // behavior for requesting an attribute on the underlying function. 96 PyObjectPtr result(PyObject_GetAttrString(method, "bar")); 97 EXPECT_TRUE(isLongEqualsLong(result, 123)); 98 EXPECT_EQ(PyErr_Occurred(), nullptr); 99} 100 101TEST_F(ClassExtensionApiTest, 102 InstanceMethodDunderGetAttrReturnsAttributeOfInstanceMethod) { 103 PyRun_SimpleString(R"( 104def foo(): 105 pass 106)"); 107 PyObjectPtr foo(mainModuleGet("foo")); 108 PyObjectPtr method(PyInstanceMethod_New(foo)); 109 ASSERT_NE(method, nullptr); 110 // Call the "__getattr__" method of the instancemethod, check 111 // behavior for requesting an attribute on the instancemethod (and 112 // *not* the underlying function). 113 PyObjectPtr result(PyObject_GetAttrString(method, "__func__")); 114 EXPECT_EQ(result, foo); 115 EXPECT_EQ(PyErr_Occurred(), nullptr); 116} 117 118TEST_F(ClassExtensionApiTest, 119 InstanceMethodDunderGetWithNonNoneObjectReturnsMethod) { 120 PyRun_SimpleString(R"( 121def foo(): 122 return 123 123)"); 124 PyObjectPtr foo(mainModuleGet("foo")); 125 PyObjectPtr method(PyInstanceMethod_New(foo)); 126 EXPECT_NE(method, nullptr); 127 PyObjectPtr instance(PyLong_FromLong(456)); 128 PyObjectPtr none((Borrowed(Py_None))); 129 PyObjectPtr result( 130 PyObject_CallMethod(method, "__get__", "OO", instance.get(), none.get())); 131 EXPECT_NE(result, nullptr); 132 EXPECT_TRUE(PyMethod_Check(result.get())); 133} 134 135TEST_F(ClassExtensionApiTest, InstanceMethodLessThanRaisesTypeError) { 136 PyRun_SimpleString(R"( 137def foo(): 138 return 123 139)"); 140 PyObjectPtr foo(mainModuleGet("foo")); 141 PyObjectPtr method(PyInstanceMethod_New(foo)); 142 EXPECT_NE(method, nullptr); 143 ASSERT_EQ(PyObject_RichCompare(method, method, Py_LT), nullptr); 144 ASSERT_NE(PyErr_Occurred(), nullptr); 145 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 146} 147 148TEST_F(ClassExtensionApiTest, InstanceMethodLessEqualRaisesTypeError) { 149 PyRun_SimpleString(R"( 150def foo(): 151 return 123 152)"); 153 PyObjectPtr foo(mainModuleGet("foo")); 154 PyObjectPtr method(PyInstanceMethod_New(foo)); 155 EXPECT_NE(method, nullptr); 156 ASSERT_EQ(PyObject_RichCompare(method, method, Py_LE), nullptr); 157 ASSERT_NE(PyErr_Occurred(), nullptr); 158 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 159} 160 161TEST_F(ClassExtensionApiTest, InstanceMethodGreaterThanRaisesTypeError) { 162 PyRun_SimpleString(R"( 163def foo(): 164 return 123 165)"); 166 PyObjectPtr foo(mainModuleGet("foo")); 167 PyObjectPtr method(PyInstanceMethod_New(foo)); 168 EXPECT_NE(method, nullptr); 169 ASSERT_EQ(PyObject_RichCompare(method, method, Py_GT), nullptr); 170 ASSERT_NE(PyErr_Occurred(), nullptr); 171 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 172} 173 174TEST_F(ClassExtensionApiTest, InstanceMethodGreaterEqualRaisesTypeError) { 175 PyRun_SimpleString(R"( 176def foo(): 177 return 123 178)"); 179 PyObjectPtr foo(mainModuleGet("foo")); 180 PyObjectPtr method(PyInstanceMethod_New(foo)); 181 EXPECT_NE(method, nullptr); 182 ASSERT_EQ(PyObject_RichCompare(method, method, Py_GE), nullptr); 183 ASSERT_NE(PyErr_Occurred(), nullptr); 184 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_TypeError)); 185} 186 187TEST_F(ClassExtensionApiTest, FunctionReturnsFunction) { 188 PyRun_SimpleString(R"( 189def foo(): 190 pass 191)"); 192 PyObjectPtr foo(mainModuleGet("foo")); 193 PyObjectPtr bar(PyLong_FromLong(42)); 194 PyObjectPtr method(PyMethod_New(foo, bar)); 195 EXPECT_EQ(PyMethod_Function(method), foo); 196} 197 198TEST_F(ClassExtensionApiTest, GetFunctionReturnsFunction) { 199 PyRun_SimpleString(R"( 200def foo(): 201 pass 202)"); 203 PyObjectPtr foo(mainModuleGet("foo")); 204 PyObjectPtr bar(PyLong_FromLong(42)); 205 PyObjectPtr method(PyMethod_New(foo, bar)); 206 EXPECT_EQ(PyMethod_GET_FUNCTION(method.get()), foo); 207} 208 209TEST_F(ClassExtensionApiTest, NewWithNullSelfRaisesRuntimeError) { 210 PyRun_SimpleString(R"( 211def foo(x): 212 return x 213)"); 214 PyObjectPtr foo(mainModuleGet("foo")); 215 PyObject* method = PyMethod_New(foo, nullptr); 216 ASSERT_NE(PyErr_Occurred(), nullptr); 217 EXPECT_EQ(method, nullptr); 218 EXPECT_TRUE(PyErr_ExceptionMatches(PyExc_SystemError)); 219} 220 221TEST_F(ClassExtensionApiTest, NewWithNoArgsReturnsBoundObject) { 222 PyRun_SimpleString(R"( 223def foo(x): 224 return x 225)"); 226 PyObjectPtr foo(mainModuleGet("foo")); 227 PyObjectPtr integer(PyLong_FromLong(123)); 228 PyObjectPtr method(PyMethod_New(foo, integer)); 229 PyObjectPtr args(PyTuple_New(0)); 230 PyObjectPtr result(PyObject_CallObject(method, args)); 231 ASSERT_NE(result, nullptr); 232 EXPECT_EQ(result, integer); 233} 234 235TEST_F(ClassExtensionApiTest, CheckWithNonMethodReturnsFalse) { 236 PyObjectPtr pylong(PyLong_FromLong(10)); 237 EXPECT_EQ(PyMethod_Check(pylong.get()), 0); 238} 239 240TEST_F(ClassExtensionApiTest, CheckWithMethodReturnsTrue) { 241 PyRun_SimpleString(R"( 242def foo(x): 243 return x 244)"); 245 PyObjectPtr foo(mainModuleGet("foo")); 246 PyObjectPtr integer(PyLong_FromLong(123)); 247 PyObjectPtr method(PyMethod_New(foo, integer)); 248 EXPECT_EQ(PyMethod_Check(method.get()), 1); 249} 250 251TEST_F(ClassExtensionApiTest, SelfReturnsSelf) { 252 PyRun_SimpleString(R"( 253def foo(): 254 pass 255)"); 256 PyObjectPtr foo(mainModuleGet("foo")); 257 PyObjectPtr bar(PyLong_FromLong(42)); 258 PyObjectPtr method(PyMethod_New(foo, bar)); 259 EXPECT_EQ(PyMethod_Self(method), bar); 260} 261 262TEST_F(ClassExtensionApiTest, GetSelfReturnsSelf) { 263 PyRun_SimpleString(R"( 264def foo(): 265 pass 266)"); 267 PyObjectPtr foo(mainModuleGet("foo")); 268 PyObjectPtr bar(PyLong_FromLong(42)); 269 PyObjectPtr method(PyMethod_New(foo, bar)); 270 EXPECT_EQ(PyMethod_GET_SELF(method.get()), bar); 271} 272 273} // namespace testing 274} // namespace py