-- 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 c_fan_group_object = require 'fan_group_object'
local c_basic_cooling_config = require 'basic_cooling_config'
local c_object_manage = require 'mc.orm.object_manage'
local c_tasks = require 'mc.orm.tasks'
local thermal_db = require 'thermal_mgmt.db'
local hook_tasks = require 'test_common.hook_tasks'
local test_utils = require 'test_utils'
local fan_service = require 'fan_service'

TestZoneSpeedAdjust = {}

function TestZoneSpeedAdjust:flush()
    c_tasks.get_instance():run_all_task()
    self.database.db:flush()
end

function TestZoneSpeedAdjust:setUp()
    self.database = thermal_db(':memory:')

    hook_tasks.hook()
    self.object_manage = c_object_manage.new(self.database)
    self.object_manage.app = self

    local fan_group1  = {
        Id = 1,
        FanSlots = {1, 2, 3, 4}
    }

    local fan_group2  = {
        Id = 2,
        FanSlots = {4, 5, 6, 7}
    }

    local basic_cooling_confg = {
        FanGroupSpeedDiffThresholdPercent = 20,
        PsuFanSpeedCalibration = 32767 -- 默认值
    }

    local fan_group1_obj = test_utils.add_fan_group_obj(self.object_manage, 'FanGroup_1', fan_group1)
    local fan_group2_obj = test_utils.add_fan_group_obj(self.object_manage, 'FanGroup_2', fan_group2)

    self.object_manage.mc:before_add_object(c_fan_group_object.__class_name, fan_group1_obj)
    self.object_manage.mc:add_object(c_fan_group_object.__class_name, fan_group1_obj, '010107')

    self.object_manage.mc:before_add_object(c_fan_group_object.__class_name, fan_group2_obj)
    self.object_manage.mc:add_object(c_fan_group_object.__class_name, fan_group2_obj, '010107')

    self.object_manage.mc:before_add_object(c_basic_cooling_config.__class_name, basic_cooling_confg)
    self.object_manage.mc:add_object(c_basic_cooling_config.__class_name, basic_cooling_confg, '010107')

    self.object_manage.mc:prepare_ok()
    self:flush()
end

function TestZoneSpeedAdjust:tearDown()
    c_object_manage.destroy()
    self.database.db:close()
    hook_tasks.unhook()
end

function TestZoneSpeedAdjust:test_obj_init()
    local obj = c_fan_group_object.collection:find({
        Id = 1
    })
    lu.assertIsTable(obj.FanSlots)

    obj = c_fan_group_object.collection:find({
        Id = 2
    })
    lu.assertIsTable(obj.FanSlots)

    obj = c_basic_cooling_config.collection:find({
        FanGroupSpeedDiffThresholdPercent = 20
    })
    lu.assertIsTable(obj)
end

function TestZoneSpeedAdjust:test_zone_speed_adjust()
    -- 初始化随机数生成器
    math.randomseed(os.time())
    for i = 1, 10000 do
        local speed1 = math.random(10, 100)
        local speed2 = math.random(10, 100)
        local speed3 = math.random(10, 100)
        local speed4 = math.random(10, 100)
        local speed5 = math.random(10, 100)
        local speed6 = math.random(10, 100)
        local speed7 = math.random(10, 100)

        local origin_pwm_table = {speed1, speed2, speed3, speed4, speed5, speed6, speed7}
        c_basic_cooling_config.collection:fold(function (_, basic_cooling_config_obj)
            new_pwm_table = basic_cooling_config_obj:fan_group_speed_adjust(origin_pwm_table)
        end)
        for j = 1, 4 do
            for k = 4, 7 do
                lu.assertEquals(math.abs(origin_pwm_table[j] - new_pwm_table[k]) <= 20, true)
            end
        end
    end
end

function TestZoneSpeedAdjust:test_fan_group_speed_adjust()
    math.randomseed(os.time())
    local speed1 = math.random(10, 100)
    local speed2 = math.random(10, 100)
    local speed3 = math.random(10, 100)
    local speed4 = math.random(10, 100)
    local origin_pwm_table = {0, speed1, speed2, speed3, speed4}
    fan_service_obj = fan_service.new()
    new_pwm_table = fan_service_obj:fan_group_speed_adjust(origin_pwm_table)
    lu.assertEquals(new_pwm_table ~= nil, true)
end

function TestZoneSpeedAdjust:test_psu_fan_speed_adjust()
    c_basic_cooling_config.PsuFanSpeedCalibration = 5
    c_basic_cooling_config.power_supplies_instance = {
        set_psu_fan_pwm = function (s, ctx, pwm)
        end
    }
    math.randomseed(os.time())
    local speed1 = math.random(10, 100)
    local speed2 = math.random(10, 100)
    local speed3 = math.random(10, 100)
    local speed4 = math.random(10, 100)
    local origin_pwm_table = {0, speed1, speed2, speed3, speed4}
    c_basic_cooling_config:set_psu_fan(origin_pwm_table)
    lu.assertEquals(c_basic_cooling_config.pre_psu_level ~= 0, true)
end