Mercurial
diff seobeo/tests/seobeo_sse_test.c @ 264:04fee26ecce0
add authenticated JRPG conversation platform
Add reusable auth/session storage, owned conversation recovery, guest quotas, admin workflows, URL-routed conversation UI, mobile frame support, and parallel browser acceptance.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Fri, 07 Aug 2026 07:34:12 -0700 |
| parents | 1f9877b637e9 |
| children |
line wrap: on
line diff
--- a/seobeo/tests/seobeo_sse_test.c Thu Aug 06 11:31:30 2026 -0700 +++ b/seobeo/tests/seobeo_sse_test.c Fri Aug 07 07:34:12 2026 -0700 @@ -8,6 +8,17 @@ #include <sys/socket.h> #include <unistd.h> +/* Counter incremented by the detach callback. */ +static _Atomic int g_detach_count = 0; +static Seobeo_SSE_Stream *g_detach_stream = NULL; + +static void test_detach_cb(Seobeo_SSE_Stream *p_stream, void *ctx) +{ + (void)ctx; + g_detach_stream = p_stream; + atomic_fetch_add(&g_detach_count, 1); +} + static void read_expected(int socket_fd, const char *expected) { size_t expected_length = strlen(expected); @@ -186,6 +197,45 @@ close(sockets[0]); close(sockets[1]); + /* + * Detach callback test: verify callback fires after handle detach and + * that the callback is called outside g_sse_mutex (no deadlock). + */ + { + int cbs[2]; + assert(socketpair(AF_UNIX, SOCK_STREAM, 0, cbs) == 0); + uint8 cb_write_buf[4096] = {0}; + Seobeo_Handle cb_handle; + initialize_handle(&cb_handle, cbs[0], cb_write_buf, sizeof(cb_write_buf)); + Seobeo_SSE_Stream *p_cb_stream = Seobeo_SSE_Server_Attach(&cb_handle, "/cb"); + assert(p_cb_stream); + assert(Seobeo_SSE_Retain(p_cb_stream)); /* extra reference */ + + /* Register detach callback. */ + atomic_store(&g_detach_count, 0); + g_detach_stream = NULL; + Seobeo_SSE_Set_Detach_Callback(p_cb_stream, test_detach_cb, NULL); + + /* Detach: fires callback outside the mutex. */ + Seobeo_SSE_Server_Detach_Handle(&cb_handle); + + assert(atomic_load(&g_detach_count) == 1); + assert(g_detach_stream == p_cb_stream); + assert(!Seobeo_SSE_Is_Open(p_cb_stream)); + + /* Second detach: no stream found, callback NOT called again. */ + Seobeo_SSE_Server_Detach_Handle(&cb_handle); + assert(atomic_load(&g_detach_count) == 1); + + /* Clear the callback and verify it isn't called on a subsequent release. */ + Seobeo_SSE_Set_Detach_Callback(p_cb_stream, NULL, NULL); + Seobeo_SSE_Release(p_cb_stream); /* release extra reference */ + Seobeo_SSE_Server_Destroy(); + close(cbs[0]); + close(cbs[1]); + printf(" detach callback fires once, outside mutex PASS\n"); + } + Seobeo_Router_Init(); Seobeo_Router_Register_SSE("/events/:topic", route_handler); Seobeo_Router_Register_SSE("/events/:topic/fixed", route_handler); @@ -193,8 +243,7 @@ "POST", "/events/:topic", post_route_handler); - Dowa_Arena *p_arena = Dowa_Arena_Create(4096); - Seobeo_Request_Entry *p_request = NULL; + Dowa_Arena *p_arena = Dowa_Arena_Create(4096); Seobeo_Request_Entry *p_request = NULL; Seobeo_SSE_Handler handler = Seobeo_Router_Find_SSE_Handler( "GET", "/events/builds",