From a4746a9ac404d7e4eade35ce60a9c2fbf1d7707e Mon Sep 17 00:00:00 2001 From: Richard Fuchs Date: Wed, 8 Jul 2026 11:06:01 -0400 Subject: [PATCH] MT#65481 add open/read/write mockups Change-Id: Ibe6da6909bc6293b3e96a1822f8305ae7f25ff76 --- t/tests-preload.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) diff --git a/t/tests-preload.c b/t/tests-preload.c index b44590199..b1f48045d 100644 --- a/t/tests-preload.c +++ b/t/tests-preload.c @@ -25,6 +25,7 @@ typedef struct { struct sockaddr_storage sockname, peername; unsigned int open:1, + mock:1, bound:1, connected:1, pktinfo:1; @@ -53,6 +54,17 @@ static const struct sockaddr *addr_find(const struct sockaddr *addr, socklen_t * static const char *p_prefix; +#define MAX_MOCK_FILES 16 +static const char *mock_files[MAX_MOCK_FILES]; +static const char *mock_peer; + +enum mock_msg { + MOCK_OPEN = 1, + MOCK_READ = 2, + MOCK_WRITE = 3, + MOCK_CLOSE = 4, +}; + int (*real_socket)(int, int, int); int (*real_bind)(int, const struct sockaddr *, socklen_t); int (*real_close)(int); @@ -68,10 +80,14 @@ ssize_t (*real_send)(int, const void *, size_t, int); ssize_t (*real_sendto)(int, const void *, size_t, int, const struct sockaddr *, socklen_t); ssize_t (*real_sendmsg)(int, const struct msghdr *, int); int (*real_setsockopt)(int, int, int, const void *, socklen_t); +int (*real_open)(const char *, int, mode_t); +ssize_t (*real_read)(int, void *, size_t); +ssize_t (*real_write)(int, const void *, size_t); static void do_init(void) { setenv("RTPE_PRELOAD_TEST_ACTIVE", "1", 1); p_prefix = getenv("TEST_SOCKET_PATH"); + mock_peer = getenv("MOCK_PEER"); real_socket = dlsym(RTLD_NEXT, "socket"); real_bind = dlsym(RTLD_NEXT, "bind"); @@ -88,6 +104,18 @@ static void do_init(void) { real_sendto = dlsym(RTLD_NEXT, "sendto"); real_sendmsg = dlsym(RTLD_NEXT, "sendmsg"); real_setsockopt = dlsym(RTLD_NEXT, "setsockopt"); + real_open = dlsym(RTLD_NEXT, "open"); + real_read = dlsym(RTLD_NEXT, "read"); + real_write = dlsym(RTLD_NEXT, "write"); + + for (unsigned int i = 0; i < MAX_MOCK_FILES; i++) { + char var[64]; + sprintf(var, "MOCK_%u", i); + char *mpath = getenv(var); + if (!mpath) + break; + mock_files[i] = mpath; + } } static void do_exit(void) { for (int i = 0; i < MAX_SOCKETS; i++) { @@ -909,3 +937,88 @@ do_set_warn: do_set: return real_setsockopt(fd, level, optname, optval, optlen); } + +int open(const char *fn, int flags, mode_t mode) { + unsigned int i; + + for (i = 0; i < MAX_MOCK_FILES; i++) { + if (!mock_files[i]) + break; + if (strcmp(fn, mock_files[i])) + continue; + + goto found; + } + + return real_open(fn, flags, mode); + +found: + if (!mock_peer) + return -1; + + int fd = real_socket(AF_UNIX, SOCK_DGRAM, 0); + if (fd == -1) + return -1; + struct sockaddr_un sun = { .sun_family = AF_UNIX }; + assert(strlen(mock_peer) < sizeof(sun.sun_path)); + strcpy(sun.sun_path, mock_peer); + + int ret = real_connect(fd, (struct sockaddr *) &sun, sizeof(sun)); + if (ret) { + close(fd); + return -1; + } + + struct { + int msg; + char fn[sizeof(sun.sun_path)]; + } m = { .msg = MOCK_OPEN }; + strcpy(m.fn, fn); + + ssize_t r = real_send(fd, &m, sizeof(m), 0); + assert(r == sizeof(m)); + + struct { + int msg; + int code; + } n; + r = real_recvfrom(fd, &n, sizeof(n), 0, NULL, NULL); + assert(r == sizeof(n)); + assert(n.msg == MOCK_OPEN); + + if (n.code != 0) { + real_close(fd); + return -1; + } + + real_sockets[fd] = (socket_t) { + .open = 1, + .mock = 1, + }; + + return fd; +} + +ssize_t read(int fd, void *buf, size_t len) { + if (fd < 0 || fd >= MAX_SOCKETS) + goto do_read; + + socket_t *s = &real_sockets[fd]; + if (!s->open || !s->mock) + goto do_read; + +do_read: + return real_read(fd, buf, len); +} + +ssize_t write(int fd, const void *buf, size_t len) { + if (fd < 0 || fd >= MAX_SOCKETS) + goto do_write; + + socket_t *s = &real_sockets[fd]; + if (!s->open || !s->mock) + goto do_write; + +do_write: + return real_write(fd, buf, len); +}