-- 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 fructl_data_keeping = require 'basic_cooling.data_keeping.fructl_data_keeping'
local enums = require 'basic_cooling.define.cooling_enums'
local thermal_mgmt_utils = require 'thermal_mgmt_utils'

TestFructlDataKeeping = {}

-- 保存原始函数
local original_get_chassis_type = thermal_mgmt_utils.get_chassis_type

-- 创建mock bus对象
local function create_mock_bus()
    return {
        match = function(self, signal, callback)
            return {}
        end
    }
end

function TestFructlDataKeeping:setUp()
    -- 清理单例实例
    fructl_data_keeping.destroy()
    -- 重置mock
    self.chassis_type_calls = 0
    -- 创建mock bus
    self.mock_bus = create_mock_bus()
end

function TestFructlDataKeeping:tearDown()
    -- 恢复原始函数
    thermal_mgmt_utils.get_chassis_type = original_get_chassis_type
    -- 清理单例实例
    fructl_data_keeping.destroy()
end

-- 测试get_power_state在RACK_MGMT类型时返回ON
function TestFructlDataKeeping:test_get_power_state_rack_mgmt()
    -- Mock get_chassis_type返回RACK_MGMT
    thermal_mgmt_utils.get_chassis_type = function()
        self.chassis_type_calls = self.chassis_type_calls + 1
        return enums.chassis_type.RACK_MGMT
    end

    local instance = fructl_data_keeping.new(self.mock_bus)
    instance.power_state = 'OFF' -- 设置一个非ON的值

    -- 第一次调用应该获取chassis_type并返回ON
    local power_state = instance:get_power_state()
    lu.assertEquals(power_state, 'ON')
    lu.assertEquals(self.chassis_type_calls, 1)

    -- 第二次调用应该使用缓存的chassis_type，仍然返回ON
    power_state = instance:get_power_state()
    lu.assertEquals(power_state, 'ON')
    lu.assertEquals(self.chassis_type_calls, 1) -- 不应该再次调用
end

-- 测试get_power_state在非RACK_MGMT类型时返回实际的power_state
function TestFructlDataKeeping:test_get_power_state_non_rack_mgmt()
    -- Mock get_chassis_type返回非RACK_MGMT
    thermal_mgmt_utils.get_chassis_type = function()
        self.chassis_type_calls = self.chassis_type_calls + 1
        return 1 -- 非RACK_MGMT类型
    end

    local instance = fructl_data_keeping.new(self.mock_bus)

    -- 测试不同的power_state值
    instance.power_state = 'ON'
    local power_state = instance:get_power_state()
    lu.assertEquals(power_state, 'ON')

    instance.power_state = 'OFF'
    power_state = instance:get_power_state()
    lu.assertEquals(power_state, 'OFF')

    instance.power_state = 'ONING'
    power_state = instance:get_power_state()
    lu.assertEquals(power_state, 'ONING')

    -- chassis_type只被调用1次（缓存机制）
    lu.assertEquals(self.chassis_type_calls, 1)
end

-- 测试get_power_state的chassis_type缓存机制
function TestFructlDataKeeping:test_get_power_state_chassis_type_cache()
    self.chassis_type_calls = 0
    thermal_mgmt_utils.get_chassis_type = function()
        self.chassis_type_calls = self.chassis_type_calls + 1
        return 1 -- 非RACK_MGMT类型
    end

    local instance = fructl_data_keeping.new(self.mock_bus)
    instance.power_state = 'ON'

    -- 多次调用get_power_state
    instance:get_power_state()
    instance:get_power_state()
    instance:get_power_state()

    -- get_chassis_type 只被调用1次
    lu.assertEquals(self.chassis_type_calls, 1)
end

-- 测试action_after_property_changed正确更新power_state
function TestFructlDataKeeping:test_action_after_property_changed()
    local instance = fructl_data_keeping.new(self.mock_bus)
    instance.power_state = 'OFF'

    -- 测试属性变更从OFF到ONING
    instance:action_after_property_changed('/path', 'interface', 'PowerState', 'ONING')
    lu.assertEquals(instance.power_state, 'ONING')

    -- 测试属性变更从ONING到ON
    instance:action_after_property_changed('/path', 'interface',' PowerState', 'ON')
    lu.assertEquals(instance.power_state, 'ON')

    -- 测试属性变更从ON到OFF
    instance:action_after_property_changed('/path', 'interface', 'PowerState', 'OFF')
    lu.assertEquals(instance.power_state, 'OFF')
end

-- 测试get_power_state和action_after_property_changed的集成
function TestFructlDataKeeping:test_get_power_state_after_property_changed()
    thermal_mgmt_utils.get_chassis_type = function()
        return 1 -- 非RACK_MGMT类型
    end

    local instance = fructl_data_keeping.new(self.mock_bus)
    instance.power_state = 'OFF'

    -- 初始状态应该是OFF
    lu.assertEquals(instance:get_power_state(), 'OFF')

    -- 属性变更为ONING
    instance:action_after_property_changed('/path', 'interface', 'PowerState', 'ONING')
    lu.assertEquals(instance:get_power_state(), 'ONING')

    -- 属性变更为ON
    instance:action_after_property_changed('/path', 'interface', 'PowerState', 'ON')
    lu.assertEquals(instance:get_power_state(), 'ON')
end

-- 测试RACK_MGMT类型下，即使power_state被设置为其他值，get_power_state仍返回'ON'
function TestFructlDataKeeping:test_rack_mgmt_always_returns_on()
    thermal_mgmt_utils.get_chassis_type = function()
        return enums.chassis_type.RACK_MGMT
    end

    local instance = fructl_data_keeping.new(self.mock_bus)

    -- 即使power_state被设置为其他值，get_power_state仍然返回ON
    instance.power_state = 'OFF'
    lu.assertEquals(instance:get_power_state(), 'ON')

    instance.power_state = 'ONING'
    lu.assertEquals(instance:get_power_state(), 'ON')

    instance.power_state = 'ON'
    lu.assertEquals(instance:get_power_state(), 'ON')
end

function TestFructlDataKeeping:test_action_after_obj_added()
    local temp = {
        power_state = "ON",
        objs = {
            ['/bmc/kepler/Systems/1/FruCtrl/1'] = {
                ['bmc.kepler.Systems.FruCtrl'] = {
                    ['PowerState'] = 'OFF'
                }
            }
        }
    }
    local path = '/bmc/kepler/Systems/1/FruCtrl/1'
    local interface = 'bmc.kepler.Systems.FruCtrl'
    local ok = pcall(function()
        fructl_data_keeping.action_after_obj_added(temp, path, interface)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(temp.power_state, 'OFF')

end

return TestFructlDataKeeping