• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ecmascript/dfx/hprof/heap_profiler.h"
17 #include "ecmascript/tests/test_helper.h"
18 #include "ecmascript/js_array.h"
19 
20 using namespace panda::ecmascript;
21 
22 namespace panda::test {
23 class GlobalHandleLeakDetectTest : public testing::Test {
24 public:
SetUpTestCase()25     static void SetUpTestCase()
26     {
27         GTEST_LOG_(INFO) << "SetUpTestCase";
28     }
29 
TearDownTestCase()30     static void TearDownTestCase()
31     {
32         GTEST_LOG_(INFO) << "TearDownCase";
33     }
34 
SetUp()35     void SetUp() override
36     {
37         JSRuntimeOptions options;
38         options.SetArkProperties(options.GetArkProperties() | GLOBAL_OBJECT_LEAK_CHECK | GLOBAL_PRIMITIVE_LEAK_CHECK);
39         ecmaVm_ = JSNApi::CreateEcmaVM(options);
40         ASSERT_TRUE(ecmaVm_ != nullptr) << "Cannot create EcmaVM";
41         thread_ = ecmaVm_->GetJSThread();
42         thread_->ManagedCodeBegin();
43         scope_ = new EcmaHandleScope(thread_);
44         ecmaVm_->SetEnableForceGC(false);
45         heapProfiler_ = reinterpret_cast<HeapProfiler *>(HeapProfilerInterface::GetInstance(ecmaVm_));
46     }
47 
TearDown()48     void TearDown() override
49     {
50         TestHelper::DestroyEcmaVMWithScope(ecmaVm_, scope_);
51     }
52 
DumpHeapSnapshot(const std::string & detectResultFilePath)53     void DumpHeapSnapshot(const std::string &detectResultFilePath)
54     {
55         DumpSnapShotOption dumpOption;
56         dumpOption.dumpFormat = DumpFormat::JSON;
57         dumpOption.captureNumericValue = true;
58         dumpOption.isSync = false;
59         FileDescriptorStream stream(-1);
60 
61         JSRuntimeOptions &options = ecmaVm_->GetJSOptions();
62         options.SwitchStartGlobalLeakCheck();
63         if (options.EnableGlobalLeakCheck() && options.IsStartGlobalLeakCheck()) {
64             int fd = open(detectResultFilePath.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0666);
65             ASSERT_NE(fd, -1) << strerror(errno);
66             thread_->SetStackTraceFd(fd);
67         }
68         heapProfiler_->DumpHeapSnapshot(&stream, dumpOption);
69     }
70 
71     EcmaVM *ecmaVm_ {nullptr};
72     JSThread *thread_ {nullptr};
73     EcmaHandleScope *scope_ {nullptr};
74     HeapProfiler *heapProfiler_ {nullptr};
75 };
76 
HWTEST_F_L0(GlobalHandleLeakDetectTest,TestDetectionResult)77 HWTEST_F_L0(GlobalHandleLeakDetectTest, TestDetectionResult)
78 {
79     std::string detectResultFilePath{"global_handle_leak_detect_result.txt"};
80     DumpHeapSnapshot(detectResultFilePath);
81 
82     JSHandle<JSTaggedValue> arrayInRoot = JSArray::ArrayCreate(thread_, JSTaggedNumber(1));
83     // New a GlobalHandle without Dispose
84     thread_->NewGlobalHandle(arrayInRoot.GetTaggedType());
85 
86     DumpHeapSnapshot(detectResultFilePath);
87 
88     std::ifstream file {detectResultFilePath};
89     std::string line;
90     bool hasHandleNumber {false};
91     bool hasLeakObject {false};
92     bool hasLeakFooter {false};
93     while (std::getline(file, line)) {
94         if (!hasHandleNumber && line.find("Global Handle Number") != std::string::npos) {
95             hasHandleNumber = true;
96             continue;
97         }
98         if (!hasLeakObject && line.find("Global maybe leak object address") != std::string::npos) {
99             hasLeakObject = true;
100             continue;
101         }
102         if (!hasLeakFooter && line.find("Global leak check success!") != std::string::npos) {
103             hasLeakFooter = true;
104             continue;
105         }
106     }
107     ASSERT_TRUE(hasHandleNumber);
108     ASSERT_TRUE(hasLeakObject);
109     ASSERT_TRUE(hasLeakFooter);
110 }
111 }  // namespace panda::test