tests: Bluetooth: ascs: Add test for ASE release on ACL disconnection

This adds test case to verify if ACL disconnects, the associated ASE
is released.

Signed-off-by: Mariusz Skamra <mariusz.skamra@codecoup.pl>
This commit is contained in:
Mariusz Skamra 2023-05-12 10:29:14 +02:00 committed by Carles Cufí
parent f5d4e9e0db
commit 6c6a66711c
4 changed files with 111 additions and 0 deletions

View file

@ -14,6 +14,7 @@
#include <zephyr/bluetooth/audio/bap.h>
#include <zephyr/bluetooth/audio/pacs.h>
#include <zephyr/bluetooth/conn.h>
#include <zephyr/bluetooth/hci_err.h>
#include <zephyr/bluetooth/gatt.h>
#include <zephyr/bluetooth/uuid.h>
#include <zephyr/sys/util_macro.h>
@ -220,3 +221,79 @@ ZTEST_F(ascs_test_suite, test_abort_client_operation_if_callback_not_registered)
param->response_code);
zassert_equal(0x00, param->reason, "unexpected Reason 0x%02x", param->reason);
}
ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection_client_terminates_cis)
{
struct bt_bap_stream *stream = &fixture->stream;
struct bt_conn *conn = &fixture->conn;
const struct bt_gatt_attr *ase;
struct bt_iso_chan *chan;
uint8_t ase_id;
if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
ase = fixture->ase_snk.attr;
ase_id = fixture->ase_snk.id;
} else {
ase = fixture->ase_src.attr;
ase_id = fixture->ase_src.id;
}
zexpect_not_null(ase);
zexpect_true(ase_id != 0x00);
bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
/* Set ASE to non-idle state */
test_preamble_state_streaming(conn, ase_id, stream, &chan,
!IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK));
/* Mock ACL disconnection */
mock_bt_conn_disconnected(conn, BT_HCI_ERR_CONN_TIMEOUT);
/* Mock CIS disconnection */
mock_bt_iso_disconnect(chan);
/* Expected to notify the upper layers */
expect_bt_bap_unicast_server_cb_release_called_once(stream);
expect_bt_bap_stream_ops_released_called_once(stream);
bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb);
}
ZTEST_F(ascs_test_suite, test_release_ase_on_acl_disconnection_server_terminates_cis)
{
struct bt_bap_stream *stream = &fixture->stream;
struct bt_conn *conn = &fixture->conn;
const struct bt_gatt_attr *ase;
struct bt_iso_chan *chan;
uint8_t ase_id;
if (IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK)) {
ase = fixture->ase_snk.attr;
ase_id = fixture->ase_snk.id;
} else {
ase = fixture->ase_src.attr;
ase_id = fixture->ase_src.id;
}
zexpect_not_null(ase);
zexpect_true(ase_id != 0x00);
bt_bap_unicast_server_register_cb(&mock_bap_unicast_server_cb);
/* Set ASE to non-idle state */
test_preamble_state_streaming(conn, ase_id, stream, &chan,
!IS_ENABLED(CONFIG_BT_ASCS_ASE_SNK));
/* Mock ACL disconnection */
mock_bt_conn_disconnected(conn, BT_HCI_ERR_CONN_TIMEOUT);
/* Client does not disconnect the CIS in expected time */
k_sleep(K_MSEC(CONFIG_BT_ASCS_ISO_DISCONNECT_DELAY));
/* Expected to notify the upper layers */
expect_bt_bap_unicast_server_cb_release_called_once(stream);
expect_bt_bap_stream_ops_released_called_once(stream);
bt_bap_unicast_server_unregister_cb(&mock_bap_unicast_server_cb);
}

View file

@ -14,4 +14,6 @@ struct bt_conn {
struct bt_conn_info info;
};
void mock_bt_conn_disconnected(struct bt_conn *conn, uint8_t err);
#endif /* MOCKS_CONN_H_ */

View file

@ -29,3 +29,12 @@ void bt_conn_unref(struct bt_conn *conn)
{
}
void mock_bt_conn_disconnected(struct bt_conn *conn, uint8_t err)
{
STRUCT_SECTION_FOREACH(bt_conn_cb, cb) {
if (cb->disconnected) {
cb->disconnected(conn, err);
}
}
}

View file

@ -38,10 +38,12 @@ int k_work_reschedule(struct k_work_delayable *dwork, k_timeout_t delay)
/* Determine whether the work item is queued already. */
SYS_SLIST_FOR_EACH_CONTAINER(&work_pending, work, node) {
if (work == &dwork->work) {
dwork->timeout.dticks = delay.ticks;
return 0;
}
}
dwork->timeout.dticks = delay.ticks;
sys_slist_append(&work_pending, &dwork->work.node);
return 0;
@ -54,6 +56,27 @@ int k_work_cancel_delayable(struct k_work_delayable *dwork)
return 0;
}
int32_t k_sleep(k_timeout_t timeout)
{
struct k_work *work;
SYS_SLIST_FOR_EACH_CONTAINER(&work_pending, work, node) {
if (work->flags & K_WORK_DELAYED) {
struct k_work_delayable *dwork = k_work_delayable_from_work(work);
if (dwork->timeout.dticks > timeout.ticks) {
dwork->timeout.dticks -= timeout.ticks;
continue;
}
}
(void)sys_slist_remove(&work_pending, NULL, &work->node);
work->handler(work);
}
return 0;
}
void mock_kernel_init(void)
{
FFF_FAKES_LIST(RESET_FAKE);