diff --git a/sys/congure/Kconfig b/sys/congure/Kconfig index 2cc77d5001..ce189fc382 100644 --- a/sys/congure/Kconfig +++ b/sys/congure/Kconfig @@ -8,6 +8,7 @@ if !TEST_KCONFIG menu "CongURE congestion control abstraction" depends on USEMODULE_CONGURE +rsource "mock/Kconfig" rsource "test/Kconfig" endmenu # CongURE congestion control abstraction @@ -20,6 +21,7 @@ menuconfig MODULE_CONGURE if MODULE_CONGURE +rsource "mock/Kconfig" rsource "test/Kconfig" endif # MODULE_CONGURE diff --git a/sys/congure/Makefile b/sys/congure/Makefile index 12697067ff..37c69ac62f 100644 --- a/sys/congure/Makefile +++ b/sys/congure/Makefile @@ -1,3 +1,6 @@ +ifneq (,$(filter congure_mock,$(USEMODULE))) + DIRS += mock +endif ifneq (,$(filter congure_test,$(USEMODULE))) DIRS += test endif diff --git a/sys/congure/mock/Kconfig b/sys/congure/mock/Kconfig new file mode 100644 index 0000000000..20355df2a8 --- /dev/null +++ b/sys/congure/mock/Kconfig @@ -0,0 +1,3 @@ +config MODULE_CONGURE_MOCK + bool "CongURE mock implementation for testing" + depends on MODULE_CONGURE diff --git a/sys/congure/mock/Makefile b/sys/congure/mock/Makefile new file mode 100644 index 0000000000..ce7732052a --- /dev/null +++ b/sys/congure/mock/Makefile @@ -0,0 +1,3 @@ +MODULE := congure_mock + +include $(RIOTBASE)/Makefile.base diff --git a/sys/congure/mock/congure_mock.c b/sys/congure/mock/congure_mock.c new file mode 100644 index 0000000000..840e3b734b --- /dev/null +++ b/sys/congure/mock/congure_mock.c @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2021 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @{ + * + * @file + * @author Martine Lenders + */ + +#include "congure/mock.h" + +static void _snd_init(congure_snd_t *cong, void *ctx); +static int32_t _snd_inter_msg_interval(congure_snd_t *cong, unsigned msg_size); +static void _snd_report_msg_sent(congure_snd_t *cong, unsigned msg_size); +static void _snd_report_msg_discarded(congure_snd_t *cong, unsigned msg_size); +static void _snd_report_msgs_lost(congure_snd_t *cong, congure_snd_msg_t *msgs); +static void _snd_report_msgs_timeout(congure_snd_t *cong, + congure_snd_msg_t *msgs); +static void _snd_report_msg_acked(congure_snd_t *cong, congure_snd_msg_t *msg, + congure_snd_ack_t *ack); +static void _snd_report_ecn_ce(congure_snd_t *cong, ztimer_now_t time); + +static const congure_snd_driver_t _driver = { + .init = _snd_init, + .inter_msg_interval = _snd_inter_msg_interval, + .report_msg_sent = _snd_report_msg_sent, + .report_msg_discarded = _snd_report_msg_discarded, + .report_msgs_timeout = _snd_report_msgs_timeout, + .report_msgs_lost = _snd_report_msgs_lost, + .report_msg_acked = _snd_report_msg_acked, + .report_ecn_ce = _snd_report_ecn_ce, +}; + +void congure_mock_snd_setup(congure_mock_snd_t *c) +{ + c->super.driver = &_driver; +} + +static void _snd_init(congure_snd_t *cong, void *ctx) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->init_calls++; + c->init_args.c = &c->super; + c->init_args.ctx = ctx; +} + +static int32_t _snd_inter_msg_interval(congure_snd_t *cong, unsigned msg_size) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->inter_msg_interval_calls++; + c->inter_msg_interval_args.c = &c->super; + c->inter_msg_interval_args.msg_size = msg_size; + return -1; +} + +static void _snd_report_msg_sent(congure_snd_t *cong, unsigned msg_size) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_msg_sent_calls++; + c->report_msg_sent_args.c = &c->super; + c->report_msg_sent_args.msg_size = msg_size; +} + +static void _snd_report_msg_discarded(congure_snd_t *cong, unsigned msg_size) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_msg_discarded_calls++; + c->report_msg_discarded_args.c = &c->super; + c->report_msg_discarded_args.msg_size = msg_size; +} + +static void _snd_report_msgs_lost(congure_snd_t *cong, congure_snd_msg_t *msgs) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_msgs_lost_calls++; + c->report_msgs_lost_args.c = &c->super; + c->report_msgs_lost_args.msgs = msgs; +} + +static void _snd_report_msgs_timeout(congure_snd_t *cong, + congure_snd_msg_t *msgs) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_msgs_timeout_calls++; + c->report_msgs_timeout_args.c = &c->super; + c->report_msgs_timeout_args.msgs = msgs; +} + +static void _snd_report_msg_acked(congure_snd_t *cong, congure_snd_msg_t *msg, + congure_snd_ack_t *ack) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_msg_acked_calls++; + c->report_msg_acked_args.c = &c->super; + c->report_msg_acked_args.msg = msg; + c->report_msg_acked_args.ack = ack; +} + +static void _snd_report_ecn_ce(congure_snd_t *cong, ztimer_now_t time) +{ + congure_mock_snd_t *c = (congure_mock_snd_t *)cong; + + c->report_ecn_ce_calls++; + c->report_ecn_ce_args.c = &c->super; + c->report_ecn_ce_args.time = time; +} + +/** @} */ diff --git a/sys/include/congure/mock.h b/sys/include/congure/mock.h new file mode 100644 index 0000000000..d93ea49a1a --- /dev/null +++ b/sys/include/congure/mock.h @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2021 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @defgroup sys_congure_mock CongURE mock implementation + * @ingroup sys_congure + * @brief A mock for testing @ref sys_congure + * @{ + * + * @file + * + * @author Martine S. Lenders + */ +#ifndef CONGURE_MOCK_H +#define CONGURE_MOCK_H + +#include + +#include "congure.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief A mock CongURE state object + * + * @extends congure_snd_t + */ +typedef struct { + congure_snd_t super; /**< see @ref congure_snd_t */ + /** + * @brief How often was the congure_snd_driver_t::init() method called? + */ + uint8_t init_calls; + /** + * @brief How often was the congure_snd_driver_t::inter_msg_interval() + * method called? + */ + uint8_t inter_msg_interval_calls; + /** + * @brief How often was the congure_snd_driver_t::report_msg_sent() + * method called? + */ + uint8_t report_msg_sent_calls; + /** + * @brief How often was the congure_snd_driver_t::report_msg_discarded() + * method called? + */ + uint8_t report_msg_discarded_calls; + /** + * @brief How often was the congure_snd_driver_t::report_msgs_timeout() + * method called? + */ + uint8_t report_msgs_timeout_calls; + /** + * @brief How often was the congure_snd_driver_t::report_msgs_lost() + * method called? + */ + uint8_t report_msgs_lost_calls; + /** + * @brief How often was the congure_snd_driver_t::report_msg_acked() + * method called? + */ + uint8_t report_msg_acked_calls; + /** + * @brief How often was the congure_snd_driver_t::report_ecn_ce() + * method called? + */ + uint8_t report_ecn_ce_calls; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::init() call? + */ + struct { + congure_snd_t *c; /**< The CongURE object to initialize */ + void *ctx; /**< Context for callbacks specific to CC */ + } init_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::inter_msg_interval() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + unsigned msg_size; /**< The size of the next message to send */ + } inter_msg_interval_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_msg_sent() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + unsigned msg_size; /**< Size of the message */ + } report_msg_sent_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_msg_discarded() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + unsigned msg_size; /**< Size of the message */ + } report_msg_discarded_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_msgs_timeout() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + /** + * @brief A collection of messages for which the ACK timed out + */ + congure_snd_msg_t *msgs; + } report_msgs_timeout_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_msgs_lost() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + /** + * @brief A collection of messages that are known to be lost + */ + congure_snd_msg_t *msgs; + } report_msgs_lost_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_msg_acked() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + congure_snd_msg_t *msg; /**< The ACK'd message */ + congure_snd_ack_t *ack; /**< The received ACK */ + } report_msg_acked_args; + /** + * @brief What were the arguments for the last + * congure_snd_driver_t::report_ecn_ce() call? + */ + struct { + congure_snd_t *c; /**< The CongURE state object */ + /** + * @brief Timestamp of the message the CE event occurred for was sent + */ + ztimer_now_t time; + } report_ecn_ce_args; +} congure_mock_snd_t; + +/** + * @brief Sets up the driver for CongURE mock object + * + * @param[in] c A CongURE mock object + */ +void congure_mock_snd_setup(congure_mock_snd_t *c); + +#ifdef __cplusplus +} +#endif + +#endif /* CONGURE_MOCK_H */ +/** @} */