]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
config tests: generalize check_answer
authorPetr Špaček <petr.spacek@nic.cz>
Mon, 10 Aug 2020 15:30:30 +0000 (17:30 +0200)
committerTomas Krizek <tomas.krizek@nic.cz>
Tue, 8 Dec 2020 17:22:20 +0000 (18:22 +0100)
Finally it does not rely on ordering in the answer.
Stringification seemed like an easy hack for tests, let's see how it
works in the long term.

daemon/lua/kres.lua
tests/config/test_utils.lua

index a2cb406138320f091aa133786f96565ba9be683b..3bc2dbf7f16a41738c843ccf45ff556895c2e43b 100644 (file)
@@ -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))
index 5a7f3111b101e358b5f96b6dbcd714553af60fdb..93a937708c65e6e1ae8faab1d24e45908b68f222 100644 (file)
@@ -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, ...)