1
0
Fork 0
knot-resolver/tests/config/test_dns_generators.lua
Daniel Baumann fbc604e215
Adding upstream version 5.7.5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
2025-06-21 13:56:17 +02:00

134 lines
3.3 KiB
Lua

-- SPDX-License-Identifier: GPL-3.0-or-later
local ffi = require('ffi')
local kr_cach = kres.context().cache
local charset = {
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-'}
local function gen_bytes(len)
local bytes = {}
for _ = 1,len do
table.insert(bytes, charset[math.random(1, #charset)])
end
local result = table.concat(bytes)
assert(#result == len)
return result
end
local function gen_ttl()
return math.random(0, 2^31-1)
end
local function gen_rrtype()
return math.random(1024, 61000)
end
local function gen_rdata(len)
assert(len >= 1 and len <= 65535)
return gen_bytes(len)
end
local function gen_label(len) -- in bytes including the length byte
assert(len >= 2 and len <= 64)
local bytes = {string.char(len - 1), gen_bytes(len - 1)}
return table.concat(bytes)
end
local function gen_dname()
local target_len -- length 2 bytes does not make sense
while target_len == nil or target_len == 2 do
target_len = math.random(1, 255)
end
local labels = {string.char(0)}
local cur_len = 1
while target_len > cur_len do
local new_len = math.random(
2,
math.min(target_len - cur_len,
64))
if (target_len - cur_len - new_len) == 1 then
-- it is a trap, single-byte label is allowed only at the end
-- we cannot leave room for single-byte label in the next round
if new_len == 64 then
goto continue -- we are at max label length, try again
end
new_len = new_len + 1
end
table.insert(labels, 1, gen_label(new_len))
cur_len = cur_len + new_len
::continue::
end
assert(target_len == cur_len)
local dname = table.concat(labels)
assert(#dname >= 1 and #dname <= 255)
assert(string.byte(dname, #dname) == 0)
return dname
end
local function gen_rrset()
local rrs = {}
local maxsize = 300 -- RR data size in bytes per RR set, does not include owner etc.
local target_len = math.random(1, maxsize)
local cur_len = 0
while target_len > cur_len do
local new_len = math.random(1, target_len - cur_len)
local new_rr = gen_rdata(new_len)
cur_len = cur_len + #new_rr
table.insert(rrs, new_rr)
end
assert(target_len == cur_len)
return rrs, cur_len
end
local function add_random_rrset()
local owner = gen_dname()
local ttl = gen_ttl()
local rr_type = gen_rrtype()
local rdata_set = gen_rrset()
local kr_rrset = kres.rrset(owner, rr_type, kres.class.IN, ttl)
for _, rr in ipairs(rdata_set) do
assert(kr_rrset:add_rdata(rr, #rr))
end
assert(kr_cach:insert(kr_rrset, nil, ffi.C.KR_RANK_SECURE))
end
ffi.cdef('int usleep(uint32_t usec);') -- at least in current glibc it's always 32-bit
local rr_count = 0
local function gen_batch()
for _ = 1,math.random(1,10) do
add_random_rrset()
rr_count = rr_count + 1
if rr_count % 100 == 0 then
print('cache usage ', cache.stats()['usage_percent'], '%')
end
end
kr_cach:commit()
ffi.C.usleep(15) -- stop *whole process* to give better chance to GC executing
local delay
if math.random(1,4) == 1 then
delay = 1 -- give a chance to DNS resolving
else
delay = 0
end
event.after(delay, gen_batch)
end
return {
add_random_rrset=add_random_rrset,
gen_batch=gen_batch,
gen_bytes=gen_bytes,
gen_dname=gen_dname,
gen_label=gen_label,
gen_rdata=gen_rdata,
gen_rrset=gen_rrset,
gen_rrtype=gen_rrtype,
gen_ttl=gen_ttl
}