• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "gtest/gtest.h"
2 #include "node.h"
3 #include "base_object-inl.h"
4 #include "node_test_fixture.h"
5 
6 using node::BaseObject;
7 using node::BaseObjectPtr;
8 using node::BaseObjectWeakPtr;
9 using node::Environment;
10 using node::MakeBaseObject;
11 using node::MakeDetachedBaseObject;
12 using v8::HandleScope;
13 using v8::Isolate;
14 using v8::Local;
15 using v8::Object;
16 
17 class BaseObjectPtrTest : public EnvironmentTestFixture {};
18 
19 class DummyBaseObject : public BaseObject {
20  public:
DummyBaseObject(Environment * env,Local<Object> obj)21   DummyBaseObject(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
22 
MakeJSObject(Environment * env)23   static Local<Object> MakeJSObject(Environment* env) {
24     return BaseObject::MakeLazilyInitializedJSTemplate(env)
25         ->GetFunction(env->context()).ToLocalChecked()
26         ->NewInstance(env->context()).ToLocalChecked();
27   }
28 
NewDetached(Environment * env)29   static BaseObjectPtr<DummyBaseObject> NewDetached(Environment* env) {
30     Local<Object> obj = MakeJSObject(env);
31     return MakeDetachedBaseObject<DummyBaseObject>(env, obj);
32   }
33 
New(Environment * env)34   static BaseObjectPtr<DummyBaseObject> New(Environment* env) {
35     Local<Object> obj = MakeJSObject(env);
36     return MakeBaseObject<DummyBaseObject>(env, obj);
37   }
38 
39   SET_NO_MEMORY_INFO()
40   SET_MEMORY_INFO_NAME(DummyBaseObject)
41   SET_SELF_SIZE(DummyBaseObject)
42 };
43 
TEST_F(BaseObjectPtrTest,ScopedDetached)44 TEST_F(BaseObjectPtrTest, ScopedDetached) {
45   const HandleScope handle_scope(isolate_);
46   const Argv argv;
47   Env env_{handle_scope, argv};
48   Environment* env = *env_;
49 
50   EXPECT_EQ(env->base_object_count(), 0);
51   {
52     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
53     EXPECT_EQ(env->base_object_count(), 1);
54   }
55   EXPECT_EQ(env->base_object_count(), 0);
56 }
57 
TEST_F(BaseObjectPtrTest,ScopedDetachedWithWeak)58 TEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
59   const HandleScope handle_scope(isolate_);
60   const Argv argv;
61   Env env_{handle_scope, argv};
62   Environment* env = *env_;
63 
64   BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
65 
66   EXPECT_EQ(env->base_object_count(), 0);
67   {
68     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
69     weak_ptr = ptr;
70     EXPECT_EQ(env->base_object_count(), 1);
71   }
72   EXPECT_EQ(weak_ptr.get(), nullptr);
73   EXPECT_EQ(env->base_object_count(), 0);
74 }
75 
TEST_F(BaseObjectPtrTest,Undetached)76 TEST_F(BaseObjectPtrTest, Undetached) {
77   const HandleScope handle_scope(isolate_);
78   const Argv argv;
79   Env env_{handle_scope, argv};
80   Environment* env = *env_;
81 
82   node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
83     EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
84   }, env);
85 
86   BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
87   EXPECT_EQ(env->base_object_count(), 1);
88 }
89 
TEST_F(BaseObjectPtrTest,GCWeak)90 TEST_F(BaseObjectPtrTest, GCWeak) {
91   const HandleScope handle_scope(isolate_);
92   const Argv argv;
93   Env env_{handle_scope, argv};
94   Environment* env = *env_;
95 
96   BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
97 
98   {
99     const HandleScope handle_scope(isolate_);
100     BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
101     weak_ptr = ptr;
102     ptr->MakeWeak();
103 
104     EXPECT_EQ(env->base_object_count(), 1);
105     EXPECT_EQ(weak_ptr.get(), ptr.get());
106     EXPECT_EQ(weak_ptr->persistent().IsWeak(), false);
107 
108     ptr.reset();
109   }
110 
111   EXPECT_EQ(env->base_object_count(), 1);
112   EXPECT_NE(weak_ptr.get(), nullptr);
113   EXPECT_EQ(weak_ptr->persistent().IsWeak(), true);
114 
115   v8::V8::SetFlagsFromString("--expose-gc");
116   isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection);
117 
118   EXPECT_EQ(env->base_object_count(), 0);
119   EXPECT_EQ(weak_ptr.get(), nullptr);
120 }
121 
TEST_F(BaseObjectPtrTest,Moveable)122 TEST_F(BaseObjectPtrTest, Moveable) {
123   const HandleScope handle_scope(isolate_);
124   const Argv argv;
125   Env env_{handle_scope, argv};
126   Environment* env = *env_;
127 
128   BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
129   EXPECT_EQ(env->base_object_count(), 1);
130   BaseObjectWeakPtr<DummyBaseObject> weak_ptr { ptr };
131   EXPECT_EQ(weak_ptr.get(), ptr.get());
132 
133   BaseObjectPtr<DummyBaseObject> ptr2 = std::move(ptr);
134   EXPECT_EQ(weak_ptr.get(), ptr2.get());
135   EXPECT_EQ(ptr.get(), nullptr);
136 
137   BaseObjectWeakPtr<DummyBaseObject> weak_ptr2 = std::move(weak_ptr);
138   EXPECT_EQ(weak_ptr2.get(), ptr2.get());
139   EXPECT_EQ(weak_ptr.get(), nullptr);
140   EXPECT_EQ(env->base_object_count(), 1);
141 
142   ptr2.reset();
143 
144   EXPECT_EQ(weak_ptr2.get(), nullptr);
145   EXPECT_EQ(env->base_object_count(), 0);
146 }
147 
TEST_F(BaseObjectPtrTest,NestedClasses)148 TEST_F(BaseObjectPtrTest, NestedClasses) {
149   class ObjectWithPtr : public BaseObject {
150    public:
151     ObjectWithPtr(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
152 
153     BaseObjectPtr<BaseObject> ptr1;
154     BaseObjectPtr<BaseObject> ptr2;
155 
156     SET_NO_MEMORY_INFO()
157     SET_MEMORY_INFO_NAME(ObjectWithPtr)
158     SET_SELF_SIZE(ObjectWithPtr)
159   };
160 
161   const HandleScope handle_scope(isolate_);
162   const Argv argv;
163   Env env_{handle_scope, argv};
164   Environment* env = *env_;
165 
166   node::AddEnvironmentCleanupHook(isolate_, [](void* arg) {
167     EXPECT_EQ(static_cast<Environment*>(arg)->base_object_count(), 0);
168   }, env);
169 
170   ObjectWithPtr* obj =
171       new ObjectWithPtr(env, DummyBaseObject::MakeJSObject(env));
172   obj->ptr1 = DummyBaseObject::NewDetached(env);
173   obj->ptr2 = DummyBaseObject::New(env);
174 
175   EXPECT_EQ(env->base_object_count(), 3);
176 }
177