diff mbox series

[BlueZ,v2,1/1] test-bass: Add unit tests for the SPE suite

Message ID 20231010153855.13825-2-iulia.tanasescu@nxp.com
State New
Headers show
Series test-bass: Add unit tests for the SPE suite | expand

Commit Message

Iulia Tanasescu Oct. 10, 2023, 3:38 p.m. UTC
This adds BASS unit tests for the Service Procedures Error
Handling suite.

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

Comments

bluez.test.bot@gmail.com Oct. 10, 2023, 5:28 p.m. UTC | #1
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
diff mbox series

Patch

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();
 }