• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ReportProgress(int32_t done,int32_t total)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 
EndOfStream()49     void EndOfStream() override {}
GetSize()50     int GetSize() override
51     {
52         static const int HEAP_PROFILER_CHUNK_SIZE = 100_KB;
53         return HEAP_PROFILER_CHUNK_SIZE;
54     }
WriteChunk(char * data,int32_t size)55     bool WriteChunk([[maybe_unused]] char *data, [[maybe_unused]] int32_t size) override
56     {
57         return true;
58     }
WriteBinBlock(char * data,int32_t size)59     bool WriteBinBlock(char *data, int32_t size) override
60     {
61         return WriteChunk(data, size);
62     }
Good()63     bool Good() override
64     {
65         return testStream_.good();
66     }
67 
UpdateHeapStats(HeapStat * updateData,int32_t count)68     void UpdateHeapStats([[maybe_unused]] HeapStat* updateData, [[maybe_unused]] int32_t count) override
69     {
70     }
71 
UpdateLastSeenObjectId(int32_t lastSeenObjectId,int64_t timeStampUs)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 
SetUp()99     void SetUp() override
100     {
101         TestHelper::CreateEcmaVMWithScope(instance, thread, scope);
102         instance->SetEnableForceGC(false);
103     }
104 
TearDown()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,GenDumpFileName_001)115 HWTEST_F_L0(HeapTrackerTest, 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,GenDumpFileName_002)151 HWTEST_F_L0(HeapTrackerTest, 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.isDumpOOM = true;
181     dumpOption.isVmMode = true;
182     dumpOption.isPrivate = true;
183     dumpOption.captureNumericValue = false;
184     heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
185     HeapProfilerInterface::Destroy(instance);
186 }
187 
HWTEST_F_L0(HeapTrackerTest,GenDumpFileName_003)188 HWTEST_F_L0(HeapTrackerTest, GenDumpFileName_003)
189 {
190     [[maybe_unused]] EcmaHandleScope handleScope(thread);
191     HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
192 
193     sleep(1);
194     int count = 100;
195     while (count-- > 0) {
196         instance->GetFactory()->NewJSAsyncFuncObject();
197     }
198     sleep(1);
199     count = 100;
200     while (count-- > 0) {
201         instance->GetFactory()->NewJSSymbol();
202     }
203     sleep(1);
204     count = 100;
205     while (count-- > 0) {
206         JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
207         JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
208         instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
209     }
210 
211     TestStream stream;
212     stream.Clear();
213     EXPECT_TRUE(!stream.Good());
214     TestProgress testProgress;
215     DumpSnapShotOption dumpOption;
216     dumpOption.dumpFormat = DumpFormat::OTHER;
217     dumpOption.isVmMode = true;
218     dumpOption.isPrivate = true;
219     dumpOption.captureNumericValue = false;
220     heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
221     HeapProfilerInterface::Destroy(instance);
222 }
223 
HWTEST_F_L0(HeapTrackerTest,GenDumpFileName_004)224 HWTEST_F_L0(HeapTrackerTest, GenDumpFileName_004)
225 {
226     [[maybe_unused]] EcmaHandleScope handleScope(thread);
227     HeapProfilerInterface *heapProfile = HeapProfilerInterface::GetInstance(instance);
228 
229     sleep(1);
230     int count = 100;
231     while (count-- > 0) {
232         instance->GetFactory()->NewJSAsyncFuncObject();
233     }
234     sleep(1);
235     count = 100;
236     while (count-- > 0) {
237         instance->GetFactory()->NewJSSymbol();
238     }
239     sleep(1);
240     count = 100;
241     while (count-- > 0) {
242         JSHandle<JSTaggedValue> undefined = instance->GetJSThread()->GlobalConstants()->GetHandledUndefined();
243         JSHandle<EcmaString> string = instance->GetFactory()->NewFromASCII("Hello World");
244         instance->GetFactory()->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
245     }
246 
247     TestStream stream;
248     stream.Clear();
249     EXPECT_TRUE(!stream.Good());
250     TestProgress testProgress;
251     DumpSnapShotOption dumpOption;
252     dumpOption.dumpFormat = static_cast<DumpFormat>(5); // 5 is exception.
253     dumpOption.isVmMode = true;
254     dumpOption.isPrivate = true;
255     dumpOption.captureNumericValue = false;
256     heapProfile->DumpHeapSnapshot(&stream, dumpOption, &testProgress);
257     HeapProfilerInterface::Destroy(instance);
258 }
259 
HWTEST_F_L0(HeapTrackerTest,FileDescriptorStreamEndOfStream)260 HWTEST_F_L0(HeapTrackerTest, FileDescriptorStreamEndOfStream)
261 {
262     int fd = 3;
263     FileDescriptorStream fileStream(fd);
264     EXPECT_TRUE(fileStream.Good());
265     fileStream.EndOfStream();
266 }
267 } // namespace panda::test