aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvgeniy Khramtsov <ekhramtsov@process-one.net>2013-06-19 20:11:20 +1000
committerEvgeniy Khramtsov <ekhramtsov@process-one.net>2013-06-19 20:12:15 +1000
commit4f8bb4f9183cc91d23991bd652ff8c9f65f7b182 (patch)
tree94d6903f1e71b592da83053776e8813d24f9d258
parentMerge branch 'master' of github.com:processone/ejabberd (diff)
Add tests for modules using MySQL/PostgreSQL
-rw-r--r--Makefile.in3
-rw-r--r--test/README15
-rw-r--r--test/ejabberd_SUITE.erl186
-rw-r--r--test/ejabberd_SUITE_data/ejabberd.cfg86
4 files changed, 237 insertions, 53 deletions
diff --git a/Makefile.in b/Makefile.in
index a663f9a85..0ae51b612 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -252,6 +252,9 @@ dialyzer: plt
--get_warnings -o dialyzer.log ebin
test:
+ @echo "************************** NOTICE ***************************************"
+ @cat test/README
+ @echo "*************************************************************************"
$(REBAR) skip_deps=true ct
.PHONY: src doc edoc dialyzer Makefile TAGS clean clean-rel distclean rel plt \
diff --git a/test/README b/test/README
new file mode 100644
index 000000000..c82b791bf
--- /dev/null
+++ b/test/README
@@ -0,0 +1,15 @@
+You need MySQL and PostgreSQL up and running.
+Both of them should grant access to user 'ejabberd_test' with
+password 'ejabberd_test' on database 'ejabberd_test'.
+
+Here is a quick setup example:
+
+$ psql template1
+template1=# CREATE USER ejabberd_test WITH PASSWORD 'ejabberd_test';
+template1=# CREATE DATABASE ejabberd_test;
+template1=# GRANT ALL PRIVILEGES ON DATABASE ejabberd_test TO ejabberd_test;
+
+$ mysql
+mysql> CREATE USER ejabberd_test IDENTIFIED BY 'ejabberd_test';
+mysql> CREATE DATABASE ejabberd_test;
+mysql> GRANT ALL ON ejabberd_test.* TO ejabberd_test;
diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl
index baa1e39f2..05c7db275 100644
--- a/test/ejabberd_SUITE.erl
+++ b/test/ejabberd_SUITE.erl
@@ -65,12 +65,19 @@
end
end)()).
+-define(COMMON_VHOST, <<"localhost">>).
+-define(MNESIA_VHOST, <<"mnesia.localhost">>).
+-define(MYSQL_VHOST, <<"mysql.localhost">>).
+-define(PGSQL_VHOST, <<"pgsql.localhost">>).
+
suite() ->
[{timetrap, {seconds,10}}].
init_per_suite(Config) ->
DataDir = proplists:get_value(data_dir, Config),
PrivDir = proplists:get_value(priv_dir, Config),
+ [_, _|Tail] = lists:reverse(filename:split(DataDir)),
+ BaseDir = filename:join(lists:reverse(Tail)),
ConfigPath = filename:join([DataDir, "ejabberd.cfg"]),
LogPath = filename:join([PrivDir, "ejabberd.log"]),
SASLPath = filename:join([PrivDir, "sasl.log"]),
@@ -83,10 +90,12 @@ init_per_suite(Config) ->
application:set_env(sasl, sasl_error_logger, {file, SASLPath}),
application:set_env(mnesia, dir, MnesiaDir),
ok = application:start(ejabberd),
- [{server, <<"localhost">>},
- {port, 5222},
- {host, "localhost"},
+ [{server_port, 5222},
+ {server_host, "localhost"},
+ {server, ?COMMON_VHOST},
+ {user, <<"test_single">>},
{certfile, CertFile},
+ {base_dir, BaseDir},
{resource, <<"resource">>},
{password, <<"password">>}
|Config].
@@ -94,20 +103,47 @@ init_per_suite(Config) ->
end_per_suite(_Config) ->
ok.
+init_per_group(no_db, Config) ->
+ User = ?config(user, Config),
+ Server = ?config(server, Config),
+ Password = ?config(password, Config),
+ {atomic, ok} = ejabberd_auth:try_register(User, Server, Password),
+ Config;
+init_per_group(mnesia, Config) ->
+ set_opt(server, ?MNESIA_VHOST, Config);
+init_per_group(mysql, Config) ->
+ case catch ejabberd_odbc:sql_query(?MYSQL_VHOST, [<<"select 1;">>]) of
+ {selected, _, _} ->
+ create_sql_tables(mysql, ?config(base_dir, Config)),
+ set_opt(server, ?MYSQL_VHOST, Config);
+ Err ->
+ {skip, {mysql_not_available, Err}}
+ end;
+init_per_group(pgsql, Config) ->
+ case catch ejabberd_odbc:sql_query(?PGSQL_VHOST, [<<"select 1;">>]) of
+ {selected, _, _} ->
+ create_sql_tables(pgsql, ?config(base_dir, Config)),
+ set_opt(server, ?PGSQL_VHOST, Config);
+ Err ->
+ {skip, {pgsql_not_available, Err}}
+ end;
init_per_group(_GroupName, Config) ->
Pid = start_event_relay(),
set_opt(event_relay, Pid, Config).
+end_per_group(mnesia, _Config) ->
+ ok;
+end_per_group(mysql, _Config) ->
+ ok;
+end_per_group(pgsql, _Config) ->
+ ok;
+end_per_group(no_db, _Config) ->
+ ok;
end_per_group(_GroupName, Config) ->
stop_event_relay(Config),
ok.
-init_per_testcase(stop_ejabberd, OrigConfig) ->
- User = <<"test_stop">>,
- Config = set_opt(user, User, OrigConfig),
- ejabberd_auth:try_register(User,
- ?config(server, Config),
- ?config(password, Config)),
+init_per_testcase(stop_ejabberd, Config) ->
open_session(bind(auth(connect(Config))));
init_per_testcase(TestCase, OrigConfig) ->
subscribe_to_events(OrigConfig),
@@ -155,49 +191,58 @@ init_per_testcase(TestCase, OrigConfig) ->
end_per_testcase(_TestCase, _Config) ->
ok.
-groups() ->
- [{single_user, [sequence],
+generic_tests() ->
+ [{generic, [sequence],
[test_connect,
test_starttls,
test_zlib,
- test_register,
- auth_plain,
- auth_md5,
test_auth,
test_bind,
test_open_session,
- roster_get,
- presence_broadcast,
+ presence,
ping,
version,
time,
stats,
- disco,
+ disco]},
+ {test_proxy65, [parallel],
+ [proxy65_master, proxy65_slave]}].
+
+tests() ->
+ [{single_user, [sequence],
+ [test_register,
+ auth_plain,
+ auth_md5,
+ presence_broadcast,
last,
+ roster_get,
private,
privacy,
blocking,
vcard,
- pubsub,
muc_single,
+ pubsub,
test_unregister]},
{test_roster_subscribe, [parallel],
[roster_subscribe_master,
roster_subscribe_slave]},
- {test_proxy65, [parallel],
- [proxy65_master, proxy65_slave]},
{test_offline, [sequence],
[offline_master, offline_slave]},
{test_roster_remove, [parallel],
[roster_remove_master,
roster_remove_slave]}].
+groups() ->
+ [{no_db, [sequence], generic_tests()},
+ {mnesia, [sequence], tests()},
+ {mysql, [sequence], tests()},
+ {pgsql, [sequence], tests()}].
+
all() ->
- [{group, single_user},
- {group, test_roster_subscribe},
- {group, test_proxy65},
- {group, test_offline},
- {group, test_roster_remove},
+ [{group, no_db},
+ {group, mnesia},
+ {group, mysql},
+ {group, pgsql},
stop_ejabberd].
stop_ejabberd(Config) ->
@@ -211,8 +256,8 @@ test_connect(Config) ->
connect(Config) ->
{ok, Sock} = ejabberd_socket:connect(
- ?config(host, Config),
- ?config(port, Config),
+ ?config(server_host, Config),
+ ?config(server_port, Config),
[binary, {packet, 0}, {active, false}]),
init_stream(set_opt(socket, Sock, Config)).
@@ -362,6 +407,12 @@ roster_get(Config) ->
send_recv(Config, #iq{type = get, sub_els = [#roster{}]}),
disconnect(Config).
+presence(Config) ->
+ send(Config, #presence{}),
+ JID = my_jid(Config),
+ #presence{from = JID, to = JID} = recv(),
+ disconnect(Config).
+
presence_broadcast(Config) ->
send(Config, #presence{}),
JID = my_jid(Config),
@@ -778,8 +829,7 @@ proxy65_master(Config) ->
Peer = ?config(slave, Config),
wait_for_slave(Config),
send(Config, #presence{}),
- ?recv2(#presence{from = MyJID, type = undefined},
- #presence{from = Peer, type = undefined}),
+ #presence{from = MyJID, type = undefined} = recv(),
true = is_feature_advertised(Config, ?NS_BYTESTREAMS, Proxy),
#iq{type = result, sub_els = [#bytestreams{hosts = [StreamHost]}]} =
send_recv(
@@ -795,7 +845,7 @@ proxy65_master(Config) ->
#iq{type = set, to = Proxy,
sub_els = [#bytestreams{activate = Peer, sid = SID}]}),
socks5_send(Socks5, Data),
- #presence{type = unavailable, from = Peer} = recv(),
+ %%#presence{type = unavailable, from = Peer} = recv(),
disconnect(Config).
proxy65_slave(Config) ->
@@ -804,7 +854,6 @@ proxy65_slave(Config) ->
send(Config, #presence{}),
#presence{from = MyJID, type = undefined} = recv(),
wait_for_master(Config),
- #presence{from = Peer, type = undefined} = recv(),
{StreamHost, SID, Data} = get_event(Config),
Socks5 = socks5_connect(StreamHost, {SID, Peer, MyJID}),
wait_for_master(Config),
@@ -1216,3 +1265,78 @@ insert(Val, N, Tuple) ->
L = tuple_to_list(Tuple),
{H, T} = lists:split(N-1, L),
list_to_tuple(H ++ [Val|T]).
+
+%%%===================================================================
+%%% SQL stuff
+%%%===================================================================
+create_sql_tables(Type, BaseDir) ->
+ {VHost, File} = case Type of
+ mysql ->
+ {?MYSQL_VHOST, "mysql.sql"};
+ pgsql ->
+ {?PGSQL_VHOST, "pg.sql"}
+ end,
+ SQLFile = filename:join([BaseDir, "sql", File]),
+ CreationQueries = read_sql_queries(SQLFile),
+ DropTableQueries = drop_table_queries(CreationQueries),
+ case ejabberd_odbc:sql_transaction(
+ VHost, DropTableQueries ++ CreationQueries) of
+ {atomic, ok} ->
+ ok;
+ Err ->
+ ct:fail({failed_to_create_sql_tables, Type, Err})
+ end.
+
+read_sql_queries(File) ->
+ case file:open(File, [read, binary]) of
+ {ok, Fd} ->
+ read_lines(Fd, File, []);
+ Err ->
+ ct:fail({open_file_failed, File, Err})
+ end.
+
+drop_table_queries(Queries) ->
+ lists:foldl(
+ fun(Query, Acc) ->
+ case split(str:to_lower(Query)) of
+ [<<"create">>, <<"table">>, Table|_] ->
+ [<<"DROP TABLE IF EXISTS ", Table/binary, ";">>|Acc];
+ _ ->
+ Acc
+ end
+ end, [], Queries).
+
+read_lines(Fd, File, Acc) ->
+ case file:read_line(Fd) of
+ {ok, Line} ->
+ NewAcc = case str:strip(str:strip(Line, both, $\r), both, $\n) of
+ <<"--", _/binary>> ->
+ Acc;
+ <<>> ->
+ Acc;
+ _ ->
+ [Line|Acc]
+ end,
+ read_lines(Fd, File, NewAcc);
+ eof ->
+ QueryList = str:tokens(list_to_binary(lists:reverse(Acc)), <<";">>),
+ lists:flatmap(
+ fun(Query) ->
+ case str:strip(str:strip(Query, both, $\r), both, $\n) of
+ <<>> ->
+ [];
+ Q ->
+ [<<Q/binary, $;>>]
+ end
+ end, QueryList);
+ {error, _} = Err ->
+ ct:fail({read_file_failed, File, Err})
+ end.
+
+split(Data) ->
+ lists:filter(
+ fun(<<>>) ->
+ false;
+ (_) ->
+ true
+ end, re:split(Data, <<"\s">>)).
diff --git a/test/ejabberd_SUITE_data/ejabberd.cfg b/test/ejabberd_SUITE_data/ejabberd.cfg
index bf7839e13..c104d9c4e 100644
--- a/test/ejabberd_SUITE_data/ejabberd.cfg
+++ b/test/ejabberd_SUITE_data/ejabberd.cfg
@@ -1,5 +1,5 @@
{loglevel, 4}.
-{hosts, ["localhost"]}.
+{hosts, ["localhost", "mnesia.localhost", "mysql.localhost", "pgsql.localhost"]}.
{define_macro, 'CERTFILE', "cert.pem"}.
{listen,
[
@@ -18,8 +18,6 @@
captcha
]}
]}.
-{define_macro, 'DB_TYPE', internal}.
-{auth_method, 'DB_TYPE'}.
{shaper, normal, {maxrate, 1000}}.
{shaper, fast, {maxrate, 50000}}.
{max_fsm_queue, 1000}.
@@ -44,35 +42,79 @@
{modules,
[
{mod_adhoc, []},
- {mod_announce, [{db_type, 'DB_TYPE'}]},
- {mod_blocking, [{db_type, 'DB_TYPE'}]},
- {mod_caps, [{db_type, 'DB_TYPE'}]},
{mod_configure, []},
{mod_disco, []},
- {mod_last, [{db_type, 'DB_TYPE'}]},
- {mod_muc, []},
- {mod_offline, [{db_type, 'DB_TYPE'}]},
{mod_ping, []},
- {mod_privacy, [{db_type, 'DB_TYPE'}]},
- {mod_private, [{db_type, 'DB_TYPE'}]},
{mod_proxy65, []},
- {mod_pubsub, [
- {access_createnode, pubsub_createnode},
- {ignore_pep_from_offline, true},
- %%{ignore_pep_from_offline, false},
- {last_item_cache, false},
- {plugins, ["flat", "hometree", "pep", "public",
- "private", "mb"]}
- ]},
{mod_register, [
{welcome_message, {"Welcome!",
- "Hi.\nWelcome to this XMPP server."}}
+ "Hi.\nWelcome to this XMPP server."}}
]},
- {mod_roster, [{db_type, 'DB_TYPE'}]},
{mod_stats, []},
{mod_time, []},
- {mod_vcard, [{db_type, 'DB_TYPE'}]},
{mod_version, []}
+]}.
+{host_config, "localhost", [{auth_method, internal}]}.
+{host_config, "mnesia.localhost",
+ [{auth_method, internal},
+ {{add, modules}, [{mod_announce, [{db_type, internal}]},
+ {mod_blocking, [{db_type, internal}]},
+ {mod_caps, [{db_type, internal}]},
+ {mod_last, [{db_type, internal}]},
+ {mod_muc, [{db_type, internal}]},
+ {mod_offline, [{db_type, internal}]},
+ {mod_privacy, [{db_type, internal}]},
+ {mod_private, [{db_type, internal}]},
+ {mod_pubsub, [{access_createnode, pubsub_createnode},
+ {ignore_pep_from_offline, true},
+ {last_item_cache, false},
+ {plugins, ["flat", "hometree", "pep"]}]},
+ {mod_roster, [{db_type, internal}]},
+ {mod_vcard, [{db_type, internal}]}]}
+ ]}.
+{host_config, "mysql.localhost",
+ [{auth_method, odbc},
+ {odbc_pool_size, 1},
+ {odbc_server, {mysql, "localhost", "ejabberd_test",
+ "ejabberd_test", "ejabberd_test"}},
+ {{add, modules}, [{mod_announce, [{db_type, odbc}]},
+ {mod_blocking, [{db_type, odbc}]},
+ {mod_caps, [{db_type, odbc}]},
+ {mod_last, [{db_type, odbc}]},
+ {mod_muc, [{db_type, odbc}]},
+ {mod_offline, [{db_type, odbc}]},
+ {mod_privacy, [{db_type, odbc}]},
+ {mod_private, [{db_type, odbc}]},
+ {mod_pubsub_odbc, [{access_createnode, pubsub_createnode},
+ {ignore_pep_from_offline, true},
+ {last_item_cache, false},
+ {plugins, ["flat_odbc",
+ "hometree_odbc",
+ "pep_odbc"]}]},
+ {mod_roster, [{db_type, odbc}]},
+ {mod_vcard, [{db_type, odbc}]}]}
+ ]}.
+{host_config, "pgsql.localhost",
+ [{auth_method, odbc},
+ {odbc_pool_size, 1},
+ {odbc_server, {pgsql, "localhost", "ejabberd_test",
+ "ejabberd_test", "ejabberd_test"}},
+ {{add, modules}, [{mod_announce, [{db_type, odbc}]},
+ {mod_blocking, [{db_type, odbc}]},
+ {mod_caps, [{db_type, odbc}]},
+ {mod_last, [{db_type, odbc}]},
+ {mod_muc, [{db_type, odbc}]},
+ {mod_offline, [{db_type, odbc}]},
+ {mod_privacy, [{db_type, odbc}]},
+ {mod_private, [{db_type, odbc}]},
+ {mod_pubsub_odbc, [{access_createnode, pubsub_createnode},
+ {ignore_pep_from_offline, true},
+ {last_item_cache, false},
+ {plugins, ["flat_odbc",
+ "hometree_odbc",
+ "pep_odbc"]}]},
+ {mod_roster, [{db_type, odbc}]},
+ {mod_vcard, [{db_type, odbc}]}]}
]}.
%%% Local Variables: