View Javadoc
1   /*
2    * Copyright 2019 The Netty Project
3    *
4    * The Netty Project licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package io.netty.testsuite.transport;
17  
18  import io.netty.channel.Channel;
19  import io.netty.channel.DefaultEventLoopGroup;
20  import io.netty.channel.EventLoop;
21  import io.netty.channel.EventLoopGroup;
22  import io.netty.channel.MultithreadEventLoopGroup;
23  import io.netty.channel.ServerChannel;
24  import io.netty.channel.SingleThreadEventLoop;
25  import io.netty.channel.local.LocalChannel;
26  import io.netty.channel.local.LocalServerChannel;
27  import io.netty.util.concurrent.EventExecutorChooserFactory;
28  import io.netty.util.concurrent.RejectedExecutionHandlers;
29  import org.junit.jupiter.api.Test;
30  import org.junit.jupiter.api.Timeout;
31  import org.junit.jupiter.api.function.Executable;
32  
33  import java.util.concurrent.Executor;
34  import java.util.concurrent.TimeUnit;
35  
36  import static org.junit.jupiter.api.Assertions.assertThrows;
37  
38  public class DefaultEventLoopTest extends AbstractSingleThreadEventLoopTest {
39  
40      @Test
41      @Timeout(value = 3000, unit = TimeUnit.MILLISECONDS)
42      public void testChannelsIteratorNotSupported() throws Exception {
43          EventLoopGroup group = newEventLoopGroup();
44          final SingleThreadEventLoop loop = (SingleThreadEventLoop) group.next();
45          try {
46              final Channel ch = newChannel();
47              loop.register(ch).syncUninterruptibly();
48  
49              assertThrows(UnsupportedOperationException.class, new Executable() {
50                  @Override
51                  public void execute() throws Throwable {
52                      loop.registeredChannelsIterator();
53                  }
54              });
55          } finally {
56              group.shutdownGracefully();
57          }
58      }
59  
60      @Override
61      protected EventLoopGroup newEventLoopGroup() {
62          return new DefaultEventLoopGroup();
63      }
64  
65      @Override
66      protected EventLoopGroup newAutoScalingEventLoopGroup() {
67          return new AutoScalingDefaultEventLoopGroup(SCALING_MAX_THREADS, AUTO_SCALING_CHOOSER_FACTORY);
68      }
69  
70      @Override
71      protected Channel newChannel() {
72          return new LocalChannel();
73      }
74  
75      @Override
76      protected Class<? extends ServerChannel> serverChannelClass() {
77          return LocalServerChannel.class;
78      }
79  
80      private static final class SuspendableDefaultEventLoop extends SingleThreadEventLoop {
81          SuspendableDefaultEventLoop(EventLoopGroup parent, Executor executor) {
82              super(parent, executor, true, true, DEFAULT_MAX_PENDING_TASKS,
83                    RejectedExecutionHandlers.reject());
84          }
85  
86          @Override
87          protected void run() {
88              for (;;) {
89                  Runnable task = takeTask();
90                  if (task != null) {
91                      runTask(task);
92                      updateLastExecutionTime();
93                  }
94  
95                  // Check if a suspend is requested and we have no more tasks. If so,
96                  // exit the run() method to allow the suspension to complete.
97                  if (canSuspend()) {
98                      break;
99                  }
100 
101                 if (confirmShutdown()) {
102                     break;
103                 }
104             }
105         }
106     }
107 
108     private static final class AutoScalingDefaultEventLoopGroup extends MultithreadEventLoopGroup {
109         AutoScalingDefaultEventLoopGroup(int nThreads, EventExecutorChooserFactory chooserFactory) {
110             super(nThreads, (Executor) null, chooserFactory);
111         }
112 
113         @Override
114         protected EventLoop newChild(Executor executor, Object... args) throws Exception {
115             return new SuspendableDefaultEventLoop(this, executor);
116         }
117     }
118 }