1 /*
2 * Copyright (c) 2024 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 <cstdio>
17
18 #include "ecmascript/dfx/cpu_profiler/cpu_profiler.h"
19 #include "ecmascript/tests/test_helper.h"
20
21 using namespace panda::ecmascript;
22
23 namespace panda::ecmascript {
24 class CpuProfilerFriendTest {
25 public:
CpuProfilerFriendTest(const EcmaVM *vm, const int interval)26 explicit CpuProfilerFriendTest(const EcmaVM *vm, const int interval) : cpu_profiler(vm, interval) {}
27
SetIsProfiling(bool isProfiling)28 void SetIsProfiling(bool isProfiling)
29 {
30 cpu_profiler.isProfiling_ = isProfiling;
31 }
32
SetOutToFile(bool outToFile)33 void SetOutToFile(bool outToFile)
34 {
35 cpu_profiler.outToFile_ = outToFile;
36 }
37
SetInterval(uint32_t intervalTest)38 void SetInterval(uint32_t intervalTest)
39 {
40 cpu_profiler.interval_ = intervalTest;
41 }
42
StartCpuProfilerForInfoTest()43 bool StartCpuProfilerForInfoTest()
44 {
45 return cpu_profiler.StartCpuProfilerForInfo();
46 }
47
StopCpuProfilerForInfoTest(std::unique_ptr<struct ProfileInfo> &profileInfo)48 bool StopCpuProfilerForInfoTest(std::unique_ptr<struct ProfileInfo> &profileInfo)
49 {
50 return cpu_profiler.StopCpuProfilerForInfo(profileInfo);
51 }
52
StartCpuProfilerForFileTest(const std::string &fileName)53 bool StartCpuProfilerForFileTest(const std::string &fileName)
54 {
55 return cpu_profiler.StartCpuProfilerForFile(fileName);
56 }
57
StopCpuProfilerForFileTest()58 bool StopCpuProfilerForFileTest()
59 {
60 return cpu_profiler.StopCpuProfilerForFile();
61 }
62
GetStackBeforeCallNapiTest(JSThread *thread)63 bool GetStackBeforeCallNapiTest(JSThread *thread)
64 {
65 return cpu_profiler.GetStackBeforeCallNapi(thread);
66 }
67
68 private:
69 CpuProfiler cpu_profiler;
70 };
71 }
72
73 namespace panda::test {
74 class CpuProfilerTest : public testing::Test {
75 public:
SetUpTestCase()76 static void SetUpTestCase()
77 {
78 GTEST_LOG_(INFO) << "SetUpTestCase";
79 }
80
TearDownTestCase()81 static void TearDownTestCase()
82 {
83 GTEST_LOG_(INFO) << "TearDownCase";
84 }
85
86 void SetUp() override
87 {
88 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
89 instance->SetEnableForceGC(false);
90 }
91
92 void TearDown() override
93 {
94 TestHelper::DestroyEcmaVMWithScope(instance, scope);
95 }
96
97 EcmaVM *instance {nullptr};
98 EcmaHandleScope *scope {nullptr};
99 JSThread *thread {nullptr};
100 };
101
HWTEST_F_L0(CpuProfilerTest, TestStopCpuProfilerForFile)102 HWTEST_F_L0(CpuProfilerTest, TestStopCpuProfilerForFile)
103 {
104 int interval = 1;
105 bool ret;
106 CpuProfilerFriendTest cpuProfilerFriend(instance, interval);
107 ret = cpuProfilerFriend.StopCpuProfilerForFileTest();
108 EXPECT_TRUE(ret);
109
110 cpuProfilerFriend.SetIsProfiling(true);
111 cpuProfilerFriend.StartCpuProfilerForInfoTest();
112 ret = cpuProfilerFriend.StopCpuProfilerForFileTest();
113 EXPECT_FALSE(ret);
114 }
115
HWTEST_F_L0(CpuProfilerTest, TestStartCpuProfilerForFile)116 HWTEST_F_L0(CpuProfilerTest, TestStartCpuProfilerForFile)
117 {
118 int interval = 1;
119 bool ret;
120 CpuProfilerFriendTest cpuProfilerFriend(instance, interval);
121 std::string filename1("__CpuprofilerTest.abc");
122 std::string filename2("");
123 std::string filename3(PATH_MAX + 1, ' ');
124
125 ret = cpuProfilerFriend.StartCpuProfilerForFileTest(filename1);
126 EXPECT_FALSE(ret);
127 ret = cpuProfilerFriend.StartCpuProfilerForFileTest(filename2);
128 EXPECT_FALSE(ret);
129 ret = cpuProfilerFriend.StartCpuProfilerForFileTest(filename3);
130 EXPECT_FALSE(ret);
131
132 cpuProfilerFriend.SetIsProfiling(true);
133 ret = cpuProfilerFriend.StartCpuProfilerForFileTest(filename1);
134 EXPECT_FALSE(ret);
135 }
136
HWTEST_F_L0(CpuProfilerTest, TestStopCpuProfilerForInfo)137 HWTEST_F_L0(CpuProfilerTest, TestStopCpuProfilerForInfo)
138 {
139 int interval = 1;
140 bool ret;
141 CpuProfilerFriendTest cpuProfilerFriend(instance, interval);
142 std::unique_ptr<ProfileInfo> profileInfo;
143
144 ret = cpuProfilerFriend.StopCpuProfilerForInfoTest(profileInfo);
145 EXPECT_TRUE(ret);
146
147 cpuProfilerFriend.StartCpuProfilerForInfoTest();
148 ret = cpuProfilerFriend.StopCpuProfilerForInfoTest(profileInfo);
149 EXPECT_TRUE(ret);
150
151 cpuProfilerFriend.SetIsProfiling(true);
152 cpuProfilerFriend.SetOutToFile(true);
153 ret = cpuProfilerFriend.StopCpuProfilerForInfoTest(profileInfo);
154 EXPECT_FALSE(ret);
155 }
156
HWTEST_F_L0(CpuProfilerTest, TestGetStackBeforeCallNapi)157 HWTEST_F_L0(CpuProfilerTest, TestGetStackBeforeCallNapi)
158 {
159 uint32_t interval = 100;
160 CpuProfilerFriendTest cpuProfilerFriend(instance, interval);
161
162 bool flag = cpuProfilerFriend.GetStackBeforeCallNapiTest(thread);
163 EXPECT_TRUE(flag);
164
165 cpuProfilerFriend.SetInterval(UINT32_MAX);
166 flag = cpuProfilerFriend.GetStackBeforeCallNapiTest(thread);
167 EXPECT_FALSE(flag);
168 }
169
HWTEST_F_L0(CpuProfilerTest, TestCpuProfilerHasSameName)170 HWTEST_F_L0(CpuProfilerTest, TestCpuProfilerHasSameName)
171 {
172 int interval = 500;
173
174 bool res = DFXJSNApi::StartCpuProfilerForInfo(instance, interval);
175 EXPECT_TRUE(res);
176 // The cpuprofiler_1.js only support test A->B->C, not support test A->C, B->C
177 std::string fileName = DEBUGGER_ABC_DIR "cpuprofiler_1.abc";
178 std::string entryPoint = "cpuprofiler_1";
179 res = JSNApi::Execute(instance, fileName, entryPoint);
180 ASSERT_TRUE(res);
181 std::unique_ptr<ProfileInfo> profileInfo = DFXJSNApi::StopCpuProfilerForInfo(instance);
182 size_t nodesLen = profileInfo->nodeCount;
183 std::unordered_set<std::string> functionNames;
184 // Check if the function has multiple nodes
185 for (size_t i = 0; i < nodesLen; ++i) {
186 const auto &cpuProfileNode = profileInfo->nodes[i];
187 std::string functionName = cpuProfileNode.codeEntry.functionName;
188 auto node = functionNames.find(functionName);
189 if (node == functionNames.end()) {
190 functionNames.insert(functionName);
191 } else {
192 res = false;
193 break;
194 }
195 }
196 ASSERT_TRUE(res);
197 }
198 } // namespace panda::test