/**
 * Copyright (c) 2025 Huawei Technologies Co., Ltd.
 * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
 * CANN Open Software License Agreement Version 2.0 (the "License").
 * Please refer to the License for details. You may not use this file except in compliance with the License.
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
 * See LICENSE in the root of the software repository for the full text of the License.
 */

#include <iostream>
#include <fstream>
#include <nlohmann/json.hpp>
#include "gtest/gtest.h"
#include "mockcpp/mockcpp.hpp"
#include "device_simulator_manager.h"
#include "errno/error_code.h"
#include "msprof_start.h"
#include "mmpa_api.h"
#include "data_manager.h"
#include "json_parser.h"
#include "aicpu_report_hdc.h"

using namespace analysis::dvvp::common::error;
using namespace Cann::Dvvp::Test;
using namespace Msprofiler::Parser;

static const char JSON_RM_RF[] = "rm -rf ./acljsonJsonstest_workspace";
static const char JSON_MKDIR[] = "mkdir ./acljsonJsonstest_workspace";
static const char JSON_OUTPUT_DIR[] = "./acljsonJsonstest_workspace/output";

class AclJsonProfJsonStest: public testing::Test {
protected:
    virtual void SetUp()
    {
        DlStub();
        const ::testing::TestInfo* curTest = ::testing::UnitTest::GetInstance()->current_test_info();
        DataMgr().Init("", "acljson");
        optind = 1;
        system(JSON_MKDIR);
        MOCKER_CPP(&AicpuReportHdc::Init).stubs().will(returnValue(-1));
        EXPECT_EQ(2, SimulatorMgr().CreateDeviceSimulator(2, StPlatformType::CHIP_V4_1_0));
        SimulatorMgr().SetSocSide(SocType::HOST);
        JsonParser::instance()->UnInit();
    }
    virtual void TearDown()
    {
        EXPECT_EQ(2, SimulatorMgr().DelDeviceSimulator(2, StPlatformType::CHIP_V4_1_0));
        DataMgr().UnInit();
        MsprofMgr().UnInit();
        JsonParser::instance()->UnInit();
        GlobalMockObject::verify();
        system(JSON_RM_RF);
        GlobalMockObject::reset();
    }
    void TestProfJson(std::string testcase)
    {
        // milan: TaskTime
        nlohmann::json data;
        data["output"] = JSON_OUTPUT_DIR;
        std::string filename = LLT_DATA_DIR "/json/" + testcase + ".json";
        JsonParser::instance()->Init(filename);
        EXPECT_EQ(PROFILING_SUCCESS, MsprofMgr().AclJsonStart(0, data));
    }
    void DlStub()
    {
        MOCKER(dlopen).stubs().will(invoke(mmDlopen));
        MOCKER(dlsym).stubs().will(invoke(mmDlsym));
        MOCKER(dlclose).stubs().will(invoke(mmDlclose));
        MOCKER(dlerror).stubs().will(invoke(mmDlerror));
    }
};

int32_t RuntimeCallbackHandle(uint32_t dataType, void *data, uint32_t dataLen);
int32_t HcclCallbackHandle(uint32_t dataType, void *data, uint32_t dataLen);
int32_t AicpuCallbackHandle(uint32_t dataType, void *data, uint32_t dataLen);
int32_t GeCallbackHandle(uint32_t dataType, void *data, uint32_t dataLen);
int32_t AclCallbackHandle(uint32_t dataType, void *data, uint32_t dataLen);

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichRuntimeOffTest)
{
    MOCKER_CPP(RuntimeCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_runtime_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichAclOffTest)
{
    MOCKER_CPP(AclCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_acl_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichAicpuOffTest)
{
    MOCKER_CPP(AicpuCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_aicpu_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichHcclOffTest)
{
    MOCKER_CPP(HcclCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_hccl_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichGeOffTest)
{
    MOCKER_CPP(GeCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_ge_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonModuleSwtichOffTest)
{
    MOCKER_CPP(GeCallbackHandle).expects(never());
    MOCKER_CPP(HcclCallbackHandle).expects(never());
    MOCKER_CPP(AicpuCallbackHandle).expects(never());
    MOCKER_CPP(RuntimeCallbackHandle).expects(never());
    MOCKER_CPP(AclCallbackHandle).expects(never());
    TestProfJson("prof_module_switch_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonReporterSwtichOnTest)
{
    // unaging.additional.hash_dic and unaging.additional.type_info_dic will be generated by default, 
    // so only check aging.additional.context_id_info
    std::vector<std::string> hostDataList = {
        "unaging.additional.context_id_info", "unaging.api_event", "unaging.compact",
        "aging.additional.context_id_info", "aging.api_event", "aging.compact"
    };
    MsprofMgr().SetHostCheckList(hostDataList);
    TestProfJson("prof_reporter_switch_on");
}

TEST_F(AclJsonProfJsonStest, AclJsonReporterSwtichOffTest)
{
    std::vector<std::string> hostDataList = {};
    std::vector<std::string> hostBlackDataList = {
        "unaging.additional.context_id_info", "unaging.api_event", "unaging.compact",
        "aging.additional.context_id_info", "aging.api_event", "aging.compact"
    };
    MsprofMgr().SetHostCheckList(hostDataList, hostBlackDataList);
    TestProfJson("prof_reporter_switch_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonReporterApiOffTest)
{
    std::vector<std::string> hostDataList = {
        "unaging.additional.context_id_info", "unaging.compact", "aging.additional.context_id_info", "aging.compact"
    };
    std::vector<std::string> hostBlackDataList = {"aging.api_event", "unaging.api_event"};
    MsprofMgr().SetHostCheckList(hostDataList, hostBlackDataList);
    TestProfJson("prof_reporter_switch_api_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonReporterCompactOffTest)
{
    std::vector<std::string> hostDataList = {
        "unaging.additional.context_id_info", "unaging.api_event", "aging.additional.context_id_info", "aging.api_event"
    };
    std::vector<std::string> hostBlackDataList = {"aging.compact", "unaging.compact"};
    MsprofMgr().SetHostCheckList(hostDataList, hostBlackDataList);
    TestProfJson("prof_reporter_switch_compact_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonReporterAdditionalOffTest)
{
    std::vector<std::string> hostDataList = {
        "unaging.api_event", "unaging.compact", "aging.api_event", "aging.compact"
    };
    std::vector<std::string> hostBlackDataList = {"aging.additional.context_id_info", "unaging.additional.context_id_info"};
    MsprofMgr().SetHostCheckList(hostDataList, hostBlackDataList);
    TestProfJson("prof_reporter_switch_additional_off");
}

int prof_drv_start_stub(unsigned int device_id, unsigned int channel_id, struct prof_start_para *start_para)
{
    return SimulatorMgr().ProfDrvStart(device_id, channel_id, *start_para);
}

void CheckChannelSwith(uint32_t profChannel)
{
    MOCKER(prof_drv_start).expects(never()).with(any(), eq(profChannel), any());
    MOCKER(prof_drv_start).stubs().with(any(), neq(profChannel), any()).will(invoke(prof_drv_start_stub));
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelFftsProfileTaskOffTest)
{
    CheckChannelSwith(CHANNEL_FFTS_PROFILE_BUFFER_TASK);
    TestProfJson("prof_channel_switch_ffts_profile_task_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelReporterFftsProfileTaskOffTest)
{
    std::vector<std::string> deviceBlackDataList = {"ffts_profile"};
    MsprofMgr().SetDeviceCheckList({}, deviceBlackDataList);
    TestProfJson("prof_channel_reporter_switch_ffts_profile_task_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelReporterLpmFreqConvOffTest)
{
    std::vector<std::string> deviceBlackDataList = {"lpmFreqConv"};
    MsprofMgr().SetDeviceCheckList({}, deviceBlackDataList);
    TestProfJson("prof_channel_reporter_switch_lpm_freq_conv_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelReporterTsTrackOffTest)
{
    std::vector<std::string> deviceBlackDataList = {"ts_track"};
    MsprofMgr().SetDeviceCheckList({}, deviceBlackDataList);
    TestProfJson("prof_channel_reporter_switch_ts_track_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelReporterStarsSocOffTest)
{
    std::vector<std::string> deviceBlackDataList = {"stars_soc."};
    MsprofMgr().SetDeviceCheckList({}, deviceBlackDataList);
    TestProfJson("prof_channel_reporter_switch_stars_soc_off");
}

TEST_F(AclJsonProfJsonStest, AclJsonChannelReporterStarsSocProfileOffTest)
{
    std::vector<std::string> deviceBlackDataList = {"stars_soc_profile"};
    MsprofMgr().SetDeviceCheckList({}, deviceBlackDataList);
    TestProfJson("prof_channel_reporter_switch_stars_soc_profile_off");
}