* [PATCH BlueZ 2/2] unit: test-mainloop: add basic mainloop test
2026-09-27 17:49 [PATCH BlueZ 1/2] shared: mainloop: Skip removed mainloop events Pauli Virtanen
@ 2026-09-27 17:49 ` Pauli Virtanen
2026-09-27 21:14 ` [BlueZ,1/2] shared: mainloop: Skip removed mainloop events bluez.test.bot
2026-09-28 17:50 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth
2 siblings, 0 replies; 4+ messages in thread
From: Pauli Virtanen @ 2026-09-27 17:49 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Pauli Virtanen
Exercise basic mainloop fd add / remove / modify and timeouts.
src/shared/tester.h depends on mainloop and cannot be used here, so
write tests without the framework.
Add tests:
Test Modify File Descriptor
Test Re-Add Other Callback
Test Timeout
Assisted-by: opencode:gpt-6-sol
---
.gitignore | 1 +
Makefile.am | 5 ++
unit/test-mainloop.c | 171 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 177 insertions(+)
create mode 100644 unit/test-mainloop.c
diff --git a/.gitignore b/.gitignore
index b1d63e1d4..a52e6eb1b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -97,6 +97,7 @@ tools/isotest
tools/iso-tester
test/bluezutils.pyc
unit/test-tester
+unit/test-mainloop
unit/test-ringbuf
unit/test-queue
unit/test-util
diff --git a/Makefile.am b/Makefile.am
index 1d46b9b93..53a3a15c3 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -593,6 +593,11 @@ unit_test_tester_SOURCES = unit/test-tester.c
unit_test_tester_LDADD = src/libshared-glib.la lib/libbluetooth-internal.la \
$(GLIB_LIBS)
+unit_tests += unit/test-mainloop
+
+unit_test_mainloop_SOURCES = unit/test-mainloop.c
+unit_test_mainloop_LDADD = src/libshared-mainloop.la
+
unit_tests += unit/test-eir
unit_test_eir_SOURCES = unit/test-eir.c src/eir.c src/uuid-helper.c
diff --git a/unit/test-mainloop.c b/unit/test-mainloop.c
new file mode 100644
index 000000000..70ee03ee4
--- /dev/null
+++ b/unit/test-mainloop.c
@@ -0,0 +1,171 @@
+// SPDX-License-Identifier: LGPL-2.1-or-later
+/*
+ *
+ * BlueZ - Bluetooth protocol stack for Linux
+ *
+ * Copyright (C) 2026 Pauli Virtanen
+ *
+ */
+
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "src/shared/mainloop.h"
+
+
+#define test_failed_msg(msg) \
+ fail_and_abort(msg, __FILE__, __LINE__, __func__)
+
+#define test_failed() \
+ test_failed_msg("")
+
+#define check(condition) \
+ ({ if (!(condition)) test_failed_msg(#condition " not true"); })
+
+
+struct test_data {
+ int fds[4];
+ unsigned int old_calls;
+ unsigned int new_calls;
+ unsigned int destroys;
+ unsigned int timeout_calls;
+};
+
+
+static void fail_and_abort(const char *msg, const char *file, int line,
+ const char *func)
+{
+ fprintf(stderr, "test failed\n");
+ fprintf(stderr, " %s in %s:%d (%s)\n", msg, file, line, func);
+ abort();
+}
+
+static void teardown(struct test_data *data)
+{
+ int i;
+
+ for (i = 0; i < 4; ++i)
+ if (data->fds[i] > 0)
+ close(data->fds[i]);
+}
+
+static void destroy(void *user_data)
+{
+ struct test_data *data = user_data;
+
+ data->destroys++;
+}
+
+static void fd_callback(int fd, uint32_t events, void *user_data)
+{
+ struct test_data *data = user_data;
+ char buf;
+
+ check(events & EPOLLIN);
+ check(read(fd, &buf, 1) == 1);
+ check(buf == 'a');
+ data->old_calls++;
+ mainloop_exit_failure();
+}
+
+static void test_modify_fd(struct test_data *data)
+{
+ check(pipe(data->fds) == 0);
+
+ mainloop_init();
+
+ check(mainloop_add_fd(data->fds[0], EPOLLOUT, fd_callback,
+ data, destroy) == 0);
+ check(mainloop_modify_fd(data->fds[0], EPOLLIN) == 0);
+ check(write(data->fds[1], "a", 1) == 1);
+ check(mainloop_run() == EXIT_FAILURE);
+ check(data->old_calls == 1);
+ check(data->destroys == 1);
+}
+
+static void new_callback(int fd, uint32_t events, void *user_data)
+{
+ struct test_data *data = user_data;
+
+ data->new_calls++;
+}
+
+static void old_callback(int fd, uint32_t events, void *user_data)
+{
+ struct test_data *data = user_data;
+ int other_fd = fd == data->fds[0] ? data->fds[2] : data->fds[0];
+
+ data->old_calls++;
+ check(mainloop_remove_fd(other_fd) == 0);
+ check(data->destroys == 1);
+ check(mainloop_add_fd(other_fd, EPOLLIN, new_callback, data,
+ destroy) == 0);
+ mainloop_exit_success();
+}
+
+static void test_readd_other_callback(struct test_data *data)
+{
+ check(pipe(&data->fds[0]) == 0);
+ check(pipe(&data->fds[2]) == 0);
+
+ mainloop_init();
+
+ check(mainloop_add_fd(data->fds[0], EPOLLIN, old_callback,
+ data, destroy) == 0);
+ check(mainloop_add_fd(data->fds[2], EPOLLIN, old_callback,
+ data, destroy) == 0);
+ check(write(data->fds[1], "a", 1) == 1);
+ check(write(data->fds[3], "b", 1) == 1);
+
+ check(mainloop_run() == 0);
+
+ check(data->old_calls == 1);
+ check(data->new_calls == 0);
+ check(data->destroys == 3);
+}
+
+static void timeout_callback(int id, void *user_data)
+{
+ struct test_data *data = user_data;
+
+ data->timeout_calls++;
+ if (data->timeout_calls == 1) {
+ check(mainloop_modify_timeout(id, 1) == 0);
+ return;
+ }
+
+ check(mainloop_remove_timeout(id) == 0);
+ mainloop_quit();
+}
+
+static void test_timeout(struct test_data *data)
+{
+ int id;
+
+ mainloop_init();
+
+ id = mainloop_add_timeout(0, timeout_callback, data, destroy);
+ check(id > 0);
+ check(mainloop_modify_timeout(id, 1) == 0);
+ check(mainloop_run() == EXIT_SUCCESS);
+ check(data->timeout_calls == 2);
+ check(data->destroys == 1);
+}
+
+#define define_test(name, function) \
+ do { \
+ static struct test_data data = {}; \
+ fprintf(stderr, "%s - ", name); \
+ function(&data); \
+ fprintf(stderr, "test passed\n"); \
+ teardown(&data); \
+ } while (0)
+
+int main(int argc, char *argv[])
+{
+ define_test("Test Modify File Descriptor", test_modify_fd);
+ define_test("Test Re-Add Other Callback", test_readd_other_callback);
+ define_test("Test Timeout", test_timeout);
+ return 0;
+}
--
2.55.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* RE: [BlueZ,1/2] shared: mainloop: Skip removed mainloop events
2026-09-27 17:49 [PATCH BlueZ 1/2] shared: mainloop: Skip removed mainloop events Pauli Virtanen
2026-09-27 17:49 ` [PATCH BlueZ 2/2] unit: test-mainloop: add basic mainloop test Pauli Virtanen
@ 2026-09-27 21:14 ` bluez.test.bot
2026-09-28 17:50 ` [PATCH BlueZ 1/2] " patchwork-bot+bluetooth
2 siblings, 0 replies; 4+ messages in thread
From: bluez.test.bot @ 2026-09-27 21:14 UTC (permalink / raw)
To: linux-bluetooth, pav
[-- Attachment #1: Type: text/plain, Size: 2273 bytes --]
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/series/1174578/
---Test result---
Test Summary:
CheckPatch FAIL 1.13 seconds
GitLint FAIL 0.68 seconds
BuildEll PASS 19.09 seconds
BluezMake PASS 381.66 seconds
MakeCheck PASS 14.33 seconds
MakeDistcheck PASS 137.22 seconds
CheckValgrind PASS 227.86 seconds
CheckSmatch PASS 284.89 seconds
bluezmakeextell PASS 92.27 seconds
TestFunctional PASS 1082.60 seconds
IncrementalBuild PASS 406.78 seconds
ScanBuild PASS 1103.09 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[BlueZ,1/2] shared: mainloop: Skip removed mainloop events
WARNING:COMMIT_LOG_LONG_LINE: Prefer a maximum 75 chars per line (possible unwrapped commit description?)
#96:
#1 0x5637f7b41f79 in mainloop_run_with_signal src/shared/mainloop-notify.c:196
/home/runner/work/bluez/bluez/src/patch/14849970.patch total: 0 errors, 1 warnings, 48 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/home/runner/work/bluez/bluez/src/patch/14849970.patch has style problems, please review.
NOTE: Ignored message types: COMMIT_MESSAGE COMPLEX_MACRO CONST_STRUCT FILE_PATH_CHANGES MISSING_SIGN_OFF PREFER_PACKED SPDX_LICENSE_TAG SPLIT_STRING SSCANF_TO_KSTRTO
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[BlueZ,1/2] shared: mainloop: Skip removed mainloop events
18: B1 Line exceeds max length (82>80): " #1 0x5637f7b41f79 in mainloop_run_with_signal src/shared/mainloop-notify.c:196"
https://github.com/bluez/bluez/pull/2597
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 4+ messages in thread