-- Copyright (c) 2024 Huawei Technologies Co., Ltd.
-- openUBMC is licensed under Mulan PSL v2.
-- You can use this software according to the terms and conditions of the Mulan PSL v2.
-- You may obtain a copy of Mulan PSL v2 at:
--         http://license.coscl.org.cn/MulanPSL2
-- 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 FIT FOR A PARTICULAR PURPOSE.
-- See the Mulan PSL v2 for more details.

local skynet = require 'skynet'
require 'skynet.manager'
local log = require 'mc.logging'
local utils = require 'mc.utils'
local test_common = require 'test_common.utils'
local lu = require 'luaunit'
local sd_bus = require 'sd_bus'
local bs = require 'mc.bitstring'
local test_ipmi_tool = test_common.Ipmitool
local test_manufacture_common = require 'test_manufacture_common'

local function prepare_test_data()
    local test_data_dir = skynet.getenv('TEST_DATA_DIR')
    os.execute('mkdir -p ' .. test_data_dir)
    utils.copy_file('test/integration/data/passwd', test_data_dir .. '/passwd')
    utils.copy_file('test/integration/data/shadow', test_data_dir .. '/shadow')
    utils.copy_file('test/integration/data/group', test_data_dir .. '/group')
    utils.copy_file('test/integration/data/ipmi', test_data_dir .. '/ipmi')
    utils.copy_file('test/integration/data/datatocheck_default.dat',
        test_data_dir .. '/datatocheck_default.dat')

    local dir_list = {'apps/hwdiscovery/mds', 'apps/compute/mds', 'sr'}
    for _, path in pairs(dir_list) do
        os.execute('mkdir -p ' .. test_data_dir .. '/' .. path)
    end
    utils.copy_file('test/integration/test_data/root.sr', test_data_dir .. '/sr/root.sr')
    utils.copy_file('temp/opt/bmc/apps/hwdiscovery/mds/schema.json',
        test_data_dir .. '/apps/hwdiscovery/mds/schema.json')
    utils.copy_file('temp/opt/bmc/apps/compute/mds/schema.json',
        test_data_dir .. '/apps/compute/mds/schema.json')
    local tallylog_dir = skynet.getenv('PAM_TALLY_LOG_DIR')
    os.execute('mkdir -p ' .. tallylog_dir)
    local pamfaillock_dir = skynet.getenv('PAM_FAILLOCK_DIR')
    os.execute('mkdir -p ' .. pamfaillock_dir)
    os.execute('mkdir -p ' .. test_data_dir .. 'usr/lib64')
    utils.copy_file('temp/usr/lib64/mock/libsoc_adapter_it.so',
        test_data_dir .. 'usr/lib64/libsoc_adapter.so')
end

local function clear_test_data(exit_test)
    log:info('clear test data')
    local test_data_dir = utils.realpath('.') .. skynet.getenv('TEST_DATA_DIR')
    if exit_test then
        skynet.timeout(0, function()
            skynet.sleep(20)
            skynet.abort()
            utils.remove_file(test_data_dir)
        end)
    else
        utils.remove_file(test_data_dir)
    end
end

local GET_TEST_ITEM_COUNT_RSP = '<<count>>'

local function get_test_item_count()
    log:info("------  test  get test item count ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x40 0x01')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_TEST_ITEM_COUNT_RSP):unpack(rsp)
    lu.assertEquals(data.count, 1)
end

local GET_TEST_ITEM_INFO_RSP_1 = "<<end_of_list, tail/string>>"
local GET_TEST_ITEM_INFO_RSP_2 = "<<dft_id, slot_id:32, dev_num, item_name/string>>"

local function get_test_item_info_by_count()
    log:info("------  test  get test item info by count ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x41 0x00 0X20 0X01 0X01')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_TEST_ITEM_INFO_RSP_1):unpack(rsp)
    lu.assertEquals(data.end_of_list,  0)
    data = bs.new(GET_TEST_ITEM_INFO_RSP_2):unpack(data.tail)
    lu.assertEquals(data.dft_id, 9)
    lu.assertEquals(data.slot_id, 0)
    lu.assertEquals(data.dev_num, 0)
    log:info(data.item_name)
end

local function get_test_item_info_by_dftid()
    log:info("------  test  get test item info by dftid ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x41 0x00 0X20 0X01 0X09 0x00 0x00 0x00 0x00 0x00')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_TEST_ITEM_INFO_RSP_1):unpack(rsp)
    lu.assertEquals(data.end_of_list,  0)
    data = bs.new(GET_TEST_ITEM_INFO_RSP_2):unpack(data.tail)
    lu.assertEquals(data.dft_id, 9)
    lu.assertEquals(data.slot_id, 0)
    lu.assertEquals(data.dev_num, 0)
    log:info(data.item_name)
end

local START_DFT_RSP = '<<end_of_list, prompt/string>>'

local function start_dft_test_by_count()
    log:info("------  test  start dft test by count ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x42 0x00 0X20 0x01 0x01 0x01')
    lu.assertEquals(ok, true)
    local data = bs.new(START_DFT_RSP):unpack(rsp)
    lu.assertEquals(data.end_of_list, 0x80)
    lu.assertEquals(data.prompt, "")
    

    ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x42 0x00 0X20 0x01 0x00 0x01')
    lu.assertEquals(ok, true)
    data = bs.new(START_DFT_RSP):unpack(rsp)
    lu.assertEquals(data.end_of_list, 0x80)
    lu.assertEquals(data.prompt, "")
end

local function start_dft_test_by_dftid()
    log:info("------  test  start dft test by dftid ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x42 0x00 0X20 0x01 0x01 0x09 0x00 0x00 0x00 0x00 0x00')
    lu.assertEquals(ok, true)
    local data = bs.new(START_DFT_RSP):unpack(rsp)
    lu.assertEquals(data.end_of_list, 0x80)
    lu.assertEquals(data.prompt, "")
    ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x42 0x00 0X20 0x01 0x00 0x09 0x00 0x00 0x00 0x00 0x00')
    lu.assertEquals(ok, true)
    data = bs.new(START_DFT_RSP):unpack(rsp)
    lu.assertEquals(data.end_of_list, 0x80)
    lu.assertEquals(data.prompt, "")
end

local GET_DFT_RESULT_RSP_1 = '<<end_of_list, tail/string>>'
local GET_DFT_RESULT_RSP_2 = '<<result, dft_id, slot_id:32, dev_num, description/string>>'

local function get_dft_result_by_count()
    log:info("------  test get dft result by count ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x43 0x00 0X20 0x01 0x01')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_DFT_RESULT_RSP_1):unpack(rsp)
    lu.assertEquals(data.end_of_list,  0)
    data = bs.new(GET_DFT_RESULT_RSP_2):unpack(data.tail)
    lu.assertEquals(data.result, 1)
    lu.assertEquals(data.dft_id, 9)
    lu.assertEquals(data.slot_id, 0)
    lu.assertEquals(data.dev_num, 0)
    log:info(data.description)
end

local function get_dft_result_by_dftid()
    log:info("------  test get dft result by dftid ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x43 0x00 0X20 0x01 0x09 0x00 0x00 0x00 0x00 0x00')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_DFT_RESULT_RSP_1):unpack(rsp)
    lu.assertEquals(data.end_of_list,  0)
    data = bs.new(GET_DFT_RESULT_RSP_2):unpack(data.tail)
    lu.assertEquals(data.result, 1)
    lu.assertEquals(data.dft_id, 9)
    lu.assertEquals(data.slot_id, 0)
    lu.assertEquals(data.dev_num, 0)
    log:info(data.description)
end

local GET_PROCESS_TIME_RSP = '<<Time:2/unit:8>>'
local function get_process_time()
    log:info("------  test  get process time  ------")
    local ipmi_tool = test_ipmi_tool.new('Administrator')
    local ok, rsp = pcall(ipmi_tool.raw, ipmi_tool, '0x30 0x90 0x50 0x00')
    lu.assertEquals(ok, true)
    local data = bs.new(GET_PROCESS_TIME_RSP):unpack(rsp)
    lu.assertEquals(data.Time, 240)
end

local function test_run()
    log:info('================ test start ================')
    local bus = sd_bus.open_user(true)
    test_manufacture_common.set_bus(bus)
    log:info('================ test complete ================')
end

skynet.start(function()
    -- clear_test_data()
    -- prepare_test_data()
    -- test_common.dbus_launch()
    -- skynet.uniqueservice('sd_bus')
    -- skynet.uniqueservice('persistence/service/main')
    -- skynet.uniqueservice('maca/service/main')
    -- skynet.uniqueservice('ipmi_core/service/main')
    -- skynet.uniqueservice('key_mgmt/service/main')
    -- skynet.uniqueservice('compute/service/main')
    -- skynet.uniqueservice('hwdiscovery/service/main')
    -- skynet.uniqueservice('main')
    -- skynet.sleep(200)
    skynet.fork(function()
        local ok, err = pcall(test_run)
        clear_test_data(true)
        if not ok then
            log:error('=== test failed ===: %s', err)
        end
    end)
end)
