-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The original `treegen` module (path: tarantool/test/treegen.lua) has been moved to the current project with the following changes: - refactoring the public functions variables; - updated documentation. Part of #364
- Loading branch information
Oleg Chaplashkin
committed
Apr 17, 2024
1 parent
d985997
commit bc05810
Showing
3 changed files
with
202 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
-- Working tree generator. | ||
-- | ||
-- Generates a tree of Lua files using provided templates and | ||
-- filenames. | ||
-- | ||
-- Basic usage: | ||
-- | ||
-- | local t = require('luatest') | ||
-- | local treegen = require('test.treegen') | ||
-- | | ||
-- | local g = t.group() | ||
-- | | ||
-- | local SCRIPT_TEMPLATE = [[ | ||
-- | <...> | ||
-- | ]] | ||
-- | | ||
-- | g.before_all(function(g) | ||
-- | treegen.init(g) | ||
-- | treegen.add_template(g, '^.*$', SCRIPT_TEMPLATE) | ||
-- | end) | ||
-- | | ||
-- | g.after_all(function(g) | ||
-- | treegen.clean(g) | ||
-- | end) | ||
-- | | ||
-- | g.foobar_test = function(g) | ||
-- | local dir = treegen.prepare_directory(g, | ||
-- | {'foo/bar.lua', 'main.lua'}) | ||
-- | <..test case..> | ||
-- | end | ||
|
||
local fio = require('fio') | ||
local fun = require('fun') | ||
|
||
local log = require('luatest.log') | ||
|
||
local treegen = {} | ||
|
||
local function find_template(group, script) | ||
for _, template_def in ipairs(group.templates) do | ||
if script:match(template_def.pattern) then | ||
return template_def.template | ||
end | ||
end | ||
error(("treegen: can't find a template for script %q"):format(script)) | ||
end | ||
|
||
-- Write provided script into the given directory. | ||
-- | ||
-- @string directory Directory where the script will be created. | ||
-- @string filename File to write (possible nested path: /foo/bar/main.lua). | ||
-- @string script The body of the script to write. | ||
-- @return string | ||
function treegen.write_script(directory, filename, script) | ||
local script_abspath = fio.pathjoin(directory, filename) | ||
local flags = {'O_CREAT', 'O_WRONLY', 'O_TRUNC'} | ||
local mode = tonumber('644', 8) | ||
|
||
local scriptdir_abspath = fio.dirname(script_abspath) | ||
log.info('Creating a directory: %s', scriptdir_abspath) | ||
fio.mktree(scriptdir_abspath) | ||
|
||
log.info('Writing a script: %s', script_abspath) | ||
local fh = fio.open(script_abspath, flags, mode) | ||
fh:write(script) | ||
fh:close() | ||
return script_abspath | ||
end | ||
|
||
-- Generate a script that follows a template and write it at the | ||
-- given path in the given directory. | ||
-- | ||
-- @table group Group of tests. | ||
-- @string directory Directory where the script will be created. | ||
-- @string filename File to write (possible nested path: /foo/bar/main.lua). | ||
-- @table replacements List of replacement templates. | ||
-- @return string | ||
local function gen_script(group, directory, filename, replacements) | ||
local template = find_template(group, filename) | ||
replacements = fun.chain({filename = filename}, replacements):tomap() | ||
local body = template:gsub('<(.-)>', replacements) | ||
return treegen.write_script(directory, filename, body) | ||
end | ||
|
||
-- Initialize treegen module in the given group of tests. | ||
-- | ||
-- @table group Group of tests. | ||
function treegen.init(group) | ||
group.tempdirs = {} | ||
group.templates = {} | ||
end | ||
|
||
-- Remove all temporary directories created by the test | ||
-- unless KEEP_DATA environment variable is set to a | ||
-- non-empty value. | ||
-- | ||
-- @table group Group of tests. | ||
function treegen.clean(group) | ||
local dirs = table.copy(group.tempdirs) or {} | ||
group.tempdirs = nil | ||
|
||
local keep_data = (os.getenv('KEEP_DATA') or '') ~= '' | ||
|
||
for _, dir in ipairs(dirs) do | ||
if keep_data then | ||
log.info('Left intact due to KEEP_DATA env var: %s', dir) | ||
else | ||
log.info('Recursively removing: %s', dir) | ||
fio.rmtree(dir) | ||
end | ||
end | ||
|
||
group.templates = nil | ||
end | ||
|
||
-- Save the template in the given group of test with the given pattern. | ||
-- | ||
-- @table group Group of tests. | ||
-- @string pattern File name template | ||
-- @string template A content template for creating a file. | ||
function treegen.add_template(group, pattern, template) | ||
table.insert(group.templates, { | ||
pattern = pattern, | ||
template = template, | ||
}) | ||
end | ||
|
||
-- Create a temporary directory with given scripts. | ||
-- | ||
-- The scripts are generated using templates added by | ||
-- treegen.add_template(). | ||
-- | ||
-- Example for {'foo/bar.lua', 'baz.lua'}: | ||
-- | ||
-- / | ||
-- + tmp/ | ||
-- + rfbWOJ/ | ||
-- + foo/ | ||
-- | + bar.lua | ||
-- + baz.lua | ||
-- | ||
-- The return value is '/tmp/rfbWOJ' for this example. | ||
-- | ||
-- @table group Group of tests. | ||
-- @table scripts List of bodies of the script to write. | ||
-- @table replacements List of replacement templates. | ||
-- @return string | ||
function treegen.prepare_directory(group, scripts, replacements) | ||
replacements = replacements or {} | ||
|
||
assert(type(scripts) == 'table') | ||
assert(type(replacements) == 'table') | ||
|
||
local dir = fio.tempdir() | ||
|
||
-- fio.tempdir() follows the TMPDIR environment variable. | ||
-- If it ends with a slash, the return value contains a double | ||
-- slash in the middle: for example, if TMPDIR=/tmp/, the | ||
-- result is like `/tmp//rfbWOJ`. | ||
-- | ||
-- It looks harmless on the first glance, but this directory | ||
-- path may be used later to form an URI for a Unix domain | ||
-- socket. As result the URI looks like | ||
-- `unix/:/tmp//rfbWOJ/instance-001.iproto`. | ||
-- | ||
-- It confuses net_box.connect(): it reports EAI_NONAME error | ||
-- from getaddrinfo(). | ||
-- | ||
-- It seems, the reason is a peculiar of the URI parsing: | ||
-- | ||
-- tarantool> uri.parse('unix/:/foo/bar.iproto') | ||
-- --- | ||
-- - host: unix/ | ||
-- service: /foo/bar.iproto | ||
-- unix: /foo/bar.iproto | ||
-- ... | ||
-- | ||
-- tarantool> uri.parse('unix/:/foo//bar.iproto') | ||
-- --- | ||
-- - host: unix | ||
-- path: /foo//bar.iproto | ||
-- ... | ||
-- | ||
-- Let's normalize the path using fio.abspath(), which | ||
-- eliminates the double slashes. | ||
dir = fio.abspath(dir) | ||
|
||
table.insert(group.tempdirs, dir) | ||
|
||
for _, script in ipairs(scripts) do | ||
gen_script(group, dir, script, replacements) | ||
end | ||
|
||
return dir | ||
end | ||
|
||
return treegen |