2023-10-10 15:39:21

by Iulia Tanasescu

[permalink] [raw]
Subject: [PATCH BlueZ v2 0/1] test-bass: Add unit tests for the SPE suite

This patch series adds BASS unit tests for the Service Procedures Error
Handling suite.

Iulia Tanasescu (1):
test-bass: Add unit tests for the SPE suite

unit/test-bass.c | 430 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 428 insertions(+), 2 deletions(-)


base-commit: d4a0d223eaa5d220263be1f3ad0cd396869f6245
--
2.39.2


2023-10-10 15:39:28

by Iulia Tanasescu

[permalink] [raw]
Subject: [PATCH BlueZ v2 1/1] test-bass: Add unit tests for the SPE suite

This adds BASS unit tests for the Service Procedures Error
Handling suite.

---
unit/test-bass.c | 430 ++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 428 insertions(+), 2 deletions(-)

diff --git a/unit/test-bass.c b/unit/test-bass.c
index 2ab61f760..ace47d9ed 100644
--- a/unit/test-bass.c
+++ b/unit/test-bass.c
@@ -190,6 +190,301 @@ struct ccc_state {
DISC_BCAST_AUDIO_SCAN_CP, \
BASS_READ_CHAR_DESC

+/* ATT: Write Request (0x12) len 4
+ * Handle: 0x0004 Type: Client Characteristic Configuration (0x2902)
+ * Data: 0100
+ * Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ * ATT: Write Request (0x12) len 4
+ * Handle: 0x0007 Type: Client Characteristic Configuration (0x2902)
+ * Data: 0100
+ * Notification (0x01)
+ * ATT: Write Response (0x13) len 0
+ */
+#define BASS_WRITE_CHAR_DESC \
+ IOV_DATA(0x12, 0x04, 0x00, 0x01, 0x00), \
+ IOV_DATA(0x13), \
+ IOV_DATA(0x12, 0x07, 0x00, 0x01, 0x00), \
+ IOV_DATA(0x13)
+
+/* ATT: Read Request (0x0a) len 2
+ * Handle: 0x0003 Type: Broadcast Receive State (0x2bc8)
+ * ATT: Read Response (0x0b) len 0
+ * Handle: 0x0003 Broadcast Receive State (0x2bc8)
+ * ATT: Read Request (0x0a) len 2
+ * Handle: 0x0006 Type: Broadcast Receive State (0x2bc8)
+ * ATT: Read Response (0x0b) len 0
+ * Handle: 0x0006 Broadcast Receive State (0x2bc8)
+ */
+#define BASS_READ_BCAST_RECV_STATE_CHARS \
+ IOV_DATA(0x0a, 0x03, 0x00), \
+ IOV_DATA(0x0b), \
+ IOV_DATA(0x0a, 0x06, 0x00), \
+ IOV_DATA(0x0b)
+
+#define BASS_CP_WRITE_CMD(_op, _args...) \
+ IOV_DATA(0x52, 0x09, 0x00, _op, _args)
+
+#define BASS_CP_WRITE_REQ(_op, _args...) \
+ IOV_DATA(0x12, 0x09, 0x00, _op, _args)
+
+/* ATT: Write Command (0x52) len 19
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0401693C4572685526613465597073275455
+ * Opcode: Set Broadcast_Code
+ * Source_ID: 1
+ * Broadcast_Code: 0x55542773705965346126556872453c69
+ * ATT: Write Command (0x52) len 2
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0501
+ * Opcode: Remove Source
+ * Source_ID: 1
+ */
+#define IGNORE_INVALID_SRC_ID \
+ EXCHANGE_MTU, \
+ BASS_FIND_BY_TYPE_VALUE, \
+ DISC_BASS_CHAR, \
+ BASS_FIND_INFO, \
+ BASS_WRITE_CHAR_DESC, \
+ BASS_READ_BCAST_RECV_STATE_CHARS, \
+ BASS_CP_WRITE_CMD(0x04, 0x01, 0x69, 0x3C, 0x45, 0x72, 0x68, \
+ 0x55, 0x26, 0x61, 0x34, 0x65, 0x59, 0x70, \
+ 0x73, 0x27, 0x54, 0x55), \
+ IOV_NULL, \
+ BASS_CP_WRITE_CMD(0x05, 0x01)
+
+/* ATT: Write Command (0x52) len 26
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0200F2698BE807C0003412000610270200000000000000000000
+ * Opcode: Add Source
+ * Advertiser_Address_Type: Public Device or Public Identity Address
+ * Advertiser_Address: c0:07:e8:8b:69:f2
+ * Advertising_SID: 0x00
+ * Broadcast_ID: 0x001234
+ * PA_Sync: 0x06 (Reserved for Future Use)
+ * PA_Interval: 0x2710
+ * Num_Subgroups: 2
+ * Subgroup #0:
+ * BIS_Sync: 00000000000000000000000000000000
+ * Metadata_Length: 0
+ * Subgroup #1:
+ * BIS_Sync: 00000000000000000000000000000000
+ * Metadata_Length: 0
+ * ATT: Write Command (0x52) len 26
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0205F2698BE807C0003412000210270200000000000000000000
+ * Opcode: Add Source
+ * Advertiser_Address_Type: 0x05 (Reserved for Future Use)
+ * Advertiser_Address: c0:07:e8:8b:69:f2
+ * Advertising_SID: 0x00
+ * Broadcast_ID: 0x001234
+ * PA_Sync: Synchronize to PA (PAST not available)
+ * PA_Interval: 0x2710
+ * Num_Subgroups: 2
+ * Subgroup #0:
+ * BIS_Sync: 00000000000000000000000000000000
+ * Metadata_Length: 0
+ * Subgroup #1:
+ * BIS_Sync: 00000000000000000000000000000000
+ * Metadata_Length: 0
+ * ATT: Write Command (0x52) len 26
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0200F2698BE807C0003412000210270201000000000100000000
+ * Opcode: Add Source
+ * Advertiser_Address_Type: Public Device or Public Identity Address
+ * Advertiser_Address: c0:07:e8:8b:69:f2
+ * Advertising_SID: 0x00
+ * Broadcast_ID: 0x001234
+ * PA_Sync: Synchronize to PA (PAST not available)
+ * PA_Interval: 0x2710
+ * Num_Subgroups: 2
+ * Subgroup #0:
+ * BIS_Sync: 00000000000000000000000000000001
+ * Metadata_Length: 0
+ * Subgroup #1:
+ * BIS_Sync: 00000000000000000000000000000001
+ * Metadata_Length: 0
+ */
+#define ADD_SRC_INVALID_PARAMS \
+ EXCHANGE_MTU, \
+ BASS_FIND_BY_TYPE_VALUE, \
+ DISC_BASS_CHAR, \
+ BASS_FIND_INFO, \
+ BASS_WRITE_CHAR_DESC,\
+ BASS_READ_BCAST_RECV_STATE_CHARS, \
+ BASS_CP_WRITE_CMD(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+ 0x00, 0x34, 0x12, 0x00, 0x06, 0x10, 0x27, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00), \
+ IOV_NULL, \
+ BASS_CP_WRITE_CMD(0x02, 0x05, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+ 0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00), \
+ IOV_NULL, \
+ BASS_CP_WRITE_CMD(0x02, 0x05, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+ 0x3F, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00), \
+ IOV_NULL, \
+ BASS_CP_WRITE_CMD(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+ 0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x02, \
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, \
+ 0x00, 0x00)
+
+/* ATT: Write Request (0x12) len 3
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: FF
+ * Opcode: 0xff (Reserved For Future Use)
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Opcode Not Supported (0x80)
+ */
+#define OPCODE_NOT_SUPPORTED \
+ EXCHANGE_MTU, \
+ BASS_FIND_BY_TYPE_VALUE, \
+ DISC_BASS_CHAR, \
+ BASS_FIND_INFO, \
+ BASS_WRITE_CHAR_DESC,\
+ BASS_READ_BCAST_RECV_STATE_CHARS, \
+ BASS_CP_WRITE_REQ(0xFF), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x80)
+
+/* ATT: Write Request (0x12) len 5
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 006dfe
+ * Opcode: Remote Scan Stopped
+ * Extra Data: 0xfe6d
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 5
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 006dfe
+ * Opcode: Remote Scan Started
+ * Extra Data: 0xa2c2
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 25
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0200F2698BE807C0003412000210270100000000000000
+ * Opcode: Add Source
+ * Advertiser_Address_Type: Public Device or Public Identity Address
+ * Advertiser_Address: c0:07:e8:8b:69:f2
+ * Advertising_SID: 0x00
+ * Broadcast_ID: 0x001234
+ * PA_Sync: Synchronize to PA (PAST not available)
+ * PA_Interval: 0x2710
+ * Num_Subgroups: 1
+ * Subgroup #0:
+ * BIS_Sync: 00000000000000000000000000000001
+ * Metadata_Length: 0
+ * Extra Data: 0x0000
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 13
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 03000210270100000000001500
+ * Opcode: Modify Source
+ * Source_ID: 0x00
+ * PA_Sync: Synchronize to PA (PAST not available)
+ * PA_Interval: 0x2710
+ * Num_Subgroups: 1
+ * Subgroup #0:
+ * BIS_Sync: 00000000000000000000000000000001
+ * Metadata_Length: 0
+ * Extra Data: 0x0015
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 20
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0400B803EAC6AFBB65A25A41F153056802010000
+ * Opcode: Set Broadcast_Code
+ * Source_ID: 0x00
+ * Broadcast_Code: 0x0102680553f1415aa265bbafc6ea03b8
+ * Extra Data: 0x0000
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ * ATT: Write Request (0x12) len 4
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 05008F13
+ * Opcode: Remove Source
+ * Source_ID: 0x00
+ * Extra Data: 0x138f
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Write Request Rejected (0xFC)
+ */
+#define INVALID_LEN \
+ EXCHANGE_MTU, \
+ BASS_FIND_BY_TYPE_VALUE, \
+ DISC_BASS_CHAR, \
+ BASS_FIND_INFO, \
+ BASS_WRITE_CHAR_DESC,\
+ BASS_READ_BCAST_RECV_STATE_CHARS, \
+ BASS_CP_WRITE_REQ(0x00, 0x6D, 0xFE), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+ BASS_CP_WRITE_REQ(0x01, 0xC2, 0xA2), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+ BASS_CP_WRITE_REQ(0x02, 0x00, 0xF2, 0x69, 0x8B, 0xE8, 0x07, 0xC0, \
+ 0x00, 0x34, 0x12, 0x00, 0x02, 0x10, 0x27, 0x01, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+ BASS_CP_WRITE_REQ(0x03, 0x00, 0x02, 0x10, 0x27, 0x01, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x15, 0x00), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+ BASS_CP_WRITE_REQ(0x04, 0x00, 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, \
+ 0x65, 0xA2, 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, \
+ 0x02, 0x01, 0x00, 0x00), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC), \
+ BASS_CP_WRITE_REQ(0x05, 0x00, 0x8F, 0x13), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0xFC)
+
+/* ATT: Write Request (0x12) len 20
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 0400B803EAC6AFBB65A25A41F153056802010000
+ * Opcode: Set Broadcast_Code
+ * Source_ID: 0x05
+ * Broadcast_Code: 0x0102680553f1415aa265bbafc6ea03b
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Invalid Source ID (0x81)
+ * ATT: Write Request (0x12) len 4
+ * Handle: 0x0009 Type: Broadcast Audio Scan Control Point (0x2bc7)
+ * Data: 005
+ * Opcode: Remove Source
+ * Source_ID: 0x05
+ * ATT: Error Response (0x01) len 4
+ * Write Request (0x12)
+ * Handle: 0x0009
+ * Error: Invalid Source ID (0x81)
+ */
+#define INVALID_SRC_ID \
+ EXCHANGE_MTU, \
+ BASS_FIND_BY_TYPE_VALUE, \
+ DISC_BASS_CHAR, \
+ BASS_FIND_INFO, \
+ BASS_WRITE_CHAR_DESC, \
+ BASS_READ_BCAST_RECV_STATE_CHARS, \
+ BASS_CP_WRITE_REQ(0x04, 0x05, 0xB8, 0x03, 0xEA, 0xC6, 0xAF, 0xBB, \
+ 0x65, 0xA2, 0x5A, 0x41, 0xF1, 0x53, 0x05, 0x68, \
+ 0x02, 0x01), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x81), \
+ BASS_CP_WRITE_REQ(0x05, 0x05), \
+ IOV_DATA(0x01, 0x12, 0x09, 0x00, 0x81)
+
#define iov_data(args...) ((const struct iovec[]) { args })

#define define_test(name, function, _cfg, args...) \
@@ -287,6 +582,63 @@ done:
gatt_db_attribute_read_result(attrib, id, ecode, value, len);
}

+static void gatt_ccc_write_cb(struct gatt_db_attribute *attrib,
+ unsigned int id, uint16_t offset,
+ const uint8_t *value, size_t len,
+ uint8_t opcode, struct bt_att *att,
+ void *user_data)
+{
+ struct test_data *data = (void *)user_data;
+ struct ccc_state *ccc_state;
+ uint16_t val;
+ uint8_t ecode = 0;
+
+ if (!value || len > 2) {
+ ecode = BT_ATT_ERROR_INVALID_ATTRIBUTE_VALUE_LEN;
+ goto done;
+ }
+
+ if (offset > 2) {
+ ecode = BT_ATT_ERROR_INVALID_OFFSET;
+ goto done;
+ }
+
+ if (len == 1)
+ val = *value;
+ else
+ val = get_le16(value);
+
+ ccc_state = get_ccc_state(data, gatt_db_attribute_get_handle(attrib));
+ if (!ccc_state)
+ return;
+
+ /* If value is identical, then just succeed */
+ if (val == ccc_state->value)
+ goto done;
+
+ ccc_state->value = val;
+
+done:
+ gatt_db_attribute_write_result(attrib, id, ecode);
+}
+
+static void gatt_notify_cb(struct gatt_db_attribute *attrib,
+ struct gatt_db_attribute *ccc,
+ const uint8_t *value, size_t len,
+ struct bt_att *att, void *user_data)
+{
+ struct test_data *data = user_data;
+ struct ccc_state *ccc_state;
+
+ ccc_state = find_ccc_state(data, gatt_db_attribute_get_handle(ccc));
+ if (!ccc_state || !(ccc_state->value & 0x0001))
+ return;
+
+ bt_gatt_server_send_notification(data->server,
+ gatt_db_attribute_get_handle(attrib),
+ value, len, false);
+}
+
static void test_server(const void *user_data)
{
struct test_data *data = (void *)user_data;
@@ -306,12 +658,17 @@ static void test_server(const void *user_data)
data->db = gatt_db_new();
g_assert(data->db);

- gatt_db_ccc_register(data->db, gatt_ccc_read_cb, NULL,
- NULL, data);
+ gatt_db_ccc_register(data->db, gatt_ccc_read_cb, gatt_ccc_write_cb,
+ gatt_notify_cb, data);

data->bass = bt_bass_new(data->db, NULL, BDADDR_ANY);
g_assert(data->bass);

+ bt_bass_set_att(data->bass, att);
+ bt_bass_attach(data->bass, NULL);
+
+ bt_bass_set_debug(data->bass, print_debug, "bt_bass:", NULL);
+
data->server = bt_gatt_server_new(data->db, att, 64, 0);
g_assert(data->server);

@@ -387,11 +744,80 @@ static void test_sggit(void)
DISC_BCAST_RECV_STATE);
}

+static void test_spe(void)
+{
+ /* BASS/SR/SPE/BI-01-C [Ignore Invalid Source ID]
+ *
+ * Test Purpose:
+ * Verify that the BASS Server IUT does not respond to a control point
+ * procedure call that uses an invalid Source_ID parameter.
+ *
+ * Pass verdict:
+ * The IUT does not send a notification of the Broadcast Receive State
+ * characteristic.
+ */
+ define_test("BASS/SR/SPE/BI-01-C", test_server, NULL,
+ IGNORE_INVALID_SRC_ID);
+
+ /* BASS/SR/SPE/BI-03-C [Add Source - Ignore Invalid Values]
+ *
+ * Test Purpose:
+ * Verify that the BASS Server IUT ignores Add Source control point
+ * procedure calls that include an RFU or Invalid parameter.
+ *
+ * Pass verdict:
+ * The IUT does not send a notification of the Broadcast Receive State
+ * characteristic.
+ */
+ define_test("BASS/SR/SPE/BI-03-C", test_server, NULL,
+ ADD_SRC_INVALID_PARAMS);
+
+ /* BASS/SR/SPE/BI-04-C [Opcode Not Supported]
+ *
+ * Test Purpose:
+ * Verify that the BASS Server IUT returns an Opcode Not Supported error
+ * response when the opcode written is not supported by the IUT or is
+ * within a range that is reserved for future use being written to the
+ * Broadcast Audio Scan Control Point.
+ *
+ * Pass verdict:
+ * The IUT sends an error response of OPCODE NOT SUPPORTED.
+ */
+ define_test("BASS/SR/SPE/BI-04-C", test_server, NULL,
+ OPCODE_NOT_SUPPORTED);
+
+ /* BASS/SR/SPE/BI-06-C [Invalid Length]
+ *
+ * Test Purpose:
+ * Verify that the BASS Server IUT rejects writing of an opcode with
+ * an invalid length.
+ *
+ * Pass verdict:
+ * The IUT rejects the opcode.
+ */
+ define_test("BASS/SR/SPE/BI-06-C", test_server, NULL,
+ INVALID_LEN);
+
+ /* BASS/SR/SPE/BI-07-C [Invalid Source ID]
+ *
+ * Test Purpose:
+ * Verify that the BASS Server IUT returns an error when a control
+ * point procedure passing an invalid Source_ID parameter is called.
+ *
+ * Pass verdict:
+ * The IUT sends an ATT Error Response with the Error Code set to
+ * Invalid Source_ID.
+ */
+ define_test("BASS/SR/SPE/BI-07-C", test_server, NULL,
+ INVALID_SRC_ID);
+}
+
int main(int argc, char *argv[])
{
tester_init(&argc, &argv);

test_sggit();
+ test_spe();

return tester_run();
}
--
2.39.2

2023-10-10 17:29:29

by bluez.test.bot

[permalink] [raw]
Subject: RE: test-bass: Add unit tests for the SPE suite

This is automated email and please do not reply to this email!

Dear submitter,

Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=791853

---Test result---

Test Summary:
CheckPatch PASS 0.74 seconds
GitLint PASS 0.24 seconds
BuildEll PASS 32.78 seconds
BluezMake PASS 1005.82 seconds
MakeCheck PASS 13.36 seconds
MakeDistcheck PASS 191.75 seconds
CheckValgrind PASS 309.55 seconds
CheckSmatch PASS 409.34 seconds
bluezmakeextell PASS 126.04 seconds
IncrementalBuild PASS 824.50 seconds
ScanBuild PASS 1298.06 seconds



---
Regards,
Linux Bluetooth

2023-10-10 23:40:32

by patchwork-bot+bluetooth

[permalink] [raw]
Subject: Re: [PATCH BlueZ v2 0/1] test-bass: Add unit tests for the SPE suite

Hello:

This patch was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <[email protected]>:

On Tue, 10 Oct 2023 18:38:54 +0300 you wrote:
> This patch series adds BASS unit tests for the Service Procedures Error
> Handling suite.
>
> Iulia Tanasescu (1):
> test-bass: Add unit tests for the SPE suite
>
> unit/test-bass.c | 430 ++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 428 insertions(+), 2 deletions(-)
>
> [...]

Here is the summary with links:
- [BlueZ,v2,1/1] test-bass: Add unit tests for the SPE suite
https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=4ea09cf6b9b1

You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html