1 /*
   2  * Copyright (c) 2011, 2013, 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 /**
  25  @test
  26  @summary This tests the basic functionality of sockets and selectors via local channels.
  27  @summary It starts a server on one Thread, then it starts a client on another thread.
  28  @summary It then checks for the validity of the data transfered betweenthem.
  29  @summary If the data is not transmitted correctly the tests reports an error.
  30  @summary com.apple.junit.java.nio.Selector
  31  @library ../../regtesthelpers
  32  @run junit TestNIOLocalChannels
  33  */
  34 
  35 import junit.framework.*;
  36 
  37 import java.io.IOException;
  38 import java.io.InputStream;
  39 import java.net.InetSocketAddress;
  40 import java.net.URL;
  41 import java.nio.ByteBuffer;
  42 import java.nio.channels.*;
  43 import java.util.Iterator;
  44 
  45 public class TestNIOLocalChannels extends TestCase
  46 {
  47     static final int PORT = 10000;
  48 
  49     public static Object lock = new Object();
  50     public static boolean finishedReading = false;
  51     public static int correctAnswers = 0;
  52 
  53 
  54     protected void setUp()
  55     {
  56     new Server().start();
  57 
  58     }
  59 
  60     protected void tearDown()
  61     {
  62     }
  63 
  64     public void testTestMe() throws Exception
  65     {
  66     int count = 0;
  67     while (true)
  68     {
  69     count++;
  70     synchronized(lock)
  71     {
  72 if (finishedReading)
  73 {
  74 assertTrue(" The transfered data from the server to the client didn't match exactly", correctAnswers > 50);
  75 break;
  76 }
  77 }
  78     Thread.sleep(200);
  79 
  80     // this means that the test hung - ABORT
  81     if (count == 1000)
  82     {
  83     finishedReading = true;
  84     assertTrue(" The test hung - ABORTING", false);
  85     break;
  86     }
  87     }
  88     }
  89 
  90     public static Test suite()
  91     {
  92         return new TestSuite(TestNIOLocalChannels.class);
  93     }
  94 
  95     public static void main (String[] args)
  96     {
  97         junit.textui.TestRunner.run(suite());
  98     }
  99 }
 100 
 101 /*
 102  * Simple HTTP response server, adapted from O'Reilly NIO book's echo
 103  * server example.
 104  */
 105 class Server extends Thread {
 106 
 107     static final byte [] RESPONSE_BYTES =
 108     "HTTP/1.0 200 OK\r\nContent-Type: image/gif\r\nContent-Length: 2\r\nServer: D1\r\nConnection: close\r\n\r\nHello".getBytes();
 109 
 110     final ByteBuffer mRequestBuf;
 111     final ByteBuffer mResponseBuf;
 112 
 113     Server() {
 114         mRequestBuf = ByteBuffer.allocateDirect(4096);
 115         mResponseBuf = ByteBuffer.allocateDirect(RESPONSE_BYTES.length);
 116         mResponseBuf.put(RESPONSE_BYTES);
 117         mResponseBuf.flip();
 118     }
 119 
 120     public void run() {
 121         try {
 122 
 123             final ServerSocketChannel serverChannel = ServerSocketChannel.open();
 124 
 125             serverChannel.socket().bind(new InetSocketAddress(TestNIOLocalChannels.PORT));
 126             serverChannel.configureBlocking(false);
 127 
 128             final Selector selector = Selector.open();
 129             serverChannel.register(selector, SelectionKey.OP_ACCEPT);
 130 
 131             // now we can run our client thread
 132             new Client().start();
 133 
 134             while (true) {
 135 
 136 synchronized(TestNIOLocalChannels.lock)
 137 {
 138 if (TestNIOLocalChannels.finishedReading)
 139 {
 140 break;
 141 }
 142 }
 143 
 144                 // Block and spin until at least one key is ready.
 145                 if (selector.select(1000) == 0)
 146                     continue;
 147 
 148                 final Iterator keyItr = selector.selectedKeys().iterator();
 149                 while (keyItr.hasNext()) {
 150 
 151                     final SelectionKey key = (SelectionKey) keyItr.next();
 152 
 153                     // Set new connections to readable.
 154                     if (key.isAcceptable()) {
 155                         final SocketChannel ch = ((ServerSocketChannel) key.channel()).accept();
 156                         if (ch == null)
 157                             return;
 158                         ch.configureBlocking(false);
 159                         ch.register(selector, SelectionKey.OP_READ);
 160                     }
 161 
 162                     // Handle readable connections.
 163                     else if (key.isReadable()) {
 164                         final SocketChannel ch = (SocketChannel) key.channel();
 165                         ch.read(mRequestBuf);
 166                         mRequestBuf.clear(); // don't need data for testing.
 167 mResponseBuf.rewind();
 168                         ch.write(mResponseBuf);
 169                         ch.close();
 170                     }
 171 
 172                     // assert increment();
 173                     keyItr.remove();
 174                 }
 175             }
 176 
 177         } catch (Exception e) {
 178             System.err.println("PixelServer: exception in main select loop!");
 179             e.printStackTrace();
 180         }
 181     }
 182 }
 183 
 184 /**
 185  * Simple HTTP client with statistics logging.
 186  */
 187 class Client extends Thread {
 188     public void run() {
 189         try {
 190             final byte [] buf = new byte[4096];
 191             char[] expectedResponse = { 'H', 'e', 'l', 'l', 'o' };
 192             int count = 0;
 193             while (true) {
 194 
 195             synchronized(TestNIOLocalChannels.lock)
 196 {
 197 if (TestNIOLocalChannels.finishedReading)
 198 {
 199 break;
 200 }
 201 }
 202 
 203             final InputStream is = new URL("http://localhost:"+TestNIOLocalChannels.PORT+"/" + count).openStream();
 204                 int num = 0;
 205                 while (num != -1)
 206                 {
 207                 num = is.read(buf);
 208                 for (int i = 0; i < num; i++)
 209                 {
 210                 if (((char) buf[i]) == expectedResponse[i])
 211                 {
 212                 TestNIOLocalChannels.correctAnswers++;
 213                 }
 214                 else
 215                 {
 216                 TestNIOLocalChannels.correctAnswers = -1;
 217                 break;
 218                 }
 219                 }
 220                 }
 221                 is.close();
 222 
 223                 // we got 50 correct answers, we can break now
 224                 if (TestNIOLocalChannels.correctAnswers > 50)
 225                 {
 226                 break;
 227                 }
 228 
 229                 if (TestNIOLocalChannels.correctAnswers == -1)
 230                 {
 231                 break;
 232                 }
 233                 //                 if (count % 5000 == 0) {
 234                 //                     long t = System.currentTimeMillis();
 235                 //                     System.out.println("5k hits in " + (t - time) + "ms");
 236                 //                     time = t;
 237                 //                 }
 238             }
 239         } catch (IOException e) {
 240             e.printStackTrace();
 241         }
 242 
 243 synchronized(TestNIOLocalChannels.lock)
 244 {
 245 TestNIOLocalChannels.finishedReading = true;
 246 }
 247     }
 248 }