-- 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 file_service = require 'service.file_service'
local bs_util = require 'util.base_util'
local json_util = require 'util.json_util'
local prop_def = require 'macros.property_def'
local registry_service = require 'service.registry_service'
local bios_service = require 'service.bios_service'
local bios_factory = require 'factory.bios_factory'
local pro_global = require 'macros.property_global'
local struct = require 'pojo.struct_def'
local lu = require 'luaunit'
local json = require 'cjson'
local project_dir = os.getenv('PROJECT_DIR')
local fructl_handler = require 'infrastructure.fructl'

local test_common = require 'test_common.utils'
local bus = test_common.dbus_launch('../.dbus', nil, true)

TestJsonSetup = {}

function TestJsonSetup:test_bean()
    local bios_ser = bios_service.get_instance(bus, {})
    assert(bios_ser ~= nil)

    pro_global.G_BIOS_FILE_CHANGE[0] = struct.bios_file_Change.new({})
    bios_factory.register_bean('bios_service', bios_ser)

    os.execute('cp ../test_data/setting.json ../test_data/setting1.json')
    bios_ser:set_bios_prop('CurrentValueFileName', project_dir .. '/test/test_data/currentvalue.json')
    bios_ser:set_bios_prop('ResultFileName', project_dir .. '/test/test_data/result.json')
    bios_ser:set_bios_prop('SettingFileName', project_dir .. '/test/test_data/setting1.json')
    bios_ser:set_bios_prop('RegistryFileName', project_dir .. '/test/test_data/registry.json')
end

function TestJsonSetup:test_z_clear()
    local bios_ser = bios_service.get_instance(bus, {})
    assert(bios_ser ~= nil)

    os.execute('rm -rf ../test_data/setting1.json')
    bios_ser:set_bios_prop('CurrentValueFileName', '/data/opt/currentvalue.json')
    bios_ser:set_bios_prop('ResultFileName', '/data/opt/result.json')
    bios_ser:set_bios_prop('SettingFileName', '/data/opt/setting.json')
    bios_ser:set_bios_prop('RegistryFileName', '/data/opt/registry.json')
end

function TestJsonSetup:test_json_util()
    local list = json_util.get_list()
    lu.assertEquals(list, nil)

    local table = {['a'] = 'a', ['b'] = 'b', ['c'] = 'c', ['d'] = 'd'}
    list = json_util.get_list(table)
    lu.assertEquals(#list, 4)
end

function TestJsonSetup:test_get_dependency_msg()
    local registry_path = project_dir .. '/test/test_data/registry.json'
    local registry_json = bs_util.get_file_json(registry_path)

    local registry_ser = registry_service.new(registry_json)
    local res = registry_ser:get_dependency_msg()
    lu.assertEquals(res, nil)

    res = registry_ser:get_dependency_msg('Hidden', 'DdrRefreshRate')
    lu.assertNotEquals(res, not nil)

    res = registry_ser:get_dependency_msg('Hidden', 'IPv6DuidType')
    lu.assertNotEquals(res, not nil)
end

local function construct_ctx()
    local ctx = {}
    ctx.ChanType = 1
    ctx.get_initiator = function()
        return {}
    end

    ctx.has_initiator = function()
        return true
    end

    return ctx
end

local function import_bios_json_success(file_ser)
    --2.成功
    local setup_data = '{"Attributes": {"DDRDebugLevel": "Disabled"}}'
    json.json_object_dump_pretty = function()
        return 1
    end
    local ok, res = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(res, prop_def.HTTP_OK)
end

function TestJsonSetup:test_check_prop_valid()
    local file_ser = file_service.new()
    local res
    local ok, _ = pcall(function()
        file_ser:check_prop_valid()
    end)
    lu.assertEquals(ok, false)

    ok, _ = pcall(function()
        file_ser:import_bios_json()
    end)
    lu.assertEquals(ok, false)

    ok, _ = pcall(function()
        file_ser:import_bios_json({}, 'registry',
            {['a'] = 'a', ['b'] = 'b', ['c'] = 'c', ['d'] = 'd'})
    end)
    lu.assertEquals(ok, false)

    -- 1.PropertyUnknown,属性未知
    local setup_data = {['a'] = 'a', ['b'] = 'b', ['c'] = 'c', ['d'] = 'd'}
    local setup_encode_data = json.encode(setup_data)
    ok, _ = pcall(function()
        file_ser:import_bios_json(construct_ctx(), 'Setting', setup_encode_data)
    end)
    lu.assertEquals(ok, false)

    import_bios_json_success(file_ser)

    -- 3.SettingPropertyFailedExtend,不可修改
    setup_data = '{"Attributes": {"PcieLinkDeEmphasisPortX6000[8]": "Level-3.5dB"}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)

    -- 4.PropertyNotWritable,只读
    setup_data = '{"Attributes": {"RedfishSupport": "Enable"}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)

    -- 5.SettingPropertyFailed,不可修改
    setup_data = '{"Attributes": {"CusFlag": "Enabled"}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)

    -- 6.PropertyValueNotInList,取值不在列表
    setup_data = '{"Attributes": {"DDRFreqLimit": "Auto1"}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)

    -- 7.ValueOutOfRange,取值超出范围
    setup_data = '{"Attributes": {"Port6TqpNumber": 1666}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)

    -- 8.PropertyValueTypeError,类型错误
    setup_data = '{"Attributes": {"Port6TqpNumber": "aaaa"}}'
    ok, _ = pcall(function()
        return file_ser:import_bios_json(construct_ctx(), 'Setting', setup_data)
    end)
    lu.assertEquals(ok, false)
end

function TestJsonSetup:test_set_bios_config_item()
    local file_ser = file_service.new()
    local req = {}
    req.ManufactureId = 0x0007DB
    req.Length = 0x0003
    req.Item = 0x00
    req.Option = 0x0001
    local res
    local ok
    ok, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 1、测试正常场景
    lu.assertEquals(ok, true)
    lu.assertEquals(res.CompletionCode, prop_def.BIOS_CONFIG_ITEM_SUCCESS)

    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'NotSetting')
    end)
    -- 2、测试import_setup_json导入失败
    lu.assertEquals(res.CompletionCode, prop_def.BIOS_CONFIG_ITEM_FIELD)

    req.ManufactureId = 0x0007DA
    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 3、测试ManufactureId 为其他值的场景
    lu.assertEquals(res.CompletionCode, prop_def.BIOS_CONFIG_ITEM_INVALID_FIELD)

    req.Length = nil
    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 4、测试Length 为空场景
    lu.assertEquals(res.CompletionCode, prop_def.BIOS_CONFIG_ITEM_INVALID_FIELD)

    req.Length = 0x0004
    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 5、测试Length 不为0003场景
    lu.assertEquals(res.CompletionCode, prop_def.COMP_CODE_OUTOF_RANGE)

    req.Length = 0x0003
    req.Item = 0x01
    req.ManufactureId = 0x0007DB
    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 6、测试Item 不为0x00时
    lu.assertEquals(res.CompletionCode, prop_def.BIOS_CONFIG_ITEM_INVALID_FIELD)

    req.Item = 0x00
    req.Option = 0x0005
    _, res = pcall(function()
        return file_ser:set_bios_config_item(req, construct_ctx(), 'Setting')
    end)
    -- 7、测试Operation 不在x00 - 0x04范围
    lu.assertEquals(res.CompletionCode, prop_def.COMP_CODE_OUTOF_RANGE)
end

function TestJsonSetup:test_set_power_state()
    local ctx = fructl_handler.get_context()
    lu.assertEquals(ctx.Requestor, 'bmc.kepler.bios')
    fructl_handler.get_fructl_obj = function ()
        return {
            pcall = {
                PowerCtrl = function ()
                    return
                end
            }
        }
    end
    fructl_handler.set_power_state("ForceOff", "Unknown", 1)
end

function TestJsonSetup:test_update_registry_and_check_cfg()
    local file_ser = file_service.new()
    file_ser.user_setting_service = {
        check_boot_order = function ()
            error('check boot order failed')
        end
    }
    file_ser.register_service = {
        update_registry = function ()
            return {ErrCode = prop_def.E_OK}
        end
    }
    file_ser.current_service = {
        get_setting_obj = function ()
        end
    }
    file_ser.check_setting_cfg = function ()
        return {ErrCode = prop_def.E_OK}
    end
    file_ser.invalid_cfg = {}
    local message = file_ser:update_registry_and_check_cfg()
    lu.assertEquals(message.ErrCode, prop_def.RESPONSE_BOOTTYPEORDER_ERROR)
    file_ser.from_web = true
    message = file_ser:update_registry_and_check_cfg()
    lu.assertEquals(message.ErrCode, prop_def.E_OK)
    lu.assertEquals(file_ser.invalid_cfg, {'BootTypeOrder0', 'BootTypeOrder1',
        'BootTypeOrder2', 'BootTypeOrder3'})
end

function TestJsonSetup:test_remove_invalid_web_config()
    local file_ser = file_service.new()
    file_ser.fill_cfg = {'a'}
    file_ser.invalid_cfg = {'b'}
    file_ser.current_service = {
        get_prop_val = function ()
            return '111'
        end
    }
    local config_data = {
        Attributes = {
            b = '222'
        }
    }
    file_ser:remove_invalid_web_config(true, config_data)
    lu.assertEquals(config_data['Attributes'], {a = '111'})
end