/*
 * Copyright 2017 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel.epoll;

import io.netty.channel.DefaultSelectStrategyFactory;
import io.netty.channel.EventLoop;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.SingleThreadEventLoop;
import io.netty.util.concurrent.DefaultThreadFactory;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.ThreadPerTaskExecutor;
import org.junit.Test;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;

public class EpollEventLoopTest {

    @Test
    public void testScheduleBigDelayNotOverflow() {
        final AtomicReference<Throwable> capture = new AtomicReference<>();

        final EventLoopGroup group = new SingleThreadEventLoop(
                new ThreadPerTaskExecutor(new DefaultThreadFactory(getClass())),
                new EpollHandler(0, DefaultSelectStrategyFactory.INSTANCE.newSelectStrategy()) {
                    @Override
                    void handleLoopException(Throwable t) {
                        capture.set(t);
                        super.handleLoopException(t);
                    }
                });

        try {
            final EventLoop eventLoop = group.next();
            Future<?> future = eventLoop.schedule(() -> {
                // NOOP
            }, Long.MAX_VALUE, TimeUnit.MILLISECONDS);

            assertFalse(future.awaitUninterruptibly(1000));
            assertTrue(future.cancel(true));
            assertNull(capture.get());
        } finally {
            group.shutdownGracefully();
        }
    }
}

@@ -829,32 +829,77 @@
 hreadEventLoop;%0A
+import io.netty.channel.unix.FileDescriptor;%0A
 import io.netty.
@@ -928,32 +928,32 @@
 tThreadFactory;%0A
-
 import io.netty.
@@ -1055,16 +1055,44 @@
 .Test;%0A%0A
+import java.io.IOException;%0A
 import j
@@ -1121,16 +1121,66 @@
 meUnit;%0A
+import java.util.concurrent.atomic.AtomicInteger;%0A
 import j
@@ -1224,16 +1224,61 @@
 rence;%0A%0A
+import static org.junit.Assert.assertEquals;%0A
 import s
@@ -2409,24 +2409,24 @@
 %7D finally %7B%0A
-
             
@@ -2468,11 +2468,1858 @@
  %7D%0A    %7D
+%0A%0A    @Test%0A    public void testEventFDETSemantics() throws Throwable %7B%0A        final FileDescriptor epoll = Native.newEpollCreate();%0A        final FileDescriptor eventFd = Native.newEventFd();%0A        final FileDescriptor timerFd = Native.newTimerFd();%0A        final EpollEventArray array = new EpollEventArray(1024);%0A        try %7B%0A            Native.epollCtlAdd(epoll.intValue(), eventFd.intValue(), Native.EPOLLIN %7C Native.EPOLLET);%0A            final AtomicReference%3CThrowable%3E causeRef = new AtomicReference%3C%3E();%0A            final AtomicInteger integer = new AtomicInteger();%0A            final Thread t = new Thread(() -%3E %7B%0A                try %7B%0A                    for (int i = 0; i %3C 2; i++) %7B%0A                        int ready = Native.epollWait(epoll, array, timerFd, -1, -1);%0A                        assertEquals(1, ready);%0A                        assertEquals(eventFd.intValue(), array.fd(0));%0A                        integer.incrementAndGet();%0A                    %7D%0A                %7D catch (IOException e) %7B%0A                    causeRef.set(e);%0A                %7D%0A            %7D);%0A            t.start();%0A            Native.eventFdWrite(eventFd.intValue(), 1);%0A%0A            // Spin until we was the wakeup.%0A            while (integer.get() != 1) %7B%0A                Thread.sleep(10);%0A            %7D%0A            // Sleep for a short moment to ensure there is not other wakeup.%0A            Thread.sleep(1000);%0A            assertEquals(1, integer.get());%0A            Native.eventFdWrite(eventFd.intValue(), 1);%0A            t.join();%0A            Throwable cause = causeRef.get();%0A            if (cause != null) %7B%0A                throw cause;%0A            %7D%0A            assertEquals(2, integer.get());%0A        %7D finally %7B%0A            array.free();%0A            epoll.close();%0A            eventFd.close();%0A            timerFd.close();%0A        %7D%0A    %7D
 %0A%7D%0A

Add testcase to prove that ET semantics for eventFD are correct (#9385)