Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
37d4448
Remove leftovers after old code (actually causing warnings)
chrzaszcz Mar 3, 2026
536879f
Reimplement mod_caps
chrzaszcz Mar 3, 2026
080567f
Update caps-related hooks
chrzaszcz Mar 3, 2026
77cf835
Update mod_pubsub after the introduction of new mod_caps
chrzaszcz Mar 3, 2026
e1e3d30
Add/update unit tests for the new mod_caps
chrzaszcz Mar 3, 2026
25ec78b
Delete the obsolete 'caps' DB table
chrzaszcz Mar 3, 2026
e821d28
Add/update big tests for the new mod_caps
chrzaszcz Mar 3, 2026
1cf8f23
Update documentation of mod_caps
chrzaszcz Mar 3, 2026
ac0873f
Fix an issue with mod_caps requiring cets in config tests
chrzaszcz Mar 3, 2026
7702e30
Support XEP-0390 as version v2 in mod_caps
chrzaszcz Mar 13, 2026
639de64
Support XEP-0390 as version v2 in mod_caps_hash
chrzaszcz Mar 13, 2026
b6e94ba
Add config tests for modules.mod_caps.versions
chrzaszcz Mar 13, 2026
654deb5
Document the modules.mod_caps.versions option
chrzaszcz Mar 13, 2026
fa5d644
Test hashing for v1 and v2 in mod_caps_SUITE
chrzaszcz Mar 13, 2026
5f1b167
Update big tests to use v1 and v2 of mod_caps
chrzaszcz Mar 13, 2026
18d8ab0
Use the new version of escalus with caps helpers
chrzaszcz Mar 16, 2026
fca7f70
Corrections after code review
chrzaszcz Mar 17, 2026
a05cdaf
Merge pull request #4666 from esl/caps-v2
chrzaszcz Mar 17, 2026
4a7ca8b
Merge branch 'master' into feature/caps
chrzaszcz Mar 20, 2026
78bf75c
Merge branch 'master' into feature/caps
chrzaszcz Mar 20, 2026
6989a22
Document the migration for mod_caps
chrzaszcz Mar 19, 2026
81439c6
Merge pull request #4678 from esl/caps-migrations
chrzaszcz Mar 20, 2026
5d42a57
Align the implemenetation with XEP-0300 and XEP-0414
chrzaszcz Mar 20, 2026
52e7b13
Drop MD5 and shake* from mod_caps_SUITE
chrzaszcz Mar 20, 2026
deb89f7
Check hashing functions in server features
chrzaszcz Mar 20, 2026
7a1478a
Use the new version of escalus
chrzaszcz Mar 20, 2026
70ae6f9
Merge pull request #4679 from esl/caps-hash
chrzaszcz Mar 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion big_tests/rebar.config
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
{proper, "1.4.0"},
{gun, "2.1.0"},
{fusco, "0.1.1"},
{escalus, "4.5.6"},
{escalus, "4.6.1"},
{ranch, "2.2.0"},
{cowboy, "2.13.0"},
{csv, "3.0.3", {pkg, csve}},
Expand Down
6 changes: 3 additions & 3 deletions big_tests/rebar.lock
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
{<<"ct_groups_summary_hook">>,
{pkg,<<"ct_groups_summary_hook">>,<<"0.1.1">>},
0},
{<<"escalus">>,{pkg,<<"escalus">>,<<"4.5.6">>},0},
{<<"escalus">>,{pkg,<<"escalus">>,<<"4.6.1">>},0},
{<<"esip">>,{pkg,<<"esip">>,<<"1.0.57">>},0},
{<<"exml">>,{pkg,<<"hexml">>,<<"4.1.2">>},0},
{<<"fast_pbkdf2">>,{pkg,<<"fast_pbkdf2">>,<<"2.0.0">>},2},
Expand Down Expand Up @@ -42,7 +42,7 @@
{<<"credentials_obfuscation">>, <<"61E282ADFB4439486B3994FAAEC69543C7EE6CC7E70C6340E8853FD9DEAF8219">>},
{<<"csv">>, <<"69E7D9B3FDC72016644368762C6A3E6CBFEB85BCCADBF1BD99AB6C827E360E04">>},
{<<"ct_groups_summary_hook">>, <<"21B94902B6CF2D345F4D790D34B49654E71CB8E570DCCC9C1C3616DAE720A7AA">>},
{<<"escalus">>, <<"054826CE22FA65FEB243107163487AC0A1A6742E4605216DF0C89613FF68033F">>},
{<<"escalus">>, <<"C0058279F580CB74D7A387E476ABC75D7D7A5F741B96E299786E5AF36683B3B3">>},
{<<"esip">>, <<"4B14E4832D08B9FFC10D855B5D10B3083232B1D53DEB4C046679496CE85569C4">>},
{<<"exml">>, <<"4EA6B95AF18922F94FD67BBDEAA325A75CCE04487083C786E7417BA862D590E5">>},
{<<"fast_pbkdf2">>, <<"72CDEE3C10C6B9B40E31194DE946A883CEEF6CF1F37D7FC9FD1A9D87502723F5">>},
Expand Down Expand Up @@ -73,7 +73,7 @@
{<<"credentials_obfuscation">>, <<"843ADBE3246861CE0F1A0FA3222F384834EB31DEFD8D6B9CBA7AFD2977C957BC">>},
{<<"csv">>, <<"741D1A55AABADAA3E0FE13051050101A73E90C4570B9F9403A939D9546813521">>},
{<<"ct_groups_summary_hook">>, <<"997CDE48FEB0C398989E4091A341D4FFF43CFA06CDB8FB2E80CC4A0E0362691C">>},
{<<"escalus">>, <<"4818627C907ECD557D5162A6FBFE8B6FF6628AD5AC819104CB070E451928B7E0">>},
{<<"escalus">>, <<"042E78F9F596087E61DB448FE175EBFFE637EFD5CAFCD37462EFB9754F0E6746">>},
{<<"esip">>, <<"19C357E1817B1E04792EF359BF900400F3E6D0E5ADE929FD72F88EA9B44AF2ED">>},
{<<"exml">>, <<"03883AE3E27970E9DAC204B27CE330B54A6C2772455E43FE2319349DFF40B1DC">>},
{<<"fast_pbkdf2">>, <<"74159FD09FB8BF5E97D25137C6C83C28E2CF7E97D7C127D83310DFD0904BD732">>},
Expand Down
116 changes: 116 additions & 0 deletions big_tests/tests/caps_helper.erl
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
-module(caps_helper).

-include_lib("escalus/include/escalus_xmlns.hrl").
-include_lib("exml/include/exml.hrl").
-include_lib("stdlib/include/assert.hrl").

-compile([export_all, nowarn_export_all]).

-import(distributed_helper, [mim/0, rpc/4]).

-type feature() :: binary().
-type host_type() :: binary().
-type caps() :: exml:element().
-type version() :: v1 | v2.

check_backend() ->
case ct_helper:get_internal_database() of
cets -> ok;
mnesia -> {skip, "mod_caps has no mnesia backend"}
end.

%% Stanza flow

-spec enable_new_caps(escalus:client(), [feature()], version()) -> caps().
enable_new_caps(Client, Features, Version) ->
Caps = caps(Features, Version),
send_presence_with_caps(Client, Caps),
handle_requested_caps(Client, Caps, Features),
receive_presence_with_caps(Client, Client, Caps),
Caps.

-spec enable_caps(escalus:client(), [binary()], version()) -> caps().
enable_caps(Client, Features, Version) ->
Caps = caps(Features, Version),
send_presence_with_caps(Client, Caps),
receive_presence_with_caps(Client, Client, Caps),
Caps.

-spec send_presence_with_caps(escalus:client(), caps()) -> ok.
send_presence_with_caps(Client, Caps) ->
Presence = escalus_stanza:presence(~"available", [Caps]),
escalus:send(Client, Presence).

-spec receive_presence_with_caps(escalus:client(), escalus:client(), caps()) -> ok.
receive_presence_with_caps(Client, Sender, Caps) ->
PresenceNotification = escalus:wait_for_stanza(Client),
escalus:assert(is_presence, PresenceNotification),
escalus:assert(is_stanza_from, [Sender], PresenceNotification),
?assertEqual(Caps, exml_query:subelement(PresenceNotification, ~"c")).

-spec handle_requested_caps(escalus:client(), caps(), [feature()]) -> ok.
handle_requested_caps(Client, Caps, Features) ->
DiscoRequest = receive_caps_request(Client, Caps),
send_caps_disco_result(Client, DiscoRequest, Features).

-spec receive_caps_request(escalus:client(), caps()) -> exml:element().
receive_caps_request(Client, Caps) ->
DiscoRequest = escalus:wait_for_stanza(Client),
escalus:assert(is_iq_with_ns, [?NS_DISCO_INFO], DiscoRequest),
#xmlel{children = [#xmlel{attrs = #{~"node" := QueryNode}}]} = DiscoRequest,
?assertEqual(escalus_stanza:caps_to_node(Caps), QueryNode),
DiscoRequest.

-spec send_caps_disco_result(escalus:client(), exml:element(), [feature()]) -> ok.
send_caps_disco_result(Client, DiscoRequest, Features) ->
QueryEl = escalus_stanza:query_el(?NS_DISCO_INFO, feature_elems(Features)),
DiscoResult = escalus_stanza:iq_result(DiscoRequest, [QueryEl]),
escalus:send(Client, DiscoResult).

%% Assertions

-spec assert_caps(host_type(), escalus:client(), [feature()]) -> ok.
assert_caps(HostType, Client, Features) ->
ExpectedFeatures = all_features(Features),
?assertEqual(ExpectedFeatures, get_client_features(HostType, Client)).

-spec assert_no_caps(host_type(), escalus:client()) -> ok.
assert_no_caps(HostType, Client) ->
?assertEqual([], get_client_features(HostType, Client)).

-spec wait_for_caps(host_type(), escalus:client(), [feature()]) -> ok.
wait_for_caps(HostType, Client, Features) ->
ExpectedFeatures = all_features(Features),
wait_helper:wait_until(fun() -> get_client_features(HostType, Client) end,
ExpectedFeatures, #{sleep_time => 200}),
ok.

-spec wait_for_no_caps(host_type(), escalus:client()) -> ok.
wait_for_no_caps(HostType, Client) ->
wait_helper:wait_until(fun() -> get_client_features(HostType, Client) end,
[], #{sleep_time => 200}),
ok.

%% XML elements

feature_elems(Features) ->
[escalus_stanza:identity(~"client", ~"pc", ~"Psi") |
lists:map(fun escalus_stanza:feature/1, all_features(Features))].

-spec caps([feature()], version()) -> caps().
caps(Features, Version) ->
Alg = alg(Version),
escalus_stanza:caps(Alg, caps_hash(Features, Version, Alg), Version).

alg(v1) -> ~"sha-1";
alg(v2) -> ~"sha-256".

all_features(Features) ->
[?NS_DISCO_INFO, ?NS_DISCO_ITEMS | Features].

caps_hash(Features, Version, Alg) ->
rpc(mim(), mod_caps_hash, generate, [feature_elems(Features), Version, Alg]).

get_client_features(HostType, Client) ->
Jid = jid:from_binary(escalus_client:full_jid(Client)),
rpc(mim(), mod_caps, get_features, [HostType, Jid]).
Loading