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