Diff between ee1d6fe79da20c2c4a4d9abc9d9b6ab3d4610fa7 and 84be78a05b55d47b709c1b94c2885e50b0d65ded

Changed Files

File Additions Deletions Status
unit/test-gattrib.c +139 -1 modified

Full Patch

diff --git a/unit/test-gattrib.c b/unit/test-gattrib.c
index d90536b..5ee8953 100644
--- a/unit/test-gattrib.c
+++ b/unit/test-gattrib.c
@@ -346,9 +346,147 @@ static void test_cancel(struct context *cxt, gconstpointer unused)
 	g_assert(!canceled);
 }
 
+static void send_test_pdus(gpointer context, struct test_pdu *pdus)
+{
+	struct context *cxt = context;
+	size_t len;
+	int fd;
+	struct test_pdu *cur_pdu;
+
+	fd = g_io_channel_unix_get_fd(cxt->server_io);
+
+	for (cur_pdu = pdus; cur_pdu->valid; cur_pdu++)
+		cur_pdu->sent = false;
+
+	for (cur_pdu = pdus; cur_pdu->valid; cur_pdu++) {
+		if (g_test_verbose())
+			util_hexdump('>', cur_pdu->data, cur_pdu->size,
+						test_debug, "send_test_pdus: ");
+		len = write(fd, cur_pdu->data, cur_pdu->size);
+		g_assert_cmpint(len, ==, cur_pdu->size);
+		cur_pdu->sent = true;
+	}
+
+	g_idle_add(context_stop_main_loop, cxt);
+	g_main_loop_run(cxt->main_loop);
+}
+
+#define PDU_MTU_RESP pdu(ATT_OP_MTU_RESP, 0x17)
+#define PDU_FIND_INFO_REQ pdu(ATT_OP_FIND_INFO_REQ, 0x01, 0x00, 0xFF, 0xFF)
+#define PDU_IND_NODATA pdu(ATT_OP_HANDLE_IND, 0x01, 0x00)
+#define PDU_INVALID_IND pdu(ATT_OP_HANDLE_IND, 0x14)
+#define PDU_IND_DATA pdu(ATT_OP_HANDLE_IND, 0x14, 0x00, 0x01)
+
+static void notify_canary_expect(const guint8 *pdu, guint16 len, gpointer data)
+{
+	struct test_pdu *expected = data;
+	int cmp;
+
+	if (g_test_verbose())
+		util_hexdump('<', pdu, len, test_debug,
+						      "notify_canary_expect: ");
+
+	while (expected->valid && expected->received)
+		expected++;
+
+	g_assert(expected->valid);
+
+	if (g_test_verbose())
+		util_hexdump('?', expected->data, expected->size, test_debug,
+						      "notify_canary_expect: ");
+
+	g_assert_cmpint(expected->size, ==, len);
+
+	cmp = memcmp(pdu, expected->data, expected->size);
+
+	g_assert(cmp == 0);
+
+	expected->received = true;
+}
+
 static void test_register(struct context *cxt, gconstpointer user_data)
 {
-	/* TODO */
+	guint reg_id;
+	gboolean success;
+	struct test_pdu pdus[] = {
+		/* Unmatched by any (GATTRIB_ALL_EVENTS) */
+		PDU_MTU_RESP,
+		/*
+		 * Unmatched PDU opcode
+		 * Unmatched handle (GATTRIB_ALL_REQS) */
+		PDU_FIND_INFO_REQ,
+		/*
+		 * Matched PDU opcode
+		 * Unmatched handle (GATTRIB_ALL_HANDLES) */
+		PDU_IND_NODATA,
+		/*
+		 * Matched PDU opcode
+		 * Invalid length? */
+		PDU_INVALID_IND,
+		/*
+		 * Matched PDU opcode
+		 * Matched handle */
+		PDU_IND_DATA,
+		{ },
+	};
+	struct test_pdu req_pdus[] = { PDU_FIND_INFO_REQ, { } };
+	struct test_pdu all_ind_pdus[] = {
+		PDU_IND_NODATA,
+		PDU_INVALID_IND,
+		PDU_IND_DATA,
+		{ },
+	};
+	struct test_pdu followed_ind_pdus[] = { PDU_IND_DATA, { } };
+
+	/*
+	 * Without registering anything, should be able to ignore everything but
+	 * an unexpected response. */
+	send_test_pdus(cxt, pdus + 1);
+
+	reg_id = g_attrib_register(cxt->att, GATTRIB_ALL_EVENTS,
+				      GATTRIB_ALL_HANDLES, notify_canary_expect,
+								    pdus, NULL);
+
+	send_test_pdus(cxt, pdus);
+
+	g_attrib_unregister(cxt->att, reg_id);
+
+	if (g_test_verbose())
+		g_print("ALL_REQS, ALL_HANDLES\r\n");
+
+	reg_id = g_attrib_register(cxt->att, GATTRIB_ALL_REQS,
+				      GATTRIB_ALL_HANDLES, notify_canary_expect,
+								req_pdus, NULL);
+
+	send_test_pdus(cxt, pdus);
+
+	g_attrib_unregister(cxt->att, reg_id);
+
+	if (g_test_verbose())
+		g_print("IND, ALL_HANDLES\r\n");
+
+	reg_id = g_attrib_register(cxt->att, ATT_OP_HANDLE_IND,
+				      GATTRIB_ALL_HANDLES, notify_canary_expect,
+							    all_ind_pdus, NULL);
+
+	send_test_pdus(cxt, pdus);
+
+	g_attrib_unregister(cxt->att, reg_id);
+
+	if (g_test_verbose())
+		g_print("IND, 0x0014\r\n");
+
+	reg_id = g_attrib_register(cxt->att, ATT_OP_HANDLE_IND, 0x0014,
+					notify_canary_expect, followed_ind_pdus,
+									  NULL);
+
+	send_test_pdus(cxt, pdus);
+
+	g_attrib_unregister(cxt->att, reg_id);
+
+	success = g_attrib_unregister(cxt->att, reg_id);
+
+	g_assert(!success);
 }
 
 static void test_buffers(struct context *cxt, gconstpointer unused)