-- 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 lu = require 'luaunit'

local function install_add_event_mocks(client_tbl)
    package.preload['cjson'] = function()
        local cjson = {}
        function cjson.encode(data)
            local values = {}
            for _, value in ipairs(data or {}) do
                values[#values + 1] = string.format('"%s"', tostring(value))
            end
            return '[' .. table.concat(values, ',') .. ']'
        end
        return cjson
    end

    package.preload['mc.context'] = function()
        return {
            new = function()
                return {}
            end
        }
    end

    package.preload['mc.singleton'] = function()
        return function(class_obj)
            return class_obj
        end
    end

    package.preload['mc.class'] = function()
        return function()
            return {}
        end
    end

    package.preload['mc.logging'] = function()
        return {
            notice = function(...) end,
            error = function(...) end
        }
    end

    package.preload['power_mgmt.client'] = function()
        return client_tbl
    end

    package.loaded['cjson'] = nil
    package.loaded['mc.context'] = nil
    package.loaded['mc.singleton'] = nil
    package.loaded['mc.class'] = nil
    package.loaded['mc.logging'] = nil
    package.loaded['power_mgmt.client'] = nil
    package.loaded['device_tree.adapters.power_mgmt.add_event'] = nil
end

local function clear_add_event_mocks()
    package.preload['cjson'] = nil
    package.preload['mc.context'] = nil
    package.preload['mc.singleton'] = nil
    package.preload['mc.class'] = nil
    package.preload['mc.logging'] = nil
    package.preload['power_mgmt.client'] = nil

    package.loaded['cjson'] = nil
    package.loaded['mc.context'] = nil
    package.loaded['mc.singleton'] = nil
    package.loaded['mc.class'] = nil
    package.loaded['mc.logging'] = nil
    package.loaded['power_mgmt.client'] = nil
    package.loaded['device_tree.adapters.power_mgmt.add_event'] = nil
end

TestAddEvent = {}

function TestAddEvent:setUp()
    self.client = {}
    install_add_event_mocks(self.client)
    self.add_event = require 'device_tree.adapters.power_mgmt.add_event'
end

function TestAddEvent:tearDown()
    clear_add_event_mocks()
end

-- Given: EventsEventsAddEvent 可正常被调用。
-- When: 调用 generate_switch_page_failure('true', '1', 'A')。
-- Then: 上报参数完整且事件键为 PSU.PSUSwitchoverNotificationChannelFailure。
function TestAddEvent:test_generate_switch_page_failure_success()
    local client_calls = {}
    self.client.EventsEventsAddEvent = function(self_client, ctx, system_info, param)
        table.insert(client_calls, {
            method = 'EventsEventsAddEvent',
            ctx = ctx,
            system_info = system_info,
            param = param
        })
        return true
    end

    self.add_event.generate_switch_page_failure('true', '1', 'A')

    lu.assertEquals(#client_calls, 1)
    lu.assertEquals(client_calls[1].method, 'EventsEventsAddEvent')
    lu.assertEquals(client_calls[1].system_info['SystemId'], 1)

    local param = client_calls[1].param
    lu.assertEquals(#param, 8)
    lu.assertEquals(param[1][1], 'ComponentName')
    lu.assertEquals(param[1][2], 'PS')
    lu.assertEquals(param[2][1], 'State')
    lu.assertEquals(param[2][2], 'true')
    lu.assertEquals(param[3][1], 'EventKeyId')
    lu.assertEquals(param[3][2], 'PSU.PSUSwitchoverNotificationChannelFailure')
    lu.assertEquals(param[4][1], 'MessageArgs')
    lu.assertEquals(param[4][2], '["1","A"]')
    lu.assertEquals(param[5][1], 'SystemId')
    lu.assertEquals(param[5][2], '')
    lu.assertEquals(param[6][1], 'ManagerId')
    lu.assertEquals(param[6][2], '')
    lu.assertEquals(param[7][1], 'ChassisId')
    lu.assertEquals(param[7][2], '')
    lu.assertEquals(param[8][1], 'NodeId')
    lu.assertEquals(param[8][2], '')
end

-- Given: EventsEventsAddEvent 抛出异常。
-- When: 调用 generate_switch_page_failure('true', '1', 'A')。
-- Then: 函数内部处理异常，对外不抛错。
function TestAddEvent:test_generate_switch_page_failure_failed()
    self.client.EventsEventsAddEvent = function(self_client, ctx, system_info, param)
        error('send failed')
    end

    local ok = pcall(function()
        self.add_event.generate_switch_page_failure('true', '1', 'A')
    end)
    lu.assertEquals(ok, true)
end
