1 /*
2 * Copyright (c) 2021 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 #include <fstream>
18 #include <fcntl.h>
19
20 #include "ecmascript/dfx/hprof/heap_profiler_interface.h"
21 #include "ecmascript/dfx/hprof/heap_profiler.h"
22 #include "ecmascript/dfx/hprof/heap_snapshot_json_serializer.h"
23 #include "ecmascript/dfx/hprof/heap_snapshot.h"
24 #include "ecmascript/ecma_string.h"
25 #include "ecmascript/global_env.h"
26
27 #include "ecmascript/js_tagged_value.h"
28 #include "ecmascript/js_thread.h"
29 #include "ecmascript/mem/heap.h"
30 #include "ecmascript/tests/test_helper.h"
31 #include "ecmascript/dfx/hprof/file_stream.h"
32
33 using namespace panda::ecmascript;
34
35 namespace panda::ecmascript {
36 class TestProgress : public Progress {
37 public:
38 TestProgress() = default;
39 ~TestProgress() = default;
40
41 void ReportProgress([[maybe_unused]] int32_t done, [[maybe_unused]] int32_t total) override {}
42 };
43
44 class TestStream : public Stream {
45 public:
46 TestStream() = default;
47 ~TestStream() = default;
48
49 void EndOfStream() override {}
50 int GetSize() override
51 {
52 static const int HEAP_PROFILER_CHUNK_SIZE = 100_KB;
53 return HEAP_PROFILER_CHUNK_SIZE;
54 }
55 bool WriteChunk([[maybe_unused]] char *data, [[maybe_unused]] int32_t size) override
56 {
57 return true;
58 }
59 bool WriteBinBlock(char *data, int32_t size) override
60 {
61 return WriteChunk(data, size);
62 }
63 bool Good() override
64 {
65 return testStream_.good();
66 }
67
68 void UpdateHeapStats([[maybe_unused]] HeapStat* updateData, [[maybe_unused]] int32_t count) override
69 {
70 }
71
72 void UpdateLastSeenObjectId([[maybe_unused]] int32_t lastSeenObjectId, [[maybe_unused]]int64_t timeStampUs) override
73 {
74 }
75
Clear()76 void Clear()
77 {
78 testStream_.clear(std::ios::badbit);
79 }
80
81 private:
82 std::fstream testStream_;
83 };
84 }
85
86 namespace panda::test {
87 class HeapTrackerTest : public testing::Test {
88 public:
SetUpTestCase()89 static void SetUpTestCase()
90 {
91 GTEST_LOG_(INFO) << "SetUpTestCase";
92 }
93
TearDownTestCase()94 static void TearDownTestCase()
95 {
96 GTEST_LOG_(INFO) << "TearDownCase";
97 }
98
99 void SetUp() override
100 {
101 TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
102 instance->SetEnableForceGC(false);
103 }
104
105 void TearDown() override
106 {
107 TestHelper::DestroyEcmaVMWithScope(instance, scope);
108 }
109
110 EcmaVM *instance {nullptr};
111 EcmaHandleScope *scope {nullptr};
112 JSThread *thread {nullptr};
113 };
114
HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_001)115 HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_001)
116 {
117 [[maybe_unused]] EcmaHandleScope handleScope(thread);
118 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
119
120 sleep(1);
121 int count = 100;
122 while (count-- > 0) {
123 instance->GetFactory()->NewJSAsyncFuncObject();
124 }
125 sleep(1);
126 count = 100;
127 while (count-- > 0) {
128 instance->GetFactory()->NewJSSymbol();
129 }
130 sleep(1);
131 count = 100;
132 while (count-- > 0) {
133 JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
134 JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
135 instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
136 }
137
138 TestStream stream;
139 stream.Clear();
140 EXPECT_TRUE(!stream.Good());
141 TestProgress testProgress;
142 DumpSnapShotOption dumpOption;
143 dumpOption.dumpFormat = DumpFormat::JSON;
144 dumpOption.isVmMode = true;
145 dumpOption.isPrivate = true;
146 dumpOption.captureNumericValue = false;
147 heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
148 HeapProfilerInterface::Destroy(instance);
149 }
150
HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_002)151 HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_002)
152 {
153 [[maybe_unused]] EcmaHandleScope handleScope(thread);
154 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
155
156 sleep(1);
157 int count = 100;
158 while (count-- > 0) {
159 instance->GetFactory()->NewJSAsyncFuncObject();
160 }
161 sleep(1);
162 count = 100;
163 while (count-- > 0) {
164 instance->GetFactory()->NewJSSymbol();
165 }
166 sleep(1);
167 count = 100;
168 while (count-- > 0) {
169 JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
170 JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
171 instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
172 }
173
174 TestStream stream;
175 stream.Clear();
176 EXPECT_TRUE(!stream.Good());
177 TestProgress testProgress;
178 DumpSnapShotOption dumpOption;
179 dumpOption.dumpFormat = DumpFormat::BINARY;
180 dumpOption.isVmMode = true;
181 dumpOption.isPrivate = true;
182 dumpOption.captureNumericValue = false;
183 heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
184 HeapProfilerInterface::Destroy(instance);
185 }
186
HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_003)187 HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_003)
188 {
189 [[maybe_unused]] EcmaHandleScope handleScope(thread);
190 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
191
192 sleep(1);
193 int count = 100;
194 while (count-- > 0) {
195 instance->GetFactory()->NewJSAsyncFuncObject();
196 }
197 sleep(1);
198 count = 100;
199 while (count-- > 0) {
200 instance->GetFactory()->NewJSSymbol();
201 }
202 sleep(1);
203 count = 100;
204 while (count-- > 0) {
205 JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
206 JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
207 instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
208 }
209
210 TestStream stream;
211 stream.Clear();
212 EXPECT_TRUE(!stream.Good());
213 TestProgress testProgress;
214 DumpSnapShotOption dumpOption;
215 dumpOption.dumpFormat = DumpFormat::OTHER;
216 dumpOption.isVmMode = true;
217 dumpOption.isPrivate = true;
218 dumpOption.captureNumericValue = false;
219 heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
220 HeapProfilerInterface::Destroy(instance);
221 }
222
HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_004)223 HWTEST_F_L0(HeapTrackerTest, DISABLED_GenDumpFileName_004)
224 {
225 [[maybe_unused]] EcmaHandleScope handleScope(thread);
226 HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
227
228 sleep(1);
229 int count = 100;
230 while (count-- > 0) {
231 instance->GetFactory()->NewJSAsyncFuncObject();
232 }
233 sleep(1);
234 count = 100;
235 while (count-- > 0) {
236 instance->GetFactory()->NewJSSymbol();
237 }
238 sleep(1);
239 count = 100;
240 while (count-- > 0) {
241 JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
242 JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
243 instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
244 }
245
246 TestStream stream;
247 stream.Clear();
248 EXPECT_TRUE(!stream.Good());
249 TestProgress testProgress;
250 DumpSnapShotOption dumpOption;
251 dumpOption.dumpFormat = static_cast<DumpFormat>(5); // 5 is exception.
252 dumpOption.isVmMode = true;
253 dumpOption.isPrivate = true;
254 dumpOption.captureNumericValue = false;
255 heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
256 HeapProfilerInterface::Destroy(instance);
257 }
258
HWTEST_F_L0(HeapTrackerTest, DISABLED_FileDescriptorStreamEndOfStream)259 HWTEST_F_L0(HeapTrackerTest, DISABLED_FileDescriptorStreamEndOfStream)
260 {
261 int fd = 3;
262 FileDescriptorStream fileStream(fd);
263 EXPECT_TRUE(fileStream.Good());
264 fileStream.EndOfStream();
265 }
266 } // namespace panda::test