diff options
author | dfuchs <none@none> | 2012-11-07 13:24:39 +0100 |
---|---|---|
committer | dfuchs <none@none> | 2012-11-07 13:24:39 +0100 |
commit | f9e3bee55aa0dff73df09eb9367bbc298a11b2f8 (patch) | |
tree | ac8d192b77267130f8665cc5b0d884b4ca833d77 /test/java/nio/channels | |
parent | c6973e7708a77baef62b92f67604e9c45881896b (diff) |
6720349: (ch) Channels tests depending on hosts inside Sun
Summary: This changeset make the nio tests start small TCP or UDP servers from within the tests, instead of relying on external services.
Reviewed-by: alanb
--HG--
rename : test/java/nio/channels/TestUtil.java => test/java/nio/channels/TestServers.java
Diffstat (limited to 'test/java/nio/channels')
20 files changed, 1214 insertions, 244 deletions
diff --git a/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java b/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java index 022455fe4..1763ef3a1 100644 --- a/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java +++ b/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,29 +27,16 @@ * @library .. */ -import java.io.*; import java.net.*; -import java.nio.*; import java.nio.channels.*; -import java.nio.charset.*; import java.util.*; public class AdaptDatagramSocket { static java.io.PrintStream out = System.out; - static Random rand = new Random(); - static final int ECHO_PORT = 7; - static final int DISCARD_PORT = 9; - static final String REMOTE_HOST = TestUtil.HOST; - - static final InetSocketAddress echoAddress - = new InetSocketAddress(REMOTE_HOST, ECHO_PORT); - static final InetSocketAddress discardAddress - = new InetSocketAddress(REMOTE_HOST, DISCARD_PORT); - static String toString(DatagramPacket dp) { return ("DatagramPacket[off=" + dp.getOffset() + ", len=" + dp.getLength() @@ -88,10 +75,11 @@ public class AdaptDatagramSocket { out.println("rtt: " + (System.currentTimeMillis() - start)); out.println("post op: " + toString(op) + " ip: " + toString(ip)); - for (int i = 0; i < ip.getLength(); i++) + for (int i = 0; i < ip.getLength(); i++) { if (ip.getData()[ip.getOffset() + i] != op.getData()[op.getOffset() + i]) throw new Exception("Incorrect data received"); + } if (!(ip.getSocketAddress().equals(dst))) { throw new Exception("Incorrect sender address, expected: " + dst @@ -130,8 +118,9 @@ public class AdaptDatagramSocket { ds.setSoTimeout(timeout); out.println("timeout: " + ds.getSoTimeout()); - for (int i = 0; i < 5; i++) + for (int i = 0; i < 5; i++) { test(ds, dst, shouldTimeout); + } // Leave the socket open so that we don't reuse the old src address //ds.close(); @@ -139,10 +128,23 @@ public class AdaptDatagramSocket { } public static void main(String[] args) throws Exception { - test(echoAddress, 0, false, false); - test(echoAddress, 0, false, true); - test(echoAddress, 5000, false, false); - test(discardAddress, 10, true, false); + // need an UDP echo server + try (TestServers.UdpEchoServer echoServer + = TestServers.UdpEchoServer.startNewServer(100)) { + final InetSocketAddress address + = new InetSocketAddress(echoServer.getAddress(), + echoServer.getPort()); + test(address, 0, false, false); + test(address, 0, false, true); + test(address, 5000, false, false); + } + try (TestServers.UdpDiscardServer discardServer + = TestServers.UdpDiscardServer.startNewServer()) { + final InetSocketAddress address + = new InetSocketAddress(discardServer.getAddress(), + discardServer.getPort()); + test(address, 10, true, false); + } } } diff --git a/test/java/nio/channels/DatagramChannel/IsBound.java b/test/java/nio/channels/DatagramChannel/IsBound.java index 6fae66812..7a028ec9b 100644 --- a/test/java/nio/channels/DatagramChannel/IsBound.java +++ b/test/java/nio/channels/DatagramChannel/IsBound.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,25 @@ import java.nio.channels.*; public class IsBound { public static void main(String argv[]) throws Exception { - InetSocketAddress isa = new InetSocketAddress( - InetAddress.getByName(TestUtil.HOST), 13); - ByteBuffer bb = ByteBuffer.allocateDirect(256); - bb.put("hello".getBytes()); - bb.flip(); + try (TestServers.UdpDayTimeServer daytimeServer + = TestServers.UdpDayTimeServer.startNewServer(100)) { + InetSocketAddress isa = new InetSocketAddress( + daytimeServer.getAddress(), + daytimeServer.getPort()); + ByteBuffer bb = ByteBuffer.allocateDirect(256); + bb.put("hello".getBytes()); + bb.flip(); - DatagramChannel dc = DatagramChannel.open(); - dc.send(bb, isa); - if(!dc.socket().isBound()) - throw new Exception("Test failed"); - dc.close(); + DatagramChannel dc = DatagramChannel.open(); + dc.send(bb, isa); + if(!dc.socket().isBound()) + throw new Exception("Test failed"); + dc.close(); - dc = DatagramChannel.open(); - if(dc.socket().isBound()) - throw new Exception("Test failed"); - dc.close(); + dc = DatagramChannel.open(); + if(dc.socket().isBound()) + throw new Exception("Test failed"); + dc.close(); + } } } diff --git a/test/java/nio/channels/DatagramChannel/IsConnected.java b/test/java/nio/channels/DatagramChannel/IsConnected.java index f71d8696c..db4cb8969 100644 --- a/test/java/nio/channels/DatagramChannel/IsConnected.java +++ b/test/java/nio/channels/DatagramChannel/IsConnected.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,21 +28,23 @@ */ import java.net.*; -import java.nio.*; import java.nio.channels.*; public class IsConnected { public static void main(String argv[]) throws Exception { - InetSocketAddress isa = new InetSocketAddress( - InetAddress.getByName(TestUtil.HOST), 13); - DatagramChannel dc = DatagramChannel.open(); - dc.configureBlocking(true); - dc.connect(isa); - if (!dc.isConnected()) - throw new RuntimeException("channel.isConnected inconsistent"); - if (!dc.socket().isConnected()) - throw new RuntimeException("socket.isConnected inconsistent"); - dc.close(); + try (TestServers.UdpDayTimeServer daytimeServer + = TestServers.UdpDayTimeServer.startNewServer(100)) { + InetSocketAddress isa = new InetSocketAddress( + daytimeServer.getAddress(), daytimeServer.getPort()); + DatagramChannel dc = DatagramChannel.open(); + dc.configureBlocking(true); + dc.connect(isa); + if (!dc.isConnected()) + throw new RuntimeException("channel.isConnected inconsistent"); + if (!dc.socket().isConnected()) + throw new RuntimeException("socket.isConnected inconsistent"); + dc.close(); + } } } diff --git a/test/java/nio/channels/Selector/Alias.java b/test/java/nio/channels/Selector/Alias.java index c3554b9cc..731703bd4 100644 --- a/test/java/nio/channels/Selector/Alias.java +++ b/test/java/nio/channels/Selector/Alias.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,11 @@ * @library .. */ -import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; -import java.util.*; import java.nio.channels.spi.SelectorProvider; +import java.util.*; public class Alias { @@ -40,18 +39,26 @@ public class Alias { static int LIMIT = 20; // Hangs after just 1 if problem is present public static void main(String[] args) throws Exception { - test1(); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + test1(daytimeServer); + } } - public static void test1() throws Exception { + static void test1(TestServers.DayTimeServer daytimeServer) throws Exception { Selector selector = SelectorProvider.provider().openSelector(); - InetAddress myAddress=InetAddress.getByName(TestUtil.HOST); - InetSocketAddress isa = new InetSocketAddress(myAddress,13); + InetAddress myAddress = daytimeServer.getAddress(); + InetSocketAddress isa + = new InetSocketAddress(myAddress, + daytimeServer.getPort()); for (int j=0; j<LIMIT; j++) { SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); boolean result = sc.connect(isa); + + // On some platforms - given that we're using a local server, + // we may not enter into the if () { } statement below... if (!result) { SelectionKey key = sc.register(selector, SelectionKey.OP_CONNECT); diff --git a/test/java/nio/channels/Selector/BasicConnect.java b/test/java/nio/channels/Selector/BasicConnect.java index 61575b153..e440fe7ee 100644 --- a/test/java/nio/channels/Selector/BasicConnect.java +++ b/test/java/nio/channels/Selector/BasicConnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,10 @@ * @library .. */ -import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.SelectorProvider; -import java.nio.charset.*; import java.util.*; @@ -44,52 +42,57 @@ import java.util.*; public class BasicConnect { - static final int PORT = 7; // echo - static final String HOST = TestUtil.HOST; - public static void main(String[] args) throws Exception { Selector connectSelector = SelectorProvider.provider().openSelector(); - InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(HOST), PORT); - SocketChannel sc = SocketChannel.open(); - sc.configureBlocking(false); - boolean result = sc.connect(isa); - while (!result) { - SelectionKey connectKey = sc.register(connectSelector, - SelectionKey.OP_CONNECT); - int keysAdded = connectSelector.select(); - if (keysAdded > 0) { - Set readyKeys = connectSelector.selectedKeys(); - Iterator i = readyKeys.iterator(); - while (i.hasNext()) { - SelectionKey sk = (SelectionKey)i.next(); - i.remove(); - SocketChannel nextReady = (SocketChannel)sk.channel(); - result = nextReady.finishConnect(); - if (result) - sk.cancel(); + try (TestServers.EchoServer echoServer + = TestServers.EchoServer.startNewServer(100)) { + InetSocketAddress isa + = new InetSocketAddress(echoServer.getAddress(), + echoServer.getPort()); + SocketChannel sc = SocketChannel.open(); + sc.configureBlocking(false); + boolean result = sc.connect(isa); + if (result) { + System.out.println("Socket immediately connected on " + + System.getProperty("os.name") + + ": " + sc); + } + while (!result) { + SelectionKey connectKey = sc.register(connectSelector, + SelectionKey.OP_CONNECT); + int keysAdded = connectSelector.select(); + if (keysAdded > 0) { + Set readyKeys = connectSelector.selectedKeys(); + Iterator i = readyKeys.iterator(); + while (i.hasNext()) { + SelectionKey sk = (SelectionKey)i.next(); + i.remove(); + SocketChannel nextReady = (SocketChannel)sk.channel(); + result = nextReady.finishConnect(); + if (result) + sk.cancel(); + } } } - } - byte[] bs = new byte[] { (byte)0xca, (byte)0xfe, - (byte)0xba, (byte)0xbe }; - ByteBuffer bb = ByteBuffer.wrap(bs); - sc.configureBlocking(true); - sc.write(bb); - bb.rewind(); + byte[] bs = new byte[] { (byte)0xca, (byte)0xfe, + (byte)0xba, (byte)0xbe }; + ByteBuffer bb = ByteBuffer.wrap(bs); + sc.configureBlocking(true); + sc.write(bb); + bb.rewind(); - ByteBuffer bb2 = ByteBuffer.allocateDirect(100); - int n = sc.read(bb2); - bb2.flip(); + ByteBuffer bb2 = ByteBuffer.allocateDirect(100); + int n = sc.read(bb2); + bb2.flip(); - sc.close(); - connectSelector.close(); + sc.close(); + connectSelector.close(); - if (!bb.equals(bb2)) - throw new Exception("Echoed bytes incorrect: Sent " - + bb + ", got " + bb2); + if (!bb.equals(bb2)) + throw new Exception("Echoed bytes incorrect: Sent " + + bb + ", got " + bb2); + } } - } diff --git a/test/java/nio/channels/Selector/Connect.java b/test/java/nio/channels/Selector/Connect.java index af1ce984e..67f48d8eb 100644 --- a/test/java/nio/channels/Selector/Connect.java +++ b/test/java/nio/channels/Selector/Connect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,11 @@ * @library .. */ -import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; -import java.util.*; import java.nio.channels.spi.SelectorProvider; +import java.util.*; public class Connect { @@ -40,12 +39,18 @@ public class Connect { static int LIMIT = 100; public static void main(String[] args) throws Exception { - scaleTest(); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(50)) { + scaleTest(daytimeServer); + } } - public static void scaleTest() throws Exception { - InetAddress myAddress=InetAddress.getByName(TestUtil.HOST); - InetSocketAddress isa = new InetSocketAddress(myAddress,13); + static void scaleTest(TestServers.DayTimeServer daytimeServer) + throws Exception + { + InetAddress myAddress = daytimeServer.getAddress(); + InetSocketAddress isa + = new InetSocketAddress(myAddress, daytimeServer.getPort()); for (int j=0; j<LIMIT; j++) { SocketChannel sc = SocketChannel.open(); diff --git a/test/java/nio/channels/Selector/ConnectWrite.java b/test/java/nio/channels/Selector/ConnectWrite.java index 904f3a64a..f1ce97580 100644 --- a/test/java/nio/channels/Selector/ConnectWrite.java +++ b/test/java/nio/channels/Selector/ConnectWrite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,23 +27,25 @@ * @library .. */ -import java.io.*; import java.net.*; -import java.nio.*; import java.nio.channels.*; -import java.util.*; import java.nio.channels.spi.SelectorProvider; +import java.util.*; public class ConnectWrite { public static void main(String[] args) throws Exception { - test1(13); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(25)) { + test1(daytimeServer); + } } - public static void test1(int port) throws Exception { + static void test1(TestServers.DayTimeServer daytimeServer) throws Exception { Selector selector = SelectorProvider.provider().openSelector(); - InetAddress myAddress=InetAddress.getByName(TestUtil.HOST); - InetSocketAddress isa = new InetSocketAddress(myAddress, port); + InetAddress myAddress = daytimeServer.getAddress(); + InetSocketAddress isa + = new InetSocketAddress(myAddress, daytimeServer.getPort()); SocketChannel sc = SocketChannel.open(); try { sc.configureBlocking(false); diff --git a/test/java/nio/channels/Selector/KeysReady.java b/test/java/nio/channels/Selector/KeysReady.java index ba09a4c6e..de27aa4a5 100644 --- a/test/java/nio/channels/Selector/KeysReady.java +++ b/test/java/nio/channels/Selector/KeysReady.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,21 +28,15 @@ */ import java.net.*; -import java.io.*; -import java.nio.*; import java.nio.channels.*; -import java.nio.charset.*; import java.nio.channels.spi.SelectorProvider; public class KeysReady { - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - - static void test() throws Exception { + static void test(TestServers.DayTimeServer dayTimeServer) throws Exception { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(dayTimeServer.getAddress(), + dayTimeServer.getPort()); SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); sc.connect(isa); @@ -64,7 +58,10 @@ public class KeysReady { } public static void main(String[] args) throws Exception { - test(); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(50)) { + test(daytimeServer); + } } } diff --git a/test/java/nio/channels/SocketChannel/AdaptSocket.java b/test/java/nio/channels/SocketChannel/AdaptSocket.java index d479b49ef..1e1fdee80 100644 --- a/test/java/nio/channels/SocketChannel/AdaptSocket.java +++ b/test/java/nio/channels/SocketChannel/AdaptSocket.java @@ -35,19 +35,16 @@ public class AdaptSocket { static java.io.PrintStream out = System.out; - static final int ECHO_PORT = 7; - static final int DAYTIME_PORT = 13; - static final String REMOTE_HOST = TestUtil.HOST; - static final String VERY_REMOTE_HOST = TestUtil.FAR_HOST; - - static void test(String hn, int timeout, boolean shouldTimeout) + static void test(TestServers.DayTimeServer dayTimeServer, + int timeout, + boolean shouldTimeout) throws Exception { out.println(); InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(hn), - DAYTIME_PORT); + = new InetSocketAddress(dayTimeServer.getAddress(), + dayTimeServer.getPort()); SocketChannel sc = SocketChannel.open(); Socket so = sc.socket(); out.println("opened: " + so); @@ -116,13 +113,16 @@ public class AdaptSocket { } } - static void testRead(String hn, int timeout, boolean shouldTimeout) + static void testRead(TestServers.EchoServer echoServer, + int timeout, + boolean shouldTimeout) throws Exception { out.println(); InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(hn), ECHO_PORT); + = new InetSocketAddress(echoServer.getAddress(), + echoServer.getPort()); SocketChannel sc = SocketChannel.open(); sc.connect(isa); Socket so = sc.socket(); @@ -134,22 +134,38 @@ public class AdaptSocket { out.println("timeout: " + so.getSoTimeout()); testRead(so, shouldTimeout); - for (int i = 0; i < 4; i++) + for (int i = 0; i < 4; i++) { testRead(so, shouldTimeout); + } sc.close(); } public static void main(String[] args) throws Exception { - test(REMOTE_HOST, 0, false); - test(REMOTE_HOST, 1000, false); - test(VERY_REMOTE_HOST, 10, true); + try (TestServers.DayTimeServer dayTimeServer + = TestServers.DayTimeServer.startNewServer()) { + test(dayTimeServer, 0, false); + test(dayTimeServer, 1000, false); + } + + try (TestServers.DayTimeServer lingerDayTimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + // this test no longer really test the connection timeout + // since there is no way to prevent the server from eagerly + // accepting connection... + test(lingerDayTimeServer, 10, true); + } - testRead(REMOTE_HOST, 0, false); - testRead(REMOTE_HOST, 8000, false); - testRead(VERY_REMOTE_HOST, 10, true); + try (TestServers.EchoServer echoServer + = TestServers.EchoServer.startNewServer()) { + testRead(echoServer, 0, false); + testRead(echoServer, 8000, false); + } + try (TestServers.EchoServer lingerEchoServer + = TestServers.EchoServer.startNewServer(100)) { + testRead(lingerEchoServer, 10, true); + } } - } diff --git a/test/java/nio/channels/SocketChannel/Basic.java b/test/java/nio/channels/SocketChannel/Basic.java index 79ea9ced2..9cf789f20 100644 --- a/test/java/nio/channels/SocketChannel/Basic.java +++ b/test/java/nio/channels/SocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,13 +36,10 @@ public class Basic { static java.io.PrintStream out = System.out; - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - - static void test() throws Exception { + static void test(TestServers.DayTimeServer daytimeServer) throws Exception { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); SocketChannel sc = SocketChannel.open(isa); out.println("opened: " + sc); /* @@ -76,7 +73,10 @@ public class Basic { } public static void main(String[] args) throws Exception { - test(); + try (TestServers.DayTimeServer dayTimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + test(dayTimeServer); + } } } diff --git a/test/java/nio/channels/SocketChannel/BufferSize.java b/test/java/nio/channels/SocketChannel/BufferSize.java index f7d84bb86..736d0e141 100644 --- a/test/java/nio/channels/SocketChannel/BufferSize.java +++ b/test/java/nio/channels/SocketChannel/BufferSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,17 +28,10 @@ */ import java.nio.channels.*; -import java.net.*; public class BufferSize { - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - public static void main(String[] args) throws Exception { - InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); ServerSocketChannel sc = ServerSocketChannel.open(); try { sc.socket().setReceiveBufferSize(-1); diff --git a/test/java/nio/channels/SocketChannel/Connect.java b/test/java/nio/channels/SocketChannel/Connect.java index 260bf53da..76a32e732 100644 --- a/test/java/nio/channels/SocketChannel/Connect.java +++ b/test/java/nio/channels/SocketChannel/Connect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,9 @@ * @library .. */ +import java.net.*; import java.nio.*; import java.nio.channels.*; -import java.net.*; import java.util.*; public class Connect { @@ -37,21 +37,26 @@ public class Connect { private static final long INCREMENTAL_DELAY = 30L * 1000L; public static void main(String args[]) throws Exception { - test1(TestUtil.HOST); + try (TestServers.EchoServer echoServer + = TestServers.EchoServer.startNewServer(1000)) { + test1(echoServer); + } try { - test1(TestUtil.REFUSING_HOST); + TestServers.RefusingServer refusingServer + = TestServers.RefusingServer.startNewServer(); + test1(refusingServer); throw new Exception("Refused connection throws no exception"); } catch (ConnectException ce) { // Correct result } } - static void test1(String hostname) throws Exception { + static void test1(TestServers.AbstractServer server) throws Exception { Selector selector; SocketChannel sc; SelectionKey sk; InetSocketAddress isa = new InetSocketAddress( - InetAddress.getByName (hostname), 80); + server.getAddress(), server.getPort()); sc = SocketChannel.open(); sc.configureBlocking(false); diff --git a/test/java/nio/channels/SocketChannel/ConnectState.java b/test/java/nio/channels/SocketChannel/ConnectState.java index 9c86d9649..df7d0cdad 100644 --- a/test/java/nio/channels/SocketChannel/ConnectState.java +++ b/test/java/nio/channels/SocketChannel/ConnectState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,20 +30,39 @@ import java.io.*; import java.net.*; import java.nio.*; import java.nio.channels.*; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; public class ConnectState { static PrintStream log = System.err; - static String REMOTE_HOST = TestUtil.HOST; - static int REMOTE_PORT = 7; // echo static InetSocketAddress remote; final static int ST_UNCONNECTED = 0; final static int ST_PENDING = 1; final static int ST_CONNECTED = 2; final static int ST_CLOSED = 3; + final static int ST_PENDING_OR_CONNECTED = 4; + // NO exceptions expected + final static Collection<Class<?>> NONE = Collections.emptySet(); + + // make a set of expected exception. + static Collection<Class<?>> expectedExceptions(Class<?>... expected) { + final Collection<Class<?>> exceptions; + if (expected.length == 0) { + exceptions = NONE; + } else if (expected.length == 1) { + assert expected[0] != null; + exceptions = Collections.<Class<?>>singleton(expected[0]); + } else { + exceptions = new HashSet<>(Arrays.asList(expected)); + } + return exceptions; + } static abstract class Test { @@ -76,37 +95,65 @@ public class ConnectState { check(!sc.isConnectionPending(), "!isConnectionPending"); check(sc.isOpen(), "isOpen"); break; + case ST_PENDING_OR_CONNECTED: + check(sc.isConnected() || sc.isConnectionPending(), + "isConnected || isConnectionPending"); + check(sc.isOpen(), "isOpen"); + break; } } - Test(String name, Class exception, int state) throws Exception { + Test(String name, Class<?> exception, int state) throws Exception { + this(name, expectedExceptions(exception), state); + } + + // On some architecture we may need to accept several exceptions. + // For instance on Solaris, when using a server colocated on the + // machine we cannot guarantee that we will get a + // ConnectionPendingException when connecting twice on the same + // non-blocking socket. We may instead get a an + // AlreadyConnectedException, which is also valid: it simply means + // that the first connection has been immediately accepted. + Test(String name, Collection<Class<?>> exceptions, int state) + throws Exception { SocketChannel sc = SocketChannel.open(); - String note = null; + String note; try { try { note = go(sc); } catch (Exception x) { - if (exception != null) { + Class<?> expectedExceptionClass = null; + for (Class<?> exception : exceptions) { if (exception.isInstance(x)) { log.println(name + ": As expected: " + x); + expectedExceptionClass = exception; check(sc, state); - return; - } else { - throw new Exception(name + break; + } + } + if (expectedExceptionClass == null + && !exceptions.isEmpty()) { + // we had an exception, but it's not of the set of + // exceptions we expected. + throw new Exception(name + ": Incorrect exception", x); - } - } else { + } else if (exceptions.isEmpty()) { + // we didn't expect any exception throw new Exception(name + ": Unexpected exception", x); } + // if we reach here, we have our expected exception + assert expectedExceptionClass != null; + return; } - if (exception != null) + if (!exceptions.isEmpty()) { throw new Exception(name + ": Expected exception not thrown: " - + exception); + + exceptions.iterator().next()); + } check(sc, state); log.println(name + ": Returned normally" + ((note != null) ? ": " + note : "")); @@ -123,6 +170,7 @@ public class ConnectState { new Test("Read unconnected", NotYetConnectedException.class, ST_UNCONNECTED) { + @Override String go(SocketChannel sc) throws Exception { ByteBuffer b = ByteBuffer.allocateDirect(1024); sc.read(b); @@ -131,19 +179,22 @@ public class ConnectState { new Test("Write unconnected", NotYetConnectedException.class, ST_UNCONNECTED) { + @Override String go(SocketChannel sc) throws Exception { ByteBuffer b = ByteBuffer.allocateDirect(1024); sc.write(b); return null; }}; - new Test("Simple connect", null, ST_CONNECTED) { + new Test("Simple connect", NONE, ST_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.connect(remote); return null; }}; - new Test("Simple connect & finish", null, ST_CONNECTED) { + new Test("Simple connect & finish", NONE, ST_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.connect(remote); if (!sc.finishConnect()) @@ -153,6 +204,7 @@ public class ConnectState { new Test("Double connect", AlreadyConnectedException.class, ST_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.connect(remote); sc.connect(remote); @@ -161,12 +213,16 @@ public class ConnectState { new Test("Finish w/o start", NoConnectionPendingException.class, ST_UNCONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.finishConnect(); return null; }}; - new Test("NB simple connect", null, ST_CONNECTED) { + // Note: using our local EchoServer rather than echo on a distant + // host - we see that Tries to finish = 0 (instead of ~ 18). + new Test("NB simple connect", NONE, ST_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.configureBlocking(false); sc.connect(remote); @@ -179,8 +235,15 @@ public class ConnectState { return ("Tries to finish = " + n); }}; + // Note: using our local EchoServer rather than echo on a distant + // host - we cannot guarantee that this test will get a + // a ConnectionPendingException: it may get an + // AlreadyConnectedException, so we should allow for both. new Test("NB double connect", - ConnectionPendingException.class, ST_PENDING) { + expectedExceptions(ConnectionPendingException.class, + AlreadyConnectedException.class), + ST_PENDING_OR_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.configureBlocking(false); sc.connect(remote); @@ -190,13 +253,15 @@ public class ConnectState { new Test("NB finish w/o start", NoConnectionPendingException.class, ST_UNCONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.configureBlocking(false); sc.finishConnect(); return null; }}; - new Test("NB connect, B finish", null, ST_CONNECTED) { + new Test("NB connect, B finish", NONE, ST_CONNECTED) { + @Override String go(SocketChannel sc) throws Exception { sc.configureBlocking(false); sc.connect(remote); @@ -208,9 +273,12 @@ public class ConnectState { } public static void main(String[] args) throws Exception { - remote = new InetSocketAddress(InetAddress.getByName(REMOTE_HOST), - REMOTE_PORT); - tests(); + try (TestServers.EchoServer echoServer + = TestServers.EchoServer.startNewServer(500)) { + remote = new InetSocketAddress(echoServer.getAddress(), + echoServer.getPort()); + tests(); + } } } diff --git a/test/java/nio/channels/SocketChannel/FinishConnect.java b/test/java/nio/channels/SocketChannel/FinishConnect.java index 3d53c986e..efcf38a43 100644 --- a/test/java/nio/channels/SocketChannel/FinishConnect.java +++ b/test/java/nio/channels/SocketChannel/FinishConnect.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,21 +36,25 @@ import java.util.*; public class FinishConnect { - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - public static void main(String[] args) throws Exception { - test1(true, true); - test1(true, false); - test1(false, true); - test1(false, false); - test2(); + try (TestServers.DayTimeServer dayTimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + test1(dayTimeServer, true, true); + test1(dayTimeServer, true, false); + test1(dayTimeServer, false, true); + test1(dayTimeServer, false, false); + test2(dayTimeServer); + } } - static void test1(boolean select, boolean setBlocking) throws Exception { + static void test1(TestServers.DayTimeServer daytimeServer, + boolean select, + boolean setBlocking) + throws Exception + { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); boolean connected = sc.connect(isa); @@ -109,15 +113,27 @@ public class FinishConnect { sc.close(); } - static void test2() throws Exception { + static void test2(TestServers.DayTimeServer daytimeServer) throws Exception { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); boolean done = false; int globalAttempts = 0; + int connectSuccess = 0; while (!done) { - if (globalAttempts++ > 50) + // When using a local daytime server it is not always possible + // to get a pending connection, as sc.connect(isa) may always + // return true. + // So we're going to throw the exception only if there was + // at least 1 case where we did not manage to connect. + if (globalAttempts++ > 50) { + if (globalAttempts == connectSuccess + 1) { + System.out.println("Can't fully test on " + + System.getProperty("os.name")); + break; + } throw new RuntimeException("Failed to connect"); + } SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); boolean connected = sc.connect(isa); @@ -132,6 +148,9 @@ public class FinishConnect { } Thread.sleep(10); } + if (connected) { + connectSuccess++; + } sc.close(); } } diff --git a/test/java/nio/channels/SocketChannel/IsConnectable.java b/test/java/nio/channels/SocketChannel/IsConnectable.java index d646d194a..21bdd80b3 100644 --- a/test/java/nio/channels/SocketChannel/IsConnectable.java +++ b/test/java/nio/channels/SocketChannel/IsConnectable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,24 +28,19 @@ */ import java.net.*; -import java.io.*; -import java.nio.*; import java.nio.channels.*; import java.nio.channels.spi.SelectorProvider; import java.util.*; public class IsConnectable { - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - - static void test() throws Exception { + static void test(TestServers.DayTimeServer daytimeServer) throws Exception { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); SocketChannel sc = SocketChannel.open(); sc.configureBlocking(false); - sc.connect(isa); + final boolean immediatelyConnected = sc.connect(isa); Selector selector = SelectorProvider.provider().openSelector(); try { @@ -67,7 +62,12 @@ public class IsConnectable { throw new Exception("Test failed: 4737146 detected"); } } else { - throw new Exception("Select failed"); + if (!immediatelyConnected) { + throw new Exception("Select failed"); + } else { + System.out.println("IsConnectable couldn't be fully tested for " + + System.getProperty("os.name")); + } } } finally { sc.close(); @@ -76,7 +76,10 @@ public class IsConnectable { } public static void main(String[] args) throws Exception { - test(); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + test(daytimeServer); + } } } diff --git a/test/java/nio/channels/SocketChannel/LocalAddress.java b/test/java/nio/channels/SocketChannel/LocalAddress.java index 1bcd0a189..03a038285 100644 --- a/test/java/nio/channels/SocketChannel/LocalAddress.java +++ b/test/java/nio/channels/SocketChannel/LocalAddress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,18 +28,20 @@ */ import java.net.*; -import java.nio.*; import java.nio.channels.*; public class LocalAddress { public static void main(String[] args) throws Exception { - test1(); + try (TestServers.EchoServer echoServer + = TestServers.EchoServer.startNewServer()) { + test1(echoServer); + } } - static void test1() throws Exception { + static void test1(TestServers.AbstractServer server) throws Exception { InetAddress bogus = InetAddress.getByName("0.0.0.0"); InetSocketAddress saddr = new InetSocketAddress( - InetAddress.getByName(TestUtil.HOST), 23); + server.getAddress(), server.getPort()); //Test1: connect only SocketChannel sc = SocketChannel.open(); diff --git a/test/java/nio/channels/SocketChannel/Stream.java b/test/java/nio/channels/SocketChannel/Stream.java index 456363fbf..fadf0dc90 100644 --- a/test/java/nio/channels/SocketChannel/Stream.java +++ b/test/java/nio/channels/SocketChannel/Stream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,22 +27,17 @@ * @library .. */ -import java.net.*; import java.io.*; -import java.nio.*; +import java.net.*; import java.nio.channels.*; -import java.nio.charset.*; public class Stream { - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; - - static void test() throws Exception { + static void test(TestServers.DayTimeServer daytimeServer) throws Exception { InetSocketAddress isa - = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); SocketChannel sc = SocketChannel.open(); sc.connect(isa); sc.configureBlocking(false); @@ -58,7 +53,9 @@ public class Stream { } public static void main(String[] args) throws Exception { - test(); + try (TestServers.DayTimeServer dayTimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + test(dayTimeServer); + } } - } diff --git a/test/java/nio/channels/SocketChannel/VectorParams.java b/test/java/nio/channels/SocketChannel/VectorParams.java index 9696927c2..f90867f38 100644 --- a/test/java/nio/channels/SocketChannel/VectorParams.java +++ b/test/java/nio/channels/SocketChannel/VectorParams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,31 +27,31 @@ * @library .. */ -import java.net.*; import java.io.*; +import java.net.*; import java.nio.*; import java.nio.channels.*; -import java.nio.charset.*; public class VectorParams { static java.io.PrintStream out = System.out; - static final int DAYTIME_PORT = 13; - static final String DAYTIME_HOST = TestUtil.HOST; static final int testSize = 10; static ByteBuffer[] bufs = null; static InetSocketAddress isa = null; public static void main(String[] args) throws Exception { - initBufs(); - testSocketChannelVectorParams(); - testDatagramChannelVectorParams(); - testPipeVectorParams(); - testFileVectorParams(); + try (TestServers.DayTimeServer daytimeServer + = TestServers.DayTimeServer.startNewServer(100)) { + initBufs(daytimeServer); + testSocketChannelVectorParams(); + testDatagramChannelVectorParams(); + testPipeVectorParams(); + testFileVectorParams(); + } } - static void initBufs() throws Exception { + static void initBufs(TestServers.DayTimeServer daytimeServer) throws Exception { bufs = new ByteBuffer[testSize]; for(int i=0; i<testSize; i++) { String source = "buffer" + i; @@ -59,8 +59,8 @@ public class VectorParams { bufs[i].put(source.getBytes("8859_1")); bufs[i].flip(); } - isa = new InetSocketAddress(InetAddress.getByName(DAYTIME_HOST), - DAYTIME_PORT); + isa = new InetSocketAddress(daytimeServer.getAddress(), + daytimeServer.getPort()); } static void testSocketChannelVectorParams() throws Exception { diff --git a/test/java/nio/channels/TestServers.java b/test/java/nio/channels/TestServers.java new file mode 100644 index 000000000..22d452333 --- /dev/null +++ b/test/java/nio/channels/TestServers.java @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* Test utility classes + * + */ + +import java.io.*; +import java.net.*; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + + +public class TestServers { + + private TestServers() { } + + /** + * An abstract server identifies a server which listens on a port on on a + * given machine. + */ + static abstract class AbstractServer { + + private AbstractServer() { + } + + public abstract int getPort(); + + public abstract InetAddress getAddress(); + } + + /** + * A downgraded type of AbstractServer which will refuse connections. Note: + * use it once and throw it away - this implementation opens an anonymous + * socket and closes it, returning the address of the closed socket. If + * other servers are started afterwards, the address/port might get reused + * and become connectable again - so it's not a good idea to assume that + * connections using this address/port will always be refused. Connections + * will be refused as long as the address/port of the refusing server has + * not been reused. + */ + static class RefusingServer extends AbstractServer { + + final InetAddress address; + final int port; + + private RefusingServer(InetAddress address, int port) { + this.address = address; + this.port = port; + } + + @Override + public int getPort() { + return port; + } + + @Override + public InetAddress getAddress() { + return address; + } + + public static RefusingServer startNewServer() throws IOException { + ServerSocket socket = new ServerSocket(0, 100, + InetAddress.getLocalHost()); + RefusingServer server = new RefusingServer(socket.getInetAddress(), + socket.getLocalPort()); + socket.close(); + return server; + } + } + + /** + * An abstract class for implementing small TCP servers for the nio tests + * purposes. Disclaimer: This is a naive implementation that uses the old + * networking APIs (not those from {@code java.nio.*}) and shamelessly + * extends/creates Threads instead of using an executor service. + */ + static abstract class AbstractTcpServer extends AbstractServer + implements Runnable, Closeable { + + protected final long linger; // #of ms to wait before responding + private Thread acceptThread; // thread waiting for accept + // list of opened connections that should be closed on close. + private List<TcpConnectionThread> connections = new ArrayList<>(); + private ServerSocket serverSocket; // the server socket + private boolean started = false; // whether the server is started + Throwable error = null; + + /** + * Creates a new abstract TCP server. + * + * @param linger the amount of time the server should wait before + * responding to requests. + */ + protected AbstractTcpServer(long linger) { + this.linger = linger; + } + + /** + * The local port to which the server is bound. + * + * @return The local port to which the server is bound. + * @exception IllegalStateException is thrown if the server is not + * started. + */ + @Override + public final synchronized int getPort() { + if (!started) { + throw new IllegalStateException("Not started"); + } + return serverSocket.getLocalPort(); + } + + /** + * The local address to which the server is bound. + * + * @return The local address to which the server is bound. + * @exception IllegalStateException is thrown if the server is not + * started. + */ + @Override + public final synchronized InetAddress getAddress() { + if (!started) { + throw new IllegalStateException("Not started"); + } + return serverSocket.getInetAddress(); + } + + /** + * Tells whether the server is started. + * + * @return true if the server is started. + */ + public final synchronized boolean isStarted() { + return started; + } + + /** + * Creates a new server socket. + * + * @param port local port to bind to. + * @param backlog requested maximum length of the queue of incoming + * connections. + * @param address local address to bind to. + * @return a new bound server socket ready to accept connections. + * @throws IOException if the socket cannot be created or bound. + */ + protected ServerSocket newServerSocket(int port, int backlog, + InetAddress address) + throws IOException { + return new ServerSocket(port, backlog, address); + } + + /** + * Starts listening for connections. + * + * @throws IOException if the server socket cannot be created or bound. + */ + public final synchronized void start() throws IOException { + if (started) { + return; + } + final ServerSocket socket = + newServerSocket(0, 100, InetAddress.getLocalHost()); + serverSocket = socket; + acceptThread = new Thread(this); + acceptThread.setDaemon(true); + acceptThread.start(); + started = true; + } + + /** + * Calls {@code Thread.sleep(linger);} + */ + protected final void lingerIfRequired() { + if (linger > 0) { + try { + Thread.sleep(linger); + } catch (InterruptedException x) { + Thread.interrupted(); + final ServerSocket socket = serverSocket(); + if (socket != null && !socket.isClosed()) { + System.err.println("Thread interrupted..."); + } + } + } + } + + final synchronized ServerSocket serverSocket() { + return this.serverSocket; + } + + /** + * The main accept loop. + */ + @Override + public final void run() { + final ServerSocket sSocket = serverSocket(); + try { + Socket s; + while (isStarted() && !Thread.interrupted() + && (s = sSocket.accept()) != null) { + lingerIfRequired(); + listen(s); + } + } catch (Exception x) { + error = x; + } finally { + synchronized (this) { + if (!sSocket.isClosed()) { + try { + sSocket.close(); + } catch (IOException x) { + System.err.println("Failed to close server socket"); + } + } + if (started && this.serverSocket == sSocket) { + started = false; + this.serverSocket = null; + this.acceptThread = null; + } + } + } + } + + /** + * Represents a connection accepted by the server. + */ + protected abstract class TcpConnectionThread extends Thread { + + protected final Socket socket; + + protected TcpConnectionThread(Socket socket) { + this.socket = socket; + this.setDaemon(true); + } + + public void close() throws IOException { + socket.close(); + interrupt(); + } + } + + /** + * Creates a new TcpConnnectionThread to handle the connection through + * an accepted socket. + * + * @param s the socket returned by {@code serverSocket.accept()}. + * @return a new TcpConnnectionThread to handle the connection through + * an accepted socket. + */ + protected abstract TcpConnectionThread createConnection(Socket s); + + /** + * Creates and starts a new TcpConnectionThread to handle the accepted + * socket. + * + * @param s the socket returned by {@code serverSocket.accept()}. + */ + private synchronized void listen(Socket s) { + TcpConnectionThread c = createConnection(s); + c.start(); + addConnection(c); + } + + /** + * Add the connection to the list of accepted connections. + * + * @param connection an accepted connection. + */ + protected synchronized void addConnection( + TcpConnectionThread connection) { + connections.add(connection); + } + + /** + * Remove the connection from the list of accepted connections. + * + * @param connection an accepted connection. + */ + protected synchronized void removeConnection( + TcpConnectionThread connection) { + connections.remove(connection); + } + + /** + * Close the server socket and all the connections present in the list + * of accepted connections. + * + * @throws IOException + */ + @Override + public synchronized void close() throws IOException { + if (serverSocket != null && !serverSocket.isClosed()) { + serverSocket.close(); + } + if (acceptThread != null) { + acceptThread.interrupt(); + } + int failed = 0; + for (TcpConnectionThread c : connections) { + try { + c.close(); + } catch (IOException x) { + // no matter - we're closing. + failed++; + } + } + connections.clear(); + if (failed > 0) { + throw new IOException("Failed to close some connections"); + } + } + } + + /** + * A small TCP Server that emulates the echo service for tests purposes. See + * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous + * port - NOT the standard port 7. We don't guarantee that its behavior + * exactly matches the RFC - the only purpose of this server is to have + * something that responds to nio tests... + */ + static final class EchoServer extends AbstractTcpServer { + + public EchoServer() { + this(0L); + } + + public EchoServer(long linger) { + super(linger); + } + + @Override + protected TcpConnectionThread createConnection(Socket s) { + return new EchoConnection(s); + } + + private final class EchoConnection extends TcpConnectionThread { + + public EchoConnection(Socket socket) { + super(socket); + } + + @Override + public void run() { + try { + final InputStream is = socket.getInputStream(); + final OutputStream out = socket.getOutputStream(); + byte[] b = new byte[255]; + int n; + while ((n = is.read(b)) > 0) { + lingerIfRequired(); + out.write(b, 0, n); + } + } catch (IOException io) { + // fall through to finally + } finally { + if (!socket.isClosed()) { + try { + socket.close(); + } catch (IOException x) { + System.err.println( + "Failed to close echo connection socket"); + } + } + removeConnection(this); + } + } + } + + public static EchoServer startNewServer() throws IOException { + return startNewServer(0); + } + + public static EchoServer startNewServer(long linger) throws IOException { + final EchoServer echoServer = new EchoServer(linger); + echoServer.start(); + return echoServer; + } + } + + /** + * A small TCP server that emulates the Day & Time service for tests + * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server + * uses an anonymous port - NOT the standard port 13. We don't guarantee + * that its behavior exactly matches the RFC - the only purpose of this + * server is to have something that responds to nio tests... + */ + static final class DayTimeServer extends AbstractTcpServer { + + public DayTimeServer() { + this(0L); + } + + public DayTimeServer(long linger) { + super(linger); + } + + @Override + protected TcpConnectionThread createConnection(Socket s) { + return new DayTimeServerConnection(s); + } + + @Override + protected void addConnection(TcpConnectionThread connection) { + // do nothing - the connection just write the date and terminates. + } + + @Override + protected void removeConnection(TcpConnectionThread connection) { + // do nothing - we're not adding connections to the list... + } + + private final class DayTimeServerConnection extends TcpConnectionThread { + + public DayTimeServerConnection(Socket socket) { + super(socket); + } + + @Override + public void run() { + try { + final OutputStream out = socket.getOutputStream(); + lingerIfRequired(); + out.write(new Date(System.currentTimeMillis()) + .toString().getBytes("US-ASCII")); + out.flush(); + } catch (IOException io) { + // fall through to finally + } finally { + if (!socket.isClosed()) { + try { + socket.close(); + } catch (IOException x) { + System.err.println( + "Failed to close echo connection socket"); + } + } + } + } + } + + public static DayTimeServer startNewServer() + throws IOException { + return startNewServer(0); + } + + public static DayTimeServer startNewServer(long linger) + throws IOException { + final DayTimeServer daytimeServer = new DayTimeServer(linger); + daytimeServer.start(); + return daytimeServer; + } + } + + /** + * An abstract class for implementing small UDP Servers for the nio tests + * purposes. Disclaimer: This is a naive implementation that uses the old + * networking APIs (not those from {@code java.nio.*}) and shamelessly + * extends/creates Threads instead of using an executor service. + */ + static abstract class AbstractUdpServer extends AbstractServer + implements Runnable, Closeable { + + protected final long linger; // #of ms to wait before responding + private Thread acceptThread; // thread waiting for packets + private DatagramSocket serverSocket; // the server socket + private boolean started = false; // whether the server is started + Throwable error = null; + + /** + * Creates a new abstract UDP server. + * + * @param linger the amount of time the server should wait before + * responding to requests. + */ + protected AbstractUdpServer(long linger) { + this.linger = linger; + } + + /** + * The local port to which the server is bound. + * + * @return The local port to which the server is bound. + * @exception IllegalStateException is thrown if the server is not + * started. + */ + @Override + public final synchronized int getPort() { + if (!started) { + throw new IllegalStateException("Not started"); + } + return serverSocket.getLocalPort(); + } + + /** + * The local address to which the server is bound. + * + * @return The local address to which the server is bound. + * @exception IllegalStateException is thrown if the server is not + * started. + */ + @Override + public final synchronized InetAddress getAddress() { + if (!started) { + throw new IllegalStateException("Not started"); + } + return serverSocket.getLocalAddress(); + } + + /** + * Tells whether the server is started. + * + * @return true if the server is started. + */ + public final synchronized boolean isStarted() { + return started; + } + + /** + * Creates a new datagram socket. + * + * @param port local port to bind to. + * @param address local address to bind to. + * @return a new bound server socket ready to listen for packets. + * @throws IOException if the socket cannot be created or bound. + */ + protected DatagramSocket newDatagramSocket(int port, + InetAddress address) + throws IOException { + return new DatagramSocket(port, address); + } + + /** + * Starts listening for connections. + * + * @throws IOException if the server socket cannot be created or bound. + */ + public final synchronized void start() throws IOException { + if (started) { + return; + } + final DatagramSocket socket = + newDatagramSocket(0, InetAddress.getLocalHost()); + serverSocket = socket; + acceptThread = new Thread(this); + acceptThread.setDaemon(true); + acceptThread.start(); + started = true; + } + + /** + * Calls {@code Thread.sleep(linger);} + */ + protected final void lingerIfRequired() { + if (linger > 0) { + try { + Thread.sleep(linger); + } catch (InterruptedException x) { + Thread.interrupted(); + final DatagramSocket socket = serverSocket(); + if (socket != null && !socket.isClosed()) { + System.err.println("Thread interrupted..."); + } + } + } + } + + final synchronized DatagramSocket serverSocket() { + return this.serverSocket; + } + + final synchronized boolean send(DatagramSocket socket, + DatagramPacket response) throws IOException { + if (!socket.isClosed()) { + socket.send(response); + return true; + } else { + return false; + } + } + + /** + * The main receive loop. + */ + @Override + public final void run() { + final DatagramSocket sSocket = serverSocket(); + try { + final int size = Math.max(1024, sSocket.getReceiveBufferSize()); + if (size > sSocket.getReceiveBufferSize()) { + sSocket.setReceiveBufferSize(size); + } + while (isStarted() && !Thread.interrupted() && !sSocket.isClosed()) { + final byte[] buf = new byte[size]; + final DatagramPacket packet = + new DatagramPacket(buf, buf.length); + lingerIfRequired(); + sSocket.receive(packet); + //System.out.println("Received packet from: " + // + packet.getAddress()+":"+packet.getPort()); + handle(sSocket, packet); + } + } catch (Exception x) { + error = x; + } finally { + synchronized (this) { + if (!sSocket.isClosed()) { + sSocket.close(); + } + if (started && this.serverSocket == sSocket) { + started = false; + this.serverSocket = null; + this.acceptThread = null; + } + } + } + } + + /** + * Represents an UDP request received by the server. + */ + protected abstract class UdpRequestThread extends Thread { + + protected final DatagramPacket request; + protected final DatagramSocket socket; + + protected UdpRequestThread(DatagramSocket socket, DatagramPacket request) { + this.socket = socket; + this.request = request; + this.setDaemon(true); + } + } + + /** + * Creates a new UdpRequestThread to handle a DatagramPacket received + * through a DatagramSocket. + * + * @param socket the socket through which the request was received. + * @param request the datagram packet received through the socket. + * @return a new UdpRequestThread to handle the request received through + * a DatagramSocket. + */ + protected abstract UdpRequestThread createConnection(DatagramSocket socket, + DatagramPacket request); + + /** + * Creates and starts a new UdpRequestThread to handle the received + * datagram packet. + * + * @param socket the socket through which the request was received. + * @param request the datagram packet received through the socket. + */ + private synchronized void handle(DatagramSocket socket, + DatagramPacket request) { + UdpRequestThread c = createConnection(socket, request); + // c can be null if the request requires no response. + if (c != null) { + c.start(); + } + } + + /** + * Close the server socket. + * + * @throws IOException + */ + @Override + public synchronized void close() throws IOException { + if (serverSocket != null && !serverSocket.isClosed()) { + serverSocket.close(); + } + if (acceptThread != null) { + acceptThread.interrupt(); + } + } + } + + /** + * A small UDP Server that emulates the discard service for tests purposes. + * See http://en.wikipedia.org/wiki/Discard_Protocol This server uses an + * anonymous port - NOT the standard port 9. We don't guarantee that its + * behavior exactly matches the RFC - the only purpose of this server is to + * have something that responds to nio tests... + */ + static final class UdpDiscardServer extends AbstractUdpServer { + + public UdpDiscardServer() { + this(0L); + } + + public UdpDiscardServer(long linger) { + super(linger); + } + + @Override + protected UdpRequestThread createConnection(DatagramSocket socket, + DatagramPacket request) { + // no response required + return null; + } + + public static UdpDiscardServer startNewServer() throws IOException { + return startNewServer(0); + } + + public static UdpDiscardServer startNewServer(long linger) throws IOException { + final UdpDiscardServer discardServer = new UdpDiscardServer(linger); + discardServer.start(); + return discardServer; + } + } + + /** + * A small UDP Server that emulates the echo service for tests purposes. See + * http://en.wikipedia.org/wiki/Echo_Protocol This server uses an anonymous + * port - NOT the standard port 7. We don't guarantee that its behavior + * exactly matches the RFC - the only purpose of this server is to have + * something that responds to nio tests... + */ + static final class UdpEchoServer extends AbstractUdpServer { + + public UdpEchoServer() { + this(0L); + } + + public UdpEchoServer(long linger) { + super(linger); + } + + @Override + protected UdpEchoRequest createConnection(DatagramSocket socket, + DatagramPacket request) { + return new UdpEchoRequest(socket, request); + } + + private final class UdpEchoRequest extends UdpRequestThread { + + public UdpEchoRequest(DatagramSocket socket, DatagramPacket request) { + super(socket, request); + } + + @Override + public void run() { + try { + lingerIfRequired(); + final DatagramPacket response = + new DatagramPacket(request.getData(), + request.getOffset(), request.getLength(), + request.getAddress(), request.getPort()); + send(socket, response); + } catch (IOException io) { + System.err.println("Failed to send response: " + io); + io.printStackTrace(System.err); + } + } + } + + public static UdpEchoServer startNewServer() throws IOException { + return startNewServer(0); + } + + public static UdpEchoServer startNewServer(long linger) throws IOException { + final UdpEchoServer echoServer = new UdpEchoServer(linger); + echoServer.start(); + return echoServer; + } + } + + /** + * A small UDP server that emulates the Day & Time service for tests + * purposes. See http://en.wikipedia.org/wiki/Daytime_Protocol This server + * uses an anonymous port - NOT the standard port 13. We don't guarantee + * that its behavior exactly matches the RFC - the only purpose of this + * server is to have something that responds to nio tests... + */ + static final class UdpDayTimeServer extends AbstractUdpServer { + + public UdpDayTimeServer() { + this(0L); + } + + public UdpDayTimeServer(long linger) { + super(linger); + } + + @Override + protected UdpDayTimeRequestThread createConnection(DatagramSocket socket, + DatagramPacket request) { + return new UdpDayTimeRequestThread(socket, request); + } + + private final class UdpDayTimeRequestThread extends UdpRequestThread { + + public UdpDayTimeRequestThread(DatagramSocket socket, + DatagramPacket request) { + super(socket, request); + } + + @Override + public void run() { + try { + lingerIfRequired(); + final byte[] data = new Date(System.currentTimeMillis()) + .toString().getBytes("US-ASCII"); + final DatagramPacket response = + new DatagramPacket(data, 0, data.length, + request.getAddress(), request.getPort()); + send(socket, response); + } catch (IOException io) { + System.err.println("Failed to send response: " + io); + io.printStackTrace(System.err); + } + } + } + + public static UdpDayTimeServer startNewServer() throws IOException { + return startNewServer(0); + } + + public static UdpDayTimeServer startNewServer(long linger) + throws IOException { + final UdpDayTimeServer echoServer = new UdpDayTimeServer(linger); + echoServer.start(); + return echoServer; + } + } +} diff --git a/test/java/nio/channels/TestUtil.java b/test/java/nio/channels/TestUtil.java index f06ffc4a8..5fbdf9ce4 100644 --- a/test/java/nio/channels/TestUtil.java +++ b/test/java/nio/channels/TestUtil.java @@ -27,7 +27,6 @@ import java.io.*; import java.net.*; -import java.nio.*; import java.nio.channels.*; import java.util.Random; @@ -36,9 +35,6 @@ public class TestUtil { // Test hosts used by the channels tests - change these when // executing in a different network. - public static final String HOST = "javaweb.sfbay.sun.com"; - public static final String REFUSING_HOST = "jano1.sfbay.sun.com"; - public static final String FAR_HOST = "irejano.ireland.sun.com"; public static final String UNRESOLVABLE_HOST = "blah-blah.blah-blah.blah"; private TestUtil() { } |