this repo has no description
at trunk 174 lines 4.8 kB view raw
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