1/*
2 * Copyright (c) 2022-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 "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/ecma_context.h"
20#include "ecmascript/mem/heap-inl.h"
21#include "ecmascript/mem/concurrent_marker.h"
22#include "ecmascript/mem/concurrent_sweeper.h"
23#include "ecmascript/napi/include/dfx_jsnapi.h"
24#include "ecmascript/tests/test_helper.h"
25#include "ecmascript/dfx/cpu_profiler/samples_record.h"
26#include "ecmascript/dfx/tracing/tracing.h"
27
28using namespace panda;
29using namespace panda::ecmascript;
30
31namespace panda::test {
32class DFXJSNApiTests : public testing::Test {
33public:
34    static void SetUpTestCase()
35    {
36        GTEST_LOG_(INFO) << "SetUpTestCase";
37    }
38
39    static void TearDownTestCase()
40    {
41        GTEST_LOG_(INFO) << "TearDownCase";
42    }
43
44    void SetUp() override
45    {
46        TestHelper::CreateEcmaVMWithScope(vm_, thread_, scope_);
47        vm_->GetJSThread()->GetCurrentEcmaContext()->SetRuntimeStatEnable(true);
48        vm_->SetEnableForceGC(false);
49    }
50
51    void TearDown() override
52    {
53        TestHelper::DestroyEcmaVMWithScope(vm_, scope_);
54    }
55
56protected:
57    EcmaVM *vm_ {nullptr};
58    JSThread *thread_ = {nullptr};
59    EcmaHandleScope *scope_ {nullptr};
60};
61
62bool MatchJSONLineHeader(std::fstream &fs, const std::string filePath, int lineNum, CString lineContent)
63{
64    CString tempLineContent = "";
65    int lineCount = 1;
66    fs.open(filePath.c_str(), std::ios::in);
67    while (getline(fs, tempLineContent)) {
68        if (lineNum == lineCount && tempLineContent.find(lineContent) != CString::npos) {
69            fs.close();
70            fs.clear();
71            return true;
72        }
73        lineCount++;
74    }
75    fs.close();
76    fs.clear();
77    return false;
78}
79
80HWTEST_F_L0(DFXJSNApiTests, DumpHeapSnapshot_001)
81{
82    const std::string filePath = "DFXJSNApiTests_json_001.heapsnapshot";
83    std::fstream outputString(filePath, std::ios::out);
84    outputString.close();
85    outputString.clear();
86
87    std::fstream inputFile {};
88    EXPECT_TRUE(inputFile.good());
89
90    DumpSnapShotOption dumpOption;
91    dumpOption.dumpFormat = ecmascript::DumpFormat::JSON;
92    dumpOption.isVmMode = true;
93    dumpOption.isPrivate = false;
94    dumpOption.captureNumericValue = false;
95    DFXJSNApi::DumpHeapSnapshot(vm_, filePath, dumpOption);
96    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 1, "{\"snapshot\":"));
97    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 2, "{\"meta\":"));
98    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 3, "{\"node_fields\":"));
99    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 4, "\"node_types\":"));
100    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 5, "\"edge_fields\":"));
101    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 6, "\"edge_types\":"));
102    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 7, "\"trace_function_info_fields\":"));
103    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 8, "\"trace_node_fields\":"));
104    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 9, "\"sample_fields\":"));
105    EXPECT_TRUE(MatchJSONLineHeader(inputFile, filePath, 10, "\"location_fields\":"));
106    std::remove(filePath.c_str());
107}
108
109HWTEST_F_L0(DFXJSNApiTests, DumpHeapSnapshot_002)
110{
111    const std::string filePath = "DFXJSNApiTests_json_002.heapsnapshot";
112    std::fstream outputString(filePath, std::ios::out);
113    outputString.close();
114    outputString.clear();
115
116    ecmascript::FileStream stream(filePath);
117    EXPECT_TRUE(stream.Good());
118
119    ecmascript::Progress *progress = nullptr;
120    std::fstream fStream {};
121    EXPECT_TRUE(fStream.good());
122
123    DumpSnapShotOption dumpOption;
124    dumpOption.dumpFormat = ecmascript::DumpFormat::JSON;
125    dumpOption.isVmMode = true;
126    dumpOption.isPrivate = false;
127    dumpOption.captureNumericValue = false;
128    DFXJSNApi::DumpHeapSnapshot(vm_, &stream, dumpOption, progress);
129    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 1, "{\"snapshot\":"));
130    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 2, "{\"meta\":"));
131    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 3, "{\"node_fields\":"));
132    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 4, "\"node_types\":"));
133    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 5, "\"edge_fields\":"));
134    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 6, "\"edge_types\":"));
135    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 7, "\"trace_function_info_fields\":"));
136    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 8, "\"trace_node_fields\":"));
137    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 9, "\"sample_fields\":"));
138    EXPECT_TRUE(MatchJSONLineHeader(fStream, filePath, 10, "\"location_fields\":"));
139    std::remove(filePath.c_str());
140}
141
142HWTEST_F_L0(DFXJSNApiTests, BuildNativeAndJsStackTrace)
143{
144    bool result = false;
145    std::string stackTraceStr = "stack_trace_str";
146    result = DFXJSNApi::BuildNativeAndJsStackTrace(vm_, stackTraceStr);
147#if defined(ENABLE_EXCEPTION_BACKTRACE)
148    EXPECT_FALSE(stackTraceStr.empty());
149    EXPECT_TRUE(result);
150#else
151    EXPECT_TRUE(stackTraceStr.empty());
152    EXPECT_FALSE(result);
153#endif
154}
155
156HWTEST_F_L0(DFXJSNApiTests, BuildJsStackTrace)
157{
158    std::string stackTraceStr = "stack_trace_str";
159    bool result = DFXJSNApi::BuildJsStackTrace(vm_, stackTraceStr);
160#if defined(ENABLE_EXCEPTION_BACKTRACE)
161    EXPECT_FALSE(stackTraceStr.empty());
162    EXPECT_TRUE(result);
163#else
164    EXPECT_TRUE(stackTraceStr.empty());
165    EXPECT_FALSE(result);
166#endif
167}
168
169HWTEST_F_L0(DFXJSNApiTests, Start_Stop_HeapTracking_001)
170{
171    [[maybe_unused]] EcmaHandleScope handleScope(thread_);
172    vm_->SetEnableForceGC(false);
173
174    auto factory = vm_->GetFactory();
175    bool isVmMode = true;
176    bool traceAllocation = false;
177    double timeInterval = 50; // 50 : time interval 50 ms
178    ecmascript::FileStream *stream = nullptr;
179    bool startResult = false;
180    startResult = DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode, stream, traceAllocation);
181    EXPECT_TRUE(startResult);
182
183    sleep(1);
184    int count = 300;
185    while (count-- > 0) {
186        JSHandle<JSTaggedValue> undefined = thread_->GlobalConstants()->GetHandledUndefined();
187        JSHandle<EcmaString> string = factory->NewFromASCII("Start_Stop_HeapTracking_001_TestString");
188        factory->NewJSString(JSHandle<JSTaggedValue>(string), undefined);
189    }
190    const std::string filePath = "Start_Stop_HeapTracking_001.heaptimeline";
191    std::fstream outputString(filePath, std::ios::out);
192    outputString.close();
193    outputString.clear();
194
195    bool stopResult = DFXJSNApi::StopHeapTracking(vm_, filePath);
196    EXPECT_TRUE(stopResult);
197
198    std::fstream inputStream(filePath, std::ios::in);
199    std::string line;
200    std::string emptySample = "\"samples\":";
201    std::string firstSample = "\"samples\":[0, ";
202    bool isFind = false;
203    while (getline(inputStream, line)) {
204        if (line.substr(0U, emptySample.size()) == emptySample) {
205            EXPECT_TRUE(line.substr(0, firstSample.size()) == firstSample);
206            isFind = true;
207        }
208    }
209    EXPECT_TRUE(isFind);
210
211    inputStream.close();
212    inputStream.clear();
213    std::remove(filePath.c_str());
214    vm_->SetEnableForceGC(true);
215}
216
217HWTEST_F_L0(DFXJSNApiTests, Start_Stop_HeapTracking_002)
218{
219    [[maybe_unused]] EcmaHandleScope handleScope(thread_);
220    vm_->SetEnableForceGC(false);
221
222    auto factory = vm_->GetFactory();
223    bool isVmMode = true;
224    bool traceAllocation = false;
225    double timeInterval = 50; // 50 : time interval 50 ms
226    ecmascript::FileStream *stream = nullptr;
227    bool startResult = false;
228    startResult = DFXJSNApi::StartHeapTracking(vm_, timeInterval, isVmMode, stream, traceAllocation);
229    EXPECT_TRUE(startResult);
230
231    sleep(1);
232    int count = 300;
233    while (count-- > 0) {
234        factory->NewJSAsyncFuncObject();
235        factory->NewJSSymbol();
236    }
237    const std::string filePath = "Start_Stop_HeapTracking_002.heaptimeline";
238    std::fstream outputString(filePath, std::ios::out);
239    outputString.close();
240    outputString.clear();
241
242    ecmascript::FileStream fileStream(filePath);
243    bool stopResult = DFXJSNApi::StopHeapTracking(vm_, &fileStream);
244    EXPECT_TRUE(stopResult);
245
246    std::fstream inputStream(filePath, std::ios::in);
247    std::string line;
248    std::string emptySample = "\"samples\":";
249    std::string firstSample = "\"samples\":[0, ";
250    bool isFind = false;
251    while (getline(inputStream, line)) {
252        if (line.substr(0U, emptySample.size()) == emptySample) {
253            EXPECT_TRUE(line.substr(0, firstSample.size()) == firstSample);
254            isFind = true;
255        }
256    }
257    EXPECT_TRUE(isFind);
258
259    inputStream.close();
260    inputStream.clear();
261    std::remove(filePath.c_str());
262    vm_->SetEnableForceGC(true);
263}
264
265HWTEST_F_L0(DFXJSNApiTests, Start_Stop_RuntimeStat)
266{
267    EcmaRuntimeStat *ecmaRuntimeStat = vm_->GetJSThread()->GetCurrentEcmaContext()->GetRuntimeStat();
268    EXPECT_TRUE(ecmaRuntimeStat != nullptr);
269
270    ecmaRuntimeStat->SetRuntimeStatEnabled(false);
271    EXPECT_TRUE(!ecmaRuntimeStat->IsRuntimeStatEnabled());
272
273    DFXJSNApi::StartRuntimeStat(vm_);
274    EXPECT_TRUE(ecmaRuntimeStat->IsRuntimeStatEnabled());
275
276    DFXJSNApi::StopRuntimeStat(vm_);
277    EXPECT_TRUE(!ecmaRuntimeStat->IsRuntimeStatEnabled());
278}
279
280HWTEST_F_L0(DFXJSNApiTests, GetArrayBufferSize_GetHeapTotalSize_GetHeapUsedSize)
281{
282    auto heap = vm_->GetHeap();
283    size_t arrayBufferSize = DFXJSNApi::GetArrayBufferSize(vm_);
284    size_t expectArrayBufferSize = heap->GetArrayBufferSize();
285    EXPECT_EQ(arrayBufferSize, expectArrayBufferSize);
286
287    size_t heapTotalSize = DFXJSNApi::GetHeapTotalSize(vm_);
288    size_t expectHeapTotalSize = heap->GetCommittedSize();
289    EXPECT_EQ(heapTotalSize, expectHeapTotalSize);
290
291    size_t heapUsedSize = DFXJSNApi::GetHeapUsedSize(vm_);
292    size_t expectHeapUsedSize = heap->GetLiveObjectSize();
293    EXPECT_EQ(heapUsedSize, expectHeapUsedSize);
294
295    size_t heapObjectSize = DFXJSNApi::GetHeapObjectSize(vm_);
296    size_t expectHeapObjectSize = heap->GetHeapObjectSize();
297    EXPECT_EQ(heapObjectSize, expectHeapObjectSize);
298
299    size_t processHeapLimitSize = DFXJSNApi::GetProcessHeapLimitSize();
300    EXPECT_GE(processHeapLimitSize, heap->GetEcmaParamConfiguration().GetMaxHeapSize());
301    EXPECT_LE(processHeapLimitSize, MAX_MEM_POOL_CAPACITY);
302}
303
304HWTEST_F_L0(DFXJSNApiTests, DFXJSNApiForGCInfo)
305{
306    size_t oldGCCount = DFXJSNApi::GetGCCount(vm_);
307    size_t expectGCCount = vm_->GetEcmaGCStats()->GetGCCount() +
308        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCCount();
309    EXPECT_EQ(oldGCCount, expectGCCount);
310
311    size_t oldGCDuration = DFXJSNApi::GetGCDuration(vm_);
312    size_t expectGCDuration = vm_->GetEcmaGCStats()->GetGCDuration() +
313        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCDuration();
314    EXPECT_EQ(oldGCDuration, expectGCDuration);
315
316    size_t oldAllocateSize = DFXJSNApi::GetAccumulatedAllocateSize(vm_);
317    size_t expectAllocateSize = vm_->GetEcmaGCStats()->GetAccumulatedAllocateSize() +
318        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedAllocateSize();
319    EXPECT_EQ(oldAllocateSize, expectAllocateSize);
320
321    size_t oldFreeSize = DFXJSNApi::GetAccumulatedFreeSize(vm_);
322    size_t expectFreeSize = vm_->GetEcmaGCStats()->GetAccumulatedFreeSize() +
323        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedFreeSize();
324    EXPECT_EQ(oldFreeSize, expectFreeSize);
325
326    size_t oldLongTimeCount = DFXJSNApi::GetFullGCLongTimeCount(vm_);
327    size_t expectLongTimeCount = vm_->GetEcmaGCStats()->GetFullGCLongTimeCount() +
328        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetFullGCLongTimeCount();
329    EXPECT_EQ(oldLongTimeCount, expectLongTimeCount);
330
331    ObjectFactory *factory = vm_->GetFactory();
332    auto heap = const_cast<Heap *>(vm_->GetHeap());
333    heap->CollectGarbage(TriggerGCType::FULL_GC);
334    {
335        [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread_);
336        for (int i = 0; i < 10240; i++) {
337            factory->NewTaggedArray(512, JSTaggedValue::Undefined(), MemSpaceType::OLD_SPACE);
338        }
339        size_t newAllocateSize = DFXJSNApi::GetAccumulatedAllocateSize(vm_);
340        EXPECT_TRUE(oldAllocateSize < newAllocateSize);
341    }
342    ecmascript::SharedHeap::GetInstance()->CollectGarbage<TriggerGCType::SHARED_GC, GCReason::OTHER>(thread_);
343    heap->CollectGarbage(TriggerGCType::FULL_GC);
344    size_t newFreeSize = DFXJSNApi::GetAccumulatedFreeSize(vm_);
345    EXPECT_TRUE(oldFreeSize < newFreeSize);
346    size_t newGCCount = DFXJSNApi::GetGCCount(vm_);
347    EXPECT_TRUE(oldGCCount < newGCCount);
348    size_t newGCDuration = DFXJSNApi::GetGCDuration(vm_);
349    EXPECT_TRUE(oldGCDuration < newGCDuration);
350}
351
352HWTEST_F_L0(DFXJSNApiTests, NotifyApplicationState)
353{
354    auto heap = vm_->GetHeap();
355    auto concurrentMarker = heap->GetConcurrentMarker();
356    auto sweeper = heap->GetSweeper();
357
358    DFXJSNApi::NotifyApplicationState(vm_, false);
359#if !ECMASCRIPT_DISABLE_CONCURRENT_MARKING
360    EXPECT_TRUE(!concurrentMarker->IsDisabled());
361#endif
362    EXPECT_TRUE(!sweeper->IsDisabled());
363
364    const_cast<ecmascript::Heap *>(heap)->CollectGarbage(TriggerGCType::OLD_GC, GCReason::OTHER);
365    DFXJSNApi::NotifyApplicationState(vm_, true);
366    EXPECT_TRUE(concurrentMarker->IsDisabled());
367    EXPECT_TRUE(sweeper->IsRequestDisabled() || sweeper->IsDisabled());
368}
369
370HWTEST_F_L0(DFXJSNApiTests, NotifyMemoryPressure)
371{
372    auto heap = vm_->GetHeap();
373    bool inHighMemoryPressure = true;
374    DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
375    EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::PRESSURE);
376
377    inHighMemoryPressure = false;
378    DFXJSNApi::NotifyMemoryPressure(vm_, inHighMemoryPressure);
379    EXPECT_EQ(heap->GetMemGrowingType(), MemGrowingType::CONSERVATIVE);
380}
381
382HWTEST_F_L0(DFXJSNApiTests, BuildJsStackInfoList)
383{
384    uint32_t hostTid = vm_->GetJSThread()->GetThreadId();
385    std::vector<ecmascript::JsFrameInfo> jsFrameInfo;
386    bool result = DFXJSNApi::BuildJsStackInfoList(vm_, hostTid, jsFrameInfo);
387    EXPECT_FALSE(result);
388}
389
390HWTEST_F_L0(DFXJSNApiTests, StartSampling)
391{
392    uint64_t samplingInterval = 32768;
393    bool result = DFXJSNApi::StartSampling(vm_, samplingInterval);
394    EXPECT_TRUE(result);
395    result = DFXJSNApi::StartSampling(vm_, samplingInterval);
396    EXPECT_FALSE(result);
397}
398
399HWTEST_F_L0(DFXJSNApiTests, StopSampling)
400{
401    uint64_t samplingInterval = 32768;
402    bool result = DFXJSNApi::StartSampling(vm_, samplingInterval);
403    EXPECT_TRUE(result);
404    DFXJSNApi::StopSampling(vm_);
405    result = DFXJSNApi::StartSampling(vm_, samplingInterval);
406    EXPECT_TRUE(result);
407}
408
409HWTEST_F_L0(DFXJSNApiTests, GetAllocationProfile)
410{
411    const SamplingInfo *result = DFXJSNApi::GetAllocationProfile(vm_);
412    EXPECT_TRUE(result == nullptr);
413    uint64_t samplingInterval = 32768;
414    DFXJSNApi::StartSampling(vm_, samplingInterval);
415    result = DFXJSNApi::GetAllocationProfile(vm_);
416    EXPECT_TRUE(result != nullptr);
417}
418
419HWTEST_F_L0(DFXJSNApiTests, NotifyIdleStatusControl)
420{
421    bool receivedValue = false;
422    std::function<void(bool)> cb = [&](bool value) {
423        receivedValue = value;
424    };
425    DFXJSNApi::NotifyIdleStatusControl(vm_, cb);
426    const_cast<ecmascript::Heap *>(vm_->GetHeap())->DisableNotifyIdle();
427    EXPECT_TRUE(receivedValue);
428}
429
430HWTEST_F_L0(DFXJSNApiTests, NotifyIdleTime)
431{
432    auto heap = const_cast<ecmascript::Heap *>(vm_->GetHeap());
433    heap->SetIdleTask(IdleTaskType::YOUNG_GC);
434    DFXJSNApi::NotifyIdleTime(vm_, 10);
435    EXPECT_EQ(vm_->GetEcmaGCStats()->GetGCReason(), GCReason::IDLE);
436}
437
438HWTEST_F_L0(DFXJSNApiTests, NotifyHighSensitive)
439{
440    auto heap = const_cast<ecmascript::Heap *>(vm_->GetHeap());
441    DFXJSNApi::NotifyHighSensitive(vm_, true);
442    EXPECT_TRUE(heap->GetSensitiveStatus() == AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
443    DFXJSNApi::NotifyHighSensitive(vm_, false);
444    EXPECT_TRUE(heap->GetSensitiveStatus() == AppSensitiveStatus::EXIT_HIGH_SENSITIVE);
445}
446
447HWTEST_F_L0(DFXJSNApiTests, GetGCCount)
448{
449    vm_->GetJSOptions().SetIsWorker(true);
450    size_t count = DFXJSNApi::GetGCCount(vm_);
451    ASSERT_EQ(count, vm_->GetEcmaGCStats()->GetGCCount());
452
453    vm_->GetJSOptions().SetIsWorker(false);
454    count = DFXJSNApi::GetGCCount(vm_);
455    ASSERT_EQ(count, vm_->GetEcmaGCStats()->GetGCCount() +
456        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCCount());
457}
458
459HWTEST_F_L0(DFXJSNApiTests, GetGCDuration)
460{
461    vm_->GetJSOptions().SetIsWorker(true);
462    size_t duration = DFXJSNApi::GetGCDuration(vm_);
463    ASSERT_EQ(duration, vm_->GetEcmaGCStats()->GetGCDuration());
464
465    vm_->GetJSOptions().SetIsWorker(false);
466    duration = DFXJSNApi::GetGCDuration(vm_);
467    ASSERT_EQ(duration, vm_->GetEcmaGCStats()->GetGCDuration() +
468        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetGCDuration());
469}
470
471HWTEST_F_L0(DFXJSNApiTests, GetAccumulatedAllocateSize)
472{
473    vm_->GetJSOptions().SetIsWorker(true);
474    size_t size = DFXJSNApi::GetAccumulatedAllocateSize(vm_);
475    ASSERT_EQ(size, vm_->GetEcmaGCStats()->GetAccumulatedAllocateSize());
476
477    vm_->GetJSOptions().SetIsWorker(false);
478    size = DFXJSNApi::GetAccumulatedAllocateSize(vm_);
479    ASSERT_EQ(size, vm_->GetEcmaGCStats()->GetAccumulatedAllocateSize() +
480        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedAllocateSize());
481}
482
483HWTEST_F_L0(DFXJSNApiTests, GetAccumulatedFreeSize)
484{
485    vm_->GetJSOptions().SetIsWorker(true);
486    size_t size = DFXJSNApi::GetAccumulatedFreeSize(vm_);
487    ASSERT_EQ(size, vm_->GetEcmaGCStats()->GetAccumulatedFreeSize());
488
489    vm_->GetJSOptions().SetIsWorker(false);
490    size = DFXJSNApi::GetAccumulatedFreeSize(vm_);
491    ASSERT_EQ(size, vm_->GetEcmaGCStats()->GetAccumulatedFreeSize() +
492        ecmascript::SharedHeap::GetInstance()->GetEcmaGCStats()->GetAccumulatedFreeSize());
493}
494
495HWTEST_F_L0(DFXJSNApiTests, StopCpuProfilerForColdStart)
496{
497#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
498    ASSERT_FALSE(DFXJSNApi::StopCpuProfilerForColdStart(vm_));
499
500    vm_->GetJSOptions().SetArkProperties(ArkProperties::CPU_PROFILER_COLD_START_MAIN_THREAD);
501    ASSERT_TRUE(DFXJSNApi::StopCpuProfilerForColdStart(vm_));
502
503    vm_->GetJSOptions().SetArkProperties(ArkProperties::CPU_PROFILER_COLD_START_WORKER_THREAD);
504    ASSERT_TRUE(DFXJSNApi::StopCpuProfilerForColdStart(vm_));
505#else
506    ASSERT_FALSE(DFXJSNApi::StopCpuProfilerForColdStart(vm_));
507#endif
508}
509
510HWTEST_F_L0(DFXJSNApiTests, CpuProfilerSamplingAnyTime)
511{
512#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
513    ASSERT_FALSE(DFXJSNApi::CpuProfilerSamplingAnyTime(vm_));
514#else
515    ASSERT_FALSE(DFXJSNApi::CpuProfilerSamplingAnyTime(vm_));
516#endif
517}
518
519HWTEST_F_L0(DFXJSNApiTests, StartCpuProfilerForFile)
520{
521    int interval = 32768;
522#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
523    int illegalInterval = 0;
524    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForFile(vm_, "StartCpuProfilerForFile", illegalInterval));
525
526    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForFile(nullptr, "StartCpuProfilerForFile", interval));
527
528    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForFile(vm_, "StartCpuProfilerForFile", interval));
529#else
530    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForFile(vm_, "StartCpuProfilerForFile", interval));
531#endif
532}
533
534HWTEST_F_L0(DFXJSNApiTests, StartCpuProfilerForInfo)
535{
536    int interval = 32768;
537#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
538    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForInfo(nullptr, interval));
539
540    int illegalInterval = 0;
541    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForInfo(vm_, illegalInterval));
542
543    ASSERT_TRUE(DFXJSNApi::StartCpuProfilerForInfo(vm_, interval));
544    ASSERT_NE(DFXJSNApi::StopCpuProfilerForInfo(vm_), nullptr);
545#else
546    ASSERT_FALSE(DFXJSNApi::StartCpuProfilerForInfo(vm_, interval));
547#endif
548}
549
550HWTEST_F_L0(DFXJSNApiTests, StopCpuProfilerForInfo)
551{
552#if defined(ECMASCRIPT_SUPPORT_CPUPROFILER)
553    ASSERT_EQ(DFXJSNApi::StopCpuProfilerForInfo(nullptr), nullptr);
554
555    vm_->SetProfiler(nullptr);
556    ASSERT_EQ(DFXJSNApi::StopCpuProfilerForInfo(vm_), nullptr);
557#else
558    ASSERT_EQ(DFXJSNApi::StopCpuProfilerForInfo(vm_), nullptr);
559#endif
560}
561
562HWTEST_F_L0(DFXJSNApiTests, SuspendVM)
563{
564#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
565    ASSERT_FALSE(DFXJSNApi::SuspendVM(vm_));
566#else
567    ASSERT_FALSE(DFXJSNApi::SuspendVM(vm_));
568#endif
569}
570
571HWTEST_F_L0(DFXJSNApiTests, IsSuspended)
572{
573#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
574    ASSERT_FALSE(DFXJSNApi::IsSuspended(vm_));
575#else
576    ASSERT_FALSE(DFXJSNApi::IsSuspended(vm_));
577#endif
578}
579
580HWTEST_F_L0(DFXJSNApiTests, CheckSafepoint)
581{
582#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
583    ASSERT_FALSE(DFXJSNApi::CheckSafepoint(vm_));
584#else
585    ASSERT_FALSE(DFXJSNApi::CheckSafepoint(vm_));
586#endif
587}
588
589HWTEST_F_L0(DFXJSNApiTests, BuildJsStackInfoList_2)
590{
591    std::vector<ecmascript::JsFrameInfo> jsFrames;
592    uint32_t tid = vm_->GetAssociatedJSThread()->GetThreadId();
593    ASSERT_FALSE(DFXJSNApi::BuildJsStackInfoList(vm_, tid + 1, jsFrames));
594
595    ASSERT_FALSE(DFXJSNApi::BuildJsStackInfoList(vm_, tid, jsFrames));
596}
597
598HWTEST_F_L0(DFXJSNApiTests, StartProfiler)
599{
600    DFXJSNApi::ProfilerOption option;
601    option.profilerType = DFXJSNApi::ProfilerType::CPU_PROFILER;
602    DebuggerPostTask debuggerPostTask;
603    uint32_t tid = vm_->GetAssociatedJSThread()->GetThreadId();
604    int32_t instanceId = 1;
605    ASSERT_FALSE(DFXJSNApi::StartProfiler(nullptr, option, tid, instanceId, debuggerPostTask, true));
606
607    option.profilerType = DFXJSNApi::ProfilerType::HEAP_PROFILER;
608    ASSERT_FALSE(DFXJSNApi::StartProfiler(nullptr, option, tid, instanceId, debuggerPostTask, false));
609}
610
611HWTEST_F_L0(DFXJSNApiTests, SuspendVMById)
612{
613    uint32_t tid = vm_->GetAssociatedJSThread()->GetThreadId();
614    ASSERT_FALSE(DFXJSNApi::SuspendVMById(vm_, tid + 1));
615
616#if defined(ECMASCRIPT_SUPPORT_SNAPSHOT)
617    ASSERT_FALSE(DFXJSNApi::SuspendVMById(vm_, tid));
618#else
619    ASSERT_FALSE(DFXJSNApi::SuspendVMById(vm_, tid));
620#endif
621}
622
623HWTEST_F_L0(DFXJSNApiTests, StartTracing)
624{
625    std::string categories = "StartTracing";
626#if defined(ECMASCRIPT_SUPPORT_TRACING)
627    ASSERT_FALSE(DFXJSNApi::StartTracing(nullptr, categories));
628
629    vm_->SetTracing(nullptr);
630    ASSERT_TRUE(DFXJSNApi::StartTracing(vm_, categories));
631    ASSERT_NE(DFXJSNApi::StopTracing(vm_), nullptr);
632#else
633    ASSERT_FALSE(DFXJSNApi::StartTracing(vm_, categories));
634#endif
635}
636
637HWTEST_F_L0(DFXJSNApiTests, StopTracing)
638{
639#if defined(ECMASCRIPT_SUPPORT_TRACING)
640    ASSERT_EQ(DFXJSNApi::StopTracing(nullptr), nullptr);
641
642    vm_->SetTracing(nullptr);
643    ASSERT_EQ(DFXJSNApi::StopTracing(vm_), nullptr);
644#else
645    ASSERT_EQ(DFXJSNApi::StopTracing(vm_), nullptr);
646#endif
647}
648
649HWTEST_F_L0(DFXJSNApiTests, TranslateJSStackInfo)
650{
651    std::string resultUrl = "";
652    auto cb = [&resultUrl](std::string& url, int& line, int& column) -> bool {
653        line = 0;
654        column = 0;
655        if (url.find("TranslateJSStackInfo", 0) != std::string::npos) {
656            resultUrl = "true";
657            return true;
658        }
659        resultUrl = "false";
660        return false;
661    };
662
663    vm_->SetSourceMapTranslateCallback(nullptr);
664    std::string url = "TranslateJSStackInfo";
665    int32_t line = 0;
666    int32_t column = 0;
667    DFXJSNApi::TranslateJSStackInfo(vm_, url, line, column);
668
669    vm_->SetSourceMapTranslateCallback(cb);
670    url = "Translate";
671    DFXJSNApi::TranslateJSStackInfo(vm_, url, line, column);
672    ASSERT_STREQ(resultUrl.c_str(), "false");
673
674    url = "TranslateJSStackInfo";
675    DFXJSNApi::TranslateJSStackInfo(vm_, url, line, column);
676    ASSERT_STREQ(resultUrl.c_str(), "true");
677}
678
679HWTEST_F_L0(DFXJSNApiTests, GetCurrentThreadId)
680{
681    ASSERT_EQ(DFXJSNApi::GetCurrentThreadId(), JSThread::GetCurrentThreadId());
682}
683} // namespace panda::test
684