-- 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 test_common = require 'test_common.utils'
local dbus_sms = require 'dbus_sms'
local test_bma_1822 = require 'test_datas.bma_1822'
local json = require 'cjson'
local object_path = require 'dbus.object_path'
local test_utils = require 'test_utils'
local escape = object_path.escape

local ES_ODATA_ID = escape('@odata.id')

TEST_dbus_sms = {}

function TEST_dbus_sms:setUp()
    self.bus = test_common.dbus_launch('../.dbus', nil, true)
    self.bus:request_name('bmc.kepler.network_adapter')

    self.sms = dbus_sms.new(self.bus)
    self:install_dbus_emit_hook()
end

function TEST_dbus_sms:tearDown()
    self.bus:close()
end

function TEST_dbus_sms:install_dbus_emit_hook()
    self.result = {}
    self.bus.bus.emit_properties_changed = function(_, path, iface, props)
        self.result[#self.result + 1] = {
            type = 'emit_properties_changed',
            path = path,
            iface = iface,
            props = props
        }
    end

    self.bus.bus.emit_interfaces = function(_, is_add, path, ifaces)
        self.result[#self.result + 1] = {
            type = 'emit_interfaces',
            is_add = is_add,
            path = path,
            ifaces = ifaces
        }
    end
end

-- 测试 redfish 数据更新
function TEST_dbus_sms:test_dbus_sms_update()
    local eth_data = json.decode(test_bma_1822.EthernetInterface)
    self.sms:update(eth_data)
    lu.assertEquals(#self.result, 1)
    lu.assertEquals(self.result[1].type, 'emit_interfaces')
    lu.assertEquals(self.result[1].is_add, true)
    lu.assertEquals(self.result[1].path, dbus_sms.to_bmc_url(eth_data['@odata.id']))

    eth_data.IPv4Addresses = {
        {
            Address = '127.0.0.0',
            AddressOrigin = 'Static',
            Gateway = {'196.128.0.0'},
            SubnetMask = '0.0.0.0'
        }
    }

    self.result = {}
    self.sms:update(eth_data)
    lu.assertEquals(#self.result, 1)
    lu.assertEquals(self.result[1].type, 'emit_properties_changed')
    lu.assertEquals(self.result[1].path, dbus_sms.to_bmc_url(eth_data['@odata.id']))
    lu.assertEquals(self.result[1].iface, dbus_sms.to_bmc_interface())
end

function TEST_dbus_sms:test_dbus_sms_update_sub_interface()
    local eth_data = json.decode(test_bma_1822.EthernetInterface)
    self.sms:update(eth_data)

    local oid = eth_data['@odata.id']

    self.result = {}
    self.sms:update({['@odata.id'] = oid, OAM = {}}) -- 设置为空表
    lu.assertEquals(#self.result, 2)
    lu.assertEquals(self.result[1].is_add, false)
    lu.assertEquals(self.result[1].ifaces, {dbus_sms.to_bmc_interface('OAM')})
    lu.assertEquals(self.result[2].type, 'emit_properties_changed')
    lu.assertEquals(self.result[2].iface, dbus_sms.to_bmc_interface())
    lu.assertEquals(self.result[2].props, {'OAM'})

    self.result = {}
    self.sms:update({['@odata.id'] = oid, Sff = json.null}) -- 字段清空
    lu.assertEquals(#self.result, 2)
    lu.assertEquals(self.result[1].is_add, false)
    lu.assertEquals(self.result[1].ifaces, {dbus_sms.to_bmc_interface('Sff')})
    lu.assertEquals(self.result[2].type, 'emit_properties_changed')
    lu.assertEquals(self.result[2].iface, dbus_sms.to_bmc_interface())
    lu.assertEquals(self.result[2].props, {'Sff'})

    self.result = {}
    self.sms:update({['@odata.id'] = oid, VLANs = {['@odata.id'] = '/newpath'}}) -- 更新
    lu.assertEquals(#self.result, 1)
    lu.assertEquals(self.result[1].type, 'emit_properties_changed')
    lu.assertEquals(self.result[1].iface, dbus_sms.to_bmc_interface('VLANs'))
    lu.assertEquals(self.result[1].props, {ES_ODATA_ID})

    self.result = {}
    self.sms:update({['@odata.id'] = oid, Statistics = {NewProp = 1}}) -- 插入新字段
    lu.assertEquals(#self.result, 1)
    lu.assertEquals(self.result[1].type, 'emit_properties_changed')
    lu.assertEquals(self.result[1].iface, dbus_sms.to_bmc_interface('Statistics'))
    lu.assertEquals(self.result[1].props, {'NewProp'})
end

-- 需要上树的 BMA 资源必须是 /redfish/v1/Sms/1/Systems/1 的子资源
function TEST_dbus_sms:test_dbus_sms_skip_unknown_path()
    local eth_data = {['@odata.id'] = '/redfish/v1/Systems/1/EventService/Subscriptions'}

    self.result = {}
    self.sms:update(eth_data)
    lu.assertEquals(#self.result, 0)
end

function TEST_dbus_sms:test_bma_to_json()
    local eth_data = json.decode(test_bma_1822.EthernetInterface)
    self.sms:update(eth_data)

    local path = dbus_sms.to_bmc_url(eth_data['@odata.id'])
    local object = self.sms.bus.bus.tree:find_object(path)
    local json_val = self.sms.object_to_json(object)
    local expected = test_utils.json_data_to_dbus_data(eth_data)
    lu.assertEquals(json_val, expected)
end
