this repo has no description
1// Copyright (c) Facebook, Inc. and its affiliates. (http://www.facebook.com)
2#include "ref-builtins.h"
3
4#include "gtest/gtest.h"
5
6#include "builtins.h"
7#include "dict-builtins.h"
8#include "module-builtins.h"
9#include "runtime.h"
10#include "str-builtins.h"
11#include "super-builtins.h"
12#include "test-utils.h"
13
14namespace py {
15namespace testing {
16
17using RefBuiltinsTest = RuntimeFixture;
18
19TEST_F(RefBuiltinsTest, ReferentTest) {
20 const char* src = R"(
21from _weakref import ref
22class Foo: pass
23a = Foo()
24weak = ref(a)
25)";
26 HandleScope scope(thread_);
27 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
28 RawObject a = mainModuleAt(runtime_, "a");
29 RawObject weak = mainModuleAt(runtime_, "weak");
30 EXPECT_EQ(WeakRef::cast(weak).referent(), a);
31 EXPECT_EQ(WeakRef::cast(weak).callback(), NoneType::object());
32
33 Module main(&scope, findMainModule(runtime_));
34 Str name(&scope, Runtime::internStrFromCStr(thread_, "a"));
35 moduleRemove(thread_, main, name);
36
37 runtime_->collectGarbage();
38 weak = mainModuleAt(runtime_, "weak");
39 EXPECT_EQ(WeakRef::cast(weak).referent(), NoneType::object());
40}
41
42TEST_F(RefBuiltinsTest, CallbackTest) {
43 const char* src = R"(
44from _weakref import ref
45class Foo: pass
46a = Foo()
47b = None
48def f(ref):
49 global b
50 b = ref
51weak = ref(a, f)
52callback = weak.__callback__
53)";
54 HandleScope scope(thread_);
55 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
56 RawObject a = mainModuleAt(runtime_, "a");
57 RawObject b = mainModuleAt(runtime_, "b");
58 RawObject f = mainModuleAt(runtime_, "f");
59 RawObject cb = mainModuleAt(runtime_, "callback");
60 RawObject weak = mainModuleAt(runtime_, "weak");
61 EXPECT_EQ(WeakRef::cast(weak).referent(), a);
62 EXPECT_EQ(b, NoneType::object());
63 EXPECT_TRUE(WeakRef::cast(weak).callback().isBoundMethod());
64 EXPECT_EQ(BoundMethod::cast(WeakRef::cast(weak).callback()).self(), weak);
65 EXPECT_EQ(f, cb);
66
67 Module main(&scope, findMainModule(runtime_));
68 Str name(&scope, Runtime::internStrFromCStr(thread_, "a"));
69 moduleRemove(thread_, main, name);
70
71 runtime_->collectGarbage();
72 weak = mainModuleAt(runtime_, "weak");
73 b = mainModuleAt(runtime_, "b");
74 EXPECT_EQ(b, weak);
75 EXPECT_EQ(WeakRef::cast(weak).referent(), NoneType::object());
76 EXPECT_EQ(WeakRef::cast(weak).callback(), NoneType::object());
77}
78
79TEST_F(RefBuiltinsTest, DunderCallbackWithNoBoundMethodReturnsBoundMethod) {
80 const char* src = R"(
81from _weakref import ref
82class Foo: pass
83class Bar:
84 def method(self, wr):
85 pass
86
87a = Foo()
88b = Bar()
89original_callback = b.method
90weak = ref(a, original_callback)
91callback = weak.__callback__
92)";
93 ASSERT_FALSE(runFromCStr(runtime_, src).isError());
94 RawObject original_callback = mainModuleAt(runtime_, "original_callback");
95 RawObject callback = mainModuleAt(runtime_, "callback");
96 EXPECT_EQ(callback, original_callback);
97}
98
99TEST_F(RefBuiltinsTest, DunderCallReturnsObject) {
100 HandleScope scope(thread_);
101 Object obj(&scope, runtime_->newSet());
102 WeakRef ref(&scope, runtime_->newWeakRef(thread_, obj));
103 Object result(&scope, runBuiltin(METH(weakref, __call__), ref));
104 EXPECT_EQ(result, obj);
105}
106
107TEST_F(RefBuiltinsTest, DunderHashWithDeadRefRaisesTypeError) {
108 ASSERT_FALSE(runFromCStr(runtime_, R"(
109import _weakref
110class C:
111 pass
112ref = _weakref.ref(C())
113)")
114 .isError());
115 runtime_->collectGarbage();
116 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "ref.__hash__()"),
117 LayoutId::kTypeError, "weak object has gone away"));
118}
119
120TEST_F(RefBuiltinsTest, DunderHashCallsHashOfReferent) {
121 ASSERT_FALSE(runFromCStr(runtime_, R"(
122import _weakref
123class C:
124 def __hash__(self):
125 raise Exception("foo")
126c = C()
127ref = _weakref.ref(c)
128)")
129 .isError());
130 EXPECT_TRUE(raisedWithStr(runFromCStr(runtime_, "ref.__hash__()"),
131 LayoutId::kException, "foo"));
132}
133
134TEST_F(RefBuiltinsTest, WeakRefUnderlyingReturnsUnderlyingRef) {
135 ASSERT_FALSE(runFromCStr(runtime_, R"(
136import _weakref
137class SubRef(_weakref.ref):
138 pass
139
140class C:
141 pass
142
143c = C()
144sub_ref = SubRef(c)
145)")
146 .isError());
147 HandleScope scope(thread_);
148 Object sub_ref_obj(&scope, mainModuleAt(runtime_, "sub_ref"));
149 WeakRef ref(&scope, weakRefUnderlying(*sub_ref_obj));
150 EXPECT_EQ(ref.referent(), mainModuleAt(runtime_, "c"));
151}
152
153TEST_F(RefBuiltinsTest, RefSubclassReferentSetsToNone) {
154 ASSERT_FALSE(runFromCStr(runtime_, R"(
155import _weakref
156class SubRef(_weakref.ref):
157 pass
158
159class C:
160 pass
161
162c = C()
163sub_ref = SubRef(c)
164c = None
165)")
166 .isError());
167 runtime_->collectGarbage();
168 HandleScope scope(thread_);
169 WeakRef ref(&scope, weakRefUnderlying(mainModuleAt(runtime_, "sub_ref")));
170 EXPECT_EQ(ref.referent(), NoneType::object());
171}
172
173} // namespace testing
174} // namespace py