-- 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 utils = require 'mc.utils'
local log = require 'mc.logging'
local libmgmt_protocol = require 'libmgmt_protocol'

local T = {}

local function pack(obj)
    local result = ''
    for _, v in ipairs(obj) do
        result = result .. v
    end
    return result
end

local expect_called_and_return<const> = {
    {
        Write = {
            0, pack({
                '\x00\x00', -- lun
                '\x04\x04', -- opcode
                '\x00\x00\x00\x00', -- offset
                '\x30\x00\x00\x00', -- length
                '\x1e\xa1\x83\x2c' -- crc32
            })
        },
        Read = pack({
            '\x00\x00', -- error_code
            '\x04\x04', -- opcode
            '\x24\x00\x00\x00', -- total_length
            '\x24\x00\x00\x00', -- length
            '\x00\x00\x00\x04\x8C\x16\x59\xC8\x6D' .. -- data
            '\x01\x00\x01\x04\x8C\x16\x59\xC8\x6E' .. '\x02\x00\x02\x04\x8C\x16\x59\xC8\x6F' ..
                '\x03\x00\x03\x04\x8C\x16\x59\xC8\x70', string.rep('\x00', 12), -- fill
            '\x74\x51\xB0\x1E' -- crc32
        })
    }, {
        Write = {
            0, pack({
                '\x00\x00', -- lun
                '\x03\x00', -- opcode
                '\x00\x00\x00\x00', -- offset
                '\x02\x00\x00\x00', -- length
                '\x38\x2A\x95\xC6' -- crc32
            })
        },
        Read = pack({
            '\x00\x00', -- error_code
            '\x03\x00', -- opcode
            '\x02\x00\x00\x00', -- total_length
            '\x02\x00\x00\x00', -- length
            '\x2F\x00', '\x72\x96\x70\x59', -- crc32
            string.rep('\xFF', 46) -- fill
        })
    }
}

local function test_get_mac_address(obj)
    log:info('-------------------test_get_mac_address start------------------------------------')

    local expect_results<const> = {
        mac_address = {
            {port = 0, PF_VF = 0, addr = '04:8C:16:59:C8:6D'},
            {port = 1, PF_VF = 0x100, addr = '04:8C:16:59:C8:6E'},
            {port = 2, PF_VF = 0x200, addr = '04:8C:16:59:C8:6F'},
            {port = 3, PF_VF = 0x300, addr = '04:8C:16:59:C8:70'}
        }
    }

    local mac_address = obj:MacAddress({})
    lu.assertNotNil(mac_address)

    for i, addr in ipairs(mac_address) do
        lu.assertEquals(addr.port, expect_results.mac_address[i].port)
        lu.assertEquals(addr.PF_VF, expect_results.mac_address[i].PF_VF)
        lu.assertEquals(addr.addr, expect_results.mac_address[i].addr)
    end

    log:info('-------------------test_get_mac_address end------------------------------------')
end

local function test_get_chip_temp(obj)
    log:info('-------------------test_get_chip_temp start------------------------------------')

    local chip_temp = obj:ChipTemp({})
    lu.assertNotNil(chip_temp)

    lu.assertEquals(chip_temp:get(), 0x2F)

    chip_temp:deconstruct()

    log:info('-------------------test_get_chip_temp end------------------------------------')
end


function T:run()
    local Hi1822 = require 'hardware_config.Hi182X'
    Hi1822.protocol_dependencies.smbus.ref_chip = {
        Write = function(chip, _, a, b)
            for _, expect in ipairs(expect_called_and_return) do
                if utils.table_compare({a, b}, expect.Write) then
                    chip.next_return = expect.Read
                    return true
                end
            end
            assert(false, 'no matched call')
        end,
        Read = function(chip, _, ...)
            if chip.next_return ~= nil then
                local tmp = chip.next_return
                chip.next_return = nil
                return tmp
            end
            assert(false, 'nothing to read')
        end
    }

    local obj = libmgmt_protocol.device_spec_parser(Hi1822)
    lu.assertNotNil(obj)
    test_get_mac_address(obj)
    test_get_chip_temp(obj)
end

return T