1 /*
2  * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 package test.java.nio.channels.SelectionKey;
26 
27 /* @test
28  * @bug 6350055
29  * @run testng AtomicUpdates
30  * @summary Unit test for SelectionKey interestOpsOr and interestOpsAnd
31  */
32 
33 import java.io.Closeable;
34 import java.io.IOException;
35 import java.net.InetAddress;
36 import java.net.InetSocketAddress;
37 import java.nio.channels.CancelledKeyException;
38 import java.nio.channels.SelectableChannel;
39 import java.nio.channels.SelectionKey;
40 import java.nio.channels.Selector;
41 import java.nio.channels.ServerSocketChannel;
42 import java.nio.channels.SocketChannel;
43 import org.testng.annotations.Test;
44 
45 import static java.nio.channels.SelectionKey.OP_READ;
46 import static java.nio.channels.SelectionKey.OP_WRITE;
47 import static java.nio.channels.SelectionKey.OP_CONNECT;
48 import static java.nio.channels.SelectionKey.OP_ACCEPT;
49 import static org.testng.Assert.*;
50 
51 @Test
52 public class AtomicUpdates {
53 
keyFor(SocketChannel sc)54     private SelectionKey keyFor(SocketChannel sc) {
55         return new SelectionKey() {
56             private int ops;
57             private boolean invalid;
58             private void ensureValid() {
59                 if (!isValid())
60                     throw new CancelledKeyException();
61             }
62             @Override
63             public SelectableChannel channel() {
64                 return sc;
65             }
66             @Override
67             public Selector selector() {
68                 throw new RuntimeException();
69             }
70             @Override
71             public boolean isValid() {
72                 return !invalid;
73             }
74             @Override
75             public void cancel() {
76                 invalid = true;
77             }
78             @Override
79             public int interestOps() {
80                 ensureValid();
81                 return ops;
82             }
83             @Override
84             public SelectionKey interestOps(int ops) {
85                 ensureValid();
86                 if ((ops & ~channel().validOps()) != 0)
87                     throw new IllegalArgumentException();
88                 this.ops = ops;
89                 return this;
90             }
91             @Override
92             public int readyOps() {
93                 ensureValid();
94                 return 0;
95             }
96         };
97     }
98 
test(SelectionKey key)99     private void test(SelectionKey key) {
100         assertTrue(key.channel() instanceof SocketChannel);
101         key.interestOps(0);
102 
103         // 0 -> 0
104         int previous = key.interestOpsOr(0);
105         assertTrue(previous == 0);
106         assertTrue(key.interestOps() == 0);
107 
108         // 0 -> OP_CONNECT
109         previous = key.interestOpsOr(OP_CONNECT);
110         assertTrue(previous == 0);
111         assertTrue(key.interestOps() == OP_CONNECT);
112 
113         // OP_CONNECT -> OP_CONNECT
114         previous = key.interestOpsOr(0);
115         assertTrue(previous == OP_CONNECT);
116         assertTrue(key.interestOps() == OP_CONNECT);
117 
118         // OP_CONNECT -> OP_CONNECT | OP_READ | OP_WRITE
119         previous = key.interestOpsOr(OP_READ | OP_WRITE);
120         assertTrue(previous == OP_CONNECT);
121         assertTrue(key.interestOps() == (OP_CONNECT | OP_READ | OP_WRITE));
122 
123         // OP_CONNECT | OP_READ | OP_WRITE -> OP_CONNECT
124         previous = key.interestOpsAnd(~(OP_READ | OP_WRITE));
125         assertTrue(previous == (OP_CONNECT | OP_READ | OP_WRITE));
126         assertTrue(key.interestOps() == OP_CONNECT);
127 
128         // OP_CONNECT -> 0
129         previous = key.interestOpsAnd(~OP_CONNECT);
130         assertTrue(previous == OP_CONNECT);
131         assertTrue(key.interestOps() == 0);
132 
133         // OP_READ | OP_WRITE -> OP_READ | OP_WRITE
134         key.interestOps(OP_READ | OP_WRITE);
135         previous = key.interestOpsAnd(~OP_ACCEPT);
136         assertTrue(previous == (OP_READ | OP_WRITE));
137         assertTrue(key.interestOps() == (OP_READ | OP_WRITE));
138 
139         // OP_READ | OP_WRITE -> 0
140         previous = key.interestOpsAnd(0);
141         assertTrue(previous == (OP_READ | OP_WRITE));
142         assertTrue(key.interestOps() == 0);
143 
144         // 0 -> 0
145         previous = key.interestOpsAnd(0);
146         assertTrue(previous == 0);
147         assertTrue(key.interestOps() == 0);
148 
149         try {
150             key.interestOpsOr(OP_ACCEPT);
151             fail("IllegalArgumentException expected");
152         } catch (IllegalArgumentException expected) { }
153 
154         key.cancel();
155         try {
156             key.interestOpsOr(OP_READ);
157             fail("CancelledKeyException expected");
158         } catch (CancelledKeyException expected) { }
159         try {
160             key.interestOpsAnd(~OP_READ);
161             fail("CancelledKeyException expected");
162         } catch (CancelledKeyException expected) { }
163     }
164 
165     /**
166      * Test default implementation of interestOpsOr/interestOpsAnd
167      */
testDefaultImplementation()168     public void testDefaultImplementation() throws Exception {
169         try (SocketChannel sc = SocketChannel.open()) {
170             SelectionKey key = keyFor(sc);
171             test(key);
172         }
173     }
174 
175     /**
176      * Test the default provider implementation of SelectionKey.
177      */
testNioImplementation()178     public void testNioImplementation() throws Exception {
179         try (SocketChannel sc = SocketChannel.open();
180              Selector sel = Selector.open()) {
181             sc.configureBlocking(false);
182             SelectionKey key = sc.register(sel, 0);
183             test(key);
184         }
185     }
186 }