lsyncd/tests/testlib.lua

614 lines
10 KiB
Lua
Raw Normal View History

2010-11-18 13:27:55 +00:00
-- common testing environment
2016-12-06 12:19:35 +00:00
posix = require( 'posix' )
string = require( 'string' )
path = require( 'pl.path' )
stringx = require( 'pl.stringx' )
2021-12-09 12:50:15 +00:00
local sys_stat = require "posix.sys.stat"
2010-11-18 13:27:55 +00:00
-- escape codes to colorize output on terminal
local c1='\027[47;34m'
2016-12-21 13:21:32 +00:00
local c0='\027[0m'
2010-11-18 13:27:55 +00:00
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Writes colorized.
2010-11-18 13:27:55 +00:00
--
2016-12-21 13:21:32 +00:00
function cwriteln
(...)
2016-12-06 12:19:35 +00:00
io.write( c1, '++ ', ... )
io.write( c0, '\n' )
2010-11-18 13:27:55 +00:00
end
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Initializes the pseudo random generator
--
-- If environment variable 'SEED' is set,
-- that one is used seed.
--
2016-12-06 12:19:35 +00:00
local seed = os.getenv( 'SEED') or os.time( )
math.randomseed( seed )
cwriteln( 'random seed: ', seed )
2010-11-24 20:34:56 +00:00
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Creates a tmp directory.
--
2016-12-21 13:21:32 +00:00
-- Returns the name of the directory.
2010-11-24 19:45:18 +00:00
--
2016-12-21 13:21:32 +00:00
function mktempd
( )
2016-12-06 12:19:35 +00:00
local f = io.popen( 'mktemp -td ltest.XXX', 'r' )
local s = f:read( '*a' )
f:close( )
2016-12-06 12:19:35 +00:00
s = s:gsub( '[\n\r]+', ' ' )
2016-12-06 12:19:35 +00:00
s = s:match( '^%s*(.-)%s*$' )
2010-11-18 13:27:55 +00:00
return s
end
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Creates a tmp directory with the
-- typical lsyncd test architecture.
--
2016-12-21 13:21:32 +00:00
-- returns path of tmpdir
-- path of srcdir
-- path of trgdir
--
2016-12-21 13:21:32 +00:00
function mktemps
( )
2016-12-06 12:19:35 +00:00
local tdir = mktempd() .. '/'
cwriteln( 'using ', tdir, ' as test root' )
local srcdir = tdir..'src/'
local trgdir = tdir..'trg/'
2016-12-06 12:19:35 +00:00
posix.mkdir( srcdir )
posix.mkdir( trgdir )
return tdir, srcdir, trgdir
end
2016-12-06 12:19:35 +00:00
--
-- Writes a file with 'text' in it
-- and adds a newline.
--
2016-12-21 13:21:32 +00:00
function writefile
(
filename,
text
)
2016-12-06 12:19:35 +00:00
local f = io.open( filename, 'w' )
if not f
then
cwriteln( 'Cannot open "'..filename..'" for writing.' )
return false
end
2016-12-06 12:19:35 +00:00
f:write( text )
f:write( '\n' )
f:close( )
return true
end
function script_path()
-- local str = debug.getinfo(2, "S").source:sub(2)
-- return str:match("(.*/)")
return path.dirname(path.abspath(debug.getinfo(1).short_src))
2021-12-09 12:50:15 +00:00
end
function which(exec)
local path = os.getenv("PATH")
for match in (path..':'):gmatch("(.-)"..':') do
local fname = match..'/'..exec
local s = sys_stat.stat(fname)
if s ~= nil then
return fname
end
end
end
--
-- Starts test ssh server
--
function startSshd()
-- local f = io.open(script_path() .. "ssh/sshd.pid", 'r')
-- if f
-- then
-- return false
-- end
cwriteln(arg[0])
cwriteln(script_path() .. "ssh/sshd_config")
local sshdPath = script_path() .. "/ssh/"
2021-12-08 17:26:11 +00:00
if posix.stat( sshdPath ) == nil then
cwriteln("setup ssh server in " .. sshdPath)
posix.mkdir(sshdPath)
os.execute("ssh-keygen -t rsa -N '' -f" .. sshdPath .. "id_rsa")
os.execute("cp ".. sshdPath .. "id_rsa.pub ".. sshdPath .. "authorized_keys")
os.execute("ssh-keygen -t rsa -N '' -f ".. sshdPath .. "ssh_host_rsa_key")
cwriteln("done")
end
local f = io.open( sshdPath .. "sshd_config", 'w')
f:write([[
Port 2468
HostKey ]] .. sshdPath .. [[ssh_host_rsa_key
AuthorizedKeysFile ]] .. sshdPath .. [[authorized_keys
ChallengeResponseAuthentication no
UsePAM no
#Subsystem sftp /usr/lib/ssh/sftp-server
PidFile ]] .. sshdPath .. [[sshd.pid
]])
f:close( )
2021-12-09 12:50:15 +00:00
--local which = io.popen("which sshd")
exePath = which('sshd')
cwriteln("Using sshd: "..exePath)
local pid = spawn(exePath, "-f", sshdPath .. "sshd_config")
cwriteln( 'spawned sshd server: ' .. pid)
return true
end
--
-- Stop test ssh server
--
function stopSshd()
local f = io.open(script_path() .. "/ssh/sshd.pid", 'r')
if not f
then
return false
end
pid = stringx.strip(f:read("*a"))
posix.kill(tonumber(pid))
end
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Spawns a subprocess.
2010-11-18 13:27:55 +00:00
--
2016-12-21 13:21:32 +00:00
-- Returns the processes pid.
2010-11-18 16:33:48 +00:00
--
function spawn(...)
2016-12-06 12:19:35 +00:00
args = { ... }
cwriteln( 'spawning: ', table.concat( args, ' ' ) )
local pid = posix.fork( )
if pid < 0
then
cwriteln( 'Error, failed fork!' )
os.exit( -1 )
2010-11-18 13:27:55 +00:00
end
2016-12-06 12:19:35 +00:00
if pid == 0
then
posix.exec( ... )
2010-11-18 13:27:55 +00:00
-- should not return
2016-12-06 12:19:35 +00:00
cwriteln( 'Error, failed to spawn: ', ... )
os.exit( -1 )
2010-11-18 13:27:55 +00:00
end
2016-12-06 12:19:35 +00:00
2010-11-18 13:27:55 +00:00
return pid
end
2016-12-06 12:19:35 +00:00
--
2010-11-24 19:45:18 +00:00
-- Makes a lot of random data
--
--
2016-12-21 13:21:32 +00:00
function churn
(
rootdir, -- the directory to make data in
n, -- roughly how much data action will be done
init -- if true init random data only, no sleeps or moves
)
2010-11-24 19:45:18 +00:00
-- all dirs created, indexed by integer and path
2016-12-06 12:19:35 +00:00
root = { name = '' }
alldirs = { root }
dirsWithFileI = { }
dirsWithFileD = { }
--
2010-11-24 19:45:18 +00:00
-- returns the name of a directory
--
-- name is internal recursive paramter, keep it nil.
--
2016-12-21 13:21:32 +00:00
local function dirname
(
dir,
name
)
name = name or ''
2016-12-06 12:19:35 +00:00
if not dir
then
2010-11-24 19:45:18 +00:00
return name
end
2016-12-06 12:19:35 +00:00
return dirname( dir.parent, dir.name .. '/' .. name )
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
--
2010-11-24 19:45:18 +00:00
-- Picks a random dir.
--
2016-12-21 13:21:32 +00:00
local function pickDir
(
notRoot
)
2016-12-06 12:19:35 +00:00
if notRoot
then
if #alldirs <= 2
then
2010-11-24 19:45:18 +00:00
return nil
end
2016-12-06 12:19:35 +00:00
return alldirs[ math.random( 2, #alldirs ) ]
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
return alldirs[ math.random( #alldirs ) ]
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
--
2010-11-24 19:45:18 +00:00
-- Picks a random file.
--
-- Returns 3 values:
2010-11-24 19:45:18 +00:00
-- * the directory
-- * the filename
-- * number of files in directory
--
2016-12-21 13:21:32 +00:00
local function pickFile
( )
2010-11-24 19:45:18 +00:00
-- picks the random directory
2016-12-06 12:19:35 +00:00
if #dirsWithFileI < 1
then
2010-11-24 19:45:18 +00:00
return
end
2016-12-06 12:19:35 +00:00
local rdir = dirsWithFileI[ math.random( 1, #dirsWithFileI ) ]
if not rdir
then
2010-11-24 19:45:18 +00:00
return
end
-- counts the files in there
local c = 0
2016-12-06 12:19:35 +00:00
for name, _ in pairs(rdir)
do
if #name == 2
then
2010-11-24 19:45:18 +00:00
c = c + 1
end
end
-- picks one file at random
2016-12-06 12:19:35 +00:00
local cr = math.random( 1, c )
local fn
2016-12-06 12:19:35 +00:00
for name, _ in pairs( rdir )
do
if #name == 2
then
2010-11-24 19:45:18 +00:00
-- filenames are 2 chars wide.
cr = cr - 1
2016-12-06 12:19:35 +00:00
if cr == 0
then
2010-11-24 19:45:18 +00:00
fn = name
break
end
end
end
2016-12-06 12:19:35 +00:00
2010-11-24 19:45:18 +00:00
return rdir, fn, c
end
2016-12-06 12:19:35 +00:00
--
2010-11-24 19:45:18 +00:00
-- Removes a reference to a file
--
2016-12-06 12:19:35 +00:00
-- @param dir -- directory reference
-- @param fn -- filename
-- @param c -- number of files in dir
2010-11-24 19:45:18 +00:00
--
2016-12-21 13:21:32 +00:00
local function rmFileReference
( dir, fn, c )
2010-11-24 19:45:18 +00:00
dir[fn] = nil
2016-12-06 12:19:35 +00:00
if c == 1
then
2010-11-24 19:45:18 +00:00
-- if last file from origin dir, it has no files anymore
2016-12-06 12:19:35 +00:00
for i, v in ipairs( dirsWithFileI )
do
if v == dir
then
table.remove( dirsWithFileI, i )
2010-11-24 19:45:18 +00:00
break
end
end
2016-12-06 12:19:35 +00:00
dirsWithFileD[ dir ] = nil
2010-11-24 19:45:18 +00:00
end
end
2016-12-06 12:19:35 +00:00
--
-- possible randomized behaviour.
2010-11-24 19:45:18 +00:00
-- just gives it a pause
--
2016-12-21 13:21:32 +00:00
local function sleep
( )
2016-12-06 12:19:35 +00:00
cwriteln( '..zzz..' )
posix.sleep( 1 )
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
--
-- possible randomized behaviour.
2010-11-24 19:45:18 +00:00
-- creates a directory
--
2016-12-21 13:21:32 +00:00
local function mkdir
( )
2010-11-24 19:45:18 +00:00
-- chooses a random directory to create it into
2016-12-06 12:19:35 +00:00
local rdir = pickDir( )
2010-11-24 19:45:18 +00:00
-- creates a new random one letter name
2016-12-06 12:19:35 +00:00
local nn = string.char( 96 + math.random( 26 ) )
if not rdir[nn]
then
2010-11-24 19:45:18 +00:00
local ndir = {
name = nn,
parent = rdir,
2010-11-24 19:45:18 +00:00
}
2016-12-06 12:19:35 +00:00
local dn = dirname( ndir )
rdir[ nn ] = dn
table.insert( alldirs, ndir )
cwriteln( 'mkdir '..rootdir..dn )
posix.mkdir( rootdir..dn )
2010-11-24 19:45:18 +00:00
end
end
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Possible randomized behaviour:
-- Creates a file.
2010-11-24 19:45:18 +00:00
--
2016-12-21 13:21:32 +00:00
local function mkfile
( )
2010-11-24 19:45:18 +00:00
-- chooses a random directory to create it into
local rdir = pickDir()
2016-12-06 12:19:35 +00:00
2010-11-24 19:45:18 +00:00
-- creates a new random one letter name
2016-12-06 12:19:35 +00:00
local nn = 'f'..string.char( 96 + math.random( 26 ) )
local fn = dirname( rdir ) .. nn
cwriteln( 'mkfile ' .. rootdir .. fn )
local f = io.open(rootdir..fn, 'w')
2016-12-06 12:19:35 +00:00
if f
then
for i = 1, 10
do
f:write( string.char( 96 + math.random( 26 ) ) )
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
f:write( '\n' )
f:close( )
rdir[ nn ]=true
if not dirsWithFileD[ rdir ]
then
table.insert( dirsWithFileI, rdir )
dirsWithFileD[ rdir ]=true
2010-11-24 19:45:18 +00:00
end
end
end
--
2016-12-06 12:19:35 +00:00
-- Possible randomized behaviour:
-- Moves a directory.
--
2016-12-21 13:21:32 +00:00
local function mvdir
( )
2016-12-06 12:19:35 +00:00
if #alldirs <= 2
then
2010-11-24 19:45:18 +00:00
return
end
2016-12-06 12:19:35 +00:00
-- chooses a random directory to move
2016-12-06 12:19:35 +00:00
local odir = pickDir( true )
2010-11-24 19:45:18 +00:00
-- chooses a random directory to move to
2016-12-06 12:19:35 +00:00
local tdir = pickDir( )
2010-11-24 19:45:18 +00:00
-- makes sure tdir is not a subdir of odir
local dd = tdir
2016-12-06 12:19:35 +00:00
while dd
do
if odir == dd
then
2010-11-24 19:45:18 +00:00
return
end
2016-12-06 12:19:35 +00:00
2010-11-24 19:45:18 +00:00
dd = dd.parent
end
2016-12-06 12:19:35 +00:00
2010-11-24 19:45:18 +00:00
-- origin name in the target dir already
2016-12-06 12:19:35 +00:00
if tdir[odir.name] ~= nil
then
2010-11-24 19:45:18 +00:00
return
end
2016-12-06 12:19:35 +00:00
local on = dirname( odir )
local tn = dirname( tdir )
cwriteln( 'mvdir ', rootdir,on, ' -> ', rootdir, tn, odir.name )
os.rename( rootdir..on, rootdir..tn..odir.name )
odir.parent[ odir.name ] = nil
2010-11-24 19:45:18 +00:00
odir.parent = tdir
2016-12-06 12:19:35 +00:00
tdir[ odir.name ] = odir
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
--
-- possible randomized behaviour,
-- moves a file.
2010-11-24 19:45:18 +00:00
--
2016-12-21 13:21:32 +00:00
local function mvfile
( )
2016-12-06 12:19:35 +00:00
local odir, fn, c = pickFile( )
2016-12-06 12:19:35 +00:00
if not odir
then
2010-11-24 19:45:18 +00:00
return
end
2016-12-06 12:19:35 +00:00
2010-11-24 19:45:18 +00:00
-- picks a directory with a file at random
-- picks a target directory at random
2016-12-06 12:19:35 +00:00
local tdir = pickDir( )
local on = dirname( odir )
local tn = dirname( tdir )
cwriteln( 'mvfile ', rootdir, on, fn, ' -> ', rootdir, tn, fn )
os.rename( rootdir..on..fn, rootdir..tn..fn )
rmFileReference( odir, fn, c )
tdir[ fn ] = true
if not dirsWithFileD[ tdir ]
then
dirsWithFileD[ tdir ] = true
table.insert( dirsWithFileI, tdir )
2010-11-24 19:45:18 +00:00
end
end
2016-12-06 12:19:35 +00:00
--
2016-12-21 13:21:32 +00:00
-- Possible randomized behaviour:
-- Removes a file.
2010-11-24 19:45:18 +00:00
--
2016-12-21 13:21:32 +00:00
local function rmfile
( )
2016-12-06 12:19:35 +00:00
local dir, fn, c = pickFile( )
if dir
then
local dn = dirname( dir )
cwriteln( 'rmfile ', rootdir, dn, fn )
posix.unlink( rootdir..dn..fn )
rmFileReference( dir, fn, c )
2010-11-24 19:45:18 +00:00
end
end
2016-12-21 13:21:32 +00:00
local dice
2016-12-21 13:21:32 +00:00
if init
then
dice =
{
{ 10, mkfile },
{ 10, mkdir },
}
else
dice =
{
{ 50, sleep },
2016-12-21 13:21:32 +00:00
{ 20, mkfile },
{ 20, mkdir },
{ 20, mvdir },
{ 20, rmfile },
}
end
2010-11-24 19:45:18 +00:00
2016-12-06 12:19:35 +00:00
cwriteln( 'making random data' )
2010-11-24 19:45:18 +00:00
local ndice = 0
2016-12-06 12:19:35 +00:00
for i, d in ipairs( dice )
do
ndice = ndice + d[ 1 ]
d[ 1 ] = ndice
2010-11-24 19:45:18 +00:00
end
2016-12-06 12:19:35 +00:00
for ai = 1, n
do
-- throws a die what to do
2016-12-06 12:19:35 +00:00
local acn = math.random( ndice )
for i, d in ipairs( dice )
do
if acn <= d[ 1 ]
then
d[ 2 ]( )
2010-11-24 19:45:18 +00:00
break
end
end
end
end
2021-12-08 17:21:16 +00:00
-- check if tables are equal
function isTableEqual(o1, o2, ignore_mt)
if o1 == o2 then return true end
local o1Type = type(o1)
local o2Type = type(o2)
if o1Type ~= o2Type then return false end
if o1Type ~= 'table' then return false end
if not ignore_mt then
local mt1 = getmetatable(o1)
if mt1 and mt1.__eq then
--compare using built in method
return o1 == o2
end
end
local keySet = {}
for key1, value1 in pairs(o1) do
local value2 = o2[key1]
if value2 == nil or isTableEqual(value1, value2, ignore_mt) == false then
return false
end
keySet[key1] = true
end
for key2, _ in pairs(o2) do
if not keySet[key2] then return false end
end
return true
end
2010-11-24 19:45:18 +00:00