1: %%============================================================================== 2: %% Copyright 2011 Erlang Solutions Ltd. 3: %% 4: %% Licensed under the Apache License, Version 2.0 (the "License"); 5: %% you may not use this file except in compliance with the License. 6: %% You may obtain a copy of the License at 7: %% 8: %% http://www.apache.org/licenses/LICENSE-2.0 9: %% 10: %% Unless required by applicable law or agreed to in writing, software 11: %% distributed under the License is distributed on an "AS IS" BASIS, 12: %% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13: %% See the License for the specific language governing permissions and 14: %% limitations under the License. 15: %%============================================================================== 16: -module(last_SUITE). 17: -compile([export_all, nowarn_export_all]). 18: 19: -include_lib("escalus/include/escalus.hrl"). 20: -include_lib("common_test/include/ct.hrl"). 21: 22: %%-------------------------------------------------------------------- 23: %% Suite configuration 24: %%-------------------------------------------------------------------- 25: 26: all() -> 27: [{group, valid_queries}, 28: {group, invalid_queries}]. 29: 30: groups() -> 31: G = [{valid_queries, [sequence], valid_test_cases()}, 32: {invalid_queries, invalid_test_cases()}], 33: ct_helper:repeat_all_until_all_ok(G). 34: 35: valid_test_cases() -> [last_online_user, 36: last_offline_user, 37: last_server]. 38: 39: invalid_test_cases() -> [user_not_subscribed_receives_error]. 40: 41: suite() -> 42: escalus:suite(). 43: 44: init_per_suite(Config0) -> 45: HostType = domain_helper:host_type(), 46: Config1 = dynamic_modules:save_modules(HostType, Config0), 47: Backend = mongoose_helper:get_backend_mnesia_rdbms_riak(HostType), 48: dynamic_modules:ensure_modules(HostType, required_modules(Backend)), 49: escalus:init_per_suite([{backend, Backend} | Config1]). 50: 51: end_per_suite(Config) -> 52: dynamic_modules:restore_modules(Config), 53: escalus:end_per_suite(Config). 54: 55: init_per_group(valid_queries, Config0) -> 56: Config1 = escalus_fresh:create_users(Config0, [{alice, 1}, {bob, 1}]), 57: Config2 = escalus:make_everyone_friends(Config1), 58: %% This check ensures that there are no registered sessions. 59: %% But in ejabberd_c2s we first unset session, 60: %% then broadcast presence unavailable. 61: %% This check uses ejabberd_sm to get information about sessions. 62: escalus_ejabberd:wait_for_session_count(Config2, 0), 63: %% Kick "friendly" users 64: %% kick_everyone uses ejabberd_c2s_sup to information about client processes. 65: mongoose_helper:kick_everyone(), 66: Config2; 67: init_per_group(invalid_queries, Config) -> 68: Config. 69: 70: end_per_group(_GroupName, _Config) -> 71: escalus_fresh:clean(). 72: 73: init_per_testcase(CaseName, Config) -> 74: escalus:init_per_testcase(CaseName, Config). 75: 76: end_per_testcase(CaseName, Config) -> 77: mongoose_helper:kick_everyone(), 78: escalus:end_per_testcase(CaseName, Config). 79: 80: %%-------------------------------------------------------------------- 81: %% Last tests 82: %%-------------------------------------------------------------------- 83: last_online_user(Config) -> 84: %% Alice and Bob are friends 85: escalus:story(Config, [{alice, 1}, {bob, 1}], 86: fun(Alice, Bob) -> 87: %% Alice asks about Bob's last activity 88: BobShortJID = escalus_client:short_jid(Bob), 89: escalus_client:send(Alice, escalus_stanza:last_activity(BobShortJID)), 90: 91: %% server replies on Bob's behalf 92: Stanza = escalus_client:wait_for_stanza(Alice), 93: escalus:assert(is_last_result, Stanza), 94: 0 = get_last_activity(Stanza) 95: end). 96: 97: last_offline_user(Config) -> 98: %% Alice and Bob are friends 99: escalus:story(Config, [{alice, 1}], 100: fun(Alice) -> 101: %% Bob logs in 102: {ok, Bob} = escalus_client:start_for(Config, bob, <<"bob">>), 103: 104: %% Bob logs out with a status 105: Status = escalus_stanza:tags([{<<"status">>, <<"I am a banana!">>}]), 106: Presence = escalus_stanza:presence(<<"unavailable">>, Status), 107: escalus_client:send(Bob, Presence), 108: escalus_client:stop(Config, Bob), 109: timer:sleep(1024), % more than a second 110: 111: %% Alice asks for Bob's last availability 112: BobShortJID = escalus_client:short_jid(Bob), 113: escalus_client:send(Alice, escalus_stanza:last_activity(BobShortJID)), 114: 115: %% Alice receives Bob's status and last online time > 0 116: Stanza = escalus_client:wait_for_stanza(Alice), 117: escalus:assert(is_last_result, Stanza), 118: true = (1 =< get_last_activity(Stanza)), 119: <<"I am a banana!">> = get_last_status(Stanza) 120: end). 121: 122: last_server(Config) -> 123: %% This story can be fresh_story 124: escalus:story(Config, [{alice, 1}], 125: fun(Alice) -> 126: %% Alice asks for server's uptime 127: Server = escalus_users:get_server(Config, alice), 128: escalus_client:send(Alice, escalus_stanza:last_activity(Server)), 129: 130: %% Server replies with the uptime > 0 131: Stanza = escalus_client:wait_for_stanza(Alice), 132: escalus:assert(is_last_result, Stanza), 133: true = (get_last_activity(Stanza) > 0) 134: end). 135: 136: user_not_subscribed_receives_error(Config) -> 137: escalus:fresh_story(Config, [{alice, 1}, {bob, 1}], fun(Alice, Bob) -> 138: %% Alice asks about Bob's last activity 139: BobShortJID = escalus_client:short_jid(Bob), 140: escalus_client:send(Alice, escalus_stanza:last_activity(BobShortJID)), 141: 142: %% server replies with an error, since there is no subscription 143: Error = escalus_client:wait_for_stanza(Alice), 144: escalus:assert(is_error, [<<"auth">>, <<"forbidden">>], Error), 145: 146: BobFullJID = escalus_client:full_jid(Bob), 147: escalus_client:send(Alice, escalus_stanza:last_activity(BobFullJID)), 148: 149: Error1 = escalus_client:wait_for_stanza(Alice), 150: escalus:assert(is_error, [<<"auth">>, <<"forbidden">>], Error1), 151: ok 152: end). 153: 154: 155: %%----------------------------------------------------------------- 156: %% Helpers 157: %%----------------------------------------------------------------- 158: get_last_activity(Stanza) -> 159: S = exml_query:path(Stanza, [{element, <<"query">>}, {attr, <<"seconds">>}]), 160: list_to_integer(binary_to_list(S)). 161: 162: get_last_status(Stanza) -> 163: exml_query:path(Stanza, [{element, <<"query">>}, cdata]). 164: 165: required_modules(Backend) -> 166: [{mod_last, [{backend, Backend}]}].