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 
  26 /* @test
  27  * @bug 6350055
  28  * @run testng AtomicUpdates
  29  * @summary Unit test for SelectionKey interestOpsOr and interestOpsAnd
  30  */
  31 
  32 import java.io.Closeable;
  33 import java.io.IOException;
  34 import java.net.InetAddress;
  35 import java.net.InetSocketAddress;
  36 import java.nio.channels.CancelledKeyException;
  37 import java.nio.channels.SelectableChannel;
  38 import java.nio.channels.SelectionKey;
  39 import java.nio.channels.Selector;
  40 import java.nio.channels.ServerSocketChannel;
  41 import java.nio.channels.SocketChannel;
  42 import org.testng.annotations.Test;
  43 
  44 import static java.nio.channels.SelectionKey.OP_READ;
  45 import static java.nio.channels.SelectionKey.OP_WRITE;
  46 import static java.nio.channels.SelectionKey.OP_CONNECT;
  47 import static java.nio.channels.SelectionKey.OP_ACCEPT;
  48 import static org.testng.Assert.*;
  49 
  50 @Test
  51 public class AtomicUpdates {
  52 
  53     private SelectionKey keyFor(SocketChannel sc) {
  54         return new SelectionKey() {
  55             private int ops;
  56             private boolean invalid;
  57             private void ensureValid() {
  58                 if (!isValid())
  59                     throw new CancelledKeyException();
  60             }
  61             @Override
  62             public SelectableChannel channel() {
  63                 return sc;
  64             }
  65             @Override
  66             public Selector selector() {
  67                 throw new RuntimeException();
  68             }
  69             @Override
  70             public boolean isValid() {
  71                 return !invalid;
  72             }
  73             @Override
  74             public void cancel() {
  75                 invalid = true;
  76             }
  77             @Override
  78             public int interestOps() {
  79                 ensureValid();
  80                 return ops;
  81             }
  82             @Override
  83             public SelectionKey interestOps(int ops) {
  84                 ensureValid();
  85                 if ((ops & ~channel().validOps()) != 0)
  86                     throw new IllegalArgumentException();
  87                 this.ops = ops;
  88                 return this;
  89             }
  90             @Override
  91             public int readyOps() {
  92                 ensureValid();
  93                 return 0;
  94             }
  95         };
  96     }
  97 
  98     private void test(SelectionKey key) {
  99         assertTrue(key.channel() instanceof SocketChannel);
 100         key.interestOps(0);
 101 
 102         // 0 -> 0
 103         int previous = key.interestOpsOr(0);
 104         assertTrue(previous == 0);
 105         assertTrue(key.interestOps() == 0);
 106 
 107         // 0 -> OP_CONNECT
 108         previous = key.interestOpsOr(OP_CONNECT);
 109         assertTrue(previous == 0);
 110         assertTrue(key.interestOps() == OP_CONNECT);
 111 
 112         // OP_CONNECT -> OP_CONNECT
 113         previous = key.interestOpsOr(0);
 114         assertTrue(previous == OP_CONNECT);
 115         assertTrue(key.interestOps() == OP_CONNECT);
 116 
 117         // OP_CONNECT -> OP_CONNECT | OP_READ | OP_WRITE
 118         previous = key.interestOpsOr(OP_READ | OP_WRITE);
 119         assertTrue(previous == OP_CONNECT);
 120         assertTrue(key.interestOps() == (OP_CONNECT | OP_READ | OP_WRITE));
 121 
 122         // OP_CONNECT | OP_READ | OP_WRITE -> OP_CONNECT
 123         previous = key.interestOpsAnd(~(OP_READ | OP_WRITE));
 124         assertTrue(previous == (OP_CONNECT | OP_READ | OP_WRITE));
 125         assertTrue(key.interestOps() == OP_CONNECT);
 126 
 127         // OP_CONNECT -> 0
 128         previous = key.interestOpsAnd(~OP_CONNECT);
 129         assertTrue(previous == OP_CONNECT);
 130         assertTrue(key.interestOps() == 0);
 131 
 132         // OP_READ | OP_WRITE -> OP_READ | OP_WRITE
 133         key.interestOps(OP_READ | OP_WRITE);
 134         previous = key.interestOpsAnd(~OP_ACCEPT);
 135         assertTrue(previous == (OP_READ | OP_WRITE));
 136         assertTrue(key.interestOps() == (OP_READ | OP_WRITE));
 137 
 138         // OP_READ | OP_WRITE -> 0
 139         previous = key.interestOpsAnd(0);
 140         assertTrue(previous == (OP_READ | OP_WRITE));
 141         assertTrue(key.interestOps() == 0);
 142 
 143         // 0 -> 0
 144         previous = key.interestOpsAnd(0);
 145         assertTrue(previous == 0);
 146         assertTrue(key.interestOps() == 0);
 147 
 148         try {
 149             key.interestOpsOr(OP_ACCEPT);
 150             fail("IllegalArgumentException expected");
 151         } catch (IllegalArgumentException expected) { }
 152 
 153         key.cancel();
 154         try {
 155             key.interestOpsOr(OP_READ);
 156             fail("CancelledKeyException expected");
 157         } catch (CancelledKeyException expected) { }
 158         try {
 159             key.interestOpsAnd(~OP_READ);
 160             fail("CancelledKeyException expected");
 161         } catch (CancelledKeyException expected) { }
 162     }
 163 
 164     /**
 165      * Test default implementation of interestOpsOr/interestOpsAnd
 166      */
 167     public void testDefaultImplementation() throws Exception {
 168         try (SocketChannel sc = SocketChannel.open()) {
 169             SelectionKey key = keyFor(sc);
 170             test(key);
 171         }
 172     }
 173 
 174     /**
 175      * Test the default provider implementation of SelectionKey.
 176      */
 177     public void testNioImplementation() throws Exception {
 178         try (SocketChannel sc = SocketChannel.open();
 179              Selector sel = Selector.open()) {
 180             sc.configureBlocking(false);
 181             SelectionKey key = sc.register(sel, 0);
 182             test(key);
 183         }
 184     }
 185 }
 186