mirror of
https://github.com/c3lang/c3c.git
synced 2026-02-27 12:01:16 +00:00
Add epoll bindings to std::os::linux + misc (#2350)
* Add epoll to std::os::linux + misc * Fix import in linux.c3 * epoll: Add unit tests * epoll: Fix imports in unit tests * epoll: Add libc import
This commit is contained in:
123
test/unit/stdlib/os/linux_epoll.c3
Normal file
123
test/unit/stdlib/os/linux_epoll.c3
Normal file
@@ -0,0 +1,123 @@
|
||||
module std::os::linux @test @if (env::LINUX);
|
||||
import std::net::os;
|
||||
import std::os::posix;
|
||||
import libc;
|
||||
|
||||
fn void test_epoll_create()
|
||||
{
|
||||
// Test epoll_create with valid size
|
||||
int epoll_fd = epoll_create(1);
|
||||
assert(epoll_fd >= 0, "epoll_create failed");
|
||||
libc::close(epoll_fd);
|
||||
|
||||
// Test epoll_create with size 0 (should work on Linux)
|
||||
epoll_fd = epoll_create1(0);
|
||||
assert(epoll_fd >= 0, "epoll_create1 failed");
|
||||
libc::close(epoll_fd);
|
||||
|
||||
// Test epoll_create with negative size (should fail)
|
||||
epoll_fd = epoll_create(-1);
|
||||
assert(epoll_fd == -1, "epoll_create with negative size should fail");
|
||||
}
|
||||
|
||||
fn void test_epoll_ctl()
|
||||
{
|
||||
int epoll_fd = epoll_create(1);
|
||||
assert(epoll_fd >= 0, "epoll_create failed");
|
||||
|
||||
// Create a socket to monitor
|
||||
int sock_fd = os::socket(os::AF_INET, os::SOCK_STREAM, 0);
|
||||
assert(sock_fd >= 0, "socket creation failed");
|
||||
|
||||
EpollEvent event;
|
||||
event.events = EPOLLIN;
|
||||
event.data.fd = sock_fd;
|
||||
|
||||
// Test EPOLL_CTL_ADD
|
||||
int ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock_fd, &event);
|
||||
assert(ret == 0, "EPOLL_CTL_ADD failed");
|
||||
|
||||
// Test EPOLL_CTL_MOD
|
||||
event.events = EPOLLIN | EPOLLOUT;
|
||||
ret = epoll_ctl(epoll_fd, EPOLL_CTL_MOD, sock_fd, &event);
|
||||
assert(ret == 0, "EPOLL_CTL_MOD failed");
|
||||
|
||||
// Test EPOLL_CTL_DEL
|
||||
ret = epoll_ctl(epoll_fd, EPOLL_CTL_DEL, sock_fd, null);
|
||||
assert(ret == 0, "EPOLL_CTL_DEL failed");
|
||||
|
||||
// Test invalid operations
|
||||
ret = epoll_ctl(epoll_fd, -1, sock_fd, &event); // invalid op
|
||||
assert(ret == -1, "Invalid operation should fail");
|
||||
|
||||
libc::close(sock_fd);
|
||||
libc::close(epoll_fd);
|
||||
}
|
||||
|
||||
fn void test_epoll_edge_triggered()
|
||||
{
|
||||
int epoll_fd = epoll_create(1);
|
||||
assert(epoll_fd >= 0, "epoll_create failed");
|
||||
|
||||
int[2] pipe_fds;
|
||||
assert(posix::pipe(&pipe_fds) == 0, "pipe creation failed");
|
||||
|
||||
// Set up edge-triggered monitoring
|
||||
EpollEvent event;
|
||||
event.events = EPOLLIN | EPOLLET;
|
||||
event.data.fd = pipe_fds[0];
|
||||
assert(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_fds[0], &event) == 0,
|
||||
"epoll_ctl add failed");
|
||||
|
||||
// Write to pipe
|
||||
char[] buf = "test";
|
||||
assert(libc::write(pipe_fds[1], buf, buf.len) == buf.len,
|
||||
"write to pipe failed");
|
||||
|
||||
// First epoll_wait should get the event
|
||||
EpollEvent[10] events;
|
||||
int num_events = epoll_wait(epoll_fd, &events[0], events.len, 0);
|
||||
assert(num_events == 1, "epoll_wait should return 1 event");
|
||||
|
||||
// Second epoll_wait shouldn't get the same event (edge-triggered behavior)
|
||||
num_events = epoll_wait(epoll_fd, &events[0], events.len, 0);
|
||||
assert(num_events == 0, "epoll_wait should not return event again for edge-triggered");
|
||||
|
||||
libc::close(pipe_fds[0]);
|
||||
libc::close(pipe_fds[1]);
|
||||
libc::close(epoll_fd);
|
||||
}
|
||||
|
||||
fn void test_epoll_level_triggered()
|
||||
{
|
||||
int epoll_fd = epoll_create(1);
|
||||
assert(epoll_fd >= 0, "epoll_create failed");
|
||||
|
||||
int[2] pipe_fds;
|
||||
assert(posix::pipe(&pipe_fds) == 0, "pipe creation failed");
|
||||
|
||||
// Set up level-triggered monitoring
|
||||
EpollEvent event;
|
||||
event.events = EPOLLIN; // Default is level-triggered
|
||||
event.data.fd = pipe_fds[0];
|
||||
assert(epoll_ctl(epoll_fd, EPOLL_CTL_ADD, pipe_fds[0], &event) == 0,
|
||||
"epoll_ctl add failed");
|
||||
|
||||
// Write to pipe
|
||||
char[] buf = "test";
|
||||
assert(libc::write(pipe_fds[1], buf, buf.len) == buf.len,
|
||||
"write to pipe failed");
|
||||
|
||||
// First epoll_wait should get the event
|
||||
EpollEvent[10] events;
|
||||
int num_events = epoll_wait(epoll_fd, &events[0], events.len, 0);
|
||||
assert(num_events == 1, "epoll_wait should return 1 event");
|
||||
|
||||
// Second epoll_wait should get the same event again (level-triggered behavior)
|
||||
num_events = epoll_wait(epoll_fd, &events[0], events.len, 0);
|
||||
assert(num_events == 1, "epoll_wait should return event again for level-triggered");
|
||||
|
||||
libc::close(pipe_fds[0]);
|
||||
libc::close(pipe_fds[1]);
|
||||
libc::close(epoll_fd);
|
||||
}
|
||||
Reference in New Issue
Block a user