Skip to content

Commit

Permalink
Migrate cbuilder module and adapt it
Browse files Browse the repository at this point in the history
The original `cbuilder` module (tarantool/test/config-luatest/cbuilder.lua)
has been moved to the current project with minor changes and will be
available as follows:

    local t = require('luatest')
    t.cbuilder:new(...)

The helper requires Tarantool 3.0.0 and newer. Otherwise `Builder:new()`
will cause an error.

Also added tests for Tarantool versions 2.11 and 3.0 in GitHub workflow.

Closes #366
  • Loading branch information
Oleg Chaplashkin committed May 14, 2024
1 parent ae8e3d2 commit 6e2e70a
Show file tree
Hide file tree
Showing 6 changed files with 493 additions and 2 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/test_on_push.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ jobs:
github.event_name == 'pull_request' && github.event.pull_request.head.repo.owner.login != 'tarantool'
strategy:
matrix:
tarantool: ["1.10", "2.6", "2.7", "2.8", "2.10"]
tarantool: ["1.10", "2.6", "2.7", "2.8", "2.10", "2.11", "3.0"]
fail-fast: false
runs-on: [ubuntu-20.04]
steps:
- uses: actions/checkout@master
- uses: tarantool/setup-tarantool@v1
- uses: tarantool/setup-tarantool@v3
with:
tarantool-version: '${{ matrix.tarantool }}'

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Add more logs (gh-326).
- Add `justrun` helper as a tarantool runner and output catcher (gh-365).
- Changed error message for too long Unix domain socket paths (gh-341).
- Add `cbuilder` helper as a declarative configuration builder (gh-366).

## 1.0.1

Expand Down
1 change: 1 addition & 0 deletions config.ld
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ file = {
'luatest/server.lua',
'luatest/replica_set.lua',
'luatest/justrun.lua',
'luatest/cbuilder.lua'
}
topics = {
'CHANGELOG.md',
Expand Down
231 changes: 231 additions & 0 deletions luatest/cbuilder.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
--- Configuration builder.
--
-- It allows to construct a declarative configuration for a test case using
-- less boilerplace code/options, especially when a replicaset is to be
-- tested, not a single instance. All the methods supports chaining (returns
-- the builder object back).
--
-- @usage
--
-- local config = Builder:new()
-- :add_instance('instance-001', {
-- database = {
-- mode = 'rw',
-- },
-- })
-- :add_instance('instance-002', {})
-- :add_instance('instance-003', {})
-- :config()
--
-- By default, all instances are added to replicaset-001 in group-001,
-- but it's possible to select a different replicaset and/or group:
--
-- local config = Builder:new()
-- :use_group('group-001')
-- :use_replicaset('replicaset-001')
-- :add_instance(<...>)
-- :add_instance(<...>)
-- :add_instance(<...>)
--
-- :use_group('group-002')
-- :use_replicaset('replicaset-002')
-- :add_instance(<...>)
-- :add_instance(<...>)
-- :add_instance(<...>)
--
-- :config()
--
-- The default credentials and iproto options are added to
-- setup replication and to allow a test to connect to the
-- instances.
--
-- There is a few other methods:
--
-- * :set_replicaset_option('foo.bar', value)
-- * :set_instance_option('instance-001', 'foo.bar', value)
--
-- @classmod luatest.cbuilder

local checks = require('checks')
local fun = require('fun')

local Builder = require('luatest.class').new()

-- Do a post-reqiure of the `internal.config.cluster_config`,
-- since it is available from version 3.0.0+. Otherwise we
-- will get an error when initializing the module in `luatest.init`.
local cluster_config = {}

local base_config = {
credentials = {
users = {
replicator = {
password = 'secret',
roles = {'replication'},
},
client = {
password = 'secret',
roles = {'super'},
},
},
},
iproto = {
listen = {{
uri = 'unix/:./{{ instance_name }}.iproto'
}},
advertise = {
peer = {
login = 'replicator',
}
},
},
replication = {
-- The default value is 1 second. It is good for a real
-- usage, but often suboptimal for testing purposes.
--
-- If an instance can't connect to another instance (say,
-- because it is not started yet), it retries the attempt
-- after so called 'replication interval', which is equal
-- to replication timeout.
--
-- One second waiting means one more second for a test
-- case and, if there are many test cases with a
-- replicaset construction, it affects the test timing a
-- lot.
--
-- replication.timeout = 0.1 second reduces the timing
-- by half for my test.
timeout = 0.1,
},
}

function Builder:inherit(object)
setmetatable(object, self)
self.__index = self
return object
end

function Builder:new(config)
cluster_config = require('internal.config.cluster_config')

config = table.deepcopy(config or base_config)
self._config = config
self._group = 'group-001'
self._replicaset = 'replicaset-001'
return self
end

--- Select a group for following calls.
--
-- @string group_name Group of test.
function Builder:use_group(group_name)
checks('table', 'string')
self._group = group_name
return self
end

--- Select a replicaset for following calls.
--
-- @string replicaset_name Replica set name.
function Builder:use_replicaset(replicaset_name)
checks('table', 'string')
self._replicaset = replicaset_name
return self
end

--- Set option to the cluster config.
--
-- @string path Option path.
-- @param value Option value (int, string, table).
function Builder:set_global_option(path, value)
checks('table', 'string', '?')
cluster_config:set(self._config, path, value)
return self
end

--- Set an option for the selected group.
--
-- @string path Option path.
-- @param value Option value (int, string, table).
function Builder:set_group_option(path, value)
checks('table', 'string', '?')
path = fun.chain({
'groups', self._group,
}, path:split('.')):totable()

cluster_config:set(self._config, path, value)
return self
end

--- Set an option for the selected replicaset.
--
-- @string path Option path.
-- @param value Option value (int, string, table).
function Builder:set_replicaset_option(path, value)
checks('table', 'string', '?')
path = fun.chain({
'groups', self._group,
'replicasets', self._replicaset,
}, path:split('.')):totable()

-- <schema object>:set() validation is too tight. Workaround
-- it. Maybe we should reconsider this :set() behavior in a
-- future.
if value == nil then
local cur = self._config
for i = 1, #path - 1 do
-- Create missed fields.
local component = path[i]
if cur[component] == nil then
cur[component] = {}
end

cur = cur[component]
end
cur[path[#path]] = value
return self
end

cluster_config:set(self._config, path, value)
return self
end

-- Set an option of a particular instance in the selected replicaset.
--
-- @string instance_name Instance where the option will be saved.
-- @string path Option path.
-- @param value Option value (int, string, table).
function Builder:set_instance_option(instance_name, path, value)
checks('table', 'string', 'string', '?')
path = fun.chain({
'groups', self._group,
'replicasets', self._replicaset,
'instances', instance_name,
}, path:split('.')):totable()

cluster_config:set(self._config, path, value)
return self
end

--- Add an instance with the given options to the selected replicaset.
--
-- @string instance_name Instance where the config will be saved.
-- @tab iconfig Declarative config for the instance.
function Builder:add_instance(instance_name, iconfig)
checks('table', 'string', '?')
local path = {
'groups', self._group,
'replicasets', self._replicaset,
'instances', instance_name,
}
cluster_config:set(self._config, path, iconfig)
return self
end

--- Return the resulting configuration.
--
function Builder:config()
return self._config
end

return Builder
5 changes: 5 additions & 0 deletions luatest/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ luatest.log = require('luatest.log')
-- @see luatest.justrun
luatest.justrun = require('luatest.justrun')

--- Declarative configuration builder helper.
--
-- @see luatest.cbuilder
luatest.cbuilder = require('luatest.cbuilder')

--- Add before suite hook.
--
-- @function before_suite
Expand Down
Loading

0 comments on commit 6e2e70a

Please sign in to comment.