comparison seobeo/tests/seobeo_http_timeout_test.c @ 221:ce7f4400c2de hg-web

[hg-web] Harden forge and add changeset UI
author MrJuneJune <me@mrjunejune.com>
date Sun, 02 Aug 2026 09:01:24 -0700
parents
children
comparison
equal deleted inserted replaced
219:8c9bb0b0759e 221:ce7f4400c2de
1 #include "seobeo/seobeo.h"
2
3 #include <arpa/inet.h>
4 #include <pthread.h>
5 #include <stdio.h>
6 #include <string.h>
7 #include <time.h>
8
9 typedef struct {
10 int listener;
11 } Timeout_Server;
12
13 static int64_t monotonic_milliseconds(void)
14 {
15 struct timespec now;
16 clock_gettime(CLOCK_MONOTONIC, &now);
17 return (int64_t)now.tv_sec * 1000 + now.tv_nsec / 1000000;
18 }
19
20 static void *serve_stalled_response(void *argument)
21 {
22 Timeout_Server *server = argument;
23 int client = accept(server->listener, NULL, NULL);
24 if (client >= 0) {
25 char request[1024];
26 (void)read(client, request, sizeof(request));
27 usleep(250000);
28 close(client);
29 }
30 return NULL;
31 }
32
33 int main(void)
34 {
35 int listener = socket(AF_INET, SOCK_STREAM, 0);
36 if (listener < 0)
37 return 1;
38
39 struct sockaddr_in address = {
40 .sin_family = AF_INET,
41 .sin_addr.s_addr = htonl(INADDR_LOOPBACK),
42 .sin_port = 0,
43 };
44 if (bind(listener, (struct sockaddr *)&address, sizeof(address)) != 0 ||
45 listen(listener, 1) != 0) {
46 close(listener);
47 return 1;
48 }
49
50 socklen_t address_length = sizeof(address);
51 if (getsockname(listener, (struct sockaddr *)&address, &address_length) != 0) {
52 close(listener);
53 return 1;
54 }
55
56 Timeout_Server server = {.listener = listener};
57 pthread_t thread;
58 if (pthread_create(&thread, NULL, serve_stalled_response, &server) != 0) {
59 close(listener);
60 return 1;
61 }
62
63 char url[128];
64 snprintf(url, sizeof(url), "http://127.0.0.1:%u/", ntohs(address.sin_port));
65 Seobeo_Client_Request *request = Seobeo_Client_Request_Create(url);
66 Seobeo_Client_Request_Set_Timeout_Milliseconds(request, 50);
67
68 int64_t started = monotonic_milliseconds();
69 Seobeo_Client_Response *response = Seobeo_Client_Request_Execute(request);
70 int64_t elapsed = monotonic_milliseconds() - started;
71
72 int failed = response != NULL || elapsed < 40 || elapsed > 2000;
73 if (failed)
74 fprintf(stderr, "Expected a bounded timeout; response=%p elapsed=%lldms\n",
75 (void *)response, (long long)elapsed);
76
77 Seobeo_Client_Response_Destroy(response);
78 Seobeo_Client_Request_Destroy(request);
79 pthread_join(thread, NULL);
80 close(listener);
81 return failed;
82 }