/*
 * Copyright (c) 2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ecmascript/ecma_vm.h"
#include "ecmascript/mem/idle_gc_trigger.h"
#include "ecmascript/mem/heap.h"
#include "ecmascript/mem/heap-inl.h"
#include "ecmascript/tests/test_helper.h"
#include "ecmascript/mem/concurrent_marker.h"
#include "ecmascript/mem/partial_gc.h"
#include "ecmascript/mem/shared_heap/shared_concurrent_marker.h"
#include "ecmascript/napi/include/jsnapi_expo.h"

using namespace panda::ecmascript;
using namespace panda::ecmascript::base;
using TRIGGER_IDLE_GC_TYPE = panda::JSNApi::TRIGGER_IDLE_GC_TYPE;
using TriggerGCData = std::pair<void*, uint8_t>;
using TriggerGCTaskCallback = std::function<void(TriggerGCData& data)>;

namespace panda::test {
class IdleGCTriggerTest :  public BaseTestWithScope<false> {
public:
    void SetUp() override
    {
        JSRuntimeOptions options;
        options.SetEnableForceGC(false);
        instance = JSNApi::CreateEcmaVM(options);
        ASSERT_TRUE(instance != nullptr) << "Cannot create EcmaVM";
        thread = instance->GetJSThread();
        thread->ManagedCodeBegin();
        scope = new EcmaHandleScope(thread);
        auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
        heap->GetConcurrentMarker()->EnableConcurrentMarking(EnableConcurrentMarkType::ENABLE);
        heap->GetSweeper()->EnableConcurrentSweep(EnableConcurrentSweepType::ENABLE);
        auto idleGCTrigger = heap->GetIdleGCTrigger();
        idleGCTrigger->SetTriggerGCTaskCallback([idleGCTrigger](TriggerGCData& data) {
            idleGCTrigger->ClearPostGCTask(static_cast<panda::JSNApi::TRIGGER_IDLE_GC_TYPE>(data.second));
        });
    }
};

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();

    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    sheap->NotifyHeapAliveSizeAfterGC(1);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest003)
{
    constexpr size_t LIVE_SIZE = 5242889;
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->GetOldSpace()->IncreaseLiveObjectSize(LIVE_SIZE);
    sheap->NotifyHeapAliveSizeAfterGC(1);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest004)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->SetOnSerializeEvent(true);
    
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest001)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetOldSpace()->SetInitialCapacity(10000);
    heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    heap->NotifyHeapAliveSizeAfterGC(1);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest003)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest004)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetOldSpace()->SetInitialCapacity(10000);
    heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    heap->NotifyHeapAliveSizeAfterGC(1);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    TriggerGCTaskCallback callback = [](TriggerGCData& data) {
        data.second = 1;
    };
    trigger->SetTriggerGCTaskCallback(callback);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest005)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest006)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetOldSpace()->SetInitialCapacity(10000);
    heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    heap->NotifyHeapAliveSizeAfterGC(1);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    TriggerGCTaskCallback callback = [](TriggerGCData& data) {
        data.second = 1;
    };
    trigger->SetTriggerGCTaskCallback(callback);
    ASSERT_EQ(trigger->TryTriggerIdleLocalOldGC(), true);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetNativeAreaAllocator()->IncreaseNativeMemoryUsage(83886100);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->ReachIdleLocalOldGCThresholds(), true);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest002)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetNativeAreaAllocator()->IncreaseNativeMemoryUsage(1);
    heap->GetOldSpace()->IncreaseCommitted(83886100);
    heap->GetOldSpace()->SetMaximumCapacity(100000);
    heap->GetOldSpace()->SetOvershootSize(100000);
    heap->GetOldSpace()->SetOvershootSize(100000);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->ReachIdleLocalOldGCThresholds(), true);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->NotifyLooperIdleStart(1, 1);
    trigger->TryPostHandleMarkFinished();
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryPostHandleMarkFinished();
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest002)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    auto idleGCTrigger = heap->GetIdleGCTrigger();
    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest003)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    heap->NotifyHeapAliveSizeAfterGC(1);
    heap->GetOldSpace()->SetInitialCapacity(10000);
    heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    auto idleGCTrigger = heap->GetIdleGCTrigger();
    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest004)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest011)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->SetOnSerializeEvent(true);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest012)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(0);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::FULL_GC);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest013)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(0);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, ShouldCheckIdleOldGCTest001)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->NotifyHeapAliveSizeAfterGC(0);
    heap->GetOldSpace()->SetInitialCapacity(10000);
    heap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest014)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(0);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest015)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest016)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5245000);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest017)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5245000);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    sheap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest018)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5245000);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    sheap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest019)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    sheap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGCTest020)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyNeedFreeze001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    bool freeze = false;
    auto callback = [&freeze](bool needFreeze) {
        if (needFreeze) {
            freeze = true;
        }
    };
    Runtime::GetInstance()->SetNotifyDeferFreezeCallback(callback);
    SharedHeap *sheap = SharedHeap::GetInstance();
    sheap->NotifyHeapAliveSizeAfterGC(1);
    sheap->GetOldSpace()->SetInitialCapacity(10000);
    sheap->GetOldSpace()->IncreaseLiveObjectSize(5242889);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC);
    sheap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::OTHER>(thread);
    ASSERT_TRUE(freeze);
    delete trigger;
}

/**
 * @tc.name: ExpectedMemoryReclamationSize001
 * @tc.desc: ExpectedMemoryReclamationSize
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, ExpectedMemoryReclamationSize001)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);
    auto oldExceptedSize = idleGCTrigger->GetExpectedMemoryReclamationSize();
    ASSERT_TRUE(oldExceptedSize < 100_MB);

    size_t oldAliveSizeAfterGC = heap->GetHeapAliveSizeAfterGC();
    size_t oldHeapObjSize = heap->GetHeapObjectSize();
    ASSERT_TRUE(oldHeapObjSize >= oldAliveSizeAfterGC);

    size_t oldFragmentSizeAfterGC = heap->GetFragmentSizeAfterGC();
    size_t heapBasicLoss = heap->GetHeapBasicLoss();
    ASSERT_TRUE(oldFragmentSizeAfterGC >= heapBasicLoss);

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    size_t newHeapObjSize = heap->GetHeapObjectSize();
    ASSERT_EQ(newHeapObjSize, oldHeapObjSize + 100_MB);
    auto newExceptedSize = idleGCTrigger->GetExpectedMemoryReclamationSize();
    ASSERT_TRUE(newExceptedSize >= 100_MB);
}

/**
 * @tc.name: ExpectedMemoryReclamationSize002
 * @tc.desc: ExpectedMemoryReclamationSize
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, ExpectedMemoryReclamationSize002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);
    auto oldExceptedSize = idleGCTrigger->GetExpectedMemoryReclamationSize();

    size_t oldAliveSizeAfterGC = heap->GetHeapAliveSizeAfterGC();
    size_t oldHeapObjSize = heap->GetHeapObjectSize();
    ASSERT_TRUE(oldHeapObjSize >= oldAliveSizeAfterGC);

    size_t oldFragmentSizeAfterGC = heap->GetFragmentSizeAfterGC();
    size_t heapBasicLoss = heap->GetHeapBasicLoss();
    ASSERT_TRUE(oldFragmentSizeAfterGC >= heapBasicLoss);

    ASSERT_TRUE(oldExceptedSize == 0);

    ASSERT_TRUE(oldAliveSizeAfterGC <= 100_MB);
    heap->NotifyHeapAliveSizeAfterGC(100_MB);
    auto newExceptedSize = idleGCTrigger->GetExpectedMemoryReclamationSize();
    ASSERT_TRUE(newExceptedSize == 0);
}

/**
 * @tc.name: PossiblePostGCTaskTest001
 * @tc.desc: PossiblePostGCTaskTest
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, PossiblePostGCTaskTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());
    SharedHeap *sheap = SharedHeap::GetInstance();

    sheap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::IDLE>(thread);
    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    sheap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    sheap->NotifyHeapAliveSizeAfterGC(1);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK));
    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK));

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK));
}

/**
 * @tc.name: PossiblePostGCTaskTest002
 * @tc.desc: PossiblePostGCTaskTest
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, PossiblePostGCTaskTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());
    SharedHeap *sheap = SharedHeap::GetInstance();

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    sheap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    sheap->NotifyHeapAliveSizeAfterGC(1);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
}


/**
 * @tc.name: PossiblePostGCTaskTest003
 * @tc.desc: PossiblePostGCTaskTest
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, PossiblePostGCTaskTest003)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));
    idleGCTrigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_FALSE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));

    {
        [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
        for (int i = 0; i < 100; i++) {
            [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
                10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
        }
    }

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));

    idleGCTrigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_FALSE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));
    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
}

/**
 * @tc.name: PossiblePostGCTaskTest004
 * @tc.desc: PossiblePostGCTaskTest
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, PossiblePostGCTaskTest004)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
    idleGCTrigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_FALSE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    heap->NotifyHeapAliveSizeAfterGC(1_MB);

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));

    idleGCTrigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_FALSE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
}

/**
 * @tc.name: PossiblePostGCTaskTest005
 * @tc.desc: PossiblePostGCTaskTest
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, PossiblePostGCTaskTest005)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    {
        [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
        for (int i = 0; i < 720; i++) {
            [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
                1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
        }
    }

    auto newSpace = heap->GetNewSpace();
    newSpace->SetInitialCapacity(1);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));
    ASSERT_TRUE(idleGCTrigger->TryTriggerIdleYoungGC());

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK));
}

/**
 * @tc.name: TryTriggerIdleLocalOldGCTest1
 * @tc.desc: TryTriggerIdleLocalOldGCTest1
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGCTest1)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    heap->NotifyHeapAliveSizeAfterGC(1_MB);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
    ASSERT_TRUE(idleGCTrigger->TryTriggerIdleLocalOldGC());

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
}

/**
 * @tc.name: TryTriggerIdleSharedOldGCTest1
 * @tc.desc: TryTriggerIdleSharedOldGC
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGCTest1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());
    SharedHeap *sheap = SharedHeap::GetInstance();

    sheap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::IDLE>(thread);
    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    sheap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    sheap->NotifyHeapAliveSizeAfterGC(1_MB);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
    ASSERT_TRUE(idleGCTrigger->TryTriggerIdleSharedOldGC());

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
}


/**
 * @tc.name: ReachIdleLocalOldGCThresholdsTest1
 * @tc.desc: ReachIdleLocalOldGCThresholdsTest1
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, ReachIdleLocalOldGCThresholdsTest1)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());

    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    heap->NotifyHeapAliveSizeAfterGC(1_MB);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
    ASSERT_TRUE(idleGCTrigger->ReachIdleLocalOldGCThresholds());
    ASSERT_TRUE(idleGCTrigger->TryTriggerIdleLocalOldGC());

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
}


/**
 * @tc.name: ReachIdleSharedGCThresholdsTest1
 * @tc.desc: ReachIdleSharedGCThresholdsTest1
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, ReachIdleSharedGCThresholdsTest1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());
    SharedHeap *sheap = SharedHeap::GetInstance();

    sheap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::IDLE>(thread);
    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    sheap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    sheap->NotifyHeapAliveSizeAfterGC(1_MB);
    sheap->GetOldSpace()->SetInitialCapacity(1);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
    ASSERT_TRUE(idleGCTrigger->ReachIdleSharedGCThresholds());

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK));
}


/**
 * @tc.name: TryPostHandleMarkFinishedTest2
 * @tc.desc: TryPostHandleMarkFinishedTest2
 * @tc.type: FUNC
 */
HWTEST_F_L0(IdleGCTriggerTest, TryPostHandleMarkFinishedTest2)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    auto idleGCTrigger = const_cast<IdleGCTrigger *>(heap->GetIdleGCTrigger());
    SharedHeap *sheap = SharedHeap::GetInstance();

    sheap->CollectGarbage<TriggerGCType::SHARED_FULL_GC, GCReason::IDLE>(thread);
    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);

    idleGCTrigger->NotifyLooperIdleStart(1, 1);
    idleGCTrigger->NotifyLooperIdleEnd(2);

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    heap->NotifyHeapAliveSizeAfterGC(1_MB);

    idleGCTrigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));
    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK));

    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK));
    idleGCTrigger->NotifyLooperIdleStart(10, 1);
    idleGCTrigger->TryPostHandleMarkFinished();
    ASSERT_FALSE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK));

    idleGCTrigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK);
    ASSERT_TRUE(idleGCTrigger->IsPossiblePostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK));
    idleGCTrigger->NotifyLooperIdleEnd(20);
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart2)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart3)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart4)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart5)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->GetConcurrentMarker()->Mark();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart6)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart7)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart8)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart9)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart10)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart11)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart12)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart13)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    trigger->SetPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    EXPECT_TRUE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, NotifyLooperIdleStart14)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK);
    trigger->ClearPostGCTask(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    EXPECT_FALSE(trigger->NotifyLooperIdleStart(1, 1));
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinished1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::CONCURRENT_MARKING_OR_FINISHED);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerHandleMarkFinished();
    EXPECT_FALSE(heap->GetJSThread()->IsReadyToSharedConcurrentMark());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinished2)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerHandleMarkFinished();
    EXPECT_TRUE(heap->GetJSThread()->IsReadyToSharedConcurrentMark());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinished3)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->SetOnSerializeEvent(true);
    heap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerHandleMarkFinished();
    EXPECT_TRUE(heap->GetJSThread()->IsMarkFinished());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinished4)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->SetOnSerializeEvent(true);
    heap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerHandleMarkFinished();
    EXPECT_TRUE(heap->GetJSThread()->IsMarkFinished());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerHandleMarkFinished5)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->Mark();
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARK_FINISHED);
    heap->SetOnSerializeEvent(false);
    heap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerHandleMarkFinished();
    EXPECT_TRUE(heap->GetJSThread()->IsMarkFinished());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMark1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->ConfigConcurrentMark(true);
    heap->GetJSThread()->SetMarkStatus(MarkStatus::READY_TO_MARK);
    EXPECT_TRUE(heap->GetConcurrentMarker()->IsEnabled());
    EXPECT_TRUE(heap->CheckCanTriggerConcurrentMarking());
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerLocalConcurrentMark(MarkType::MARK_YOUNG);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMark2)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->ConfigConcurrentMark(true);
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING);
    EXPECT_TRUE(heap->GetConcurrentMarker()->IsEnabled());
    EXPECT_FALSE(heap->CheckCanTriggerConcurrentMarking());
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerLocalConcurrentMark(MarkType::MARK_YOUNG);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalConcurrentMark3)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    heap->GetJSThread()->SetMarkStatus(MarkStatus::MARKING);
    EXPECT_FALSE(heap->GetConcurrentMarker()->IsEnabled());
    EXPECT_FALSE(heap->CheckCanTriggerConcurrentMarking());
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerLocalConcurrentMark(MarkType::MARK_YOUNG);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleLocalOldGC1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    thread->SetFullMarkRequest();
    heap->SetOnSerializeEvent(false);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->TryTriggerIdleLocalOldGC());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleSharedOldGC1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();

    sheap->SetSensitiveStatus(AppSensitiveStatus::ENTER_HIGH_SENSITIVE);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(false);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    ASSERT_EQ(trigger->TryTriggerIdleSharedOldGC(), false);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerIdleGC1)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CC_GC);
    sheap->NotifyHeapAliveSizeAfterGC(0);
    sheap->GetConcurrentMarker()->ConfigConcurrentMark(true);
    heap->GetJSThread()->SetSharedMarkStatus(SharedMarkStatus::READY_TO_CONCURRENT_MARK);
    EXPECT_FALSE(heap->NeedStopCollection());
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK);
    trigger->TryTriggerIdleGC(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, CheckIdleYoungGCTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    bool result = trigger->CheckIdleYoungGC(false);
    EXPECT_FALSE(result);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, CheckIdleYoungGCTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    bool result = trigger->CheckIdleYoungGC(true);
    EXPECT_FALSE(result);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, CheckIdleYoungGCTest003)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    {
        [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
        for (int i = 0; i < 100; i++) {
            [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
                10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
        }
    }
    
    bool result = trigger->CheckIdleYoungGC(false);
    EXPECT_TRUE(result);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, CheckIdleYoungGCTest004)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);

    {
        [[maybe_unused]] ecmascript::EcmaHandleScope baseScope(thread);
        for (int i = 0; i < 100; i++) {
            [[maybe_unused]] JSHandle<TaggedArray> array = thread->GetEcmaVM()->GetFactory()->NewTaggedArray(
                10 * 1024, JSTaggedValue::Hole(), MemSpaceType::SEMI_SPACE);
        }
    }
    
    bool result = trigger->CheckIdleYoungGC(true);
    EXPECT_TRUE(result);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, IdleStateTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    EXPECT_FALSE(trigger->IsIdleState());
    
    trigger->NotifyLooperIdleStart(1, 1);
    EXPECT_TRUE(trigger->IsIdleState());
    
    trigger->NotifyLooperIdleEnd(1);
    EXPECT_FALSE(trigger->IsIdleState());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalCCTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();

    heap->DisableLocalCC();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->TryTriggerLocalCC());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalCCTest002)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    heap->CollectGarbage(TriggerGCType::FULL_GC, GCReason::IDLE);
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->TryTriggerLocalCC());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, TryTriggerLocalCCTest003)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();

    heap->GetOldSpace()->IncreaseLiveObjectSize(100_MB);
    heap->DisableLocalCC();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    EXPECT_FALSE(trigger->TryTriggerLocalCC());
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, HintGCTest001)
{
    // fixme: adapt to cms
    if constexpr (G_USE_CMS_GC) {
        return;
    }
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    bool lowResult = trigger->HintGCInLowDegree(heap);
    bool middleResult = trigger->HintGCInMiddleDegree(heap);
    bool highResult = trigger->HintGCInHighDegree(heap);
    
    EXPECT_FALSE(lowResult);
    EXPECT_FALSE(middleResult);
    EXPECT_FALSE(highResult);
    delete trigger;
}

HWTEST_F_L0(IdleGCTriggerTest, GetGCTypeNameTest001)
{
    auto heap = const_cast<Heap *>(thread->GetEcmaVM()->GetHeap());
    SharedHeap *sheap = SharedHeap::GetInstance();
    IdleGCTrigger *trigger = new IdleGCTrigger(heap, sheap, thread);
    
    EXPECT_STREQ(trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::FULL_GC), "full gc");
    EXPECT_STREQ(trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_MARK), "shared concurrent mark");
    EXPECT_STREQ(
        trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::SHARED_CONCURRENT_PARTIAL_MARK), "shared concurrent partial mark");
    EXPECT_STREQ(trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::SHARED_FULL_GC), "shared full gc");
    EXPECT_STREQ(
        trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_YOUNG_MARK), "local concurrent young mark");
    EXPECT_STREQ(
        trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::LOCAL_CONCURRENT_FULL_MARK), "local concurrent full mark");
    EXPECT_STREQ(trigger->GetGCTypeName(TRIGGER_IDLE_GC_TYPE::LOCAL_REMARK), "local remark");
    EXPECT_STREQ(trigger->GetGCTypeName(static_cast<TRIGGER_IDLE_GC_TYPE>(999)), "UnknownType");
    delete trigger;
}
}  // namespace panda::test