diff --git a/sys/congure/test/congure_test.c b/sys/congure/test/congure_test.c index 675dd18b9f23..891a9737908f 100644 --- a/sys/congure/test/congure_test.c +++ b/sys/congure/test/congure_test.c @@ -18,10 +18,15 @@ #include #include +#include "clist.h" #include "fmt.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) { 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) { - (void)argc; - (void)argv; memset(congure_test_get_state(), 0, sizeof(congure_test_snd_t)); - print_str("{\"success\":null}\n"); + congure_test_msgs_reset(argc, argv); return 0; } @@ -126,6 +129,56 @@ int congure_test_call_inter_msg_interval(int argc, char **argv) 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) { 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 *, - congure_snd_msg_t *), - int argc, char **argv) + congure_snd_msg_t *)) { - 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(); - if (argc < 4) { - print_str("{\"error\":\"At least 3 arguments `msg_send_time`, " - "`msg_size`, `msg_resends` expected\"}\n"); + if (_msgs.next == NULL) { + print_str("{\"error\":\"Message not initialized\"}\n"); return 1; } - if ((argc - 1) % 3) { - 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); + method(&c->super, (congure_snd_msg_t *)_msgs.next); print_str("{\"success\":null}\n"); 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(); - return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_timeout, - argc, argv); + (void)argc; + (void)argv; + return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_timeout); } static int _call_report_msgs_lost(int argc, char **argv) { congure_test_snd_t *c = congure_test_get_state(); - return _call_report_msgs_timeout_lost(c->super.driver->report_msgs_lost, - argc, argv); + (void)argc; + (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 congure_snd_msg_t msg = { .size = 0 }; static congure_snd_ack_t ack = { .size = 0 }; congure_test_snd_t *c = congure_test_get_state(); uint32_t tmp; - if (argc < 10) { - print_str("{\"error\":\"At least 9 arguments `msg_send_time`, " - "`msg_size`, `msg_resends`, `ack_recv_time`, `ack_id`, " - "`ack_size`, `ack_clean`, `ack_wnd`, `ack_delay` " - "expected\"}\n"); - return 1; - } - 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"); + if (_msgs.next == NULL) { + print_str("{\"error\":\"Message not initialized\"}\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"); + 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"); return 1; } - msg.resends = tmp; - - if (!_scn_u32_dec_with_zero(argv[4], strlen(argv[4]), &tmp)) { + if (!_scn_u32_dec_with_zero(argv[1], strlen(argv[1]), &tmp)) { print_str("{\"error\":\"`ack_recv_time` expected to be integer\"}\n"); return 1; } 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"); return 1; } 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"); return 1; } 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"); return 1; } 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"); return 1; } @@ -300,7 +297,7 @@ static int _call_report_msg_acked(int argc, char **argv) } 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"); return 1; } @@ -310,7 +307,8 @@ static int _call_report_msg_acked(int argc, char **argv) } 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"); return 0; } diff --git a/sys/include/congure/test.h b/sys/include/congure/test.h index 3383aa69622f..f76cecdabda3 100644 --- a/sys/include/congure/test.h +++ b/sys/include/congure/test.h @@ -187,6 +187,57 @@ int congure_test_call_init(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":"`` expected to be integer"} @endcode + * When `argv[i] = ""` 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. * @@ -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_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 * name and `argv[1]` needs to one of the following * 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_size` parameter of * congure_snd_driver_t::report_msg_discarded() - * - `msg_timeout`: `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_timeout(): - * - `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 a an integer - * for the `size` member of @ref congure_snd_msg_t, and - * - `argv[4+i]` (`msg_resends`) is expected to be an integer - * integer for the `resends` member of - * @ref congure_snd_msg_t. - * - `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 + * - `msg_timeout`: no arguments are expected, but + * @ref congure_test_add_msg() should be called a number of + * times beforehand to add messages that are to be reported + * timed out. The list of messages is reset after the call. + * - `msg_lost`: no arguments are expected, but + * @ref congure_test_add_msg() should be called a number of + * times beforehand to add messages that are to be reported + * lost. The list of messages is reset after the call. + * - `msg_acked`: @ref congure_test_add_msg() must have been + * called to add a message for the `msg` parameter of + * congure_snd_driver_t::report_msg_acked(). + * `argc` must be 8. The 6 arguments after the sub-command + * represent members of the `ack` parameter of + * congure_snd_driver_t::report_msg_acked(): + * - `argv[2]` (`ack_recv_time`) is expected to be a an * integer for the `recv_time` member of * @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 - * - `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. - * - `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 - * `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. - * - `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. - * - `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 * @ref congure_snd_ack_t. * - `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 * ` + 2`), with the names of the arguments expected provided in * `` as a comma-seperated list of ``. - * - @code {"error":"Number of arguments must be divisible by 3"} @endcode - * When `argv[1] == "msg_timeout"` or `argv[1] == "msg_lost"` but - * the length of the argument list after `argv[1]` is not divisible by 3 (i.e. - * `(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. + * - @code {"error":"Message not initialized"} @endcode + * When `argv[0]` in `{msg_acked, msgs_lost, msgs_timout}` was not called, + * but no messages where added using @ref congure_test_add_msg(). * * @retval 0 on success. * @retval 1 on error. diff --git a/sys/shell/commands/shell_commands.c b/sys/shell/commands/shell_commands.c index 50dc2ce4b110..02aca6fd3430 100644 --- a/sys/shell/commands/shell_commands.c +++ b/sys/shell/commands/shell_commands.c @@ -350,6 +350,14 @@ const shell_command_t _shell_command_list[] = { congure_test_call_init }, { "cong_imi", "Calls inter_message_interval method of the CongURE state object", 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", congure_test_call_report }, #endif diff --git a/tests/congure_test/main.c b/tests/congure_test/main.c index bc72ab50f14c..ab7558dde7ae 100644 --- a/tests/congure_test/main.c +++ b/tests/congure_test/main.c @@ -240,6 +240,9 @@ static void _print_report_msgs_lost_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("\"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_str("\","); - assert((_congure_state.report_msg_acked_args.msg == NULL) || - (_congure_state.report_msg_acked_args.msg->super.next == NULL)); + /* Check sanity of `congure_test` internal message list: `cong_msg_add` + * should have been only called at most once by the test script */ + assert(clist_count(&msgs) < 2); print_str("\"msg\":"); if (_congure_state.report_msg_acked_args.msg) { - _print_congure_snd_msg( - (clist_node_t *)_congure_state.report_msg_acked_args.msg, NULL - ); + _print_congure_snd_msg(msgs.next, NULL); } else { print_str("null,"); diff --git a/tests/congure_test/tests/01-run.py b/tests/congure_test/tests/01-run.py index dd4e24d55a0d..ea58fc8d9055 100755 --- a/tests/congure_test/tests/01-run.py +++ b/tests/congure_test/tests/01-run.py @@ -155,6 +155,10 @@ def setUp(self): res = self.exec_cmd('cong_setup') 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): res = self.exec_cmd('cong_init') self.assertEqual(res, {'error': "`ctx` argument expected"}) @@ -246,37 +250,30 @@ def test_report_msg_discarded_success(self): self.assertEqual(res['report_msg_discarded']['last_args']['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 = "" # 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 {cmd} {args}' - .format(cmd=cmd, args=args)) + res = self.exec_cmd('cong_add_msg {args}' + .format(args=args)) self.assertEqual(res, { 'error': 'At least {} arguments {} expected' .format(len(exp_params), ', '.join('`{}`'.format(p) for p in exp_params)) }) + self._assert_report_msgs_timeout_lost_empty(cmd) - def _report_msgs_timeout_lost_argc_not_mod_3(self, cmd): - 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): + def _report_msgs_timeout_lost_args_not_int(self, cmd, exp_params): # 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))] - if cmd != 'msg_acked': - # 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))) + res = self.exec_cmd('cong_add_msg {}'.format(' '.join(args))) self.assertEqual(res, { 'error': '`{}` expected to be integer'.format(exp_params[0]) }) @@ -284,20 +281,23 @@ def _report_msgs_timeout_lost_acked_args_not_int(self, cmd, exp_params): for i in range(len(exp_params) - 1): args[i] = str(i + 1) res = self.exec_cmd( - 'cong_report {} {}'.format(cmd, ' '.join(args)) + 'cong_add_msg {}'.format(' '.join(args)) ) self.assertEqual(res, { 'error': '`{}` expected to be integer' .format(exp_params[i + 1]) }) + self._assert_report_msgs_timeout_lost_empty(cmd) def _report_msgs_timeout_lost_exceed_msg_pool_size(self, cmd): # expected to be set by Makefile pool_size = int(os.environ.get('LOST_MSG_POOL_SIZE', 4)) args = ' '.join('1' for _ in range(3 * pool_size)) args += ' 1 1 1' - res = self.exec_cmd('cong_report {cmd} {args}' - .format(cmd=cmd, args=args)) + for _ in range(pool_size): + 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, { 'error': 'List element pool depleted' }) @@ -305,12 +305,12 @@ def _report_msgs_timeout_lost_exceed_msg_pool_size(self, cmd): def _report_msgs_timeout_lost_success(self, cmd): msgs = [{'send_time': 76543, 'size': 1234, 'resends': 2}, {'send_time': 5432, 'size': 987, 'resends': 32}] - res = self.exec_cmd( - 'cong_report {cmd} ' - '{msgs[0][send_time]} {msgs[0][size]} {msgs[0][resends]} ' - '{msgs[1][send_time]} {msgs[1][size]} {msgs[1][resends]}' - .format(cmd=cmd, msgs=msgs) - ) + for msg in msgs: + res = self.exec_cmd( + 'cong_add_msg {msg[send_time]} {msg[size]} {msg[resends]}' + .format(msg=msg) + ) + res = self.exec_cmd('cong_report {}'.format(cmd)) self.assertIsNone(res['success']) res = self.exec_cmd('state') self.assertEqual(res['report_{}'.format(cmd)]['calls'], 1) @@ -320,16 +320,49 @@ def _report_msgs_timeout_lost_success(self, cmd): self.assertEqual(res['report_{}'.format(cmd)]['last_args']['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): - 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'] ) - 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): - 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'] ) @@ -340,15 +373,12 @@ def test_report_msgs_timeout_success(self): self._report_msgs_timeout_lost_success('msgs_timeout') 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'] ) - 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): - 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'] ) @@ -359,62 +389,71 @@ def test_report_msgs_lost_success(self): self._report_msgs_timeout_lost_success('msgs_lost') def test_report_msg_acked_not_enough_args(self): - self._report_msgs_timeout_lost_acked_not_enough_args( - 'msg_acked', [ - 'msg_send_time', 'msg_size', 'msg_resends', 'ack_recv_time', - 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', 'ack_delay', - ] - - ) + self._report_msg_acked_not_enough_args([ + 'ack_recv_time', 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', + 'ack_delay', + ]) def test_report_msg_acked_msg_args_not_int(self): - self._report_msgs_timeout_lost_acked_args_not_int( - 'msg_acked', [ - 'msg_send_time', 'msg_size', 'msg_resends', 'ack_recv_time', - 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', 'ack_delay', - ] + self._report_msg_acked_args_not_int([ + 'ack_recv_time', 'ack_id', 'ack_size', 'ack_clean', 'ack_wnd', + 'ack_delay', + ]) + + def test_report_msg_acked_no_msg(self): + ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667, + 'clean': 1, 'wnd': 17440, 'delay': 33325} + 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['error'], 'Message not initialized') def test_report_msg_acked_wnd_not_wnd_size(self): - msg = {'send_time': 12345, 'size': 456, 'resends': 0} - ack = {'recv_time': 12432, 'id': 18846, 'size': 12, - 'clean': 1, 'wnd': (1 << 16) + 7642, 'delay': 1235} + 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 ' - '{msg[send_time]} {msg[size]} {msg[resends]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' - '{ack[wnd]} {ack[delay]}' - .format(msg=msg, ack=ack) + '{ack[wnd]} {ack[delay]}'.format(ack=ack) ) self.assertEqual(res, { 'error': '`ack_wnd` not 16 bit wide' }) def test_report_msg_acked_delay_not_uint16(self): - msg = {'send_time': 12345, 'size': 456, 'resends': 0} - ack = {'recv_time': 12432, 'id': 18846, 'size': 12, - 'clean': 1, 'wnd': 7642, 'delay': (1 << 16) + 1235} + msg = {'send_time': 2862350241, 'size': 14679, 'resends': 0} + ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667, + '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( 'cong_report msg_acked ' - '{msg[send_time]} {msg[size]} {msg[resends]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' - '{ack[wnd]} {ack[delay]}' - .format(msg=msg, ack=ack) + '{ack[wnd]} {ack[delay]}'.format(ack=ack) ) self.assertEqual(res, { 'error': '`ack_delay` not 16 bit wide' }) def test_report_msg_acked_success(self): - msg = {'send_time': 12345, 'size': 456, 'resends': 0} - ack = {'recv_time': 12432, 'id': 18846, 'size': 12, - 'clean': 1, 'wnd': 742, 'delay': 1235} + msg = {'send_time': 2862350241, 'size': 14679, 'resends': 0} + ack = {'recv_time': 2862350405, 'id': 1197554483, 'size': 14667, + '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( 'cong_report msg_acked ' - '{msg[send_time]} {msg[size]} {msg[resends]} ' '{ack[recv_time]} {ack[id]} {ack[size]} {ack[clean]} ' - '{ack[wnd]} {ack[delay]}' - .format(msg=msg, ack=ack) + '{ack[wnd]} {ack[delay]}'.format(ack=ack) ) self.assertIsNone(res['success']) res = self.exec_cmd('state')