aboutsummaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/acl_test.exs271
-rw-r--r--test/ejabberd_SUITE.erl97
-rw-r--r--test/ejabberd_SUITE_data/cert.pem95
-rw-r--r--test/ejabberd_SUITE_data/ejabberd.ldif22
-rw-r--r--test/ejabberd_SUITE_data/ejabberd.yml7
-rw-r--r--test/ejabberd_commands_mock_test.exs18
-rw-r--r--test/elixir_SUITE.erl1
-rw-r--r--test/mod_admin_extra_test.exs1
-rw-r--r--test/mod_http_api_mock_test.exs4
-rw-r--r--test/mod_http_api_test.exs30
-rw-r--r--test/mod_roster_mock.exs67
-rw-r--r--test/suite.erl44
12 files changed, 527 insertions, 130 deletions
diff --git a/test/acl_test.exs b/test/acl_test.exs
index db6584308..38f0372e6 100644
--- a/test/acl_test.exs
+++ b/test/acl_test.exs
@@ -36,7 +36,7 @@ defmodule ACLTest do
test "access rule match with user part ACL" do
:acl.add(:global, :basic_acl_1, {:user, "test1"})
- :acl.add_access(:global, :basic_rule_1, [{:basic_acl_1, :allow}])
+ :acl.add_access(:global, :basic_rule_1, [{:allow, [{:acl, :basic_acl_1}]}])
# JID can only be passes as jid record.
# => TODO: Support passing JID as binary.
assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test1@domain1")) == :allow
@@ -46,7 +46,7 @@ defmodule ACLTest do
assert :acl.match_rule(:global, :basic_rule_1, :jid.from_string("test11@domain1")) == :deny
:acl.add(:global, :basic_acl_2, {:user, {"test2", "domain1"}})
- :acl.add_access(:global, :basic_rule_2, [{:basic_acl_2, :allow}])
+ :acl.add_access(:global, :basic_rule_2, [{:allow, [{:acl, :basic_acl_2}]}])
assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain1")) == :allow
assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@domain2")) == :deny
assert :acl.match_rule(:global, :basic_rule_2, :jid.from_string("test2@otherdomain")) == :deny
@@ -55,7 +55,7 @@ defmodule ACLTest do
test "IP based ACL" do
:acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"})
- :acl.add_access(:global, :ip_rule_1, [{:ip_acl_1, :allow}])
+ :acl.add_access(:global, :ip_rule_1, [{:allow, [{:acl, :ip_acl_1}]}])
# IP must be expressed as a tuple when calling match rule
assert :acl.match_rule(:global, :ip_rule_1, {127,0,0,1}) == :allow
assert :acl.match_rule(:global, :ip_rule_1, {127,0,1,1}) == :deny
@@ -65,7 +65,7 @@ defmodule ACLTest do
test "Access rule are evaluated sequentially" do
:acl.add(:global, :user_acl_1, {:user, {"test1", "domain2"}})
:acl.add(:global, :user_acl_2, {:user, "test1"})
- :acl.add_access(:global, :user_rule_1, [{:user_acl_1, :deny}, {:user_acl_2, :allow}])
+ :acl.add_access(:global, :user_rule_1, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :user_acl_2}]}])
assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain1")) == :allow
assert :acl.match_rule(:global, :user_rule_1, :jid.from_string("test1@domain2")) == :deny
end
@@ -74,7 +74,7 @@ defmodule ACLTest do
test "Access rules providing values" do
:acl.add(:global, :user_acl, {:user_regexp, ""})
:acl.add(:global, :admin_acl, {:user, "admin"})
- :acl.add_access(:global, :value_rule_1, [{:admin_acl, 10}, {:user_acl, 5}])
+ :acl.add_access(:global, :value_rule_1, [{10, [{:acl, :admin_acl}]}, {5, [{:acl, :user_acl}]}])
assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("test1@domain1")) == 5
assert :acl.match_rule(:global, :value_rule_1, :jid.from_string("admin@domain1")) == 10
@@ -91,19 +91,264 @@ defmodule ACLTest do
test "mixing IP and user access rules" do
:acl.add(:global, :user_acl_1, {:user, "test1"})
:acl.add(:global, :ip_acl_1, {:ip, "127.0.0.0/24"})
- :acl.add_access(:global, :mixed_rule_1, [{:user_acl_1, :allow}, {:ip_acl_1, :allow}])
+ :acl.add_access(:global, :mixed_rule_1, [{:allow, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}])
assert :acl.match_rule(:global, :mixed_rule_1, :jid.from_string("test1@domain1")) == :allow
assert :acl.match_rule(:global, :mixed_rule_1, {127,0,0,1}) == :allow
- :acl.add_access(:global, :mixed_rule_2, [{:user_acl_1, :deny}, {:ip_acl_1, :allow}])
+ :acl.add_access(:global, :mixed_rule_2, [{:deny, [{:acl, :user_acl_1}]}, {:allow, [{:acl, :ip_acl_1}]}])
assert :acl.match_rule(:global, :mixed_rule_2, :jid.from_string("test1@domain1")) == :deny
assert :acl.match_rule(:global, :mixed_rule_2, {127,0,0,1}) == :allow
end
- test "acl:match_access can match directly on user pattern" do
- pattern = {:user, {"test1", "domain1"}}
- assert :acl.match_access(:global, pattern, :jid.from_string("test1@domain1"), :allow) == :allow
- assert :acl.match_access(:global, pattern, :jid.from_string("test2@domain1"), :allow) == :deny
+ test "access_matches works with predefined access rules" do
+ :acl.add(:global, :user_acl_2, {:user, "user"})
+ :acl.add_access(:global, :user_rule_2, [{:allow, [{:acl, :user_acl_2}]}, {:deny, [:all]}])
+
+ assert :acl.access_matches(:user_rule_2, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches(:user_rule_2, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches rule all always matches" do
+ assert :acl.access_matches(:all, %{}, :global) == :allow
+ assert :acl.access_matches(:all, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ end
+
+ test "access_matches rule none never matches" do
+ assert :acl.access_matches(:none, %{}, :global) == :deny
+ assert :acl.access_matches(:none, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches with not existing rule never matches" do
+ assert :acl.access_matches(:bleble, %{}, :global) == :deny
+ assert :acl.access_matches(:bleble, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches works with inlined access rules" do
+ :acl.add(:global, :user_acl_3, {:user, "user"})
+
+ assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}],
+ %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches([{:allow, [{:acl, :user_acl_3}]}, {:deny, [:all]}],
+ %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches allow to have acl rules inlined" do
+ assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}],
+ %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches([{:allow, [{:user, "user"}]}, {:deny, [:all]}],
+ %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches test have implicit deny at end" do
+ assert :acl.access_matches([{:allow, [{:user, "user"}]}],
+ %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches([{:allow, [{:user, "user"}]}],
+ %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches requires that all subrules match" do
+ rules = [{:allow, [{:user, "user"}, {:ip, {{127,0,0,1}, 32}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,2}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches rules are matched in order" do
+ rules = [{:allow, [{:user, "user"}]}, {:deny, [{:user, "user2"}]}, {:allow, [{:user_regexp, "user"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user22", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ end
+
+ test "access_matches rules that require ip but no one is provided don't crash" do
+ rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]},
+ {:allow, [{:user, "user"}]},
+ {:allow, [{:user, "user2"}, {:ip, {{127,0,0,1}, 32}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny
+ end
+
+ test "access_matches rules that require usr but no one is provided don't crash" do
+ rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]},
+ {:allow, [{:user, "user"}]},
+ {:allow, [{:user, "user2"}, {:ip, {{127,0,0,2}, 32}}]}]
+ assert :acl.access_matches(rules, %{ip: {127,0,0,1}}, :global) == :allow
+ assert :acl.access_matches(rules, %{ip: {127,0,0,2}}, :global) == :deny
+ end
+
+ test "access_matches rules with all always matches" do
+ rules = [{:allow, [:all]}, {:deny, {:user, "user"}}]
+ assert :acl.access_matches(rules, %{}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ end
+
+ test "access_matches rules with {acl, all} always matches" do
+ rules = [{:allow, [{:acl, :all}]}, {:deny, {:user, "user"}}]
+ assert :acl.access_matches(rules, %{}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :allow
+ end
+
+ test "access_matches rules with none never matches" do
+ rules = [{:allow, [:none]}, {:deny, [:all]}]
+ assert :acl.access_matches(rules, %{}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches with no rules never matches" do
+ assert :acl.access_matches([], %{}, :global) == :deny
+ assert :acl.access_matches([], %{usr: {"user", "domain1", ""}, ip: {127,0,0,1}}, :global) == :deny
+ end
+
+ test "access_matches ip rule accepts {ip, port}" do
+ rules = [{:allow, [{:ip, {{127,0,0,1}, 32}}]}]
+ assert :acl.access_matches(rules, %{ip: {{127,0,0,1}, 5000}}, :global) == :allow
+ assert :acl.access_matches(rules, %{ip: {{127,0,0,2}, 5000}}, :global) == :deny
+ end
+
+ test "access_matches user rule works" do
+ rules = [{:allow, [{:user, "user1"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user2", "domain1", ""}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain3", ""}}, :global) == :deny
+ end
+
+ test "access_matches 2 arg user rule works" do
+ rules = [{:allow, [{:user, {"user1", "server1"}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "server1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user1", "server2", ""}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user2", "server1", ""}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user2", "server2", ""}}, :global) == :deny
+ end
+
+ test "access_matches server rule works" do
+ rules = [{:allow, [{:server, "server1"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "server2", ""}}, :global) == :deny
+ end
+
+ test "access_matches resource rule works" do
+ rules = [{:allow, [{:resource, "res1"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res2"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow
+ end
+
+ test "access_matches user_regexp rule works" do
+ rules = [{:allow, [{:user_regexp, "user[0-9]"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"userA", "domain1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny
+ end
+
+ test "access_matches 2 arg user_regexp rule works" do
+ rules = [{:allow, [{:user_regexp, {"user[0-9]", "server1"}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny
+ end
+
+ test "access_matches server_regexp rule works" do
+ rules = [{:allow, [{:server_regexp, "server[0-9]"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "serverA", ""}}, :global) == :deny
+ end
+
+ test "access_matches resource_regexp rule works" do
+ rules = [{:allow, [{:resource_regexp, "res[0-9]"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "resA"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow
+ end
+
+ test "access_matches node_regexp rule works" do
+ rules = [{:allow, [{:node_regexp, {"user[0-9]", "server[0-9]"}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"userA", "server1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "serverA", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"userA", "serverA", "res1"}}, :global) == :deny
+ end
+
+ test "access_matches user_glob rule works" do
+ rules = [{:allow, [{:user_glob, "user?"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user11", "domain1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "domain3", "res1"}}, :global) == :deny
+ end
+
+ test "access_matches 2 arg user_glob rule works" do
+ rules = [{:allow, [{:user_glob, {"user?", "server1"}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "server2", "res1"}}, :global) == :deny
+ end
+
+ test "access_matches server_glob rule works" do
+ rules = [{:allow, [{:server_glob, "server?"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "server1", ""}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "server11", ""}}, :global) == :deny
+ end
+
+ test "access_matches resource_glob rule works" do
+ rules = [{:allow, [{:resource_glob, "res?"}]}]
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user", "domain1", "res11"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user", "domain3", "res1"}}, :global) == :allow
+ end
+
+ test "access_matches node_glob rule works" do
+ rules = [{:allow, [{:node_glob, {"user?", "server?"}}]}]
+ assert :acl.access_matches(rules, %{usr: {"user1", "server1", "res1"}}, :global) == :allow
+ assert :acl.access_matches(rules, %{usr: {"user11", "server1", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user1", "server11", "res1"}}, :global) == :deny
+ assert :acl.access_matches(rules, %{usr: {"user11", "server11", "res1"}}, :global) == :deny
+ end
+
+ test "transform_access_rules_config expands allow rule" do
+ assert :acl.transform_access_rules_config([:allow]) == [{:allow, [:all]}]
+ end
+
+ test "transform_access_rules_config expands deny rule" do
+ assert :acl.transform_access_rules_config([:deny]) == [{:deny, [:all]}]
+ end
+
+ test "transform_access_rules_config expands <integer> rule" do
+ assert :acl.transform_access_rules_config([100]) == [{100, [:all]}]
+ end
+
+ test "transform_access_rules_config expands <shaper_name> rule" do
+ assert :acl.transform_access_rules_config([:fast]) == [{:fast, [:all]}]
+ end
+
+ test "transform_access_rules_config expands allow: <acl_name> rule" do
+ assert :acl.transform_access_rules_config([{:allow, :test1}]) == [{:allow, [{:acl, :test1}]}]
+ end
+
+ test "transform_access_rules_config expands deny: <acl_name> rule" do
+ assert :acl.transform_access_rules_config([{:deny, :test1}]) == [{:deny, [{:acl, :test1}]}]
+ end
+
+ test "transform_access_rules_config expands integer: <acl_name> rule" do
+ assert :acl.transform_access_rules_config([{100, :test1}]) == [{100, [{:acl, :test1}]}]
+ end
+
+ test "transform_access_rules_config expands <shaper_name>: <acl_name> rule" do
+ assert :acl.transform_access_rules_config([{:fast, :test1}]) == [{:fast, [{:acl, :test1}]}]
+ end
+
+ test "transform_access_rules_config expands allow rule (no list)" do
+ assert :acl.transform_access_rules_config(:allow) == [{:allow, [:all]}]
+ end
+
+ test "transform_access_rules_config expands deny rule (no list)" do
+ assert :acl.transform_access_rules_config(:deny) == [{:deny, [:all]}]
+ end
+
+ test "transform_access_rules_config expands <integer> rule (no list)" do
+ assert :acl.transform_access_rules_config(100) == [{100, [:all]}]
+ end
+
+ test "transform_access_rules_config expands <shaper_name> rule (no list)" do
+ assert :acl.transform_access_rules_config(:fast) == [{:fast, [:all]}]
end
## Checking ACL on both user pattern and IP
@@ -115,8 +360,8 @@ defmodule ACLTest do
test "module can test both IP and user through two independent :acl.match_rule check (deprecated)" do
:acl.add(:global, :user_acl, {:user, {"test1", "domain1"}})
:acl.add(:global, :ip_acl, {:ip, "127.0.0.0/24"})
- :acl.add_access(:global, :user_rule, [{:user_acl, :allow}])
- :acl.add_access(:global, :ip_rule, [{:ip_acl, :allow}])
+ :acl.add_access(:global, :user_rule, [{:allow, [{:acl, :user_acl}]}])
+ :acl.add_access(:global, :ip_rule, [{:allow, [{:acl, :ip_acl}]}])
# acl module in 16.03 is not able to provide a function for compound result:
assert :acl.match_rule(:global, :user_rule, :jid.from_string("test1@domain1")) == :allow
diff --git a/test/ejabberd_SUITE.erl b/test/ejabberd_SUITE.erl
index aa465fb66..d3e7ec668 100644
--- a/test/ejabberd_SUITE.erl
+++ b/test/ejabberd_SUITE.erl
@@ -162,23 +162,23 @@ init_per_testcase(TestCase, OrigConfig) ->
IsMaster = lists:suffix("_master", Test),
IsSlave = lists:suffix("_slave", Test),
IsCarbons = lists:prefix("carbons_", Test),
- User = if IsMaster or IsCarbons -> <<"test_master">>;
- IsSlave -> <<"test_slave">>;
- true -> <<"test_single">>
+ User = if IsMaster or IsCarbons -> <<"test_master!#$%^*()`~+-;_=[]{}|\\">>;
+ IsSlave -> <<"test_slave!#$%^*()`~+-;_=[]{}|\\">>;
+ true -> <<"test_single!#$%^*()`~+-;_=[]{}|\\">>
end,
MyResource = if IsMaster and IsCarbons -> MasterResource;
IsSlave and IsCarbons -> SlaveResource;
true -> Resource
end,
Slave = if IsCarbons ->
- jid:make(<<"test_master">>, Server, SlaveResource);
+ jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, SlaveResource);
true ->
- jid:make(<<"test_slave">>, Server, Resource)
+ jid:make(<<"test_slave!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource)
end,
Master = if IsCarbons ->
- jid:make(<<"test_master">>, Server, MasterResource);
+ jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, MasterResource);
true ->
- jid:make(<<"test_master">>, Server, Resource)
+ jid:make(<<"test_master!#$%^*()`~+-;_=[]{}|\\">>, Server, Resource)
end,
Config = set_opt(user, User,
set_opt(slave, Slave,
@@ -203,6 +203,8 @@ init_per_testcase(TestCase, OrigConfig) ->
auth(connect(Config));
sm_resume ->
auth(connect(Config));
+ sm_resume_failed ->
+ auth(connect(Config));
test_open_session ->
bind(auth(connect(Config)));
_ when IsMaster or IsSlave ->
@@ -231,6 +233,7 @@ no_db_tests() ->
stats,
sm,
sm_resume,
+ sm_resume_failed,
disco]},
{test_proxy65, [parallel],
[proxy65_master, proxy65_slave]}].
@@ -641,6 +644,17 @@ sm_resume(Config) ->
?recv1(#message{from = ServerJID, to = MyJID, body = [Txt]}),
?recv1(#sm_r{}),
send(Config, #sm_a{h = 1, xmlns = ?NS_STREAM_MGMT_3}),
+ %% Send another stanza to increment the server's 'h' for sm_resume_failed.
+ send(Config, #presence{to = ServerJID}),
+ close_socket(Config),
+ {save_config, set_opt(sm_previd, ID, Config)}.
+
+sm_resume_failed(Config) ->
+ {sm_resume, SMConfig} = ?config(saved_config, Config),
+ ID = ?config(sm_previd, SMConfig),
+ ct:sleep(5000), % Wait for session to time out.
+ send(Config, #sm_resume{previd = ID, h = 1, xmlns = ?NS_STREAM_MGMT_3}),
+ ?recv1(#sm_failed{reason = 'item-not-found', h = 4}),
disconnect(Config).
private(Config) ->
@@ -868,7 +882,7 @@ pubsub(Config) ->
true = lists:member(?NS_PUBSUB, Features),
%% Publish <presence/> element within node "presence"
ItemID = randoms:get_string(),
- Node = <<"presence">>,
+ Node = <<"presence!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>,
Item = #pubsub_item{id = ItemID,
xml_els = [xmpp_codec:encode(#presence{})]},
#iq{type = result,
@@ -1435,6 +1449,11 @@ muc_master(Config) ->
items = [#muc_item{affiliation = member,
jid = PeerJID,
role = participant}]}]}),
+ ?recv1(#message{from = Room,
+ sub_els = [#muc_user{
+ items = [#muc_item{affiliation = member,
+ jid = Localhost,
+ role = none}]}]}),
%% BUG: We should not receive any sub_els!
?recv1(#iq{type = result, id = I1, sub_els = [_|_]}),
%% Receive groupchat message from the peer
@@ -2255,15 +2274,46 @@ client_state_master(Config) ->
ChatState = #message{to = Peer, thread = <<"1">>,
sub_els = [#chatstate{type = active}]},
Message = ChatState#message{body = [#text{data = <<"body">>}]},
+ PepPayload = xmpp_codec:encode(#presence{}),
+ PepOne = #message{
+ to = Peer,
+ sub_els =
+ [#pubsub_event{
+ items =
+ [#pubsub_event_items{
+ node = <<"foo-1">>,
+ items =
+ [#pubsub_event_item{
+ id = <<"pep-1">>,
+ xml_els = [PepPayload]}]}]}]},
+ PepTwo = #message{
+ to = Peer,
+ sub_els =
+ [#pubsub_event{
+ items =
+ [#pubsub_event_items{
+ node = <<"foo-2">>,
+ items =
+ [#pubsub_event_item{
+ id = <<"pep-2">>,
+ xml_els = [PepPayload]}]}]}]},
%% Wait for the slave to become inactive.
wait_for_slave(Config),
- %% Should be dropped:
- send(Config, ChatState),
%% Should be queued (but see below):
send(Config, Presence),
%% Should replace the previous presence in the queue:
send(Config, Presence#presence{type = unavailable}),
- %% Should be sent immediately, together with the previous presence:
+ %% The following two PEP stanzas should be queued (but see below):
+ send(Config, PepOne),
+ send(Config, PepTwo),
+ %% The following two PEP stanzas should replace the previous two:
+ send(Config, PepOne),
+ send(Config, PepTwo),
+ %% Should be queued (but see below):
+ send(Config, ChatState),
+ %% Should replace the previous chat state in the queue:
+ send(Config, ChatState#message{sub_els = [#chatstate{type = composing}]}),
+ %% Should be sent immediately, together with the queued stanzas:
send(Config, Message),
%% Wait for the slave to become active.
wait_for_slave(Config),
@@ -2277,6 +2327,31 @@ client_state_slave(Config) ->
wait_for_master(Config),
?recv1(#presence{from = Peer, type = unavailable,
sub_els = [#delay{}]}),
+ #message{
+ from = Peer,
+ sub_els =
+ [#pubsub_event{
+ items =
+ [#pubsub_event_items{
+ node = <<"foo-1">>,
+ items =
+ [#pubsub_event_item{
+ id = <<"pep-1">>}]}]},
+ #delay{}]} = recv(),
+ #message{
+ from = Peer,
+ sub_els =
+ [#pubsub_event{
+ items =
+ [#pubsub_event_items{
+ node = <<"foo-2">>,
+ items =
+ [#pubsub_event_item{
+ id = <<"pep-2">>}]}]},
+ #delay{}]} = recv(),
+ ?recv1(#message{from = Peer, thread = <<"1">>,
+ sub_els = [#chatstate{type = composing},
+ #delay{}]}),
?recv1(#message{from = Peer, thread = <<"1">>,
body = [#text{data = <<"body">>}],
sub_els = [#chatstate{type = active}]}),
diff --git a/test/ejabberd_SUITE_data/cert.pem b/test/ejabberd_SUITE_data/cert.pem
index d6429dd68..11e18491f 100644
--- a/test/ejabberd_SUITE_data/cert.pem
+++ b/test/ejabberd_SUITE_data/cert.pem
@@ -1,51 +1,52 @@
-----BEGIN CERTIFICATE-----
-MIIDETCCAcmgAwIBAgIEUbsa1zANBgkqhkiG9w0BAQsFADAAMCIYDzIwMTMwNjE0
-MTMzMDAwWhgPMjAyMzA2MTIxMzMwMDhaMAAwggFSMA0GCSqGSIb3DQEBAQUAA4IB
-PwAwggE6AoIBMQCXdtt12OFu2j8tlF4x2Da/kbxyMxFnovJXHNzpx7CE/cGthAR5
-w7Cl92pECog2/d6ryIcjqzzCyCeOVQxIaE3Qz8z6+5UjKh3V/j6CKxcK5g1ER7Qe
-UgpE00ahHzvOpVANtrkYPGC0SFuTFL+PaylH4HW1xBSc1HD5/w7S1k1pDTz9x8ZC
-Z7JOb6NoYsz+rnmWYY2HOG6pyAyQBapIjgzCamgTStA6jTSgoXmCri/dZnJpqjZc
-V6AW7feNmMElhPvL30Cb3QB+9ODjN3pDXRR+Jqilu8ZSrpcvcFHOyKt943id1oC+
-Qu8orA0/kVInX7IuV//TciKzcH5FWz75Kb7hORPzH8M2DQcIKqKKVIwNVeJLKmcG
-RcUGsgTaz2j0JTa6YLJoczuasDWgRMT0goQpAgMBAAGjLzAtMAwGA1UdEwEB/wQC
-MAAwHQYDVR0OBBYEFBW6Si5OY8NPLagdth/JD8R18WMnMA0GCSqGSIb3DQEBCwUA
-A4IBMQAPiHxamUumu203pSVwvpWkpgKKOC2EswyFWQbNC6DWQ3LUkiR7MCiFViYt
-yiIyEh9wtfymWNF9uwaR2nVrJD5mK9Rt7xDiaT5ZOgNjLzmLeYqSlG41mCU1bmqg
-VbxmI1hvPvv3gQ/+WM0lBC6gPGJbVbzlWAIQ1cmevtL1KqOMveZl3VBPxDJD/K9c
-Rbrtx2nBKFDEl6hBljz6gsn4o8pxH3CO7qWpgY/MLwqQzEtTKYnaS9ecywNvj+/F
-ZE4SMoekw6AGRyE14/3i2xW6EmIpxVU4O6ahEFq6r6ZFbdtWnog5vT0y+/tRMgXp
-kCw8puxT2VsYNeJNOybW1IcyN5yluS/FY8iJokdL1JwvhVBVIWaim+T6iwrva7wC
-q1E9Nj30F8UbEkbkNqOdC3UlHQW4
+MIIGbDCCBVSgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJBVTET
+MBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQ
+dHkgTHRkMB4XDTE2MDUyNDE3NDIyNVoXDTQzMTAxMDE3NDIyNVowVjELMAkGA1UE
+BhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdp
+ZGdpdHMgUHR5IEx0ZDEPMA0GA1UEAxMGYWN0aXZlMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv
+VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9
+ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB
+o4ID2DCCA9QwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNTTCBHZW5l
+cmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFEynWiCoZK4tLDk3KM1wMsbrz9Ug
+MB8GA1UdIwQYMBaAFND2ZsvHIjITekPKs0ywLfoNEen5MDMGA1UdHwQsMCowKKAm
+oCSGImh0dHA6Ly9sb2NhbGhvc3Q6NTI4MC9kYXRhL2NybC5kZXIwNgYIKwYBBQUH
+AQEEKjAoMCYGCCsGAQUFBzABhhpodHRwOi8vbG9jYWxob3N0OjUyODAvb2NzcDAL
+BgNVHQ8EBAMCBeAwEwYDVR0lBAwwCgYIKwYBBQUHAwkwggLIBgNVHREEggK/MIIC
+u6A4BggrBgEFBQcIBaAsDCp0ZXN0X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318
+XEBsb2NhbGhvc3SgPwYIKwYBBQUHCAWgMwwxdGVzdF9zaW5nbGUhIyQlXiooKWB+
+Ky07Xz1bXXt9fFxAbW5lc2lhLmxvY2FsaG9zdKA+BggrBgEFBQcIBaAyDDB0ZXN0
+X3NpbmdsZSEjJCVeKigpYH4rLTtfPVtde318XEBteXNxbC5sb2NhbGhvc3SgPgYI
+KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcGdz
+cWwubG9jYWxob3N0oD8GCCsGAQUFBwgFoDMMMXRlc3Rfc2luZ2xlISMkJV4qKClg
+fistO189W117fXxcQHNxbGl0ZS5sb2NhbGhvc3SgQAYIKwYBBQUHCAWgNAwydGVz
+dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAZXh0YXV0aC5sb2NhbGhvc3Sg
+PQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxA
+bGRhcC5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVzdF9zaW5nbGUhIyQlXioo
+KWB+Ky07Xz1bXXt9fFxAcDFkYi5sb2NhbGhvc3SgPQYIKwYBBQUHCAWgMQwvdGVz
+dF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmlhay5sb2NhbGhvc3SgPgYI
+KwYBBQUHCAWgMgwwdGVzdF9zaW5nbGUhIyQlXiooKWB+Ky07Xz1bXXt9fFxAcmVk
+aXMubG9jYWxob3N0oD4GCCsGAQUFBwgFoDIMMHRlc3Rfc2luZ2xlISMkJV4qKClg
+fistO189W117fXxcQG1zc3FsLmxvY2FsaG9zdDANBgkqhkiG9w0BAQUFAAOCAQEA
+et4jpmpwlE+2bw+/iqCt7sfU/5nPmQ8YtgMB+32wf7DINNJgkwOdkYJpzhlMXKrh
+/bn8+Ybmq6MbK0r2R91Uu858xQf8VKExQm44qaGSyL5Ug3jsAWb3GLZSaWQo37e9
+QdDeP8XijCEyr3rum19tRIdiImsRAxJqwfaE4pUSgfCEQMkvb+6//8HSf9RRPToD
+o6eAg8QerEtTfxerEdW/0K1ozOrzSrQembWOu+JjvANRl+p59j+1YOWHzS/yQeZl
+K3sjFoCvXPvocRnUznvT+TSdy3ORJSjwfEcP5Crim70amZZ6NeMAxfby9wwmmX0x
+zkwPCSUXliXke6T88Olj7Q==
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
-MIIFegIBAAKCATEAl3bbddjhbto/LZReMdg2v5G8cjMRZ6LyVxzc6cewhP3BrYQE
-ecOwpfdqRAqINv3eq8iHI6s8wsgnjlUMSGhN0M/M+vuVIyod1f4+gisXCuYNREe0
-HlIKRNNGoR87zqVQDba5GDxgtEhbkxS/j2spR+B1tcQUnNRw+f8O0tZNaQ08/cfG
-QmeyTm+jaGLM/q55lmGNhzhuqcgMkAWqSI4MwmpoE0rQOo00oKF5gq4v3WZyaao2
-XFegFu33jZjBJYT7y99Am90AfvTg4zd6Q10UfiaopbvGUq6XL3BRzsirfeN4ndaA
-vkLvKKwNP5FSJ1+yLlf/03Iis3B+RVs++Sm+4TkT8x/DNg0HCCqiilSMDVXiSypn
-BkXFBrIE2s9o9CU2umCyaHM7mrA1oETE9IKEKQIDAQABAoIBMG8X8a4FbowFLhO7
-YD+FC9sFBMhqZpiyLrfwZqReID3bdeRUEYhSHU4OI/ZWF0Tmfh1Xjq992Koxbrn5
-7XFqd7DxybJJN0E8kfe0bJrDCjqnNBHh2d3nZLrIkGR7aT2PiSEV5bs+BdwVun0t
-2bdS7UtX+l5gvJGvTFJBXtkL8GleGV822Vc5gdIAFkXpOdyPkoTXdpw4qwqBnL8/
-TXMYBIgCrXMhEawcNbgPu4iFev2idoU9vXc7ZYD7+8jWB5LJ34cNngguGrnOjLoE
-9c3nZy6uYhhMWtcrSsQlrbN5MtY8w2fPH8nhfA651IxXXVxEajd24t2Csttnl7Vz
-WS5c+oPaWwt67naMrYCWG3q1zWhDqZUAulZR4DzWzGP+idLS/ojCRdTZO9D1O+XP
-fPi0wJECgZkAxh0rTSMCyrJ3VJqEgSPw3yAa1R9cdrTRvV4vRf13Dh8REaHtWt8W
-JeT5WLXL7dOii1St1Fgjo82+4iMqx3PQ2eR/1I6dA7Uy71PaSQTCQnupca2Xx8nT
-5KcrASBkDAudiKog01eC+zYrW+CbUb9AogMZLJzZinlWQ36pJVkWd9SOv25Eqcv6
-zJEmzYKpnow/m8WKNogVGpUCgZkAw7hQxs5VYVLp2XtDqRSmxfJsfsbUVo7tZnSU
-wmejgeNRs7415ZuT142k7qBImrFdYzFcfh2OZnf6D/VIz4Rl7u5YRYRCha/HOGIy
-wTe1huDckJ6lH/BkZ/6f9WSzXnNSNeXQY14WymU5V5qYCAdwECSf+xNuBYNwzA7o
-vOxPE690w3Ox2qghzRjzsBqAMgvqSyKlBpoMckUCgZhyKgD39IL5V5qYcGqHGLUH
-fzK3OdlItq5e19WaGZPv2Us2w/9JbGEQ+UAPNMQNivWSIPwC77+p9zhWjDlssnrZ
-9WkMjhpBNrvhWorhpRJkyWo9jfF3OgEXNJX9kjLVFiRzysYbw8RBC1g1G9ulYfbW
-5b4uDTz3JTDmuCi00v+1khGoktySlG80TzjzGKayLNPC6jTZc9XleQKBmA0STUrJ
-0wf5+qZMxjsPpwfHZhmde+cACrjyBlFpjJELNpSzmnPoTRpzWlWZnN/AAsWyMUQ3
-AyCy2J+iOSeq5wfrITgbWjoFgF+yp0MiTlxgvjpmbg7RBlOvvM0t2ZDwUMhKvf00
-9n6z/f1s1MSMgp6BY7HoHUv++FSYllCv06Qz7q9zFajN29wP046qZm9xPkegW7cy
-KKylAoGYTg94GOWlUTz7Pe9PDrDSFVEAi0LcDmul0ntorvEFDvU2pCRK14gyvl9O
-IJKVyYcDAqA3uvT+zMAniuf8KXNUCcYeEpfzpT+e2eznhczO8hI14M5U0X0LA8P2
-vn0Y+yUWb9Ppu/dcjvaUA+qR/UTHqjAlAr3hFTKRxXFoGwwzTXCXvZGKOnzJRTpj
-LpjI1RG7Weeoyx/8qDs=
+MIICXAIBAAKBgQC+GTA1D1+yiXgLqUhJXkSj3hj5FiqlBAfJT/8OSXYifY4M4HYv
+VQrqER2Fs7jdCaeoGWDvwfK/UOV0b1ROnf+T/2bXFs8EOeqjOz4xG2oexNKVrYj9
+ICYAgmSh6Hf2cZJM/YCAISje93Xl2J2w/N7oFC1ZXasPoBIZv3Fgg7hTtQIDAQAB
+AoGALddtJJ58eVVlOYqs/+RXsRyR8R9DUV/TcNx1qUBV2KNmafyHA4sCgsd10xQv
+9D2rzIGyOp8OpswfSSC/t+WqB9+ezSruzMuX6IURdHZbX6aWWX6maICtPKEEkCmI
+gaLxE/ojuOXnTEBTkVuVWtuFL9PsK/WGi/FIDzJbwqTWJ4ECQQDy9DrBAQM96B6u
+G4XpFzBsfgJZoS+NaMdCwK+/jgcEpI6oxobK8tuGB6drp5jNSuQ905W9n8XjA6Xq
+x8/GH9I5AkEAyE5g05HhMlxBWCq+P70pBDIamdHJcPQVL8+6NXkT+mTqqZxxkUy4
+nMfTh5zE6WfmqYNtrmNBDxXUyaoRSBydXQJACnFnCR7DBekxUGiMc/10LmWoMjQU
+eC6Vyg/APiqbsJ5mJ2kJKDYSK4uurZjxn3lloCa1HAZ/GgfxHMtj6e86OQJAetq3
+wIwE12KGIZF1xpo6gfxJHHbzWngaVozN5OYyPq2O0CDH9xpbUK2vK8oXbCDx9J5L
+s13lFV+Kd3X7y4LhcQJBAKSFg7ht33l8Sa0TdUkY6Tl1NBMCCLf+np+HYrAbQZux
+2NtR6nj2YqeOpEe1ibWZm8tj3dzlTm1FCOIpa+pm114=
-----END RSA PRIVATE KEY-----
diff --git a/test/ejabberd_SUITE_data/ejabberd.ldif b/test/ejabberd_SUITE_data/ejabberd.ldif
index 863a07e4f..a98036480 100644
--- a/test/ejabberd_SUITE_data/ejabberd.ldif
+++ b/test/ejabberd_SUITE_data/ejabberd.ldif
@@ -15,38 +15,38 @@ ou: groups
objectClass: organizationalUnit
dn: uid=test_single,ou=users,dc=localhost
-uid: test_single
-mail: test_single@localhost
+uid: test_single!#$%^*()`~+-;_=[]{}|\
+mail: test_single!#$%^*()`~+-;_=[]{}|\@localhost
objectClass: person
jpegPhoto:: /9g=
cn: Test Single
-password: password
+password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\
dn: uid=test_master,ou=users,dc=localhost
-uid: test_master
-mail: test_master@localhost
+uid: test_master!#$%^*()`~+-;_=[]{}|\
+mail: test_master!#$%^*()`~+-;_=[]{}|\@localhost
objectClass: person
jpegPhoto:: /9g=
cn: Test Master
-password: password
+password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\
dn: uid=test_slave,ou=users,dc=localhost
-uid: test_slave
-mail: test_slave@localhost
+uid: test_slave!#$%^*()`~+-;_=[]{}|\
+mail: test_slave!#$%^*()`~+-;_=[]{}|\@localhost
objectClass: person
jpegPhoto:: /9g=
cn: Test Slave
-password: password
+password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\
dn: uid=user2,ou=users,dc=localhost
uid: user2
mail: user2@localhost
objectClass: person
cn: Test User 2
-password: password
+password: password!@#$%^&*()'"`~<>+-/;:_=[]{}|\
dn: cn=group1,ou=groups,dc=localhost
objectClass: posixGroup
-memberUid: test_single
+memberUid: test_single!#$%^*()`~+-;_=[]{}|\
memberUid: user2
cn: group1
diff --git a/test/ejabberd_SUITE_data/ejabberd.yml b/test/ejabberd_SUITE_data/ejabberd.yml
index 869c24c7a..aca547d99 100644
--- a/test/ejabberd_SUITE_data/ejabberd.yml
+++ b/test/ejabberd_SUITE_data/ejabberd.yml
@@ -213,8 +213,9 @@ Welcome to this XMPP server."
db_type: internal
mod_carboncopy: []
mod_client_state:
- drop_chat_states: true
queue_presence: true
+ queue_chat_states: true
+ queue_pep: true
mod_adhoc: []
mod_configure: []
mod_disco: []
@@ -269,8 +270,9 @@ Welcome to this XMPP server."
db_type: internal
mod_carboncopy: []
mod_client_state:
- drop_chat_states: true
queue_presence: true
+ queue_chat_states: true
+ queue_pep: true
mod_adhoc: []
mod_configure: []
mod_disco: []
@@ -417,6 +419,7 @@ listen:
starttls: true
shaper: c2s_shaper
access: c2s
+ resume_timeout: 3
-
port: @@s2s_port@@
module: ejabberd_s2s_in
diff --git a/test/ejabberd_commands_mock_test.exs b/test/ejabberd_commands_mock_test.exs
index 285585034..487cf6a4b 100644
--- a/test/ejabberd_commands_mock_test.exs
+++ b/test/ejabberd_commands_mock_test.exs
@@ -127,6 +127,8 @@ defmodule EjabberdCommandsMockTest do
test "API command can be registered and executed" do
+ mock_commands_config
+
# Create & register a mocked command test() -> :result
command_name = :test
function = :test_command
@@ -142,6 +144,8 @@ defmodule EjabberdCommandsMockTest do
end
test "API command with versions can be registered and executed" do
+ mock_commands_config
+
command_name = :test
function1 = :test_command1
@@ -409,13 +413,13 @@ defmodule EjabberdCommandsMockTest do
:meck.expect(:ejabberd_config, :get_myhosts,
fn() -> [@domain] end)
:meck.new :acl
- :meck.expect(:acl, :match_rule,
- fn(@domain, :commands_admin_access, user) ->
- case :jlib.make_jid(@admin, @domain, "") do
- ^user -> :allow
- _ -> :deny
- end
- (@domain, :all, _user) ->
+ :meck.expect(:acl, :access_matches,
+ fn(:commands_admin_access, info, _scope) ->
+ case info do
+ %{usr: {@admin, @domain, _}} -> :allow
+ _ -> :deny
+ end;
+ (:all, _, _scope) ->
:allow
end)
end
diff --git a/test/elixir_SUITE.erl b/test/elixir_SUITE.erl
index 48cc94f8e..aaef9151d 100644
--- a/test/elixir_SUITE.erl
+++ b/test/elixir_SUITE.erl
@@ -18,6 +18,7 @@
-compile(export_all).
init_per_suite(Config) ->
+ suite:setup_ejabberd_lib_path(Config),
check_meck(),
code:add_pathz(filename:join(test_dir(), "../include")),
Config.
diff --git a/test/mod_admin_extra_test.exs b/test/mod_admin_extra_test.exs
index 2029cf686..761b07b7c 100644
--- a/test/mod_admin_extra_test.exs
+++ b/test/mod_admin_extra_test.exs
@@ -43,6 +43,7 @@ defmodule EjabberdModAdminExtraTest do
_ -> :ok
end
:ejabberd_commands.init
+ :ok = :ejabberd_config.start([@domain], [])
:mod_admin_extra.start(@domain, [])
:sel_application.start_app(:moka)
{:ok, _pid} = :ejabberd_hooks.start_link
diff --git a/test/mod_http_api_mock_test.exs b/test/mod_http_api_mock_test.exs
index 78832d7a5..47b1fe94a 100644
--- a/test/mod_http_api_mock_test.exs
+++ b/test/mod_http_api_mock_test.exs
@@ -75,7 +75,7 @@ defmodule ModHttpApiMockTest do
:meck.expect(:ejabberd_commands, :get_commands,
fn () -> [@acommand] end)
:meck.expect(:ejabberd_commands, :execute_command,
- fn (:undefined, {@user, @domain, @userpass, false}, @acommand, [], @version) ->
+ fn (:undefined, {@user, @domain, @userpass, false}, @acommand, [], @version, _) ->
:ok
end)
@@ -129,7 +129,7 @@ defmodule ModHttpApiMockTest do
fn () -> [@acommand] end)
:meck.expect(:ejabberd_commands, :execute_command,
fn (:undefined, {@user, @domain, {:oauth, _token}, false},
- @acommand, [], @version) ->
+ @acommand, [], @version, _) ->
:ok
end)
diff --git a/test/mod_http_api_test.exs b/test/mod_http_api_test.exs
index 9432ae471..99b8d9b28 100644
--- a/test/mod_http_api_test.exs
+++ b/test/mod_http_api_test.exs
@@ -39,6 +39,7 @@ defmodule ModHttpApiTest do
end
test "We can expose several commands to API at a time" do
+ setup_mocks()
:ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd, :user_cmd]}]])
commands = :ejabberd_commands.get_commands()
assert Enum.member?(commands, :open_cmd)
@@ -46,21 +47,24 @@ defmodule ModHttpApiTest do
end
test "We can call open commands without authentication" do
+ setup_mocks()
:ejabberd_config.add_local_option(:commands, [[{:add_commands, [:open_cmd]}]])
- request = request(method: :POST, data: "[]")
+ request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
{200, _, _} = :mod_http_api.process(["open_cmd"], request)
end
# This related to the commands config file option
test "Attempting to access a command that is not exposed as HTTP API returns 401" do
+ setup_mocks()
:ejabberd_config.add_local_option(:commands, [])
- request = request(method: :POST, data: "[]")
+ request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
{401, _, _} = :mod_http_api.process(["open_cmd"], request)
end
test "Call to user, admin or restricted commands without authentication are rejected" do
+ setup_mocks()
:ejabberd_config.add_local_option(:commands, [[{:add_commands, [:user_cmd, :admin_cmd, :restricted]}]])
- request = request(method: :POST, data: "[]")
+ request = request(method: :POST, ip: {{127,0,0,1},50000}, data: "[]")
{401, _, _} = :mod_http_api.process(["user_cmd"], request)
{401, _, _} = :mod_http_api.process(["admin_cmd"], request)
{401, _, _} = :mod_http_api.process(["restricted_cmd"], request)
@@ -68,6 +72,7 @@ defmodule ModHttpApiTest do
@tag pending: true
test "If admin_ip_access is enabled, we can call restricted API without authentication from that IP" do
+ setup_mocks()
end
# Define a set of test commands that we expose through API
@@ -86,10 +91,27 @@ defmodule ModHttpApiTest do
end
def open_cmd, do: :ok
- def user_cmd, do: :ok
+ def user_cmd(_, _), do: :ok
def admin_cmd, do: :ok
def restricted_cmd, do: :ok
+ defp setup_mocks() do
+ :meck.unload
+ mock(:gen_mod, :get_module_opt,
+ fn (_server, :mod_http_api, admin_ip_access, _, _) ->
+ [{:allow, [{:ip, {{127,0,0,2}, 32}}]}]
+ end)
+ end
+
+ defp mock(module, function, fun) do
+ try do
+ :meck.new(module)
+ catch
+ :error, {:already_started, _pid} -> :ok
+ end
+ :meck.expect(module, function, fun)
+ end
+
defp unregister_commands(commands) do
try do
:ejabberd_commands.unregister_commands(commands)
diff --git a/test/mod_roster_mock.exs b/test/mod_roster_mock.exs
index b1251ba86..ae990a6b1 100644
--- a/test/mod_roster_mock.exs
+++ b/test/mod_roster_mock.exs
@@ -45,41 +45,32 @@ defmodule ModRosterMock do
try do
module_mock = :moka.start(module)
- :moka.replace(module_mock, :mod_roster, :invalidate_roster_cache,
+ :moka.replace(module_mock, :mod_roster_mnesia, :invalidate_roster_cache,
fn (_user, _server) ->
:ok
end)
:moka.load(module_mock)
- roster_mock = :moka.start(:mod_roster)
-
- :moka.replace(roster_mock, :gen_mod, :db_type,
- fn (_host, _opts) ->
- {:none}
- end)
-
- :moka.replace(roster_mock, :gen_iq_handler, :add_iq_handler,
+ roster_mock0 = :moka.start(:mod_roster)
+ :moka.replace(roster_mock0, :gen_iq_handler, :add_iq_handler,
fn (_module, _host, _ns, _m, _f, _iqdisc) ->
:ok
end)
- :moka.replace(roster_mock, :gen_iq_handler, :remove_iq_handler,
+ :moka.replace(roster_mock0, :gen_iq_handler, :remove_iq_handler,
fn (_module, _host, _ns) ->
:ok
end)
-
- :moka.replace(roster_mock, :transaction,
- fn (_server, function) ->
- {:atomic, function.()}
+ :moka.replace(roster_mock0, :gen_mod, :db_mod,
+ fn (_host, _mod) ->
+ :mod_roster_mnesia
end)
-
- :moka.replace(roster_mock, :get_roster,
- fn (user, domain) ->
- to_records(get_roster(user, domain))
+ :moka.replace(roster_mock0, :gen_mod, :db_mod,
+ fn (_host, _opts, _mod) ->
+ :mod_roster_mnesia
end)
-
- :moka.replace(roster_mock, :update_roster_t,
+ :moka.replace(roster_mock0, :update_roster_t,
fn (user, domain, {u, d, _r}, item) ->
add_roster_item(user, domain, u<>"@"<>d,
roster(item, :name),
@@ -89,10 +80,32 @@ defmodule ModRosterMock do
roster(item, :askmessage))
end)
- :moka.replace(roster_mock, :del_roster_t,
+ :moka.replace(roster_mock0, :del_roster_t,
fn (user, domain, jid) ->
remove_roster_item(user, domain, :jid.to_string(jid))
end)
+ :moka.replace(roster_mock0, :get_roster,
+ fn (user, domain) ->
+ to_records(get_roster(user, domain))
+ end)
+
+ :moka.load(roster_mock0)
+
+ roster_mock = :moka.start(:mod_roster_mnesia)
+ :moka.replace(roster_mock, :gen_mod, :db_type,
+ fn (_host, _opts) ->
+ {:none}
+ end)
+
+ :moka.replace(roster_mock, :transaction,
+ fn (_server, function) ->
+ {:atomic, function.()}
+ end)
+
+ :moka.replace(roster_mock, :update_tables,
+ fn () ->
+ :ok
+ end)
:moka.load(roster_mock)
@@ -104,7 +117,7 @@ defmodule ModRosterMock do
def mock_with_meck do
# mock(:gen_mod, :db_type,
-# fn (_server, :mod_roster) ->
+# fn (_server, :mod_roster_mnesia) ->
# :mnesia
# end)
#
@@ -119,12 +132,16 @@ defmodule ModRosterMock do
# {:atomic, :ok}
# end)
- mock(:mod_roster, :transaction,
+ mock(:mod_roster_mnesia, :init,
+ fn (_server, _opts) ->
+ :ok
+ end)
+ mock(:mod_roster_mnesia, :transaction,
fn (_server, function) ->
{:atomic, function.()}
end)
- mock(:mod_roster, :update_roster_t,
+ mock(:mod_roster_mnesia, :update_roster_t,
fn (user, domain, {u, d, _r}, item) ->
add_roster_item(user, domain, u<>"@"<>d,
roster(item, :name),
@@ -134,7 +151,7 @@ defmodule ModRosterMock do
roster(item, :askmessage))
end)
- mock(:mod_roster, :invalidate_roster_cache,
+ mock(:mod_roster_mnesia, :invalidate_roster_cache,
fn (_user, _server) ->
:ok
end)
diff --git a/test/suite.erl b/test/suite.erl
index c605ed709..c5593c4cf 100644
--- a/test/suite.erl
+++ b/test/suite.erl
@@ -12,6 +12,7 @@
-compile(export_all).
-include("suite.hrl").
+-include_lib("kernel/include/file.hrl").
%%%===================================================================
%%% API
@@ -47,6 +48,7 @@ init_config(Config) ->
]),
ConfigPath = filename:join([CWD, "ejabberd.yml"]),
ok = file:write_file(ConfigPath, CfgContent),
+ setup_ejabberd_lib_path(Config),
ok = application:load(sasl),
ok = application:load(mnesia),
ok = application:load(ejabberd),
@@ -57,19 +59,40 @@ init_config(Config) ->
[{server_port, ct:get_config(c2s_port, 5222)},
{server_host, "localhost"},
{server, ?COMMON_VHOST},
- {user, <<"test_single">>},
- {master_nick, <<"master_nick">>},
- {slave_nick, <<"slave_nick">>},
- {room_subject, <<"hello, world!">>},
+ {user, <<"test_single!#$%^*()`~+-;_=[]{}|\\">>},
+ {master_nick, <<"master_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
+ {slave_nick, <<"slave_nick!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
+ {room_subject, <<"hello, world!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
{certfile, CertFile},
{base_dir, BaseDir},
- {resource, <<"resource">>},
- {master_resource, <<"master_resource">>},
- {slave_resource, <<"slave_resource">>},
+ {resource, <<"resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
+ {master_resource, <<"master_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
+ {slave_resource, <<"slave_resource!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
{password, <<"password!@#$%^&*()'\"`~<>+-/;:_=[]{}|\\">>},
{backends, get_config_backends()}
|Config].
+find_top_dir(Dir) ->
+ case file:read_file_info(filename:join([Dir, ebin])) of
+ {ok, #file_info{type = directory}} ->
+ Dir;
+ _ ->
+ find_top_dir(filename:dirname(Dir))
+ end.
+
+setup_ejabberd_lib_path(Config) ->
+ case code:lib_dir(ejabberd) of
+ {error, _} ->
+ DataDir = proplists:get_value(data_dir, Config),
+ {ok, CWD} = file:get_cwd(),
+ NewEjPath = filename:join([CWD, "ejabberd-0.0.1"]),
+ TopDir = find_top_dir(DataDir),
+ ok = file:make_symlink(TopDir, NewEjPath),
+ code:replace_path(ejabberd, NewEjPath);
+ _ ->
+ ok
+ end.
+
%% Read environment variable CT_DB=riak,mysql to limit the backends to test.
%% You can thus limit the backend you want to test with:
%% CT_BACKENDS=riak,mysql rebar ct suites=ejabberd
@@ -294,7 +317,12 @@ sasl_new(<<"DIGEST-MD5">>, User, Server, Password) ->
MyResponse = response(User, Password, Nonce, AuthzId,
Realm, CNonce, DigestURI, NC, QOP,
<<"AUTHENTICATE">>),
- Resp = <<"username=\"", User/binary, "\",realm=\"",
+ SUser = << <<(case Char of
+ $" -> <<"\\\"">>;
+ $\\ -> <<"\\\\">>;
+ _ -> <<Char>>
+ end)/binary>> || <<Char>> <= User >>,
+ Resp = <<"username=\"", SUser/binary, "\",realm=\"",
Realm/binary, "\",nonce=\"", Nonce/binary,
"\",cnonce=\"", CNonce/binary, "\",nc=", NC/binary,
",qop=", QOP/binary, ",digest-uri=\"",