• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_interface.h"
17 #include "ecmascript/dfx/stackinfo/js_stackinfo.h"
18 #include "ecmascript/dfx/vmstat/runtime_stat.h"
19 #include "ecmascript/mem/heap.h"
20 #include "ecmascript/mem/concurrent_marker.h"
21 #include "ecmascript/napi/include/dfx_jsnapi.h"
22 #include "ecmascript/tests/test_helper.h"
23 
24 using namespace panda;
25 using namespace panda::ecmascript;
26 
27 namespace panda::test {
28 class DFXJSNApiTests : public testing::Test {
29 public:
SetUpTestCase()30     static void SetUpTestCase()
31     {
32         GTEST_LOG_(INFO) << "SetUpTestCase";
33     }
34 
TearDownTestCase()35     static void TearDownTestCase()
36     {
37         GTEST_LOG_(INFO) << "TearDownCase";
38     }
39 
SetUp()40     void SetUp() override
41     {
42         TestHelper::CreateEcmaVMWithScope(vm_, thread_, scope_);
43         vm_->SetRuntimeStatEnable(true);
44         vm_->SetEnableForceGC(false);
45     }
46 
TearDown()47     void TearDown() override
48     {
49         TestHelper::DestroyEcmaVMWithScope(vm_, scope_);
50     }
51 
52 protected:
53     EcmaVM *vm_ {nullptr};
54     JSThread *thread_ = {nullptr};
55     EcmaHandleScope *scope_ {nullptr};
56 };
57 
MatchJSONLineHeader(std::fstream & fs,const std::string filePath,int lineNum,CString lineContent)58 bool MatchJSONLineHeader(std::fstream &fs, const std::string filePath, int lineNum, CString lineContent)
59 {
60     CString tempLineContent = "";
61     int lineCount = 1;
62     fs.open(filePath.c_str(), std::ios::in);
63     while (getline(fs, tempLineContent)) {
64         if (lineNum == lineCount && tempLineContent.find(lineContent) != CString::npos) {
65             fs.close();
66             fs.clear();
67             return true;
68         }
69         lineCount++;
70     }
71     fs.close();
72     fs.clear();
73     return false;
74 }
75 
HWTEST_F_L0(DFXJSNApiTests,DumpHeapSnapshot_001)76 HWTEST_F_L0(DFXJSNApiTests, DumpHeapSnapshot_001)
77 {
78     const int dumpFormat = static_cast<int>(ecmascript::DumpFormat::JSON);
79     const std::string filePath = "DFXJSNApiTests_json_001.heapsnapshot";
80     std::fstream outputString(filePath, std::ios::out);
81     outputString.close();
82     outputString.clear();
83 
84     bool isVmMode = true;
85     bool isPrivate = false;
86     std::fstream inputFile {};
87     EXPECT_TRUE(inputFile.good());
88 
89     DFXJSNApi::DumpHeapSnapshot(vm_, dumpFormat, filePath, isVmMode, isPrivate);
90     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 1, "{\"snapshot\":"));
91     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 2, "{\"meta\":"));
92     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 3, "{\"node_fields\":"));
93     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 4, "\"node_types\":"));
94     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 5, "\"edge_fields\":"));
95     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 6, "\"edge_types\":"));
96     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 7, "\"trace_function_info_fields\":"));
97     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 8, "\"trace_node_fields\":"));
98     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 9, "\"sample_fields\":"));
99     EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 10, "\"location_fields\":"));
100     std::remove(filePath.c_str());
101 }
102 
HWTEST_F_L0(DFXJSNApiTests,DumpHeapSnapshot_002)103 HWTEST_F_L0(DFXJSNApiTests, DumpHeapSnapshot_002)
104 {
105     const int dumpFormat = static_cast<int>(ecmascript::DumpFormat::JSON);
106     const std::string filePath = "DFXJSNApiTests_json_002.heapsnapshot";
107     std::fstream outputString(filePath, std::ios::out);
108     outputString.close();
109     outputString.clear();
110 
111     ecmascript::FileStream stream(filePath);
112     EXPECT_TRUE(stream.Good());
113 
114     ecmascript::Progress *progress = nullptr;
115     bool isVmMode = true;
116     bool isPrivate = false;
117     std::fstream fStream {};
118     EXPECT_TRUE(fStream.good());
119 
120     DFXJSNApi::DumpHeapSnapshot(vm_, dumpFormat, &stream, progress, isVmMode, isPrivate);
121     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 1, "{\"snapshot\":"));
122     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 2, "{\"meta\":"));
123     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 3, "{\"node_fields\":"));
124     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 4, "\"node_types\":"));
125     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 5, "\"edge_fields\":"));
126     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 6, "\"edge_types\":"));
127     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 7, "\"trace_function_info_fields\":"));
128     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 8, "\"trace_node_fields\":"));
129     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 9, "\"sample_fields\":"));
130     EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 10, "\"location_fields\":"));
131     std::remove(filePath.c_str());
132 }
133 
HWTEST_F_L0(DFXJSNApiTests,BuildNativeAndJsStackTrace)134 HWTEST_F_L0(DFXJSNApiTests, BuildNativeAndJsStackTrace)
135 {
136     bool result = false;
137     std::string stackTraceStr = "stack_trace_str";
138     result = DFXJSNApi::BuildNativeAndJsStackTrace(vm_, stackTraceStr);
139     EXPECT_TRUE(stackTraceStr.empty());
140     EXPECT_FALSE(result);
141 }
142 
HWTEST_F_L0(DFXJSNApiTests,BuildJsStackTrace)143 HWTEST_F_L0(DFXJSNApiTests, BuildJsStackTrace)
144 {
145     std::string stackTraceStr = "stack_trace_str";
146     bool result = DFXJSNApi::BuildJsStackTrace(vm_, stackTraceStr);
147     EXPECT_TRUE(stackTraceStr.empty());
148     EXPECT_FALSE(result);
149 }
150 
HWTEST_F_L0(DFXJSNApiTests,Start_Stop_HeapTracking_001)151 HWTEST_F_L0(DFXJSNApiTests, Start_Stop_HeapTracking_001)
152 {
153     [[maybe_unused]] EcmaHandleScope handleScope(thread_);
154     vm_->SetEnableForceGC(false);
155 
156     auto factory = vm_->GetFactory();
157     bool isVmMode = true;
158     bool traceAllocation = false;
159     double timeInterval = 50; // 50 : time interval 50 ms
160     ecmascript::FileStream *stream = nullptr;
161     bool startResult = false;
162     startResult = DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode, stream, traceAllocation);
163     EXPECT_TRUE(startResult);
164 
165     sleep(1);
166     int count = 300;
167     while (count-- > 0) {
168         JSHandle<EcmaString> string = factory->NewFromASCII("Start_Stop_HeapTracking_001_TestString");
169         factory->NewJSString(JSHandle<JSTaggedValue>(string));
170     }
171     const std::string filePath = "Start_Stop_HeapTracking_001.heaptimeline";
172     std::fstream outputString(filePath, std::ios::out);
173     outputString.close();
174     outputString.clear();
175 
176     bool stopResult = DFXJSNApi::StopHeapTracking(vm_, filePath);
177     EXPECT_TRUE(stopResult);
178 
179     std::fstream inputStream(filePath, std::ios::in);
180     std::string line;
181     std::string emptySample = "\"samples\":";
182     std::string firstSample = "\"samples\":[0, ";
183     bool isFind = false;
184     while (getline(inputStream, line)) {
185         if (line.substr(0U, emptySample.size()) == emptySample) {
186             EXPECT_TRUE(line.substr(0, firstSample.size()) == firstSample);
187             isFind = true;
188         }
189     }
190     EXPECT_TRUE(isFind);
191 
192     inputStream.close();
193     inputStream.clear();
194     std::remove(filePath.c_str());
195     vm_->SetEnableForceGC(true);
196 }
197 
HWTEST_F_L0(DFXJSNApiTests,Start_Stop_HeapTracking_002)198 HWTEST_F_L0(DFXJSNApiTests, Start_Stop_HeapTracking_002)
199 {
200     [[maybe_unused]] EcmaHandleScope handleScope(thread_);
201     vm_->SetEnableForceGC(false);
202 
203     auto factory = vm_->GetFactory();
204     bool isVmMode = true;
205     bool traceAllocation = false;
206     double timeInterval = 50; // 50 : time interval 50 ms
207     ecmascript::FileStream *stream = nullptr;
208     bool startResult = false;
209     startResult = DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode, stream, traceAllocation);
210     EXPECT_TRUE(startResult);
211 
212     sleep(1);
213     int count = 300;
214     while (count-- > 0) {
215         factory->NewJSAsyncFuncObject();
216         factory->NewJSSymbol();
217     }
218     const std::string filePath = "Start_Stop_HeapTracking_002.heaptimeline";
219     std::fstream outputString(filePath, std::ios::out);
220     outputString.close();
221     outputString.clear();
222 
223     ecmascript::FileStream fileStream(filePath);
224     bool stopResult = DFXJSNApi::StopHeapTracking(vm_, &fileStream);
225     EXPECT_TRUE(stopResult);
226 
227     std::fstream inputStream(filePath, std::ios::in);
228     std::string line;
229     std::string emptySample = "\"samples\":";
230     std::string firstSample = "\"samples\":[0, ";
231     bool isFind = false;
232     while (getline(inputStream, line)) {
233         if (line.substr(0U, emptySample.size()) == emptySample) {
234             EXPECT_TRUE(line.substr(0, firstSample.size()) == firstSample);
235             isFind = true;
236         }
237     }
238     EXPECT_TRUE(isFind);
239 
240     inputStream.close();
241     inputStream.clear();
242     std::remove(filePath.c_str());
243     vm_->SetEnableForceGC(true);
244 }
245 
HWTEST_F_L0(DFXJSNApiTests,Start_Stop_RuntimeStat)246 HWTEST_F_L0(DFXJSNApiTests, Start_Stop_RuntimeStat)
247 {
248     EcmaRuntimeStat *ecmaRuntimeStat = vm_->GetRuntimeStat();
249     EXPECT_TRUE(ecmaRuntimeStat != nullptr);
250 
251     ecmaRuntimeStat->SetRuntimeStatEnabled(false);
252     EXPECT_TRUE(!ecmaRuntimeStat->IsRuntimeStatEnabled());
253 
254     DFXJSNApi::StartRuntimeStat(vm_);
255     EXPECT_TRUE(ecmaRuntimeStat->IsRuntimeStatEnabled());
256 
257     DFXJSNApi::StopRuntimeStat(vm_);
258     EXPECT_TRUE(!ecmaRuntimeStat->IsRuntimeStatEnabled());
259 }
260 
HWTEST_F_L0(DFXJSNApiTests,GetArrayBufferSize_GetHeapTotalSize_GetHeapUsedSize)261 HWTEST_F_L0(DFXJSNApiTests, GetArrayBufferSize_GetHeapTotalSize_GetHeapUsedSize)
262 {
263     auto heap = vm_->GetHeap();
264     size_t arrayBufferSize = DFXJSNApi::GetArrayBufferSize(vm_);
265     size_t expectArrayBufferSize = heap->GetArrayBufferSize();
266     EXPECT_EQ(arrayBufferSize, expectArrayBufferSize);
267 
268     size_t heapTotalSize = DFXJSNApi::GetHeapTotalSize(vm_);
269     size_t expectHeapTotalSize = heap->GetCommittedSize();
270     EXPECT_EQ(heapTotalSize, expectHeapTotalSize);
271 
272     size_t heapUsedSize = DFXJSNApi::GetHeapUsedSize(vm_);
273     size_t expectHeapUsedSize = heap->GetHeapObjectSize();
274     EXPECT_EQ(heapUsedSize, expectHeapUsedSize);
275 }
276 
HWTEST_F_L0(DFXJSNApiTests,NotifyApplicationState)277 HWTEST_F_L0(DFXJSNApiTests, NotifyApplicationState)
278 {
279     auto heap = vm_->GetHeap();
280     auto concurrentMarker = heap->GetConcurrentMarker();
281     auto sweeper = heap->GetSweeper();
282 
283     DFXJSNApi::NotifyApplicationState(vm_, false);
284 #if !ECMASCRIPT_DISABLE_CONCURRENT_MARKING
285     EXPECT_TRUE(!concurrentMarker->IsDisabled());
286 #endif
287     EXPECT_TRUE(!sweeper->IsDisabled());
288 
289     bool fullGC = false;
290     sweeper->Sweep(fullGC);
291     DFXJSNApi::NotifyApplicationState(vm_, true);
292     EXPECT_TRUE(concurrentMarker->IsDisabled());
293     EXPECT_TRUE(sweeper->IsRequestDisabled());
294 }
295 
HWTEST_F_L0(DFXJSNApiTests,NotifyMemoryPressure)296 HWTEST_F_L0(DFXJSNApiTests, NotifyMemoryPressure)
297 {
298     auto heap = vm_->GetHeap();
299     bool inHighMemoryPressure = true;
300     DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
301     EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::PRESSURE);
302 
303     inHighMemoryPressure = false;
304     DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
305     EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::CONSERVATIVE);
306 }
307 
HWTEST_F_L0(DFXJSNApiTests,BuildJsStackInfoList)308 HWTEST_F_L0(DFXJSNApiTests, BuildJsStackInfoList)
309 {
310     uint32_t hostTid = vm_->GetJSThread()->GetThreadId();
311     std::vector<ecmascript::JsFrameInfo> jsFrameInfo;
312     bool result = DFXJSNApi::BuildJsStackInfoList(vm_, hostTid, jsFrameInfo);
313     EXPECT_FALSE(result);
314 }
315 } // namespace panda::test
316