local utils_file = require('utils.file')
local utils = require('mc.utils')
local cjson = require('cjson')
local TYPE_T <const> = { 'redfish', 'cli', 'snmp', 'web_backend' }
local METHOD_T <const> = { 'get', 'patch', 'post', 'delete' }
local M = {}
M.__index = M
function M.new(t, m)
return setmetatable({
type = nil,
cases = {},
tree = t,
mapper = m,
}, M)
end
function M:parse(path)
if string.match(path, '.+%.(.+)$') ~= 'json' then
print(string.format('The file %s is incorrect format.', path))
return false
end
local f = utils_file.open_s(path, 'r')
if not f then
print(string.format('Open %s failed.', path))
return false
end
local buf = f:read('a')
local data = cjson.json_object_ordered_decode(buf)
if not data then
print(string.format('The file %s is incorrect format.', path))
return false
end
if not data.cases then
print(string.format('The file %s lacks \'cases\'.', path))
return false
end
local type = string.match(path, '/test/unit/cases/([%a_]*)/.+')
if not utils.array_contains(TYPE_T, type) then
print('The interface type is wrong.')
return false
end
self.type = type
if data.mocks then
for k, v in pairs(data.mocks) do
self.tree.mocks[k] = cjson.json_object_to_table(v)
end
end
if data.invokes then
for k, v in pairs(data.invokes) do
self.tree.invokes[k] = cjson.json_object_to_table(v)
end
end
for _, v in pairs(data.cases) do
self.cases[#self.cases + 1] = v
end
f:close()
return true
end
local function execute_redfish(input, mapper)
local errs, rsp_body = mapper:match(input.uri, input.method, {
body = input.reqBody ~= nil and input.reqBody or {},
query = {},
user = { Interface = 'Redfish', UserName = 'Administrator', ClientIp = '0.0.0.0', AccountId = 1 },
})
if string.lower(input.method) == 'patch' then
errs, rsp_body = mapper:match(input.uri, 'GET', {
body = {},
query = {},
user = { Interface = 'Redfish', UserName = 'Administrator', ClientIp = '0.0.0.0', AccountId = 1 },
})
end
return errs, rsp_body
end
local function execute_web(input, mapper)
local errs, rsp_body = mapper:match(input.uri, input.method, {
body = input.reqBody ~= nil and input.reqBody or {},
query = {},
user = { Interface = 'WEB', UserName = 'Administrator', ClientIp = '0.0.0.0', AccountId = 1 },
})
if string.lower(input.method) == 'patch' then
errs, rsp_body = mapper:match(input.uri, 'GET', {
body = {},
query = {},
user = { Interface = 'WEB', UserName = 'Administrator', ClientIp = '0.0.0.0', AccountId = 1 },
})
end
return errs, rsp_body
end
local function execute_snmp(input, mapper) end
local function execute_cli(input, mapper) end
local execute_table = {
['redfish'] = execute_redfish,
['web_backend'] = execute_web,
['snmp'] = execute_snmp,
['cli'] = execute_cli,
}
function M:execute(input)
if not input.uri or not input.method then
print('The input lacks \'uri\' or \'method\'.')
return
end
if type(input.method) ~= 'string' or not utils.array_contains(METHOD_T, string.lower(input.method)) then
print(string.format('The method type: %s is wrong.', input.method))
return
end
return execute_table[self.type](input, self.mapper)
end
function M:cleanup(action)
if not action then
return
end
if action == 'This' then
self.tree:recover_stub()
elseif action == 'All' then
self.tree:clear_stub()
end
end
local function compare(output, rsp_body)
if not output then
print('The cases lack \'output\'.')
return false
end
local assert = output.assert == nil and 'Equal' or output.assert
if not rsp_body then
if assert == 'Equal' then
return false
else
return true
end
end
local res = cjson.json_object_is_equal(output.expect, rsp_body)
if not res then
print(cjson.json_object_ordered_encode_pretty(rsp_body))
print(cjson.json_object_ordered_encode_pretty(output.expect))
end
return res
end
function M:run_one(case)
if not case.name or not case.input or not case.output then
print('The case lacks \'name\' or \'input\' or \'output\'.')
return false
end
local t_case = cjson.json_object_to_table(case)
self.tree:mock(t_case.mocks)
self.tree:invoke(t_case.invokes)
local _, rsp_body = self:execute(t_case.input)
local res = compare(case.output, rsp_body)
self:cleanup(t_case.cleanup)
if not res then
print(t_case.name .. ' failed')
return false
end
print(t_case.name .. ' successfully')
return res
end
function M:run()
local res = true
for _, v in pairs(self.cases) do
self.tree:backup_stub()
res = res and self:run_one(v)
end
self.tree:clear()
return res
end
return M