c:commit()
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
-end
-
-local function check_answer(desc, qname, qtype, expected_rcode, expected_rdata)
- qtype_str = kres.tostring.type[qtype]
- callback = function(pkt)
- same(pkt:rcode(), expected_rcode,
- desc .. ': expecting answer for query ' .. qname .. ' ' .. qtype_str
- .. ' with rcode ' .. kres.tostring.rcode[expected_rcode])
-
- if expected_rdata then
- rr_text = rrset_to_texts(pkt:rrsets(kres.section.ANSWER)[1])
- ok(rr_text[4] == expected_rdata,
- desc ..': checking rdata of answer for ' .. qname .. ' ' .. qtype_str)
- else
- -- check empty section
- ok(pkt:rrsets(kres.section.ANSWER)[1] == nil,
- desc ..': checking empty answer section for ' .. qname .. ' ' .. qtype_str)
- end
-
- end
-
- resolve(qname, qtype, kres.class.IN, {}, callback)
-end
+local check_answer = require('test_utils').check_answer
local function test_rpz()
check_answer('"CNAME ." return NXDOMAIN',
'nxdomain.', kres.type.A, kres.rcode.NXDOMAIN)
check_answer('"CNAME *." return NODATA',
- 'nodata.', kres.type.A, kres.rcode.NOERROR)
+ 'nodata.', kres.type.A, kres.rcode.NOERROR, {})
check_answer('"CNAME *. on wildcard" return NODATA',
- 'nodata.nxdomain.', kres.type.A, kres.rcode.NOERROR)
+ 'nodata.nxdomain.', kres.type.A, kres.rcode.NOERROR, {})
check_answer('"CNAME rpz-drop." be dropped',
'rpzdrop.', kres.type.A, kres.rcode.SERVFAIL)
check_answer('"CNAME rpz-passthru" return A rrset',
check_answer('"A 192.168.7.7" with suffixed zone name in owner return local A rrset',
'testdomain.rra.', kres.type.A, kres.rcode.NOERROR, '192.168.7.7')
check_answer('non existing AAAA on rra domain return NODATA',
- 'rra.', kres.type.AAAA, kres.rcode.NOERROR)
+ 'rra.', kres.type.AAAA, kres.rcode.NOERROR, {})
check_answer('"A 192.168.8.8" and domain with uppercase and lowercase letters',
'case.sensitive.', kres.type.A, kres.rcode.NOERROR, '192.168.8.8')
check_answer('"A 192.168.8.8" and domain with uppercase and lowercase letters',
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
+end
M.NODATA = -1
-- Resolve a name and check the answer. Do *not* return until finished.
-function M.check_answer(desc, qname, qtype, expected_rcode)
+-- 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 }
+ 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
+ expected_rcode = M.NODATA
+ end
if expected_rcode == M.NODATA then wire_rcode = kres.rcode.NOERROR end
local done = false
ok((pkt:ancount() > 0) == (expected_rcode == kres.rcode.NOERROR),
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
+ end
done = true
end
resolve(qname, qtype, kres.class.IN, {}, callback)