From 9ebb6b6b56be3247bda94f50ed82e1ca25e90883 Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Wed, 17 Jul 2019 12:23:08 +0200 Subject: [PATCH] Add testcase to prove that ET semantics for eventFD are correct (#9385) Motivation: We recently made a change to use ET for the eventfd and not trigger a read each time. This testcase proves everything works as expected. Modifications: Add testcase that verifies thqat the wakeups happen correctly Result: More tests --- .../channel/epoll/EpollEventLoopTest.java | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollEventLoopTest.java b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollEventLoopTest.java index 25bba974e2..e2da34b61c 100644 --- a/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollEventLoopTest.java +++ b/transport-native-epoll/src/test/java/io/netty/channel/epoll/EpollEventLoopTest.java @@ -19,14 +19,18 @@ import io.netty.channel.DefaultSelectStrategyFactory; import io.netty.channel.EventLoop; import io.netty.channel.EventLoopGroup; import io.netty.channel.SingleThreadEventLoop; +import io.netty.channel.unix.FileDescriptor; import io.netty.util.concurrent.DefaultThreadFactory; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.ThreadPerTaskExecutor; import org.junit.Test; +import java.io.IOException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -60,4 +64,51 @@ public class EpollEventLoopTest { group.shutdownGracefully(); } } + + @Test + public void testEventFDETSemantics() throws Throwable { + final FileDescriptor epoll = Native.newEpollCreate(); + final FileDescriptor eventFd = Native.newEventFd(); + final FileDescriptor timerFd = Native.newTimerFd(); + final EpollEventArray array = new EpollEventArray(1024); + try { + Native.epollCtlAdd(epoll.intValue(), eventFd.intValue(), Native.EPOLLIN | Native.EPOLLET); + final AtomicReference causeRef = new AtomicReference<>(); + final AtomicInteger integer = new AtomicInteger(); + final Thread t = new Thread(() -> { + try { + for (int i = 0; i < 2; i++) { + int ready = Native.epollWait(epoll, array, timerFd, -1, -1); + assertEquals(1, ready); + assertEquals(eventFd.intValue(), array.fd(0)); + integer.incrementAndGet(); + } + } catch (IOException e) { + causeRef.set(e); + } + }); + t.start(); + Native.eventFdWrite(eventFd.intValue(), 1); + + // Spin until we was the wakeup. + while (integer.get() != 1) { + Thread.sleep(10); + } + // Sleep for a short moment to ensure there is not other wakeup. + Thread.sleep(1000); + assertEquals(1, integer.get()); + Native.eventFdWrite(eventFd.intValue(), 1); + t.join(); + Throwable cause = causeRef.get(); + if (cause != null) { + throw cause; + } + assertEquals(2, integer.get()); + } finally { + array.free(); + epoll.close(); + eventFd.close(); + timerFd.close(); + } + } }