Skip to content

Commit a3a33bd

Browse files
committed
Allow running test groups independently
We need to be able to run only a few test groups, even if we do not have all database backends installed and configured locally. ejabberd test suite configures a specific host per backend. I changed ejabberd to allow ignoring some hosts from config file on start, by providing the exact list of hosts we want to start. This is done by setting an ejabberd app Erlang environment variable 'hosts' and passing the list of hosts we want to actually define. When doing so, the backend specific hosts defined in ejabberd test configuration file are simply ignored. As a result, we do not try to connect to unavailable backends. I linked that part to CT run test by defining the hosts list based on environment variable CT_BACKENDS. This variable is expected to be a comma separated list of available backends. When Erlang Common Tests are run with that environment variable set, only the host matching the name of the backend will be set, plus the default "localhost", common to many tests. This can be combined with rebar ct groups list. Example commands to run tests: CT_BACKENDS=riak,mnesia rebar ct suites=ejabberd CT_BACKENDS=mnesia rebar ct suites=ejabberd groups=mnesia
1 parent 7066338 commit a3a33bd

3 files changed

Lines changed: 113 additions & 35 deletions

File tree

src/ejabberd_config.erl

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@
3838
convert_to_yaml/1, convert_to_yaml/2,
3939
env_binary_to_list/2, opt_type/1, may_hide_data/1]).
4040

41+
-export([start/2]).
42+
4143
-include("ejabberd.hrl").
4244
-include("logger.hrl").
4345
-include("ejabberd_config.hrl").
@@ -52,22 +54,12 @@
5254

5355
%% @type macro_value() = term().
5456

55-
5657
start() ->
57-
case catch mnesia:table_info(local_config, storage_type) of
58-
disc_copies ->
59-
mnesia:delete_table(local_config);
60-
_ ->
61-
ok
62-
end,
63-
mnesia:create_table(local_config,
64-
[{ram_copies, [node()]},
65-
{local_content, true},
66-
{attributes, record_info(fields, local_config)}]),
67-
mnesia:add_table_copy(local_config, node(), ram_copies),
58+
mnesia_init(),
6859
Config = get_ejabberd_config_path(),
6960
State0 = read_file(Config),
70-
State = validate_opts(State0),
61+
State1 = hosts_to_start(State0),
62+
State2 = validate_opts(State1),
7163
%% This start time is used by mod_last:
7264
UnixTime = p1_time_compat:system_time(seconds),
7365
SharedKey = case erlang:get_cookie() of
@@ -76,9 +68,45 @@ start() ->
7668
Cookie ->
7769
p1_sha:sha(jlib:atom_to_binary(Cookie))
7870
end,
79-
State1 = set_option({node_start, global}, UnixTime, State),
80-
State2 = set_option({shared_key, global}, SharedKey, State1),
81-
set_opts(State2).
71+
State3 = set_option({node_start, global}, UnixTime, State2),
72+
State4 = set_option({shared_key, global}, SharedKey, State3),
73+
set_opts(State4).
74+
75+
%% When starting ejabberd for testing, we sometimes want to start a
76+
%% subset of hosts from the one define in the config file.
77+
%% This function override the host list read from config file by the
78+
%% one we provide.
79+
%% Hosts to start are defined in an ejabberd application environment
80+
%% variable 'hosts' to make it easy to ignore some host in config
81+
%% file.
82+
hosts_to_start(State) ->
83+
case application:get_env(ejabberd, hosts) of
84+
undefined ->
85+
%% Start all hosts as defined in config file
86+
State;
87+
{ok, Hosts} ->
88+
set_hosts_in_options(Hosts, State)
89+
end.
90+
91+
%% @private
92+
%% At the moment, these functions are mainly used to setup unit tests.
93+
-spec(start/2 :: (Hosts :: [binary()], Opts :: [acl:acl() | local_config()]) -> ok).
94+
start(Hosts, Opts) ->
95+
mnesia_init(),
96+
set_opts(#state{hosts = Hosts, opts = Opts}).
97+
98+
mnesia_init() ->
99+
case catch mnesia:table_info(local_config, storage_type) of
100+
disc_copies ->
101+
mnesia:delete_table(local_config);
102+
_ ->
103+
ok
104+
end,
105+
mnesia:create_table(local_config,
106+
[{ram_copies, [node()]},
107+
{local_content, true},
108+
{attributes, record_info(fields, local_config)}]),
109+
mnesia:add_table_copy(local_config, node(), ram_copies).
82110

83111
%% @doc Get the filename of the ejabberd configuration file.
84112
%% The filename can be specified with: erl -config "/path/to/ejabberd.yml".
@@ -277,7 +305,7 @@ search_hosts(Term, State) ->
277305
{host, Host} ->
278306
if
279307
State#state.hosts == [] ->
280-
add_hosts_to_option([Host], State);
308+
set_hosts_in_options([Host], State);
281309
true ->
282310
?ERROR_MSG("Can't load config file: "
283311
"too many hosts definitions", []),
@@ -286,7 +314,7 @@ search_hosts(Term, State) ->
286314
{hosts, Hosts} ->
287315
if
288316
State#state.hosts == [] ->
289-
add_hosts_to_option(Hosts, State);
317+
set_hosts_in_options(Hosts, State);
290318
true ->
291319
?ERROR_MSG("Can't load config file: "
292320
"too many hosts definitions", []),
@@ -296,9 +324,12 @@ search_hosts(Term, State) ->
296324
State
297325
end.
298326

299-
add_hosts_to_option(Hosts, State) ->
327+
set_hosts_in_options(Hosts, State) ->
300328
PrepHosts = normalize_hosts(Hosts),
301-
set_option({hosts, global}, PrepHosts, State#state{hosts = PrepHosts}).
329+
NewOpts = lists:filter(fun({local_config,{hosts,global},_}) -> false;
330+
(_) -> true
331+
end, State#state.opts),
332+
set_option({hosts, global}, PrepHosts, State#state{hosts = PrepHosts, opts = NewOpts}).
302333

303334
normalize_hosts(Hosts) ->
304335
normalize_hosts(Hosts,[]).

test/ejabberd_SUITE.erl

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,57 @@ init_per_suite(Config) ->
3535
LDIFFile = filename:join([DataDir, "ejabberd.ldif"]),
3636
{ok, _} = file:copy(ExtAuthScript, filename:join([CWD, "extauth.py"])),
3737
{ok, _} = ldap_srv:start(LDIFFile),
38-
ok = application:start(ejabberd),
38+
start_ejabberd(NewConfig),
3939
NewConfig.
4040

41+
start_ejabberd(Config) ->
42+
case proplists:get_value(backends, Config) of
43+
all ->
44+
ok = application:start(ejabberd, transient);
45+
Backends when is_list(Backends) ->
46+
Hosts = lists:map(fun(Backend) -> Backend ++ ".localhost" end, Backends),
47+
application:load(ejabberd),
48+
AllHosts = Hosts ++ ["localhost"], %% We always need localhost for the generic no_db tests
49+
application:set_env(ejabberd, hosts, AllHosts),
50+
ok = application:start(ejabberd, transient)
51+
end.
52+
4153
end_per_suite(_Config) ->
42-
ok.
54+
application:stop(ejabberd).
4355

44-
init_per_group(no_db, Config) ->
56+
-define(BACKENDS, [mnesia,redis,mysql,pgsql,sqlite,ldap,extauth,riak]).
57+
58+
init_per_group(Group, Config) ->
59+
case lists:member(Group, ?BACKENDS) of
60+
false ->
61+
%% Not a backend related group, do default init:
62+
do_init_per_group(Group, Config);
63+
true ->
64+
case proplists:get_value(backends, Config) of
65+
all ->
66+
%% All backends enabled
67+
do_init_per_group(Group, Config);
68+
Backends ->
69+
%% Skipped backends that were not explicitely enabled
70+
case lists:member(atom_to_list(Group), Backends) of
71+
true ->
72+
do_init_per_group(Group, Config);
73+
false ->
74+
{skip, {disabled_backend, Group}}
75+
end
76+
end
77+
end.
78+
79+
do_init_per_group(no_db, Config) ->
4580
re_register(Config),
4681
Config;
47-
init_per_group(mnesia, Config) ->
82+
do_init_per_group(mnesia, Config) ->
4883
mod_muc:shutdown_rooms(?MNESIA_VHOST),
4984
set_opt(server, ?MNESIA_VHOST, Config);
50-
init_per_group(redis, Config) ->
85+
do_init_per_group(redis, Config) ->
5186
mod_muc:shutdown_rooms(?REDIS_VHOST),
5287
set_opt(server, ?REDIS_VHOST, Config);
53-
init_per_group(mysql, Config) ->
88+
do_init_per_group(mysql, Config) ->
5489
case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of
5590
{selected, _, _} ->
5691
mod_muc:shutdown_rooms(?MYSQL_VHOST),
@@ -59,7 +94,7 @@ init_per_group(mysql, Config) ->
5994
Err ->
6095
{skip, {mysql_not_available, Err}}
6196
end;
62-
init_per_group(pgsql, Config) ->
97+
do_init_per_group(pgsql, Config) ->
6398
case catch ejabberd_odbc:sql_query(?PGSQL_VHOST, [<<"select 1;">>]) of
6499
{selected, _, _} ->
65100
mod_muc:shutdown_rooms(?PGSQL_VHOST),
@@ -68,19 +103,19 @@ init_per_group(pgsql, Config) ->
68103
Err ->
69104
{skip, {pgsql_not_available, Err}}
70105
end;
71-
init_per_group(sqlite, Config) ->
106+
do_init_per_group(sqlite, Config) ->
72107
case catch ejabberd_odbc:sql_query(?SQLITE_VHOST, [<<"select 1;">>]) of
73108
{selected, _, _} ->
74109
mod_muc:shutdown_rooms(?SQLITE_VHOST),
75110
set_opt(server, ?SQLITE_VHOST, Config);
76111
Err ->
77112
{skip, {sqlite_not_available, Err}}
78113
end;
79-
init_per_group(ldap, Config) ->
114+
do_init_per_group(ldap, Config) ->
80115
set_opt(server, ?LDAP_VHOST, Config);
81-
init_per_group(extauth, Config) ->
116+
do_init_per_group(extauth, Config) ->
82117
set_opt(server, ?EXTAUTH_VHOST, Config);
83-
init_per_group(riak, Config) ->
118+
do_init_per_group(riak, Config) ->
84119
case ejabberd_riak:is_connected() of
85120
true ->
86121
mod_muc:shutdown_rooms(?RIAK_VHOST),
@@ -89,7 +124,7 @@ init_per_group(riak, Config) ->
89124
Err ->
90125
{skip, {riak_not_available, Err}}
91126
end;
92-
init_per_group(_GroupName, Config) ->
127+
do_init_per_group(_GroupName, Config) ->
93128
Pid = start_event_relay(),
94129
set_opt(event_relay, Pid, Config).
95130

@@ -967,9 +1002,9 @@ mix_master(Config) ->
9671002
retract = [ParticipantID]}]}]}),
9681003
disconnect(Config).
9691004

970-
mix_slave(Config) ->
1005+
mix_slave(Config) ->
9711006
disconnect(Config).
972-
1007+
9731008
roster_subscribe_master(Config) ->
9741009
send(Config, #presence{}),
9751010
?recv1(#presence{}),

test/suite.erl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,21 @@ init_config(Config) ->
6565
{resource, <<"resource">>},
6666
{master_resource, <<"master_resource">>},
6767
{slave_resource, <<"slave_resource">>},
68-
{password, <<"password">>}
68+
{password, <<"password">>},
69+
{backends, get_config_backends()}
6970
|Config].
7071

72+
%% Read environment variable CT_DB=riak,mysql to limit the backends to test.
73+
%% You can thus limit the backend you want to test with:
74+
%% CT_BACKENDS=riak,mysql rebar ct suites=ejabberd
75+
get_config_backends() ->
76+
case os:getenv("CT_BACKENDS") of
77+
false -> all;
78+
String ->
79+
Backends0 = string:tokens(String, ","),
80+
lists:map(fun(Backend) -> string:strip(Backend, both, $ ) end, Backends0)
81+
end.
82+
7183
process_config_tpl(Content, []) ->
7284
Content;
7385
process_config_tpl(Content, [{Name, DefaultValue} | Rest]) ->

0 commit comments

Comments
 (0)