Path: blob/master/test/jdk/com/sun/nio/sctp/SctpChannel/Send.java
41155 views
/*1* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223/* @test24* @bug 492764025* @summary Tests the SCTP protocol implementation26* @author chegar27*/2829import java.net.InetSocketAddress;30import java.net.SocketAddress;31import java.io.IOException;32import java.util.concurrent.CountDownLatch;33import java.util.concurrent.TimeUnit;34import java.nio.ByteBuffer;35import java.nio.channels.NotYetConnectedException;36import java.nio.channels.ClosedChannelException;37import com.sun.nio.sctp.AbstractNotificationHandler;38import com.sun.nio.sctp.Association;39import com.sun.nio.sctp.AssociationChangeNotification;40import com.sun.nio.sctp.AssociationChangeNotification.AssocChangeEvent;41import com.sun.nio.sctp.HandlerResult;42import com.sun.nio.sctp.InvalidStreamException;43import com.sun.nio.sctp.MessageInfo;44import com.sun.nio.sctp.Notification;45import com.sun.nio.sctp.SctpChannel;46import com.sun.nio.sctp.SctpServerChannel;47import static java.lang.System.out;48import static java.lang.System.err;4950public class Send {51/* Latches used to synchronize between the client and server so that52* connections without any IO may not be closed without being accepted */53final CountDownLatch clientFinishedLatch = new CountDownLatch(1);54final CountDownLatch serverFinishedLatch = new CountDownLatch(1);5556SendNotificationHandler handler = new SendNotificationHandler();5758void test(String[] args) {59SocketAddress address = null;60Server server = null;6162if (!Util.isSCTPSupported()) {63out.println("SCTP protocol is not supported");64out.println("Test cannot be run");65return;66}6768if (args.length == 2) {69/* requested to connecct to a specific address */70try {71int port = Integer.valueOf(args[1]);72address = new InetSocketAddress(args[0], port);73} catch (NumberFormatException nfe) {74err.println(nfe);75}76} else {77/* start server on local machine, default */78try {79server = new Server();80server.start();81address = server.address();82debug("Server started and listening on " + address);83} catch (IOException ioe) {84ioe.printStackTrace();85return;86}87}8889doTest(address);90}9192void doTest(SocketAddress peerAddress) {93SctpChannel channel = null;94ByteBuffer buffer = ByteBuffer.allocate(Util.LARGE_BUFFER);95MessageInfo info = MessageInfo.createOutgoing(null, 0);9697try {98channel = SctpChannel.open();99100/* TEST 1: Verify NotYetConnectedException thrown */101try {102channel.send(buffer, info);103fail("should have thrown NotYetConnectedException");104} catch (NotYetConnectedException unused) {105pass();106} catch (IOException ioe) {107unexpected(ioe);108}109110channel.connect(peerAddress);111/* Receive CommUp */112channel.receive(buffer, null, handler);113114/* TEST 2: send small message */115int streamNumber = 0;116debug("sending on stream number: " + streamNumber);117info = MessageInfo.createOutgoing(null, streamNumber);118buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));119buffer.flip();120int position = buffer.position();121int remaining = buffer.remaining();122123debug("sending small message: " + buffer);124int sent = channel.send(buffer, info);125126check(sent == remaining, "sent should be equal to remaining");127check(buffer.position() == (position + sent),128"buffers position should have been incremented by sent");129130buffer.clear();131132/* TEST 3: send large message */133streamNumber = handler.maxOutStreams() - 1;134debug("sending on stream number: " + streamNumber);135info = MessageInfo.createOutgoing(null, streamNumber);136buffer.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));137buffer.flip();138position = buffer.position();139remaining = buffer.remaining();140141debug("sending large message: " + buffer);142sent = channel.send(buffer, info);143144check(sent == remaining, "sent should be equal to remaining");145check(buffer.position() == (position + sent),146"buffers position should have been incremented by sent");147148/* TEST 4: InvalidStreamExcepton */149streamNumber = handler.maxInStreams;150info = MessageInfo.createOutgoing(null, streamNumber);151buffer.clear();152buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));153buffer.flip();154position = buffer.position();155remaining = buffer.remaining();156157debug("sending on stream number: " + streamNumber);158debug("sending small message: " + buffer);159try {160sent = channel.send(buffer, info);161fail("should have thrown InvalidStreamExcepton");162} catch (InvalidStreamException ise){163pass();164} catch (IOException ioe) {165unexpected(ioe);166}167check(buffer.remaining() == remaining,168"remaining should not be changed");169check(buffer.position() == position,170"buffers position should not be changed");171172/* TEST 5: Non blocking send should return zero if there is173insufficient room in the underlying output buffer */174buffer.clear();175channel.configureBlocking(false);176info = MessageInfo.createOutgoing(null, 1);177buffer.put(Util.LARGE_MESSAGE.getBytes("ISO-8859-1"));178buffer.flip();179180int count = 0; // do not loop forever181do {182position = buffer.position();183remaining = buffer.remaining();184debug("sending large message: " + buffer);185sent = channel.send(buffer, info);186if (sent == 0) {187check(buffer.remaining() == remaining,188"remaining should not be changed");189check(buffer.position() == position,190"buffers position should not be changed");191}192buffer.rewind();193} while (sent != 0 && count++ < 100);194195/* TEST 6: ClosedChannelException */196channel.close();197try {198channel.send(buffer, info);199fail("should have thrown ClosedChannelException");200} catch (ClosedChannelException cce) {201pass();202} catch (IOException ioe) {203unexpected(ioe);204}205206/* TEST 7: send without previous receive.207* Verify that send can still throw InvalidStreamExcepton */208debug("Opening new channel.");209channel = SctpChannel.open(peerAddress, 0, 0);210streamNumber = Short.MAX_VALUE - 1;211info = MessageInfo.createOutgoing(null, streamNumber);212buffer.clear();213buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));214buffer.flip();215position = buffer.position();216remaining = buffer.remaining();217218debug("sending on stream number: " + streamNumber);219debug("sending small message: " + buffer);220try {221sent = channel.send(buffer, info);222fail("should have thrown InvalidStreamExcepton");223} catch (InvalidStreamException ise){224pass();225} catch (IOException ioe) {226unexpected(ioe);227}228check(buffer.remaining() == remaining,229"remaining should not be changed");230check(buffer.position() == position,231"buffers position should not be changed");232233/* Receive CommUp */234channel.receive(buffer, null, handler);235check(handler.receivedCommUp(), "should have received COMM_UP");236237/* TEST 8: Send to an invalid preferred SocketAddress */238SocketAddress addr = new InetSocketAddress("123.123.123.123", 3456);239info = MessageInfo.createOutgoing(addr, 0);240debug("sending to " + addr);241debug("sending small message: " + buffer);242try {243sent = channel.send(buffer, info);244fail("Invalid address should have thrown an Exception.");245} catch (Exception e){246pass();247debug("OK, caught " + e);248}249250/* TEST 9: Send from heap buffer to force implementation to251* substitute with a native buffer, then check that its position252* is updated correctly */253buffer.clear();254info = MessageInfo.createOutgoing(null, 0);255buffer.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));256buffer.flip();257final int offset = 1;258buffer.position(offset);259remaining = buffer.remaining();260261debug("sending small message: " + buffer);262try {263sent = channel.send(buffer, info);264265check(sent == remaining, "sent should be equal to remaining");266check(buffer.position() == (offset + sent),267"buffers position should have been incremented by sent");268} catch (IllegalArgumentException iae) {269fail(iae + ", Error updating buffers position");270}271272} catch (IOException ioe) {273unexpected(ioe);274} finally {275clientFinishedLatch.countDown();276try { serverFinishedLatch.await(10L, TimeUnit.SECONDS); }277catch (InterruptedException ie) { unexpected(ie); }278if (channel != null) {279try { channel.close(); }280catch (IOException e) { unexpected (e);}281}282}283}284285class Server implements Runnable286{287final InetSocketAddress serverAddr;288private SctpServerChannel ssc;289290public Server() throws IOException {291ssc = SctpServerChannel.open().bind(null);292java.util.Set<SocketAddress> addrs = ssc.getAllLocalAddresses();293if (addrs.isEmpty())294debug("addrs should not be empty");295296serverAddr = (InetSocketAddress) addrs.iterator().next();297}298299public void start() {300(new Thread(this, "Server-" + serverAddr.getPort())).start();301}302303public InetSocketAddress address() {304return serverAddr;305}306307@Override308public void run() {309ByteBuffer buffer = ByteBuffer.allocateDirect(Util.LARGE_BUFFER);310SctpChannel sc1 = null, sc2 = null;311try {312sc1 = ssc.accept();313314/* receive a small message */315MessageInfo info;316do {317info = sc1.receive(buffer, null, null);318if (info == null) {319fail("Server: unexpected null from receive");320return;321}322} while (!info.isComplete());323324buffer.flip();325check(info != null, "info is null");326check(info.streamNumber() == 0,327"message not sent on the correct stream");328check(info.bytes() == Util.SMALL_MESSAGE.getBytes("ISO-8859-1").329length, "bytes received not equal to message length");330check(info.bytes() == buffer.remaining(), "bytes != remaining");331check(Util.compare(buffer, Util.SMALL_MESSAGE),332"received message not the same as sent message");333334/* receive a large message */335buffer.clear();336do {337info = sc1.receive(buffer, null, null);338if (info == null) {339fail("Server: unexpected null from receive");340return;341}342} while (!info.isComplete());343344buffer.flip();345check(info != null, "info is null");346check(info.streamNumber() == handler.maxOutStreams() - 1,347"message not sent on the correct stream");348check(info.bytes() == Util.LARGE_MESSAGE.getBytes("ISO-8859-1").349length, "bytes received not equal to message length");350check(info.bytes() == buffer.remaining(), "bytes != remaining");351check(Util.compare(buffer, Util.LARGE_MESSAGE),352"received message not the same as sent message");353354/* TEST 7 ++ */355sc2 = ssc.accept();356357/* TEST 9 */358ByteBuffer expected = ByteBuffer.allocate(Util.SMALL_BUFFER);359expected.put(Util.SMALL_MESSAGE.getBytes("ISO-8859-1"));360expected.flip();361final int offset = 1;362expected.position(offset);363buffer.clear();364do {365info = sc2.receive(buffer, null, null);366if (info == null) {367fail("Server: unexpected null from receive");368return;369}370} while (!info.isComplete());371372buffer.flip();373check(info != null, "info is null");374check(info.streamNumber() == 0, "message not sent on the correct stream");375check(info.bytes() == expected.remaining(),376"bytes received not equal to message length");377check(info.bytes() == buffer.remaining(), "bytes != remaining");378check(expected.equals(buffer),379"received message not the same as sent message");380381clientFinishedLatch.await(10L, TimeUnit.SECONDS);382serverFinishedLatch.countDown();383} catch (IOException ioe) {384unexpected(ioe);385} catch (InterruptedException ie) {386unexpected(ie);387} finally {388try { if (ssc != null) ssc.close(); }389catch (IOException unused) {}390try { if (sc1 != null) sc1.close(); }391catch (IOException unused) {}392try { if (sc2 != null) sc2.close(); }393catch (IOException unused) {}394}395}396}397398class SendNotificationHandler extends AbstractNotificationHandler<Void>399{400boolean receivedCommUp; // false401int maxInStreams;402int maxOutStreams;403404public boolean receivedCommUp() {405return receivedCommUp;406}407408public int maxInStreams() {409return maxInStreams;410}411412public int maxOutStreams(){413return maxOutStreams;414}415416@Override417public HandlerResult handleNotification(418Notification notification, Void attachment) {419fail("Unknown notification type");420return HandlerResult.CONTINUE;421}422423@Override424public HandlerResult handleNotification(425AssociationChangeNotification notification, Void attachment) {426AssocChangeEvent event = notification.event();427Association association = notification.association();428debug("AssociationChangeNotification");429debug(" Association: " + notification.association());430debug(" Event: " + event);431432if (event.equals(AssocChangeEvent.COMM_UP))433receivedCommUp = true;434435this.maxInStreams = association.maxInboundStreams();436this.maxOutStreams = association.maxOutboundStreams();437438return HandlerResult.RETURN;439}440}441442//--------------------- Infrastructure ---------------------------443boolean debug = true;444volatile int passed = 0, failed = 0;445void pass() {passed++;}446void fail() {failed++; Thread.dumpStack();}447void fail(String msg) {System.err.println(msg); fail();}448void unexpected(Throwable t) {failed++; t.printStackTrace();}449void check(boolean cond) {if (cond) pass(); else fail();}450void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}451void debug(String message) {if(debug) { System.out.println(message); } }452public static void main(String[] args) throws Throwable {453Class<?> k = new Object(){}.getClass().getEnclosingClass();454try {k.getMethod("instanceMain",String[].class)455.invoke( k.newInstance(), (Object) args);}456catch (Throwable e) {throw e.getCause();}}457public void instanceMain(String[] args) throws Throwable {458try {test(args);} catch (Throwable t) {unexpected(t);}459System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);460if (failed > 0) throw new AssertionError("Some tests failed");}461462}463464465