Changeset View
Changeset View
Standalone View
Standalone View
apps/kolab_guam/test/kolab_guam_session_SUITE.erl
- This file was added.
%% Copyright 2015 Kolab Systems AG (http://www.kolabsys.com) | |||||
%% | |||||
%% Christian Mollekopf (Kolab Systems) <mollekopf@kolabsystems.com> | |||||
%% | |||||
%% This program is free software: you can redistribute it and/or modify | |||||
%% it under the terms of the GNU General Public License as published by | |||||
%% the Free Software Foundation, either version 3 of the License, or | |||||
%% (at your option) any later version. | |||||
%% | |||||
%% This program is distributed in the hope that it will be useful, | |||||
%% but WITHOUT ANY WARRANTY; without even the implied warranty of | |||||
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||||
%% GNU General Public License for more details. | |||||
%% | |||||
%% You should have received a copy of the GNU General Public License | |||||
%% along with this program. If not, see <http://www.gnu.org/licenses/>. | |||||
-module(kolab_guam_session_SUITE). | |||||
% easier than exporting by name | |||||
-compile(export_all). | |||||
% required for common_test to work | |||||
-include_lib("common_test/include/ct.hrl"). | |||||
-include("../src/kolab_guam_session.hrl"). | |||||
%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||||
%% common test callbacks %% | |||||
%%%%%%%%%%%%%%%%%%%%%%%%%%% | |||||
% Specify a list of all unit test functions | |||||
all() -> [ | |||||
kolab_guam_session_test | |||||
]. | |||||
% required, but can just return Config. this is a suite level setup function. | |||||
init_per_suite(Config) -> | |||||
Config. | |||||
% required, but can just return Config. this is a suite level tear down function. | |||||
end_per_suite(Config) -> | |||||
Config. | |||||
% optional, can do function level setup for all functions, | |||||
% or for individual functions by matching on TestCase. | |||||
init_per_testcase(_TestCase, Config) -> | |||||
Config. | |||||
% optional, can do function level tear down for all functions, | |||||
% or for individual functions by matching on TestCase. | |||||
end_per_testcase(_TestCase, Config) -> | |||||
Config. | |||||
kolab_guam_session_test(_TestConfig) -> | |||||
%% setup boilerplate | |||||
ServerConfig = kolab_guam_sup:default_imap_server_config(), | |||||
{ ok, ImapSession } = eimap:start_link(ServerConfig), | |||||
{ ok, Socket } = gen_tcp:listen(9964, [ { reuseaddr, true }, {active, false}, inet6 ]), | |||||
lager:start(), | |||||
lager:set_loglevel(lager_console_backend, debug), | |||||
ActiveRules = [{ kolab_guam_rule_filter_groupware, kolab_guam_rule_filter_groupware:new({}) }], | |||||
State = #state{ | |||||
socket = Socket, | |||||
server_config = ServerConfig, | |||||
imap_session = ImapSession | |||||
}, | |||||
% Run without rules | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = undefined, | |||||
command_split_reset_trigger = [] %FIXME ? | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test\")\r\ny2 ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>}, State#state{ rules_deciding = [] }), | |||||
% Activate filtering | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y1">>,<<"ID">>,<<"(\"name\" \"Test\")">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
rules_active = [{kolab_guam_rule_filter_groupware, _}] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test\")\r\n">>}, State#state{ rules_deciding = ActiveRules }), | |||||
% Don't activate filtering | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y1">>,<<"ID">>,<<"(\"name\" \"Test/KOLAB\")">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
rules_active = [] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test/KOLAB\")\r\n">>}, State#state{ rules_deciding = ActiveRules }), | |||||
% Lone tag in a packet. Can/Could happen with iPhone apparently. (See commit 89f9dc93757c68032ed17f42838858bdfaefa408) | |||||
{noreply, #state{ buffered_client_data = <<"y1">>, rules_active = [] } = IntermediateState1} = kolab_guam_session:handle_info({tcp, Socket, <<"y1">>}, State#state{ rules_deciding = ActiveRules }), | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y2">>,<<"ENABLE">>,<<"QRESYNC">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
rules_active = [{kolab_guam_rule_filter_groupware, _}] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<" ID (\"name\" \"Test\")\r\ny2 ENABLE QRESYNC\r\n">>}, IntermediateState1), | |||||
% Lone tag in a packet, but with a \r\n before. See guam-0.9.2-stalling-client-buffer-and-split-command-handling.patch (This triggers the odd List buffering case) | |||||
{noreply, #state{ buffered_client_data = <<"y1 ">>, rules_active = [] } = IntermediateState2} = kolab_guam_session:handle_info({tcp, Socket, <<"\r\ny1 ">>}, State#state{ rules_deciding = ActiveRules }), | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y2">>,<<"ENABLE">>,<<"QRESYNC">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
rules_active = [{kolab_guam_rule_filter_groupware, _}] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"ID (\"name\" \"Test\")\r\ny2 ENABLE QRESYNC\r\n">>}, IntermediateState2), | |||||
% Empty line (should be considered a complete command and should not be buffered) | |||||
{noreply, #state{ buffered_client_data = <<>>, rules_active = [] } = IntermediateState3} = kolab_guam_session:handle_info({tcp, Socket, <<"\r\n">>}, State#state{ rules_deciding = ActiveRules }), | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y1">>,<<"ID">>,<<"(\"name\" \"Test\")">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
rules_active = [{kolab_guam_rule_filter_groupware, _}] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test\")\r\n">>}, IntermediateState3), | |||||
% Activate with multi-line packet | |||||
{noreply, #state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y3">>,<<"LIST">>,<<"\"\" \"%\" RETURN (SUBSCRIBED))">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
% Make sure that we have processed y3 in here (and don't stop processing at y1) | |||||
rules_active = [{kolab_guam_rule_filter_groupware, {state,undefined,<<"y3">>,true,<<>>,[<<"LIST">>,<<"list">>,<<"XLIST">>,<<"xlist">>,<<"LSUB">>,<<"lsub">>]}}] | |||||
% rules_active = [{kolab_guam_rule_filter_groupware, _}] | |||||
}} = kolab_guam_session:handle_info({tcp, Socket, <<"y1 ID (\"name\" \"Test\")\r\ny2 ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>}, State#state{ rules_deciding = ActiveRules }), | |||||
% Test various packet splits | |||||
PacketsSplits = [ | |||||
[<<"y1 ID (\"name\" \"Test\")\r\n">>, <<"y2 ENABLE QRESYNC\r\n">>, <<"y3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>], | |||||
[<<"y1 ID (\"name\" \"Test\")\r\ny2 ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>], | |||||
[<<"y1 ID (\"name\" \"Test\")">>, <<"\r\ny2">>, <<" ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>], | |||||
[<<"y1 ID (\"name\" \"Test\")">>, <<"\r\n">>, <<"y2 ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>], | |||||
[<<"y1">>, <<" ">>, <<"ID">>, <<" (\"name\" \"Test\")\r\n">>, <<"y2 ENABLE QRESYNC\r\ny3 LIST \"\" \"%\" RETURN (SUBSCRIBED))\r\n">>] | |||||
], | |||||
lists:foldl(fun(Packets, _) -> | |||||
try_packets(Packets, Socket, ServerConfig, State#state{ rules_deciding = ActiveRules }) | |||||
end, | |||||
undefined, | |||||
PacketsSplits), | |||||
lager:info("Done"). | |||||
try_packets(Packets, Socket, ServerConfig, State) -> | |||||
#state{ | |||||
server_config = ServerConfig, | |||||
buffered_client_data = <<>>, | |||||
current_command_split = {<<"y3">>,<<"LIST">>,<<"\"\" \"%\" RETURN (SUBSCRIBED))">>}, | |||||
command_split_reset_trigger = reset_for_next_client_command, | |||||
rules_deciding = [], | |||||
% Make sure that we have processed y3 in here (and don't stop processing at y1) | |||||
rules_active = [{kolab_guam_rule_filter_groupware, {state,undefined,<<"y3">>,true,<<>>,[<<"LIST">>,<<"list">>,<<"XLIST">>,<<"xlist">>,<<"LSUB">>,<<"lsub">>]}}] | |||||
} = lists:foldl(fun(Packet, _State) -> | |||||
{_, NewState} = kolab_guam_session:handle_info({tcp, Socket, Packet}, _State), | |||||
NewState | |||||
end, | |||||
State, | |||||
Packets). |