diff --git a/daemon/lua/kres.lua b/daemon/lua/kres.lua index a2cb406138320f091aa133786f96565ba9be683b..3bc2dbf7f16a41738c843ccf45ff556895c2e43b 100644 --- a/daemon/lua/kres.lua +++ b/daemon/lua/kres.lua @@ -455,6 +455,27 @@ ffi.metatype( knot_rrset_t, { C.free(dump[0]) return result end, + txt_fields = function(rr, i) + assert(ffi.istype(knot_rrset_t, rr)) + assert(i >= 0 and i < rr:rdcount()) + local bufsize = 1024 + local dump = ffi.new('char *', C.malloc(bufsize)) + ffi.gc(dump, C.free) + + local ret = knot.knot_rrset_txt_dump_data(rr, i, dump, 1024, + knot.KNOT_DUMP_STYLE_DEFAULT) + if ret >= 0 then + local out = {} + out.owner = dname2str(rr:owner()) + out.ttl = rr:ttl() + out.class = kres.tostring.class[rr:class()] + out.type = kres.tostring.type[rr.type] + out.rdata = ffi.string(dump, ret) + return out + else + panic('knot_rrset_txt_dump_data failure ' .. tostring(ret)) + end + end, -- Return RDATA count for this RR set rdcount = function(rr) assert(ffi.istype(knot_rrset_t, rr)) diff --git a/tests/config/test_utils.lua b/tests/config/test_utils.lua index 5a7f3111b101e358b5f96b6dbcd714553af60fdb..93a937708c65e6e1ae8faab1d24e45908b68f222 100644 --- a/tests/config/test_utils.lua +++ b/tests/config/test_utils.lua @@ -38,21 +38,46 @@ function M.not_contains(table, value, message) return contains(fail, pass, table, value, message) end -local function rrset_to_texts(rr) - local rr_text = {} - for w in rr:txt_dump():gmatch("%S+") do table.insert(rr_text, w) end - return rr_text +local function answer2table(pkt) + local got_answers = {} + local ans_rrs = pkt:rrsets(kres.section.ANSWER) + for i = 1, #ans_rrs do + rrs = ans_rrs[i] + for rri = 0, rrs:rdcount() - 1 do + local rr = ans_rrs[i]:txt_fields(rri) + got_answers[rr.owner] = got_answers[rr.owner] or {} + got_answers[rr.owner][rr.type] = got_answers[rr.owner][rr.type] or {} + table.insert(got_answers[rr.owner][rr.type], rr.rdata) + table.sort(got_answers[rr.owner][rr.type]) + end + end + return got_answers end + M.NODATA = -1 -- Resolve a name and check the answer. Do *not* return until finished. -- expected_rdata is one string or a table of strings in presentation format --- (not tested beyond IP addresses; TODO: handle ordering somehow?) function M.check_answer(desc, qname, qtype, expected_rcode, expected_rdata) - if expected_rdata ~= nil and type(expected_rdata) ~= 'table' then - expected_rdata = { expected_rdata } + assert(type(qtype) == 'number') + local qtype_str = kres.tostring.type[qtype] + qname = string.lower(qname) + + local expected_answer = {} + if expected_rdata ~= nil then + if type(expected_rdata) ~= 'table' then + expected_rdata = { expected_rdata } + end + if #expected_rdata > 0 then + table.sort(expected_rdata) + expected_answer = { + [qname] = { + [qtype_str] = + expected_rdata + } + } + end end - local qtype_str = kres.tostring.type[qtype] local wire_rcode = expected_rcode if expected_rcode == kres.rcode.NOERROR and type(expected_rdata) == 'table' and #expected_rdata == 0 then @@ -71,16 +96,10 @@ function M.check_answer(desc, qname, qtype, expected_rcode, expected_rdata) desc ..': checking number of answers for ' .. qname .. ' ' .. qtype_str) if expected_rdata then - local ans_rrs = pkt:rrsets(kres.section.ANSWER) - ok(#expected_rdata == #ans_rrs, - desc .. ': checking number of answer records for ' .. qname .. ' ' .. qtype_str) - for i = 1, #ans_rrs do - ok(rrset_to_texts(ans_rrs[i])[4] == expected_rdata[i], - desc .. ': checking rdata of answer for ' .. qname .. ' ' .. qtype_str) - end + same(expected_answer, answer2table(pkt), 'ANSWER section matches') end done = true - end + end resolve(qname, qtype, kres.class.IN, {}, function(...) local ok, err = xpcall(callback, debug.traceback, ...)