this repo has no description
at trunk 351 lines 8.2 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "descriptor-builtins.h" 3 4#include "gtest/gtest.h" 5 6#include "builtins.h" 7#include "handles.h" 8#include "objects.h" 9#include "runtime.h" 10#include "test-utils.h" 11 12namespace py { 13namespace testing { 14 15using DescriptorBuiltinsTest = RuntimeFixture; 16 17TEST_F(DescriptorBuiltinsTest, Classmethod) { 18 ASSERT_FALSE(runFromCStr(runtime_, R"( 19class Foo(): 20 a = 1 21 @classmethod 22 def bar(cls): 23 return cls.a 24instance_a = Foo().bar() 25Foo.a = 2 26class_a = Foo.bar() 27)") 28 .isError()); 29 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "instance_a"), 1)); 30 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "class_a"), 2)); 31} 32 33TEST_F(DescriptorBuiltinsTest, StaticmethodObjAccess) { 34 ASSERT_FALSE(runFromCStr(runtime_, R"( 35class E: 36 @staticmethod 37 def f(x): 38 return x + 1 39 40result = E().f(5) 41)") 42 .isError()); 43 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 6)); 44} 45 46TEST_F(DescriptorBuiltinsTest, StaticmethodClsAccess) { 47 ASSERT_FALSE(runFromCStr(runtime_, R"( 48class E(): 49 @staticmethod 50 def f(x, y): 51 return x + y 52 53result = E.f(1,2) 54)") 55 .isError()); 56 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result"), 3)); 57} 58 59TEST_F(DescriptorBuiltinsTest, 60 PropertyCreateEmptyGetterSetterDeleterReturnsNone) { 61 HandleScope scope(thread_); 62 ASSERT_FALSE(runFromCStr(runtime_, "x = property()").isError()); 63 Object x(&scope, mainModuleAt(runtime_, "x")); 64 ASSERT_TRUE(x.isProperty()); 65 Property prop(&scope, *x); 66 ASSERT_TRUE(prop.getter().isNoneType()); 67 ASSERT_TRUE(prop.setter().isNoneType()); 68 ASSERT_TRUE(prop.deleter().isNoneType()); 69} 70 71TEST_F(DescriptorBuiltinsTest, PropertyCreateWithGetterSetterReturnsArgs) { 72 HandleScope scope(thread_); 73 ASSERT_FALSE(runFromCStr(runtime_, R"( 74def get_foo(): 75 pass 76def set_foo(): 77 pass 78x = property(get_foo, set_foo) 79)") 80 .isError()); 81 Object x(&scope, mainModuleAt(runtime_, "x")); 82 ASSERT_TRUE(x.isProperty()); 83 Property prop(&scope, *x); 84 ASSERT_TRUE(prop.getter().isFunction()); 85 ASSERT_TRUE(prop.setter().isFunction()); 86 ASSERT_TRUE(prop.deleter().isNoneType()); 87} 88 89TEST_F(DescriptorBuiltinsTest, PropertyModifyViaGetterReturnsGetter) { 90 HandleScope scope(thread_); 91 ASSERT_FALSE(runFromCStr(runtime_, R"( 92def get_foo(): 93 pass 94def set_foo(): 95 pass 96x = property(None, set_foo) 97y = x.getter(get_foo) 98)") 99 .isError()); 100 Object x(&scope, mainModuleAt(runtime_, "x")); 101 ASSERT_TRUE(x.isProperty()); 102 Property x_prop(&scope, *x); 103 ASSERT_TRUE(x_prop.getter().isNoneType()); 104 ASSERT_TRUE(x_prop.setter().isFunction()); 105 ASSERT_TRUE(x_prop.deleter().isNoneType()); 106 107 Object y(&scope, mainModuleAt(runtime_, "y")); 108 ASSERT_TRUE(y.isProperty()); 109 Property y_prop(&scope, *y); 110 ASSERT_TRUE(y_prop.getter().isFunction()); 111 ASSERT_TRUE(y_prop.setter().isFunction()); 112 ASSERT_TRUE(y_prop.deleter().isNoneType()); 113} 114 115TEST_F(DescriptorBuiltinsTest, PropertyModifyViaSetterReturnsSetter) { 116 HandleScope scope(thread_); 117 ASSERT_FALSE(runFromCStr(runtime_, R"( 118def get_foo(): 119 pass 120def set_foo(): 121 pass 122x = property(get_foo) 123y = x.setter(set_foo) 124)") 125 .isError()); 126 Object x(&scope, mainModuleAt(runtime_, "x")); 127 ASSERT_TRUE(x.isProperty()); 128 Property x_prop(&scope, *x); 129 ASSERT_TRUE(x_prop.getter().isFunction()); 130 ASSERT_TRUE(x_prop.setter().isNoneType()); 131 ASSERT_TRUE(x_prop.deleter().isNoneType()); 132 133 Object y(&scope, mainModuleAt(runtime_, "y")); 134 ASSERT_TRUE(y.isProperty()); 135 Property y_prop(&scope, *y); 136 ASSERT_TRUE(y_prop.getter().isFunction()); 137 ASSERT_TRUE(y_prop.setter().isFunction()); 138 ASSERT_TRUE(y_prop.deleter().isNoneType()); 139} 140 141TEST_F(DescriptorBuiltinsTest, PropertyAddedViaClassAccessibleViaInstance) { 142 ASSERT_FALSE(runFromCStr(runtime_, R"( 143class C: 144 def __init__(self, x): 145 self.__x = x 146 147 def getx(self): 148 return self.__x 149 150 x = property(getx) 151 152c1 = C(24) 153c2 = C(42) 154result0 = c1.x 155result1 = c2.x 156)") 157 .isError()); 158 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result0"), 24)); 159 EXPECT_TRUE(isIntEqualsWord(mainModuleAt(runtime_, "result1"), 42)); 160} 161 162TEST_F(DescriptorBuiltinsTest, PropertyNoDeleterRaisesAttributeError) { 163 const char* src = R"( 164class C: 165 def __init__(self, x): 166 self.__x = x 167 168 def getx(self): 169 return self.__x 170 171 def setx(self, value): 172 self.__x = value 173 174 x = property(getx, setx) 175 176c1 = C(24) 177del c1.x 178)"; 179 180 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), 181 LayoutId::kAttributeError, 182 "can't delete attribute")); 183} 184 185TEST_F(DescriptorBuiltinsTest, PropertyNoGetterRaisesAttributeErrorUnreadable) { 186 const char* src = R"( 187class C: 188 def __init__(self, x): 189 self.__x = x 190 191 def setx(self, value): 192 self.__x = value 193 194 x = property(None, setx) 195 196c1 = C(24) 197c1.x 198)"; 199 200 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), 201 LayoutId::kAttributeError, "unreadable attribute")); 202} 203 204TEST_F(DescriptorBuiltinsTest, 205 PropertyNoSetterRaisesAttributeErrorCannotModify) { 206 const char* src = R"( 207class C: 208 def __init__(self, x): 209 self.__x = x 210 211 def getx(self): 212 return self.__x 213 214 x = property(getx) 215 216c1 = C(24) 217c1.x = 42 218)"; 219 220 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, src), 221 LayoutId::kAttributeError, "can't set attribute")); 222} 223 224TEST_F(DescriptorBuiltinsTest, PropertyAddedViaClassAccessibleViaClass) { 225 HandleScope scope(thread_); 226 ASSERT_FALSE(runFromCStr(runtime_, R"( 227class C: 228 def __init__(self, x): 229 self.__x = x 230 231 def getx(self): 232 return self.__x 233 234 x = property(getx) 235 236x = C.x 237)") 238 .isError()); 239 240 Object x(&scope, mainModuleAt(runtime_, "x")); 241 ASSERT_TRUE(x.isProperty()); 242} 243 244TEST_F(DescriptorBuiltinsTest, PropertyAddedViaClassModifiedViaSetter) { 245 HandleScope scope(thread_); 246 ASSERT_FALSE(runFromCStr(runtime_, R"( 247class C: 248 def __init__(self, x): 249 self.__x = x 250 251 def getx(self): 252 return self.__x 253 254 def setx(self, value): 255 self.__x = value 256 257 x = property(getx, setx) 258 259c1 = C(24) 260x1 = c1.x 261c1.x = 42 262x2 = c1.x 263)") 264 .isError()); 265 266 Object x1(&scope, mainModuleAt(runtime_, "x1")); 267 EXPECT_TRUE(isIntEqualsWord(*x1, 24)); 268 Object x2(&scope, mainModuleAt(runtime_, "x2")); 269 EXPECT_TRUE(isIntEqualsWord(*x2, 42)); 270} 271 272TEST_F(DescriptorBuiltinsTest, PropertyAddedViaDecoratorSanityCheck) { 273 HandleScope scope(thread_); 274 ASSERT_FALSE(runFromCStr(runtime_, R"( 275class C: 276 def __init__(self, x): 277 self.__x = x 278 279 @property 280 def x(self): 281 return self.__x 282 283 @x.setter 284 def x(self, value): 285 self.__x = value 286 287c1 = C(24) 288c1.x = 42 289x = c1.x 290)") 291 .isError()); 292 293 Object x(&scope, mainModuleAt(runtime_, "x")); 294 EXPECT_TRUE(isIntEqualsWord(*x, 42)); 295} 296 297TEST_F(DescriptorBuiltinsTest, PropertyWithCallableDeleterDeletesValue) { 298 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 299def deleter(obj): 300 del obj.y 301 302class Foo: 303 x = property(None, None, deleter, doc="documentation") 304 y = 123 305 306foo = Foo() 307del foo.x 308foo.y 309)"), 310 LayoutId::kAttributeError, 311 "'Foo' object has no attribute 'y'")); 312} 313 314TEST_F(DescriptorBuiltinsTest, PropertyWithCallableGetterReturnsValue) { 315 HandleScope scope(thread_); 316 ASSERT_FALSE(runFromCStr(runtime_, R"( 317class Getter: 318 def __call__(self, obj): 319 return 123 320 321class Foo: 322 x = property(Getter()) 323 324result = Foo().x 325)") 326 .isError()); 327 Object result(&scope, mainModuleAt(runtime_, "result")); 328 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 329} 330 331TEST_F(DescriptorBuiltinsTest, PropertyWithCallableSetterSetsValue) { 332 HandleScope scope(thread_); 333 ASSERT_FALSE(runFromCStr(runtime_, R"( 334class Setter: 335 def __call__(self, obj, value): 336 obj.y = value 337 338class Foo: 339 x = property(None, Setter(), None, doc="documentation") 340 341foo = Foo() 342foo.x = 123 343result = foo.y 344)") 345 .isError()); 346 Object result(&scope, mainModuleAt(runtime_, "result")); 347 EXPECT_TRUE(isIntEqualsWord(*result, 123)); 348} 349 350} // namespace testing 351} // namespace py