-- 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 log = require 'mc.logging'
local lu = require 'luaunit'
local rpc_service_subhealth = require 'rpc_services.rpc_service_subhealth'
local utils = require 'mc.utils'
local common_def = require 'common_def'

local test_subhealth = {}

local io_key_names = {
    'drive_name', 'media_type', 'manufacturer', 'serial_number', 'protocol', 'ref_controller_id',
    'glist_cnt', 'plist_cnt', 'unc_static', 'media_error', 'other_error', 'cmd_timeout',
    'bit_error_rate_zone', 'flyheight_clearance_delta_outer', 'flyheight_clearance_delta_inner',
    'flyheight_clearance_delta_middle', 'cur_farm', 'factory_farm'
}

local function get_info_prop(io_diagnose_info, prop_name)
    local data
    if io_diagnose_info and io_diagnose_info[prop_name] then
        if type(io_diagnose_info[prop_name]) == "string"then
            data = io_diagnose_info[prop_name]
        else
            data = tostring(io_diagnose_info[prop_name])
        end
    end

    return data
end

local stub_io_diagnose_info = {
    drive_name = 'Disk0',
    media_type = 'SSD',
    manufacturer = 'NEWZC1ALLK4',
    serial_number = 'NEWSEA',
    protocol = 1,
    ref_controller_id =0,
    glist_cnt = 1,
    plist_cnt = 88,
    unc_static = 10,
    media_error = 15,
    other_error = 12,
    cmd_timeout = 17,
    bit_error_rate_zone = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
    flyheight_clearance_delta_outer =
        '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
    flyheight_clearance_delta_inner =
        '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
    flyheight_clearance_delta_middle =
        '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
    cur_farm = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
    factory_farm = '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}',
}

local function fill_io_diagnose_info()
    local io_diagnose_info = utils.table_copy(stub_io_diagnose_info)
    return io_diagnose_info
end

local function get_io_deterioration_json_data()
    local io_diagnose_info = fill_io_diagnose_info()
    local io_diag_info_lists = {}
    local io_diag_info_list = {}
    for _, io_key_name in pairs(io_key_names) do
        local data = get_info_prop(io_diagnose_info, io_key_name)
        table.insert(io_diag_info_list, { key = io_key_name, value = data })
    end
    table.insert(io_diag_info_lists, io_diag_info_list)
    return io_diag_info_lists
end

local function test_collect_io_deterioration_diagnose_info()
    log:notice('====== start test_collect_io_deterioration_diagnose_info ======')
    local ok, task_id = pcall(function()
        return rpc_service_subhealth:collect_io_deterioration_diagnose_info()
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(task_id, 6090696636)
    log:notice('====== end test_collect_io_deterioration_diagnose_info ======')
end

local function test_get_drives_io_deterioration_diagnose_info()
    log:notice('====== start test_get_drives_io_deterioration_diagnose_info ======')
    local ok, io_diag_info_lists = pcall(function()
        return rpc_service_subhealth:get_drives_subhealth_diagnose_info(common_def.SUBHEALTH_STR.IO_DETERIORATION)
    end)
    lu.assertEquals(ok, true)
    lu.assertEquals(io_diag_info_lists, {})
    log:notice('====== end test_get_drives_io_deterioration_diagnose_info ======')
end

local function check_io_deterioration_json_data(io_diag_info_lists)
    for _, obj_list in pairs(io_diag_info_lists) do
        lu.assertEquals(obj_list[1].key, 'drive_name')
        lu.assertEquals(obj_list[1].value, 'Disk0')
        lu.assertEquals(obj_list[2].key, 'media_type')
        lu.assertEquals(obj_list[2].value, 'SATA')
        lu.assertEquals(obj_list[3].key, 'manufacturer')
        lu.assertEquals(obj_list[3].value, 'NEWZC1ALLK4')
        lu.assertEquals(obj_list[4].key, 'serial_number')
        lu.assertEquals(obj_list[4].value, 'NEWSEA')
        lu.assertEquals(obj_list[5].key, 'protocol')
        lu.assertEquals(obj_list[5].value, 'SSD')
        lu.assertEquals(obj_list[6].key, 'ref_controller_id')
        lu.assertEquals(obj_list[6].value, '0')
        lu.assertEquals(obj_list[7].key, 'glist_cnt')
        lu.assertEquals(obj_list[7].value, '1')
        lu.assertEquals(obj_list[8].key, 'plist_cnt')
        lu.assertEquals(obj_list[8].value, '88')
        lu.assertEquals(obj_list[9].key, 'unc_static')
        lu.assertEquals(obj_list[9].value, '10')
        lu.assertEquals(obj_list[10].key, 'media_error')
        lu.assertEquals(obj_list[10].value, '15')
        lu.assertEquals(obj_list[11].key, 'other_error')
        lu.assertEquals(obj_list[11].value, '12')
        lu.assertEquals(obj_list[12].key, 'cmd_timeout')
        lu.assertEquals(obj_list[12].value, '17')
        lu.assertEquals(obj_list[13].key, 'bit_error_rate_zone')
        lu.assertEquals(obj_list[13].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
        lu.assertEquals(obj_list[14].key, 'flyheight_clearance_delta_outer')
        lu.assertEquals(obj_list[14].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
        lu.assertEquals(obj_list[15].key, 'flyheight_clearance_delta_inner')
        lu.assertEquals(obj_list[15].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
        lu.assertEquals(obj_list[16].key, 'flyheight_clearance_delta_middle')
        lu.assertEquals(obj_list[16].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
        lu.assertEquals(obj_list[17].key, 'cur_farm')
        lu.assertEquals(obj_list[17].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
        lu.assertEquals(obj_list[18].key, 'factory_farm')
        lu.assertEquals(obj_list[18].value,
            '{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24}')
    end
end

local function test_io_deterioration_json_data()
    log:notice('====== start test_io_deterioration_json_data ======')
    local io_diag_info_lists = get_io_deterioration_json_data()
    check_io_deterioration_json_data(io_diag_info_lists)
    log:notice('====== end test_io_deterioration_json_data ======')
end

function test_subhealth.io_deterioration_test(bus)
    log:notice('====== start io_deterioration_test ======')
    rpc_service_subhealth.new(bus)
    test_collect_io_deterioration_diagnose_info()
    test_get_drives_io_deterioration_diagnose_info()
    test_io_deterioration_json_data()
    log:notice('====== end io_deterioration_test ======')
end

return test_subhealth