11cb0ef41Sopenharmony_ci#include "base_object-inl.h"
21cb0ef41Sopenharmony_ci#include "gtest/gtest.h"
31cb0ef41Sopenharmony_ci#include "node.h"
41cb0ef41Sopenharmony_ci#include "node_realm-inl.h"
51cb0ef41Sopenharmony_ci#include "node_test_fixture.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciusing node::BaseObject;
81cb0ef41Sopenharmony_ciusing node::BaseObjectPtr;
91cb0ef41Sopenharmony_ciusing node::BaseObjectWeakPtr;
101cb0ef41Sopenharmony_ciusing node::Environment;
111cb0ef41Sopenharmony_ciusing node::MakeBaseObject;
121cb0ef41Sopenharmony_ciusing node::MakeDetachedBaseObject;
131cb0ef41Sopenharmony_ciusing node::Realm;
141cb0ef41Sopenharmony_ciusing v8::HandleScope;
151cb0ef41Sopenharmony_ciusing v8::Isolate;
161cb0ef41Sopenharmony_ciusing v8::Local;
171cb0ef41Sopenharmony_ciusing v8::Object;
181cb0ef41Sopenharmony_ci
191cb0ef41Sopenharmony_ciclass BaseObjectPtrTest : public EnvironmentTestFixture {};
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ciclass DummyBaseObject : public BaseObject {
221cb0ef41Sopenharmony_ci public:
231cb0ef41Sopenharmony_ci  DummyBaseObject(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  static Local<Object> MakeJSObject(Environment* env) {
261cb0ef41Sopenharmony_ci    return BaseObject::MakeLazilyInitializedJSTemplate(env)
271cb0ef41Sopenharmony_ci        ->GetFunction(env->context()).ToLocalChecked()
281cb0ef41Sopenharmony_ci        ->NewInstance(env->context()).ToLocalChecked();
291cb0ef41Sopenharmony_ci  }
301cb0ef41Sopenharmony_ci
311cb0ef41Sopenharmony_ci  static BaseObjectPtr<DummyBaseObject> NewDetached(Environment* env) {
321cb0ef41Sopenharmony_ci    Local<Object> obj = MakeJSObject(env);
331cb0ef41Sopenharmony_ci    return MakeDetachedBaseObject<DummyBaseObject>(env, obj);
341cb0ef41Sopenharmony_ci  }
351cb0ef41Sopenharmony_ci
361cb0ef41Sopenharmony_ci  static BaseObjectPtr<DummyBaseObject> New(Environment* env) {
371cb0ef41Sopenharmony_ci    Local<Object> obj = MakeJSObject(env);
381cb0ef41Sopenharmony_ci    return MakeBaseObject<DummyBaseObject>(env, obj);
391cb0ef41Sopenharmony_ci  }
401cb0ef41Sopenharmony_ci
411cb0ef41Sopenharmony_ci  SET_NO_MEMORY_INFO()
421cb0ef41Sopenharmony_ci  SET_MEMORY_INFO_NAME(DummyBaseObject)
431cb0ef41Sopenharmony_ci  SET_SELF_SIZE(DummyBaseObject)
441cb0ef41Sopenharmony_ci};
451cb0ef41Sopenharmony_ci
461cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, ScopedDetached) {
471cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
481cb0ef41Sopenharmony_ci  const Argv argv;
491cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
501cb0ef41Sopenharmony_ci  Environment* env = *env_;
511cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
521cb0ef41Sopenharmony_ci
531cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
541cb0ef41Sopenharmony_ci  {
551cb0ef41Sopenharmony_ci    BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
561cb0ef41Sopenharmony_ci    EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
571cb0ef41Sopenharmony_ci  }
581cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
591cb0ef41Sopenharmony_ci}
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, ScopedDetachedWithWeak) {
621cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
631cb0ef41Sopenharmony_ci  const Argv argv;
641cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
651cb0ef41Sopenharmony_ci  Environment* env = *env_;
661cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci  BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
691cb0ef41Sopenharmony_ci
701cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
711cb0ef41Sopenharmony_ci  {
721cb0ef41Sopenharmony_ci    BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
731cb0ef41Sopenharmony_ci    weak_ptr = ptr;
741cb0ef41Sopenharmony_ci    EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
751cb0ef41Sopenharmony_ci  }
761cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr.get(), nullptr);
771cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
781cb0ef41Sopenharmony_ci}
791cb0ef41Sopenharmony_ci
801cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, Undetached) {
811cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
821cb0ef41Sopenharmony_ci  const Argv argv;
831cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
841cb0ef41Sopenharmony_ci  Environment* env = *env_;
851cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
861cb0ef41Sopenharmony_ci
871cb0ef41Sopenharmony_ci  node::AddEnvironmentCleanupHook(
881cb0ef41Sopenharmony_ci      isolate_,
891cb0ef41Sopenharmony_ci      [](void* arg) {
901cb0ef41Sopenharmony_ci        EXPECT_EQ(static_cast<Realm*>(arg)->base_object_count(), 0);
911cb0ef41Sopenharmony_ci      },
921cb0ef41Sopenharmony_ci      realm);
931cb0ef41Sopenharmony_ci
941cb0ef41Sopenharmony_ci  BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
951cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
961cb0ef41Sopenharmony_ci}
971cb0ef41Sopenharmony_ci
981cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, GCWeak) {
991cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
1001cb0ef41Sopenharmony_ci  const Argv argv;
1011cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
1021cb0ef41Sopenharmony_ci  Environment* env = *env_;
1031cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
1041cb0ef41Sopenharmony_ci
1051cb0ef41Sopenharmony_ci  BaseObjectWeakPtr<DummyBaseObject> weak_ptr;
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci  {
1081cb0ef41Sopenharmony_ci    const HandleScope handle_scope(isolate_);
1091cb0ef41Sopenharmony_ci    BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::New(env);
1101cb0ef41Sopenharmony_ci    weak_ptr = ptr;
1111cb0ef41Sopenharmony_ci    ptr->MakeWeak();
1121cb0ef41Sopenharmony_ci
1131cb0ef41Sopenharmony_ci    EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
1141cb0ef41Sopenharmony_ci    EXPECT_EQ(weak_ptr.get(), ptr.get());
1151cb0ef41Sopenharmony_ci    EXPECT_EQ(weak_ptr->persistent().IsWeak(), false);
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci    ptr.reset();
1181cb0ef41Sopenharmony_ci  }
1191cb0ef41Sopenharmony_ci
1201cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
1211cb0ef41Sopenharmony_ci  EXPECT_NE(weak_ptr.get(), nullptr);
1221cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr->persistent().IsWeak(), true);
1231cb0ef41Sopenharmony_ci
1241cb0ef41Sopenharmony_ci  v8::V8::SetFlagsFromString("--expose-gc");
1251cb0ef41Sopenharmony_ci  isolate_->RequestGarbageCollectionForTesting(Isolate::kFullGarbageCollection);
1261cb0ef41Sopenharmony_ci
1271cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
1281cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr.get(), nullptr);
1291cb0ef41Sopenharmony_ci}
1301cb0ef41Sopenharmony_ci
1311cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, Moveable) {
1321cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
1331cb0ef41Sopenharmony_ci  const Argv argv;
1341cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
1351cb0ef41Sopenharmony_ci  Environment* env = *env_;
1361cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
1371cb0ef41Sopenharmony_ci
1381cb0ef41Sopenharmony_ci  BaseObjectPtr<DummyBaseObject> ptr = DummyBaseObject::NewDetached(env);
1391cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
1401cb0ef41Sopenharmony_ci  BaseObjectWeakPtr<DummyBaseObject> weak_ptr { ptr };
1411cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr.get(), ptr.get());
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci  BaseObjectPtr<DummyBaseObject> ptr2 = std::move(ptr);
1441cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr.get(), ptr2.get());
1451cb0ef41Sopenharmony_ci  EXPECT_EQ(ptr.get(), nullptr);
1461cb0ef41Sopenharmony_ci
1471cb0ef41Sopenharmony_ci  BaseObjectWeakPtr<DummyBaseObject> weak_ptr2 = std::move(weak_ptr);
1481cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr2.get(), ptr2.get());
1491cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr.get(), nullptr);
1501cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 1);
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci  ptr2.reset();
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci  EXPECT_EQ(weak_ptr2.get(), nullptr);
1551cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 0);
1561cb0ef41Sopenharmony_ci}
1571cb0ef41Sopenharmony_ci
1581cb0ef41Sopenharmony_ciTEST_F(BaseObjectPtrTest, NestedClasses) {
1591cb0ef41Sopenharmony_ci  class ObjectWithPtr : public BaseObject {
1601cb0ef41Sopenharmony_ci   public:
1611cb0ef41Sopenharmony_ci    ObjectWithPtr(Environment* env, Local<Object> obj) : BaseObject(env, obj) {}
1621cb0ef41Sopenharmony_ci
1631cb0ef41Sopenharmony_ci    BaseObjectPtr<BaseObject> ptr1;
1641cb0ef41Sopenharmony_ci    BaseObjectPtr<BaseObject> ptr2;
1651cb0ef41Sopenharmony_ci
1661cb0ef41Sopenharmony_ci    SET_NO_MEMORY_INFO()
1671cb0ef41Sopenharmony_ci    SET_MEMORY_INFO_NAME(ObjectWithPtr)
1681cb0ef41Sopenharmony_ci    SET_SELF_SIZE(ObjectWithPtr)
1691cb0ef41Sopenharmony_ci  };
1701cb0ef41Sopenharmony_ci
1711cb0ef41Sopenharmony_ci  const HandleScope handle_scope(isolate_);
1721cb0ef41Sopenharmony_ci  const Argv argv;
1731cb0ef41Sopenharmony_ci  Env env_{handle_scope, argv};
1741cb0ef41Sopenharmony_ci  Environment* env = *env_;
1751cb0ef41Sopenharmony_ci  Realm* realm = env->principal_realm();
1761cb0ef41Sopenharmony_ci
1771cb0ef41Sopenharmony_ci  node::AddEnvironmentCleanupHook(
1781cb0ef41Sopenharmony_ci      isolate_,
1791cb0ef41Sopenharmony_ci      [](void* arg) {
1801cb0ef41Sopenharmony_ci        EXPECT_EQ(static_cast<Realm*>(arg)->base_object_count(), 0);
1811cb0ef41Sopenharmony_ci      },
1821cb0ef41Sopenharmony_ci      realm);
1831cb0ef41Sopenharmony_ci
1841cb0ef41Sopenharmony_ci  ObjectWithPtr* obj =
1851cb0ef41Sopenharmony_ci      new ObjectWithPtr(env, DummyBaseObject::MakeJSObject(env));
1861cb0ef41Sopenharmony_ci  obj->ptr1 = DummyBaseObject::NewDetached(env);
1871cb0ef41Sopenharmony_ci  obj->ptr2 = DummyBaseObject::New(env);
1881cb0ef41Sopenharmony_ci
1891cb0ef41Sopenharmony_ci  EXPECT_EQ(realm->base_object_created_after_bootstrap(), 3);
1901cb0ef41Sopenharmony_ci}
191