this repo has no description
at trunk 123 lines 3.9 kB view raw
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com) 2#include "function-builtins.h" 3 4#include "gtest/gtest.h" 5 6#include "builtins.h" 7#include "dict-builtins.h" 8#include "objects.h" 9#include "runtime.h" 10#include "str-builtins.h" 11#include "test-utils.h" 12 13namespace py { 14namespace testing { 15 16using FunctionBuiltinsTest = RuntimeFixture; 17 18TEST_F(FunctionBuiltinsTest, ManagedFunctionObjectsExposeDunderCode) { 19 ASSERT_FALSE(runFromCStr(runtime_, R"( 20def foo(x): 21 return x + 1 22code = foo.__code__ 23)") 24 .isError()); 25 HandleScope scope(thread_); 26 Object code(&scope, mainModuleAt(runtime_, "code")); 27 ASSERT_TRUE(code.isCode()); 28} 29 30TEST_F(FunctionBuiltinsTest, 31 ChangingCodeOfFunctionObjectChangesFunctionBehavior) { 32 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, R"( 33def foo(x): 34 return x + 1 35def bar(x): 36 return x + 5 37foo.__code__ = bar.__code__ 38a = foo(5) 39)"), 40 LayoutId::kAttributeError, 41 "'function.__code__' attribute is read-only")); 42} 43 44TEST_F(FunctionBuiltinsTest, DunderGetWithNonFunctionSelfRaisesTypeError) { 45 HandleScope scope(thread_); 46 Object none(&scope, NoneType::object()); 47 ASSERT_TRUE(runBuiltin(METH(function, __get__), none, none, none).isError()); 48 Thread* thread = Thread::current(); 49 EXPECT_EQ(thread->pendingExceptionType(), 50 runtime_->typeAt(LayoutId::kTypeError)); 51 EXPECT_TRUE(thread->pendingExceptionValue().isStr()); 52} 53 54TEST_F(FunctionBuiltinsTest, DunderGetWithNonNoneInstanceReturnsBoundMethod) { 55 HandleScope scope(thread_); 56 Object func(&scope, newEmptyFunction()); 57 Object not_none(&scope, SmallInt::fromWord(1)); 58 Object not_none_type(&scope, runtime_->typeOf(*not_none)); 59 Object result(&scope, runBuiltin(METH(function, __get__), func, not_none, 60 not_none_type)); 61 ASSERT_TRUE(result.isBoundMethod()); 62 EXPECT_EQ(BoundMethod::cast(*result).self(), *not_none); 63 EXPECT_EQ(BoundMethod::cast(*result).function(), *func); 64} 65 66TEST_F(FunctionBuiltinsTest, DunderGetWithNoneInstanceReturnsSelf) { 67 HandleScope scope(thread_); 68 Object func(&scope, newEmptyFunction()); 69 Object none(&scope, NoneType::object()); 70 Type some_type(&scope, runtime_->typeOf(*func)); 71 Object result(&scope, 72 runBuiltin(METH(function, __get__), func, none, some_type)); 73 EXPECT_EQ(result, func); 74} 75 76TEST_F(FunctionBuiltinsTest, ReprHandlesNormalFunctions) { 77 ASSERT_FALSE(runFromCStr(runtime_, R"( 78def f(): pass 79result = repr(f) 80)") 81 .isError()); 82 HandleScope scope(thread_); 83 Object result(&scope, mainModuleAt(runtime_, "result")); 84 ASSERT_TRUE(result.isStr()); 85 unique_c_ptr<char> result_str(Str::cast(*result).toCStr()); 86 EXPECT_TRUE(std::strstr(result_str.get(), "<function f at 0x")); 87} 88 89TEST_F(FunctionBuiltinsTest, ReprHandlesLambda) { 90 ASSERT_FALSE(runFromCStr(runtime_, "result = repr(lambda x: x)").isError()); 91 HandleScope scope(thread_); 92 Object result(&scope, mainModuleAt(runtime_, "result")); 93 ASSERT_TRUE(result.isStr()); 94 unique_c_ptr<char> result_str(Str::cast(*result).toCStr()); 95 EXPECT_TRUE(std::strstr(result_str.get(), "<function <lambda> at 0x")); 96} 97 98TEST_F(FunctionBuiltinsTest, DunderCallCallsFunction) { 99 ASSERT_FALSE(runFromCStr(runtime_, R"( 100def f(a): 101 return a 102result = f.__call__(3) 103)") 104 .isError()); 105 HandleScope scope(thread_); 106 Object result(&scope, mainModuleAt(runtime_, "result")); 107 EXPECT_TRUE(isIntEqualsWord(*result, 3)); 108} 109 110TEST_F(FunctionBuiltinsTest, DunderGlobalsIsModuleProxy) { 111 ASSERT_FALSE(runFromCStr(runtime_, R"( 112def f(a): 113 return a 114result = f.__globals__ 115)") 116 .isError()); 117 HandleScope scope(thread_); 118 Object result(&scope, mainModuleAt(runtime_, "result")); 119 EXPECT_TRUE(result.isModuleProxy()); 120} 121 122} // namespace testing 123} // namespace py