this repo has no description
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