congure_test: make shell commands shorter

This commit is contained in:
Martine Lenders 2021-02-26 23:13:52 +01:00
parent 43d6633536
commit f19c8bad01
No known key found for this signature in database
GPG Key ID: CCD317364F63286F
5 changed files with 279 additions and 219 deletions

View File

@ -18,10 +18,15 @@
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include "clist.h"
#include "fmt.h" #include "fmt.h"
#include "congure/test.h" #include "congure/test.h"
static congure_snd_msg_t _msgs_pool[CONFIG_CONGURE_TEST_LOST_MSG_POOL_SIZE];
static unsigned _msgs_pool_idx;
static clist_node_t _msgs;
static bool _scn_u32_dec_with_zero(const char *str, size_t n, uint32_t *res) static bool _scn_u32_dec_with_zero(const char *str, size_t n, uint32_t *res)
{ {
if ((n == 1) && str[0] == '0') { if ((n == 1) && str[0] == '0') {
@ -35,10 +40,8 @@ static bool _scn_u32_dec_with_zero(const char *str, size_t n, uint32_t *res)
int congure_test_clear_state(int argc, char **argv) int congure_test_clear_state(int argc, char **argv)
{ {
(void)argc;
(void)argv;
memset(congure_test_get_state(), 0, sizeof(congure_test_snd_t)); memset(congure_test_get_state(), 0, sizeof(congure_test_snd_t));
print_str("{\"success\":null}\n"); congure_test_msgs_reset(argc, argv);
return 0; return 0;
} }
@ -126,6 +129,56 @@ int congure_test_call_inter_msg_interval(int argc, char **argv)
return 0; return 0;
} }
int congure_test_add_msg(int argc, char **argv)
{
uint32_t tmp;
if (argc < 4) {
print_str("{\"error\":\"At least 3 arguments `msg_send_time`, "
"`msg_size`, `msg_resends` expected\"}\n");
return 1;
}
if (_msgs_pool_idx >= ARRAY_SIZE(_msgs_pool)) {
print_str("{\"error\":\"List element pool depleted\"}\n");
return 1;
}
_msgs_pool[_msgs_pool_idx].super.next = NULL;
if (!_scn_u32_dec_with_zero(argv[1], strlen(argv[1]), &tmp)) {
print_str("{\"error\":\"`msg_send_time` expected to be "
"integer\"}\n");
return 1;
}
_msgs_pool[_msgs_pool_idx].send_time = tmp;
if (!_scn_u32_dec_with_zero(argv[2], strlen(argv[2]), &tmp)) {
print_str("{\"error\":\"`msg_size` expected to be integer\"}\n");
return 1;
}
_msgs_pool[_msgs_pool_idx].size = tmp;
if (!_scn_u32_dec_with_zero(argv[3], strlen(argv[3]), &tmp)) {
print_str("{\"error\":\"`msg_resends` expected to be "
"integer\"}\n");
return 1;
}
_msgs_pool[_msgs_pool_idx].resends = tmp;
clist_rpush(&_msgs, &_msgs_pool[_msgs_pool_idx++].super);
print_str("{\"success\":null}\n");
return 0;
}
int congure_test_msgs_reset(int argc, char **argv)
{
(void)argc;
(void)argv;
_msgs.next = NULL;
_msgs_pool_idx = 0;
print_str("{\"success\":null}\n");
return 0;
}
static int _call_report_msg_sent(int argc, char **argv) static int _call_report_msg_sent(int argc, char **argv)
{ {
congure_test_snd_t *c = congure_test_get_state(); congure_test_snd_t *c = congure_test_get_state();
@ -163,56 +216,15 @@ static int _call_report_msg_discarded(int argc, char **argv)
} }
static int _call_report_msgs_timeout_lost(void (*method)(congure_snd_t *, static int _call_report_msgs_timeout_lost(void (*method)(congure_snd_t *,
congure_snd_msg_t *), congure_snd_msg_t *))
int argc, char **argv)
{ {
static congure_snd_msg_t list_pool[CONFIG_CONGURE_TEST_LOST_MSG_POOL_SIZE];
clist_node_t msgs = { .next = NULL };
congure_test_snd_t *c = congure_test_get_state(); congure_test_snd_t *c = congure_test_get_state();
if (argc < 4) { if (_msgs.next == NULL) {
print_str("{\"error\":\"At least 3 arguments `msg_send_time`, " print_str("{\"error\":\"Message not initialized\"}\n");
"`msg_size`, `msg_resends` expected\"}\n");
return 1; return 1;
} }
if ((argc - 1) % 3) { method(&c->super, (congure_snd_msg_t *)_msgs.next);
print_str("{\"error\":\"Number of arguments must be divisible "
"by 3\"}\n");
return 1;
}
if ((unsigned)((argc - 1) / 3) >= ARRAY_SIZE(list_pool)) {
print_str("{\"error\":\"List element pool depleted\"}");
return 1;
}
for (int i = 1; i < argc; i += 3) {
uint32_t tmp;
unsigned pool_idx = ((i - 1) / 3);
list_pool[pool_idx].super.next = NULL;
if (!_scn_u32_dec_with_zero(argv[i], strlen(argv[i]), &tmp)) {
print_str("{\"error\":\"`msg_send_time` expected to be "
"integer\"}\n");
return 1;
}
list_pool[pool_idx].send_time = tmp;
if (!_scn_u32_dec_with_zero(argv[i + 1], strlen(argv[i + 1]), &tmp)) {
print_str("{\"error\":\"`msg_size` expected to be integer\"}\n");
return 1;
}
list_pool[pool_idx].size = tmp;
if (!_scn_u32_dec_with_zero(argv[i + 2], strlen(argv[i + 2]), &tmp)) {
print_str("{\"error\":\"`msg_resends` expected to be "
"integer\"}\n");
return 1;
}
list_pool[pool_idx].resends = tmp;
clist_rpush(&msgs, &list_pool[pool_idx].super);
}
method(&c->super, (congure_snd_msg_t *)msgs.next);
print_str("{\"success\":null}\n"); print_str("{\"success\":null}\n");
return 0; return 0;
} }
@ -221,76 +233,61 @@ static int _call_report_msgs_timeout(int argc, char **argv)
{ {
congure_test_snd_t *c = congure_test_get_state(); congure_test_snd_t *c = congure_test_get_state();
return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_timeout, (void)argc;
argc, argv); (void)argv;
return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_timeout);
} }
static int _call_report_msgs_lost(int argc, char **argv) static int _call_report_msgs_lost(int argc, char **argv)
{ {
congure_test_snd_t *c = congure_test_get_state(); congure_test_snd_t *c = congure_test_get_state();
return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_lost, (void)argc;
argc, argv); (void)argv;
return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_lost);
} }
static int _call_report_msg_acked(int argc, char **argv) static int _call_report_msg_acked(int argc, char **argv)
{ {
static congure_snd_msg_t msg = { .size = 0 };
static congure_snd_ack_t ack = { .size = 0 }; static congure_snd_ack_t ack = { .size = 0 };
congure_test_snd_t *c = congure_test_get_state(); congure_test_snd_t *c = congure_test_get_state();
uint32_t tmp; uint32_t tmp;
if (argc < 10) { if (_msgs.next == NULL) {
print_str("{\"error\":\"At least 9 arguments `msg_send_time`, " print_str("{\"error\":\"Message not initialized\"}\n");
"`msg_size`, `msg_resends`, `ack_recv_time`, `ack_id`, " return 1;
"`ack_size`, `ack_clean`, `ack_wnd`, `ack_delay` " }
if (argc < 7) {
print_str("{\"error\":\"At least 6 arguments `ack_recv_time`, "
"`ack_id`, `ack_size`, `ack_clean`, `ack_wnd`, `ack_delay` "
"expected\"}\n"); "expected\"}\n");
return 1; return 1;
} }
if (!_scn_u32_dec_with_zero(argv[1], strlen(argv[1]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[1], strlen(argv[1]), &tmp)) {
print_str("{\"error\":\"`msg_send_time` expected to be "
"integer\"}\n");
return 1;
}
msg.send_time = tmp;
if (!_scn_u32_dec_with_zero(argv[2], strlen(argv[2]), &tmp)) {
print_str("{\"error\":\"`msg_size` expected to be integer\"}\n");
return 1;
}
msg.size = tmp;
if (!_scn_u32_dec_with_zero(argv[3], strlen(argv[3]), &tmp)) {
print_str("{\"error\":\"`msg_resends` expected to be integer\"}\n");
return 1;
}
msg.resends = tmp;
if (!_scn_u32_dec_with_zero(argv[4], strlen(argv[4]), &tmp)) {
print_str("{\"error\":\"`ack_recv_time` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_recv_time` expected to be integer\"}\n");
return 1; return 1;
} }
ack.recv_time = tmp; ack.recv_time = tmp;
if (!_scn_u32_dec_with_zero(argv[5], strlen(argv[5]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[2], strlen(argv[2]), &tmp)) {
print_str("{\"error\":\"`ack_id` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_id` expected to be integer\"}\n");
return 1; return 1;
} }
ack.id = tmp; ack.id = tmp;
if (!_scn_u32_dec_with_zero(argv[6], strlen(argv[6]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[3], strlen(argv[3]), &tmp)) {
print_str("{\"error\":\"`ack_size` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_size` expected to be integer\"}\n");
return 1; return 1;
} }
ack.size = tmp; ack.size = tmp;
if (!_scn_u32_dec_with_zero(argv[7], strlen(argv[7]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[4], strlen(argv[4]), &tmp)) {
print_str("{\"error\":\"`ack_clean` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_clean` expected to be integer\"}\n");
return 1; return 1;
} }
ack.clean = (bool)tmp; ack.clean = (bool)tmp;
if (!_scn_u32_dec_with_zero(argv[8], strlen(argv[8]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[5], strlen(argv[5]), &tmp)) {
print_str("{\"error\":\"`ack_wnd` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_wnd` expected to be integer\"}\n");
return 1; return 1;
} }
@ -300,7 +297,7 @@ static int _call_report_msg_acked(int argc, char **argv)
} }
ack.wnd = (uint16_t)tmp; ack.wnd = (uint16_t)tmp;
if (!_scn_u32_dec_with_zero(argv[9], strlen(argv[9]), &tmp)) { if (!_scn_u32_dec_with_zero(argv[6], strlen(argv[6]), &tmp)) {
print_str("{\"error\":\"`ack_delay` expected to be integer\"}\n"); print_str("{\"error\":\"`ack_delay` expected to be integer\"}\n");
return 1; return 1;
} }
@ -310,7 +307,8 @@ static int _call_report_msg_acked(int argc, char **argv)
} }
ack.delay = (uint16_t)tmp; ack.delay = (uint16_t)tmp;
c->super.driver->report_msg_acked(&c->super, &msg, &ack); c->super.driver->report_msg_acked(&c->super,
(congure_snd_msg_t *)_msgs.next, &ack);
print_str("{\"success\":null}\n"); print_str("{\"success\":null}\n");
return 0; return 0;
} }

View File

@ -187,6 +187,57 @@ int congure_test_call_init(int argc, char **argv);
*/ */
int congure_test_call_inter_msg_interval(int argc, char **argv); int congure_test_call_inter_msg_interval(int argc, char **argv);
/**
* @brief Adds a message from the message pool to the list for
* `cong_report msgs_lost` and `cong_report msgs_timeout`.
*
* @param[in] argc Number of @p argv. Needs to be at least 4
* @param[in] argv Three arguments are expected. Each call of the command
* represents an element of the `msgs` list parameter of
* congure_snd_driver_t::report_msgs_lost() and
* congure_snd_msg_t::report_msgs_timeout():
* - `argv[1]` (`msg_send_time`) is expected to be an
* integer for the `send_time` member of
* @ref congure_snd_msg_t,
* - `argv[2]` (`msg_size`) is expected to be an integer
* for the `size` member of @ref congure_snd_msg_t, and
* - `argv[3]` (`msg_resends`) is expected to be a an integer
* integer for the `resends` member of
* @ref congure_snd_msg_t.
*
* This function will generate the following JSON objects in STDOUT:
* - @code {"success":null} @endcode
* On success
* - @code {"error":"At least 3 arguments `msg_send_time`, `msg_size`,
* `msg_resends` expected"} @endcode
* When `argc < 4`.
* - @code {"error":"`<arg_name>` expected to be integer"} @endcode
* When `argv[i] = "<arg_name>"` is expected to be an integer but is not
* parseable
* - @code {"error":"List element pool depleted"} @endcode
* When called moret than > @ref CONFIG_CONGURE_TEST_LOST_MSG_POOL_SIZE) times
* without calling `cong_msgs_reset` in between.
*
* @retval 0 on success.
* @retval 1 on error.
*/
int congure_test_add_msg(int argc, char **argv);
/**
* @brief Resets the the message pool and messages list for
* `cong_report msgs_lost` and `cong_report msgs_timeout`.
*
* @param[in] argc Number of @p argv. Needs to be at least 1.
* @param[in] argv Command line arguments. No extra arguments are required
* except for the command name in `argv[0]`.
*
* Always generates the following JSON object in STDOUT:
* @code {"success": null} @endcode
*
* @return Always 0.
*/
int congure_test_msgs_reset(int argc, char **argv);
/** /**
* @brief Calls one of the `report_*()` methods for CongURE state object. * @brief Calls one of the `report_*()` methods for CongURE state object.
* *
@ -197,7 +248,7 @@ int congure_test_call_inter_msg_interval(int argc, char **argv);
* @see congure_snd_driver_t::report_msg_acked() * @see congure_snd_driver_t::report_msg_acked()
* @see congure_snd_driver_t::report_ecn_ce() * @see congure_snd_driver_t::report_ecn_ce()
* *
* @param[in] argc Number of @p argv. Needs to be at least 3. * @param[in] argc Number of @p argv. Needs to be at least 2.
* @param[in] argv Command line arguments. `argv[0]` needs to be the command * @param[in] argv Command line arguments. `argv[0]` needs to be the command
* name and `argv[1]` needs to one of the following * name and `argv[1]` needs to one of the following
* sub-commands that may require at least one extra arguments: * sub-commands that may require at least one extra arguments:
@ -207,66 +258,34 @@ int congure_test_call_inter_msg_interval(int argc, char **argv);
* - `msg_sent`: `argv[2]` is expected to be an integer for the * - `msg_sent`: `argv[2]` is expected to be an integer for the
* `msg_size` parameter of * `msg_size` parameter of
* congure_snd_driver_t::report_msg_discarded() * congure_snd_driver_t::report_msg_discarded()
* - `msg_timeout`: `argv` is expected to have a number of * - `msg_timeout`: no arguments are expected, but
* parameters divisible by 3 after `argv[1]` (i.e. * @ref congure_test_add_msg() should be called a number of
* `(argc - 2) % 3 == 0` must hold). Each group of 3 * times beforehand to add messages that are to be reported
* `argv[2+i]`, `argv[3+i]`, argv[4+i] (with `i` being the * timed out. The list of messages is reset after the call.
* offset of the group) represents an element in the `msgs` * - `msg_lost`: no arguments are expected, but
* list parameter of * @ref congure_test_add_msg() should be called a number of
* congure_snd_driver_t::report_msg_timeout(): * times beforehand to add messages that are to be reported
* - `argv[2+i]` (`msg_send_time`) is expected to be an * lost. The list of messages is reset after the call.
* integer for the `send_time` member of * - `msg_acked`: @ref congure_test_add_msg() must have been
* @ref congure_snd_msg_t, * called to add a message for the `msg` parameter of
* - `argv[3+i]` (`msg_size`) is expected to be a an integer * congure_snd_driver_t::report_msg_acked().
* for the `size` member of @ref congure_snd_msg_t, and * `argc` must be 8. The 6 arguments after the sub-command
* - `argv[4+i]` (`msg_resends`) is expected to be an integer * represent members of the `ack` parameter of
* integer for the `resends` member of * congure_snd_driver_t::report_msg_acked():
* @ref congure_snd_msg_t. * - `argv[2]` (`ack_recv_time`) is expected to be a an
* - `msg_lost`: `argv` is expected to have a number of
* parameters divisible by 3 after `argv[1]` (i.e.
* `(argc - 2) % 3 == 0` must hold. Each group of 3
* `argv[2+i]`, `argv[3+i]`, argv[4+i] (with `i` being the
* offset of the group) represents an element in the `msgs`
* list parameter of
* congure_snd_driver_t::report_msg_lost():
* - `argv[2+i]` (`msg_send_time`) is expected to be an
* integer for the `send_time` member of
* @ref congure_snd_msg_t,
* - `argv[3+i]` (`msg_size`) is expected to be an integer
* for the `size` member of @ref congure_snd_msg_t, and
* - `argv[4+i]` (`msg_resends`) is expected to be a an integer
* integer for the `resends` member of
* @ref congure_snd_msg_t.
* - `msg_acked`: `argc` must be 11. The first three arguments
* after `argv[1]` represent members of the `msg` parameter
* of congure_snd_driver_t::report_msg_acked():
* - `argv[2]` (`msg_send_time`) is expected to be an
* integer for the `send_time` member of
* @ref congure_snd_msg_t,
* - `argv[3]` (`msg_size`) is expected to be an integer
* for the `size` member of @ref congure_snd_msg_t, and
* - `argv[4]` (`msg_resends`) is expected to be an integer
* for the `resends` member of @ref congure_snd_msg_t.
*
* The `next` member of @ref congure_snd_msg_t will be
* initialized with `NULL`.
*
* The remaining 6 arguments represent members of the `ack`
* parameter of congure_snd_driver_t::report_msg_acked():
* - `argv[5]` (`ack_recv_time`) is expected to be a an
* integer for the `recv_time` member of * integer for the `recv_time` member of
* @ref congure_snd_ack_t, * @ref congure_snd_ack_t,
* - `argv[6]` (`ack_id`) is expected to be a an integer * - `argv[3]` (`ack_id`) is expected to be a an integer
* for the `ack_id` member of @ref congure_snd_ack_t, and * for the `ack_id` member of @ref congure_snd_ack_t, and
* - `argv[7]` (`ack_size`) is expected to be a an integer * - `argv[4]` (`ack_size`) is expected to be a an integer
* integer for the `size` member of @ref congure_snd_ack_t. * integer for the `size` member of @ref congure_snd_ack_t.
* - `argv[8]` (`ack_clean`) is expected to be a an integer * - `argv[5]` (`ack_clean`) is expected to be a an integer
* for the `clean` member of @ref congure_snd_ack_t. If * for the `clean` member of @ref congure_snd_ack_t. If
* `argv[8]` is `"0"`, `clean` will be set to `false` and to * `argv[5]` is `"0"`, `clean` will be set to `false` and to
* `true` otherwise. * `true` otherwise.
* - `argv[9]` (`ack_wnd`) is expected to be a 16-bit integer * - `argv[6]` (`ack_wnd`) is expected to be a 16-bit integer
* for the `wnd` member of @ref congure_snd_ack_t. * for the `wnd` member of @ref congure_snd_ack_t.
* - `argv[10]` (`ack_delay`) is expected to be a 16-bit * - `argv[7]` (`ack_delay`) is expected to be a 16-bit
* integer for the `delay` member of * integer for the `delay` member of
* @ref congure_snd_ack_t. * @ref congure_snd_ack_t.
* - `ecn_ce`: `argv[2]` is expected to be an integer for the * - `ecn_ce`: `argv[2]` is expected to be an integer for the
@ -296,15 +315,9 @@ int congure_test_call_inter_msg_interval(int argc, char **argv);
* arguments beyond the sub-command (i.e. `argc` needs at least to be * arguments beyond the sub-command (i.e. `argc` needs at least to be
* `<arg_num> + 2`), with the names of the arguments expected provided in * `<arg_num> + 2`), with the names of the arguments expected provided in
* `<arg_list>` as a comma-seperated list of <tt>`<arg_name>`</tt>. * `<arg_list>` as a comma-seperated list of <tt>`<arg_name>`</tt>.
* - @code {"error":"Number of arguments must be divisible by 3"} @endcode * - @code {"error":"Message not initialized"} @endcode
* When `argv[1] == "msg_timeout"` or `argv[1] == "msg_lost"` but * When `argv[0]` in `{msg_acked, msgs_lost, msgs_timout}` was not called,
* the length of the argument list after `argv[1]` is not divisible by 3 (i.e. * but no messages where added using @ref congure_test_add_msg().
* `(argc - 2) % 3 != 0`).
* - @code {"error":"List element pool depleted"} @endcode
* When `argv[1] == "msg_timeout"` or `argv[1] == "msg_lost"` and
* `(argc - 2) / 3` >= @ref CONFIG_CONGURE_TEST_LOST_MSG_POOL_SIZE).
*
* Provides no output on success.
* *
* @retval 0 on success. * @retval 0 on success.
* @retval 1 on error. * @retval 1 on error.

View File

@ -350,6 +350,14 @@ const shell_command_t _shell_command_list[] = {
congure_test_call_init }, congure_test_call_init },
{ "cong_imi", "Calls inter_message_interval method of the CongURE state object", { "cong_imi", "Calls inter_message_interval method of the CongURE state object",
congure_test_call_inter_msg_interval }, congure_test_call_inter_msg_interval },
{ "cong_add_msg",
"Adds a message to the list of messages to be reported with "
"report_msgs_lost or report_msgs_timeout",
congure_test_add_msg },
{ "cong_msgs_reset",
"Resets the list of messages to be reported with report_msgs_lost or "
"report_msgs_timeout",
congure_test_msgs_reset },
{ "cong_report", "Calls a report_* method of the CongURE state object", { "cong_report", "Calls a report_* method of the CongURE state object",
congure_test_call_report }, congure_test_call_report },
#endif #endif

View File

@ -240,6 +240,9 @@ static void _print_report_msgs_lost_state(void)
static void _print_report_msg_acked_state(void) static void _print_report_msg_acked_state(void)
{ {
clist_node_t msgs = {
.next = &_congure_state.report_msg_acked_args.msg->super,
};
print_str("\"report_msg_acked\":{"); print_str("\"report_msg_acked\":{");
print_str("\"calls\":"); print_str("\"calls\":");
@ -252,13 +255,12 @@ static void _print_report_msg_acked_state(void)
print_u32_hex((intptr_t)_congure_state.report_msg_acked_args.c); print_u32_hex((intptr_t)_congure_state.report_msg_acked_args.c);
print_str("\","); print_str("\",");
assert((_congure_state.report_msg_acked_args.msg == NULL) || /* Check sanity of `congure_test` internal message list: `cong_msg_add`
(_congure_state.report_msg_acked_args.msg->super.next == NULL)); * should have been only called at most once by the test script */
assert(clist_count(&msgs) < 2);
print_str("\"msg\":"); print_str("\"msg\":");
if (_congure_state.report_msg_acked_args.msg) { if (_congure_state.report_msg_acked_args.msg) {
_print_congure_snd_msg( _print_congure_snd_msg(msgs.next, NULL);
(clist_node_t *)_congure_state.report_msg_acked_args.msg, NULL
);
} }
else { else {
print_str("null,"); print_str("null,");

View File

@ -155,6 +155,10 @@ class TestCongUREWithSetup(TestCongUREBase):
res = self.exec_cmd('cong_setup') res = self.exec_cmd('cong_setup')
self.congure_state_ptr = int(res['success'], base=16) self.congure_state_ptr = int(res['success'], base=16)
def tearDown(self):
res = self.exec_cmd('cong_msgs_reset')
self.assertIn('success', res)
def test_init_no_args(self): def test_init_no_args(self):
res = self.exec_cmd('cong_init') res = self.exec_cmd('cong_init')
self.assertEqual(res, {'error': "`ctx` argument expected"}) self.assertEqual(res, {'error': "`ctx` argument expected"})
@ -246,37 +250,30 @@ class TestCongUREWithSetup(TestCongUREBase):
self.assertEqual(res['report_msg_discarded']['last_args']['msg_size'], self.assertEqual(res['report_msg_discarded']['last_args']['msg_size'],
msg_size) msg_size)
def _report_msgs_timeout_lost_acked_not_enough_args(self, cmd, exp_params): def _assert_report_msgs_timeout_lost_empty(self, cmd):
res = self.exec_cmd('cong_report {cmd}'.format(cmd=cmd))
self.assertEqual(res['error'], 'Message not initialized')
def _report_msgs_timeout_lost_not_enough_args(self, cmd, exp_params):
args = "" args = ""
# gradually append more arguments but never get full set # gradually append more arguments but never get full set
for i in range(len(exp_params) - 1): for i in range(len(exp_params) - 1):
args += ' {}'.format(i + 1) args += ' {}'.format(i + 1)
res = self.exec_cmd('cong_report {cmd} {args}' res = self.exec_cmd('cong_add_msg {args}'
.format(cmd=cmd, args=args)) .format(args=args))
self.assertEqual(res, { self.assertEqual(res, {
'error': 'At least {} arguments {} expected' 'error': 'At least {} arguments {} expected'
.format(len(exp_params), .format(len(exp_params),
', '.join('`{}`'.format(p) ', '.join('`{}`'.format(p)
for p in exp_params)) for p in exp_params))
}) })
self._assert_report_msgs_timeout_lost_empty(cmd)
def _report_msgs_timeout_lost_argc_not_mod_3(self, cmd): def _report_msgs_timeout_lost_args_not_int(self, cmd, exp_params):
res = self.exec_cmd('cong_report {cmd} 1 2 3 4'.format(cmd=cmd))
self.assertEqual(res, {
'error': 'Number of arguments must be divisible by 3'
})
res = self.exec_cmd('cong_report {cmd} 1 2 3 4 5'.format(cmd=cmd))
self.assertEqual(res, {
'error': 'Number of arguments must be divisible by 3'
})
def _report_msgs_timeout_lost_acked_args_not_int(self, cmd, exp_params):
# generate list of arguments that are exp_params string parameters # generate list of arguments that are exp_params string parameters
# and exp_params integer parameters
args = [chr(i + ord('a')) for i in range(len(exp_params))] args = [chr(i + ord('a')) for i in range(len(exp_params))]
if cmd != 'msg_acked': res = self.exec_cmd('cong_add_msg {}'.format(' '.join(args)))
# and exp_params integer parameters for msgs_timeout and msgs_lost
args += [str(i + len(exp_params)) for i in range(len(exp_params))]
res = self.exec_cmd('cong_report {} {}'.format(cmd, ' '.join(args)))
self.assertEqual(res, { self.assertEqual(res, {
'error': '`{}` expected to be integer'.format(exp_params[0]) 'error': '`{}` expected to be integer'.format(exp_params[0])
}) })
@ -284,20 +281,23 @@ class TestCongUREWithSetup(TestCongUREBase):
for i in range(len(exp_params) - 1): for i in range(len(exp_params) - 1):
args[i] = str(i + 1) args[i] = str(i + 1)
res = self.exec_cmd( res = self.exec_cmd(
'cong_report {} {}'.format(cmd, ' '.join(args)) 'cong_add_msg {}'.format(' '.join(args))
) )
self.assertEqual(res, { self.assertEqual(res, {
'error': '`{}` expected to be integer' 'error': '`{}` expected to be integer'
.format(exp_params[i + 1]) .format(exp_params[i + 1])
}) })
self._assert_report_msgs_timeout_lost_empty(cmd)
def _report_msgs_timeout_lost_exceed_msg_pool_size(self, cmd): def _report_msgs_timeout_lost_exceed_msg_pool_size(self, cmd):
# expected to be set by Makefile # expected to be set by Makefile
pool_size = int(os.environ.get('LOST_MSG_POOL_SIZE', 4)) pool_size = int(os.environ.get('LOST_MSG_POOL_SIZE', 4))
args = ' '.join('1' for _ in range(3 * pool_size)) args = ' '.join('1' for _ in range(3 * pool_size))
args += ' 1 1 1' args += ' 1 1 1'
res = self.exec_cmd('cong_report {cmd} {args}' for _ in range(pool_size):
.format(cmd=cmd, args=args)) res = self.exec_cmd('cong_add_msg 1 1 1')
self.assertIn('success', res)
res = self.exec_cmd('cong_add_msg 1 1 1')
self.assertEqual(res, { self.assertEqual(res, {
'error': 'List element pool depleted' 'error': 'List element pool depleted'
}) })
@ -305,12 +305,12 @@ class TestCongUREWithSetup(TestCongUREBase):
def _report_msgs_timeout_lost_success(self, cmd): def _report_msgs_timeout_lost_success(self, cmd):
msgs = [{'send_time': 76543, 'size': 1234, 'resends': 2}, msgs = [{'send_time': 76543, 'size': 1234, 'resends': 2},
{'send_time': 5432, 'size': 987, 'resends': 32}] {'send_time': 5432, 'size': 987, 'resends': 32}]
res = self.exec_cmd( for msg in msgs:
'cong_report {cmd} ' res = self.exec_cmd(
'{msgs[0][send_time]} {msgs[0][size]} {msgs[0][resends]} ' 'cong_add_msg {msg[send_time]} {msg[size]} {msg[resends]}'
'{msgs[1][send_time]} {msgs[1][size]} {msgs[1][resends]}' .format(msg=msg)
.format(cmd=cmd, msgs=msgs) )
) res = self.exec_cmd('cong_report {}'.format(cmd))
self.assertIsNone(res['success']) self.assertIsNone(res['success'])
res = self.exec_cmd('state') res = self.exec_cmd('state')
self.assertEqual(res['report_{}'.format(cmd)]['calls'], 1) self.assertEqual(res['report_{}'.format(cmd)]['calls'], 1)
@ -320,16 +320,49 @@ class TestCongUREWithSetup(TestCongUREBase):
self.assertEqual(res['report_{}'.format(cmd)]['last_args']['msgs'], self.assertEqual(res['report_{}'.format(cmd)]['last_args']['msgs'],
msgs) msgs)
def _report_msg_acked_not_enough_args(self, exp_params):
res = self.exec_cmd('cong_add_msg 0 1 2')
self.assertIn('success', res)
args = ""
# gradually append more arguments but never get full set
for i in range(len(exp_params) - 1):
args += ' {}'.format(i + 1)
res = self.exec_cmd('cong_report msg_acked {args}'
.format(args=args))
self.assertEqual(res, {
'error': 'At least {} arguments {} expected'
.format(len(exp_params),
', '.join('`{}`'.format(p)
for p in exp_params))
})
def _report_msg_acked_args_not_int(self, exp_params):
res = self.exec_cmd('cong_add_msg 0 1 2')
self.assertIn('success', res)
# generate list of arguments that are exp_params string parameters
args = [chr(i + ord('a')) for i in range(len(exp_params))]
res = self.exec_cmd('cong_report msg_acked {}'.format(' '.join(args)))
self.assertEqual(res, {
'error': '`{}` expected to be integer'.format(exp_params[0])
})
# gradually transform all but the last string to integer and test again
for i in range(len(exp_params) - 1):
args[i] = str(i + 1)
res = self.exec_cmd(
'cong_report msg_acked {}'.format(' '.join(args))
)
self.assertEqual(res, {
'error': '`{}` expected to be integer'
.format(exp_params[i + 1])
})
def test_report_msgs_timeout_not_enough_args(self): def test_report_msgs_timeout_not_enough_args(self):
self._report_msgs_timeout_lost_acked_not_enough_args( self._report_msgs_timeout_lost_not_enough_args(
'msgs_timeout', ['msg_send_time', 'msg_size', 'msg_resends'] 'msgs_timeout', ['msg_send_time', 'msg_size', 'msg_resends']
) )
def test_report_msgs_timeout_argc_not_mod_3(self):
self._report_msgs_timeout_lost_argc_not_mod_3('msgs_timeout')
def test_report_msgs_timeout_args_not_int(self): def test_report_msgs_timeout_args_not_int(self):
self._report_msgs_timeout_lost_acked_args_not_int( self._report_msgs_timeout_lost_args_not_int(
'msgs_timeout', ['msg_send_time', 'msg_size', 'msg_resends'] 'msgs_timeout', ['msg_send_time', 'msg_size', 'msg_resends']
) )
@ -340,15 +373,12 @@ class TestCongUREWithSetup(TestCongUREBase):
self._report_msgs_timeout_lost_success('msgs_timeout') self._report_msgs_timeout_lost_success('msgs_timeout')
def test_report_msgs_lost_not_enough_args(self): def test_report_msgs_lost_not_enough_args(self):
self._report_msgs_timeout_lost_acked_not_enough_args( self._report_msgs_timeout_lost_not_enough_args(
'msgs_lost', ['msg_send_time', 'msg_size', 'msg_resends'] 'msgs_lost', ['msg_send_time', 'msg_size', 'msg_resends']
) )
def test_report_msgs_lost_argc_not_mod_3(self):
self._report_msgs_timeout_lost_argc_not_mod_3('msgs_lost')
def test_report_msgs_lost_msg_args_not_int(self): def test_report_msgs_lost_msg_args_not_int(self):
self._report_msgs_timeout_lost_acked_args_not_int( self._report_msgs_timeout_lost_args_not_int(
'msgs_lost', ['msg_send_time', 'msg_size', 'msg_resends'] 'msgs_lost', ['msg_send_time', 'msg_size', 'msg_resends']
) )
@ -359,62 +389,71 @@ class TestCongUREWithSetup(TestCongUREBase):
self._report_msgs_timeout_lost_success('msgs_lost') self._report_msgs_timeout_lost_success('msgs_lost')
def test_report_msg_acked_not_enough_args(self): def test_report_msg_acked_not_enough_args(self):
self._report_msgs_timeout_lost_acked_not_enough_args( self._report_msg_acked_not_enough_args([
'msg_acked', [ 'ack_recv_time', 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd',
'msg_send_time', 'msg_size', 'msg_resends', 'ack_recv_time', 'ack_delay',
'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', 'ack_delay', ])
]
)
def test_report_msg_acked_msg_args_not_int(self): def test_report_msg_acked_msg_args_not_int(self):
self._report_msgs_timeout_lost_acked_args_not_int( self._report_msg_acked_args_not_int([
'msg_acked', [ 'ack_recv_time', 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd',
'msg_send_time', 'msg_size', 'msg_resends', 'ack_recv_time', 'ack_delay',
'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', 'ack_delay', ])
]
)
def test_report_msg_acked_wnd_not_wnd_size(self): def test_report_msg_acked_no_msg(self):
msg = {'send_time': 12345, 'size': 456, 'resends': 0} ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667,
ack = {'recv_time': 12432, 'id': 18846, 'size': 12, 'clean': 1, 'wnd': 17440, 'delay': 33325}
'clean': 1, 'wnd': (1 << 16) + 7642, 'delay': 1235}
res = self.exec_cmd( res = self.exec_cmd(
'cong_report msg_acked ' 'cong_report msg_acked '
'{msg[send_time]} {msg[size]} {msg[resends]} '
'{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} '
'{ack[wnd]} {ack[delay]}' '{ack[wnd]} {ack[delay]}'.format(ack=ack)
.format(msg=msg, ack=ack) )
self.assertEqual(res['error'], 'Message not initialized')
def test_report_msg_acked_wnd_not_wnd_size(self):
msg = {'send_time': 2862350241, 'size': 14679, 'resends': 0}
ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667,
'clean': 1, 'wnd': (1 << 16) + 17440,
'delay': 33325}
res = self.exec_cmd('cong_add_msg {msg[send_time]} {msg[size]} '
'{msg[resends]}'.format(msg=msg))
self.assertIn('success', res)
res = self.exec_cmd(
'cong_report msg_acked '
'{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} '
'{ack[wnd]} {ack[delay]}'.format(ack=ack)
) )
self.assertEqual(res, { self.assertEqual(res, {
'error': '`ack_wnd` not 16 bit wide' 'error': '`ack_wnd` not 16 bit wide'
}) })
def test_report_msg_acked_delay_not_uint16(self): def test_report_msg_acked_delay_not_uint16(self):
msg = {'send_time': 12345, 'size': 456, 'resends': 0} msg = {'send_time': 2862350241, 'size': 14679, 'resends': 0}
ack = {'recv_time': 12432, 'id': 18846, 'size': 12, ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667,
'clean': 1, 'wnd': 7642, 'delay': (1 << 16) + 1235} 'clean': 1, 'wnd': 17440, 'delay': (1 << 16) + 33325}
res = self.exec_cmd('cong_add_msg {msg[send_time]} {msg[size]} '
'{msg[resends]}'.format(msg=msg))
self.assertIn('success', res)
res = self.exec_cmd( res = self.exec_cmd(
'cong_report msg_acked ' 'cong_report msg_acked '
'{msg[send_time]} {msg[size]} {msg[resends]} '
'{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} '
'{ack[wnd]} {ack[delay]}' '{ack[wnd]} {ack[delay]}'.format(ack=ack)
.format(msg=msg, ack=ack)
) )
self.assertEqual(res, { self.assertEqual(res, {
'error': '`ack_delay` not 16 bit wide' 'error': '`ack_delay` not 16 bit wide'
}) })
def test_report_msg_acked_success(self): def test_report_msg_acked_success(self):
msg = {'send_time': 12345, 'size': 456, 'resends': 0} msg = {'send_time': 2862350241, 'size': 14679, 'resends': 0}
ack = {'recv_time': 12432, 'id': 18846, 'size': 12, ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667,
'clean': 1, 'wnd': 742, 'delay': 1235} 'clean': 1, 'wnd': 17440, 'delay': 33325}
res = self.exec_cmd('cong_add_msg {msg[send_time]} {msg[size]} '
'{msg[resends]}'.format(msg=msg))
self.assertIn('success', res)
res = self.exec_cmd( res = self.exec_cmd(
'cong_report msg_acked ' 'cong_report msg_acked '
'{msg[send_time]} {msg[size]} {msg[resends]} '
'{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} '
'{ack[wnd]} {ack[delay]}' '{ack[wnd]} {ack[delay]}'.format(ack=ack)
.format(msg=msg, ack=ack)
) )
self.assertIsNone(res['success']) self.assertIsNone(res['success'])
res = self.exec_cmd('state') res = self.exec_cmd('state')