mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-01-30 19:17:36 +00:00
Add multicast test that works on Linux
This test unfortunately doesn't work yet on non-Linux platforms, which wasn't what I expected since the ip_mreq ABI is the same across all of our supported platforms. There's also an automation issue due to using INADDR_ANY since it causes popups on Windows.
This commit is contained in:
parent
4b8874ceb9
commit
d0ad50f5ae
2 changed files with 111 additions and 0 deletions
106
test/libc/sock/multicast_test.c
Normal file
106
test/libc/sock/multicast_test.c
Normal file
|
@ -0,0 +1,106 @@
|
|||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/runtime/runtime.h"
|
||||
#include "libc/sock/sock.h"
|
||||
#include "libc/sock/struct/ip_mreq.h"
|
||||
#include "libc/sock/struct/sockaddr.h"
|
||||
#include "libc/sysv/consts/af.h"
|
||||
#include "libc/sysv/consts/inaddr.h"
|
||||
#include "libc/sysv/consts/ip.h"
|
||||
#include "libc/sysv/consts/ipproto.h"
|
||||
#include "libc/sysv/consts/so.h"
|
||||
#include "libc/sysv/consts/sock.h"
|
||||
#include "libc/sysv/consts/sol.h"
|
||||
#include "libc/testlib/subprocess.h"
|
||||
#include "libc/testlib/testlib.h"
|
||||
|
||||
struct Shared {
|
||||
atomic_int ready;
|
||||
atomic_int isworking;
|
||||
} * g_shared;
|
||||
|
||||
void Receiver(void) {
|
||||
int y = 1;
|
||||
char buf[8];
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(31337),
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
};
|
||||
struct ip_mreq group = {
|
||||
.imr_multiaddr.s_addr = inet_addr("224.0.0.251"),
|
||||
.imr_interface.s_addr = INADDR_ANY,
|
||||
};
|
||||
EXPECT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, 0));
|
||||
EXPECT_SYS(0, 0, setsockopt(3, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)));
|
||||
EXPECT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
EXPECT_SYS(0, 0,
|
||||
setsockopt(3, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group,
|
||||
sizeof(group)));
|
||||
g_shared->isworking = !g_testlib_failed;
|
||||
g_shared->ready = 1;
|
||||
if (g_shared->isworking) {
|
||||
ASSERT_SYS(0, 8, read(3, buf, 8));
|
||||
}
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
void Sender(void) {
|
||||
int y = 1;
|
||||
char buf[8];
|
||||
struct sockaddr_in addr = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(31337),
|
||||
.sin_addr.s_addr = INADDR_ANY,
|
||||
};
|
||||
struct sockaddr_in dest = {
|
||||
.sin_family = AF_INET,
|
||||
.sin_port = htons(31337),
|
||||
.sin_addr.s_addr = inet_addr("224.0.0.251"),
|
||||
};
|
||||
struct ip_mreq group = {
|
||||
.imr_multiaddr.s_addr = inet_addr("224.0.0.251"),
|
||||
.imr_interface.s_addr = INADDR_ANY,
|
||||
};
|
||||
ASSERT_SYS(0, 3, socket(AF_INET, SOCK_DGRAM, 0));
|
||||
ASSERT_SYS(0, 0, setsockopt(3, SOL_SOCKET, SO_REUSEADDR, &y, sizeof(y)));
|
||||
ASSERT_SYS(0, 0, bind(3, (struct sockaddr *)&addr, sizeof(addr)));
|
||||
ASSERT_SYS(0, 0,
|
||||
setsockopt(3, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group,
|
||||
sizeof(group)));
|
||||
ASSERT_SYS(0, 8,
|
||||
sendto(3, buf, 8, 0, (struct sockaddr *)&dest, sizeof(dest)));
|
||||
ASSERT_SYS(0, 0, close(3));
|
||||
}
|
||||
|
||||
TEST(multicast, test) {
|
||||
ASSERT_NE(NULL, (g_shared = _mapshared(FRAMESIZE)));
|
||||
SPAWN(fork);
|
||||
Receiver();
|
||||
PARENT();
|
||||
while (!g_shared->ready) {
|
||||
}
|
||||
if (g_shared->isworking) {
|
||||
Sender();
|
||||
}
|
||||
WAIT(exit, 0);
|
||||
munmap(g_shared, FRAMESIZE);
|
||||
}
|
|
@ -82,6 +82,11 @@ o/$(MODE)/test/libc/sock/recvmsg_test.com.runs: \
|
|||
o/$(MODE)/test/libc/sock/shutdown_test.com.runs: \
|
||||
private .PLEDGE = stdio rpath wpath cpath fattr proc inet
|
||||
|
||||
o/$(MODE)/test/libc/sock/multicast_test.com.runs: \
|
||||
private .UNSANDBOXED = 1
|
||||
o/$(MODE)/test/libc/sock/multicast_test.com.runs: \
|
||||
private .INTERNET = 1
|
||||
|
||||
$(TEST_LIBC_SOCK_OBJS): test/libc/sock/test.mk
|
||||
|
||||
.PHONY: o/$(MODE)/test/libc/sock
|
||||
|
|
Loading…
Reference in a new issue