Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
E
er
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
er
Commits
23ef74a5
Unverified
Commit
23ef74a5
authored
Mar 07, 2019
by
Сергей Прохоров
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add downstream backpressure tests
parent
e9471b25
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
140 additions
and
21 deletions
+140
-21
single_dc_SUITE.erl
test/single_dc_SUITE.erl
+139
-20
test-sys.config
test/test-sys.config
+1
-1
No files found.
test/single_dc_SUITE.erl
View file @
23ef74a5
...
@@ -8,12 +8,20 @@
...
@@ -8,12 +8,20 @@
end_per_testcase
/
2
]).
end_per_testcase
/
2
]).
-
export
([
echo_secure_case
/
1
,
-
export
([
echo_secure_case
/
1
,
echo_abridged_many_packets_case
/
1
]).
echo_abridged_many_packets_case
/
1
,
downstream_size_backpressure_case
/
1
,
downstream_qlen_backpressure_case
/
1
]).
-
export
([
gen_rpc_replies
/
3
]).
-
include_lib
(
"common_test/include/ct.hrl"
).
-
include_lib
(
"common_test/include/ct.hrl"
).
-
include_lib
(
"stdlib/include/assert.hrl"
).
-
include_lib
(
"stdlib/include/assert.hrl"
).
-
define
(
APP
,
mtproto_proxy
).
-
define
(
APP
,
mtproto_proxy
).
-
define
(
KB
(
N
),
N
*
1024
).
-
define
(
MB
(
N
),
?
KB
(
N
)
*
1024
).
all
()
->
all
()
->
%% All exported functions of arity 1 whose name ends with "_case"
%% All exported functions of arity 1 whose name ends with "_case"
Exports
=
?
MODULE
:
module_info
(
exports
),
Exports
=
?
MODULE
:
module_info
(
exports
),
...
@@ -41,71 +49,181 @@ end_per_testcase(Name, Cfg) ->
...
@@ -41,71 +49,181 @@ end_per_testcase(Name, Cfg) ->
%% @doc Send single packet and receive it back
%% @doc Send single packet and receive it back
echo_secure_case
({
pre
,
Cfg
})
->
echo_secure_case
({
pre
,
Cfg
})
->
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
Cfg
);
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
#
{},
Cfg
);
echo_secure_case
({
post
,
Cfg
})
->
echo_secure_case
({
post
,
Cfg
})
->
stop_single
(
Cfg
);
stop_single
(
Cfg
);
echo_secure_case
(
Cfg
)
when
is_list
(
Cfg
)
->
echo_secure_case
(
Cfg
)
when
is_list
(
Cfg
)
->
DcId
=
?
config
(
dc_id
,
Cfg
),
DcId
=
?
config
(
dc_id
,
Cfg
),
Host
=
?
config
(
mtp_host
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
Cli
=
mtp_test_client
:
connect
(
{
127
,
0
,
0
,
1
}
,
Port
,
Secret
,
DcId
,
mtp_secure
),
Cli
=
mtp_test_client
:
connect
(
Host
,
Port
,
Secret
,
DcId
,
mtp_secure
),
Data
=
crypto
:
strong_rand_bytes
(
64
),
Data
=
crypto
:
strong_rand_bytes
(
64
),
Cli1
=
mtp_test_client
:
send
(
Data
,
Cli
),
Cli1
=
mtp_test_client
:
send
(
Data
,
Cli
),
{
ok
,
Packet
,
Cli2
}
=
mtp_test_client
:
recv_packet
(
Cli1
,
1000
),
{
ok
,
Packet
,
Cli2
}
=
mtp_test_client
:
recv_packet
(
Cli1
,
1000
),
ok
=
mtp_test_client
:
close
(
Cli2
),
ok
=
mtp_test_client
:
close
(
Cli2
),
?
assertEqual
(
Data
,
Packet
),
?
assertEqual
(
Data
,
Packet
),
ok
=
mtp_test_metric
:
wait_for_value
(
count
,
[
?
APP
,
in_connection_closed
,
total
],
[
?
FUNCTION_NAME
],
1
,
5000
),
?
assertEqual
(
1
,
mtp_test_metric
:
get_tags
(
?
assertEqual
(
1
,
mtp_test_metric
:
get_tags
(
count
,
[
?
APP
,
in_connection
,
total
],
[
?
FUNCTION_NAME
])),
count
,
[
?
APP
,
in_connection
,
total
],
[
?
FUNCTION_NAME
])),
%% race-condition
%% ?assertEqual(1, mtp_test_metric:get_tags(
%% count, [?APP,in_connection_closed,total], [?FUNCTION_NAME])),
?
assertEqual
({
1
,
64
,
64
,
64
},
?
assertEqual
({
1
,
64
,
64
,
64
},
mtp_test_metric
:
get_tags
(
mtp_test_metric
:
get_tags
(
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
[
upstream_to_downstream
])),
[
upstream_to_downstream
])),
?
assertMatch
({
1
,
_,
_,
_},
% larger because of RPC headers
?
assertMatch
({
1
,
_,
_,
_},
% larger because of RPC headers
mtp_test_metric
:
get_tags
(
mtp_test_metric
:
get_tags
(
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
[
downstream_to_upstream
])).
[
downstream_to_upstream
])).
%% @doc Send many packets and receive them back
%% @doc Send many packets and receive them back
echo_abridged_many_packets_case
({
pre
,
Cfg
})
->
echo_abridged_many_packets_case
({
pre
,
Cfg
})
->
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
Cfg
);
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
#
{},
Cfg
);
echo_abridged_many_packets_case
({
post
,
Cfg
})
->
echo_abridged_many_packets_case
({
post
,
Cfg
})
->
stop_single
(
Cfg
);
stop_single
(
Cfg
);
echo_abridged_many_packets_case
(
Cfg
)
when
is_list
(
Cfg
)
->
echo_abridged_many_packets_case
(
Cfg
)
when
is_list
(
Cfg
)
->
DcId
=
?
config
(
dc_id
,
Cfg
),
DcId
=
?
config
(
dc_id
,
Cfg
),
Host
=
?
config
(
mtp_host
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
Cli0
=
mtp_test_client
:
connect
({
127
,
0
,
0
,
1
},
Port
,
Secret
,
DcId
,
mtp_secure
),
Cli0
=
mtp_test_client
:
connect
(
Host
,
Port
,
Secret
,
DcId
,
mtp_secure
),
NPackets
=
15
,
Packets
=
Packets
=
[
crypto
:
strong_rand_bytes
(
4
*
rand
:
uniform
(
50
))
[
crypto
:
strong_rand_bytes
(
4
*
rand
:
uniform
(
50
))
||
_
<-
lists
:
seq
(
1
,
15
)],
||
_
<-
lists
:
seq
(
1
,
NPackets
)],
Cli2
=
lists
:
foldl
(
fun
mtp_test_client
:
send
/
2
,
Cli0
,
Packets
),
Cli2
=
lists
:
foldl
(
fun
mtp_test_client
:
send
/
2
,
Cli0
,
Packets
),
timer
:
sleep
(
10
),
% TODO: some hook in proxy to find when sent
%% Wait until all packets will be sent by proxy (this actually can fail if buffers are full)
ok
=
mtp_test_metric
:
wait_for
(
histogram
,
[
?
APP
,
upstream_send_duration
,
seconds
],
[
?
FUNCTION_NAME
],
fun
({
Cnt
,
_,
_,
_})
->
Cnt
==
NPackets
;
(
not_found
)
->
false
end
,
5000
),
{
ok
,
RecvPackets
,
Cli
}
=
mtp_test_client
:
recv_all
(
Cli2
,
1000
),
{
ok
,
RecvPackets
,
Cli
}
=
mtp_test_client
:
recv_all
(
Cli2
,
1000
),
ok
=
mtp_test_client
:
close
(
Cli
),
ok
=
mtp_test_client
:
close
(
Cli
),
?
assertEqual
(
Packets
,
RecvPackets
),
?
assertEqual
(
Packets
,
RecvPackets
),
?
assertEqual
({
length
(
Packets
),
%total count
?
assertEqual
({
NPackets
,
%total count
iolist_size
(
Packets
),
%total sum
iolist_size
(
Packets
),
%total sum
lists
:
min
(
lists
:
map
(
fun
erlang
:
byte_size
/
1
,
Packets
)),
%min
lists
:
min
(
lists
:
map
(
fun
erlang
:
byte_size
/
1
,
Packets
)),
%min
lists
:
max
(
lists
:
map
(
fun
erlang
:
byte_size
/
1
,
Packets
))
%max
lists
:
max
(
lists
:
map
(
fun
erlang
:
byte_size
/
1
,
Packets
))
%max
},
},
mtp_test_metric
:
get_tags
(
mtp_test_metric
:
get_tags
(
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
histogram
,
[
?
APP
,
tg_packet_size
,
bytes
],
[
upstream_to_downstream
])).
[
upstream_to_downstream
])).
%% TODO: backpressure tests
%% TODO: send a lot, not read, and then close test
%% @doc test downstream backpressure when size of non-acknowledged packets grows above threshold
downstream_size_backpressure_case
({
pre
,
Cfg
})
->
Cfg1
=
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
#
{
rpc_handler
=>
mtp_test_cmd_rpc
},
Cfg
),
%% Disable upstream healthchecks
application
:
set_env
(
?
APP
,
upstream_healthchecks
,
[]),
Cfg1
;
downstream_size_backpressure_case
({
post
,
Cfg
})
->
stop_single
(
Cfg
);
downstream_size_backpressure_case
(
Cfg
)
when
is_list
(
Cfg
)
->
DcId
=
?
config
(
dc_id
,
Cfg
),
Host
=
?
config
(
mtp_host
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
%% Backpressure by size limit is defined in mtp_down_conn.erl:?MAX_NON_ACK_BYTES
BPressureThreshold
=
?
MB
(
6
),
PacketSize
=
?
KB
(
400
),
NPackets
=
2
*
BPressureThreshold
div
PacketSize
,
Packet
=
crypto
:
strong_rand_bytes
(
PacketSize
),
Req
=
mtp_test_cmd_rpc
:
call
(
?
MODULE
,
gen_rpc_replies
,
#
{
packet
=>
Packet
,
n
=>
NPackets
}),
Cli0
=
mtp_test_client
:
connect
(
Host
,
Port
,
Secret
,
DcId
,
mtp_secure
),
Cli1
=
mtp_test_client
:
send
(
Req
,
Cli0
),
%% Wait for backpressure-in
?
assertEqual
(
ok
,
mtp_test_metric
:
wait_for_value
(
count
,
[
?
APP
,
down_backpressure
,
total
],
[
DcId
,
true
],
1
,
5000
)),
%% Upstream healthcheck should be disabled, otherwise it can interfere
?
assertEqual
(
not_found
,
mtp_test_metric
:
get_tags
(
count
,
[
?
APP
,
healthcheck
,
total
],
[
total_memory
])),
%% No backpressure-out, because we don't read any data
?
assertEqual
(
not_found
,
mtp_test_metric
:
get_tags
(
count
,
[
?
APP
,
down_backpressure
,
total
],
[
DcId
,
false
])),
%% Amount of bytes received by proxy will be bigger than amount sent to upstreams
TgToProxy
=
mtp_test_metric
:
get_tags
(
count
,
[
?
APP
,
received
,
downstream
,
bytes
],
[
DcId
]),
ProxyToClient
=
mtp_test_metric
:
get_tags
(
count
,
[
?
APP
,
sent
,
upstream
,
bytes
],
[
?
FUNCTION_NAME
]),
?
assert
(
TgToProxy
>
ProxyToClient
),
%% Read some data to release backpressure
{
ok
,
_
RecvPackets
,
Cli2
}
=
mtp_test_client
:
recv_all
(
Cli1
,
1000
),
?
assertEqual
(
ok
,
mtp_test_metric
:
wait_for
(
count
,
[
?
APP
,
down_backpressure
,
total
],
[
DcId
,
true
],
fun
(
V
)
->
is_integer
(
V
)
and
(
V
>
0
)
end
,
5000
)),
ok
=
mtp_test_client
:
close
(
Cli2
),
%% ct:pal("t->p ~p; p->c ~p; diff ~p",
%% [TgToProxy, ProxyToClient, TgToProxy - ProxyToClient]),
%% [{_, Pid, _, _}] = supervisor:which_children(mtp_down_conn_sup),
%% ct:pal("Down conn state: ~p", [sys:get_state(Pid)]),
%% ct:pal("Metric: ~p", [sys:get_state(mtp_test_metric)]),
ok
.
%% @doc test downstream backpressure when count of non-acknowledged packets grows above threshold
downstream_qlen_backpressure_case
({
pre
,
Cfg
})
->
Cfg1
=
setup_single
(
?
FUNCTION_NAME
,
?
LINE
,
#
{
rpc_handler
=>
mtp_test_cmd_rpc
},
Cfg
),
%% Disable upstream healthchecks
application
:
set_env
(
?
APP
,
upstream_healthchecks
,
[]),
Cfg1
;
downstream_qlen_backpressure_case
({
post
,
Cfg
})
->
stop_single
(
Cfg
);
downstream_qlen_backpressure_case
(
Cfg
)
when
is_list
(
Cfg
)
->
DcId
=
?
config
(
dc_id
,
Cfg
),
Host
=
?
config
(
mtp_host
,
Cfg
),
Port
=
?
config
(
mtp_port
,
Cfg
),
Secret
=
?
config
(
mtp_secret
,
Cfg
),
SizeThreshold
=
?
MB
(
6
),
CountThreshold
=
300
,
PacketSize
=
SizeThreshold
div
CountThreshold
-
4048
,
PacketSizeAligned
=
PacketSize
-
(
PacketSize
rem
4
),
NPackets
=
10
*
CountThreshold
,
Packet
=
crypto
:
strong_rand_bytes
(
PacketSizeAligned
),
Req
=
mtp_test_cmd_rpc
:
call
(
?
MODULE
,
gen_rpc_replies
,
#
{
packet
=>
Packet
,
n
=>
NPackets
}),
Cli0
=
mtp_test_client
:
connect
(
Host
,
Port
,
Secret
,
DcId
,
mtp_secure
),
Cli1
=
mtp_test_client
:
send
(
Req
,
Cli0
),
%% Wait for backpressure-in
?
assertEqual
(
ok
,
mtp_test_metric
:
wait_for_value
(
count
,
[
?
APP
,
down_backpressure
,
total
],
[
DcId
,
true
],
1
,
5000
)),
%% Close connection to release backpressure
ok
=
mtp_test_client
:
close
(
Cli1
),
?
assertEqual
(
ok
,
mtp_test_metric
:
wait_for_value
(
count
,
[
?
APP
,
in_connection_closed
,
total
],
[
?
FUNCTION_NAME
],
1
,
5000
)),
?
assertEqual
(
ok
,
mtp_test_metric
:
wait_for
(
count
,
[
?
APP
,
down_backpressure
,
total
],
[
DcId
,
true
],
fun
(
V
)
->
is_integer
(
V
)
and
(
V
>
0
)
end
,
5000
)),
%% [{_, Pid, _, _}] = supervisor:which_children(mtp_down_conn_sup),
%% ct:pal("Down conn state: ~p", [sys:get_state(Pid)]),
%% ct:pal("Metric: ~p", [sys:get_state(mtp_test_metric)]),
ok
.
gen_rpc_replies
(
#
{
packet
:
=
Packet
,
n
:
=
N
},
ConnId
,
St
)
->
Rpcs
=
[{
proxy_ans
,
ConnId
,
Packet
}
||
_
<-
lists
:
seq
(
1
,
N
)],
{
return
,
{
rpc_multi
,
Rpcs
,
St
#
{
ConnId
=>
1
}}}.
%% TODO: send a lot, not read, and then close - assert connection IDs are cleaned up
%% Helpers
%% Helpers
setup_single
(
Name
,
Offset
,
Cfg
)
->
setup_single
(
Name
,
Offset
,
DcCfg0
,
Cfg
)
->
{
ok
,
Pid
}
=
mtp_test_metric
:
start_link
(),
{
ok
,
Pid
}
=
mtp_test_metric
:
start_link
(),
PubKey
=
crypto
:
strong_rand_bytes
(
128
),
PubKey
=
crypto
:
strong_rand_bytes
(
128
),
DcId
=
1
,
DcId
=
1
,
DcConf
=
[{
DcId
,
{
127
,
0
,
0
,
1
},
10000
+
Offset
}],
Ip
=
{
127
,
0
,
0
,
1
},
DcConf
=
[{
DcId
,
Ip
,
10000
+
Offset
}],
MtpPort
=
10000
+
Offset
+
1
,
MtpPort
=
10000
+
Offset
+
1
,
Secret
=
mtp_handler
:
hex
(
crypto
:
strong_rand_bytes
(
16
)),
Secret
=
mtp_handler
:
hex
(
crypto
:
strong_rand_bytes
(
16
)),
Listeners
=
[
#
{
name
=>
Name
,
Listeners
=
[
#
{
name
=>
Name
,
...
@@ -115,10 +233,11 @@ setup_single(Name, Offset, Cfg) ->
...
@@ -115,10 +233,11 @@ setup_single(Name, Offset, Cfg) ->
tag
=>
<<
"dcbe8f1493fa4cd9ab300891c0b5b326"
>>
}],
tag
=>
<<
"dcbe8f1493fa4cd9ab300891c0b5b326"
>>
}],
application
:
load
(
mtproto_proxy
),
application
:
load
(
mtproto_proxy
),
Cfg1
=
set_env
([{
ports
,
Listeners
}],
Cfg
),
Cfg1
=
set_env
([{
ports
,
Listeners
}],
Cfg
),
{
ok
,
DcCfg
}
=
mtp_test_datacenter
:
start_dc
(
PubKey
,
DcConf
,
#
{}
),
{
ok
,
DcCfg
}
=
mtp_test_datacenter
:
start_dc
(
PubKey
,
DcConf
,
DcCfg0
),
application
:
load
(
mtproto_proxy
),
application
:
load
(
mtproto_proxy
),
{
ok
,
_}
=
application
:
ensure_all_started
(
mtproto_proxy
),
{
ok
,
_}
=
application
:
ensure_all_started
(
mtproto_proxy
),
[{
dc_id
,
DcId
},
[{
dc_id
,
DcId
},
{
mtp_host
,
Ip
},
{
mtp_port
,
MtpPort
},
{
mtp_port
,
MtpPort
},
{
mtp_secret
,
Secret
},
{
mtp_secret
,
Secret
},
{
dc_conf
,
DcCfg
},
{
dc_conf
,
DcCfg
},
...
...
test/test-sys.config
View file @
23ef74a5
...
@@ -21,7 +21,7 @@
...
@@ -21,7 +21,7 @@
{
lager_file_backend
,
{
lager_file_backend
,
[{
file
,
"application.log"
},
[{
file
,
"application.log"
},
{
level
,
warning
},
{
level
,
info
},
%%
Do
fsync
only
on
critical
messages
%%
Do
fsync
only
on
critical
messages
{
sync_on
,
critical
}
{
sync_on
,
critical
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment