|
1 /* |
|
2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. |
|
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
4 * |
|
5 * This code is free software; you can redistribute it and/or modify it |
|
6 * under the terms of the GNU General Public License version 2 only, as |
|
7 * published by the Free Software Foundation. |
|
8 * |
|
9 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
12 * version 2 for more details (a copy is included in the LICENSE file that |
|
13 * accompanied this code). |
|
14 * |
|
15 * You should have received a copy of the GNU General Public License version |
|
16 * 2 along with this work; if not, write to the Free Software Foundation, |
|
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
18 * |
|
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
20 * or visit www.oracle.com if you need additional information or have any |
|
21 * questions. |
|
22 */ |
|
23 |
|
24 /* @test |
|
25 * @bug 8067846 |
|
26 * @summary Test for send failed notification |
|
27 */ |
|
28 |
|
29 import com.sun.nio.sctp.*; |
|
30 import java.io.IOException; |
|
31 import java.net.InetSocketAddress; |
|
32 import java.net.SocketAddress; |
|
33 import java.nio.ByteBuffer; |
|
34 import static java.lang.System.out; |
|
35 import static java.nio.ByteBuffer.*; |
|
36 |
|
37 public class SendFailed { |
|
38 |
|
39 static final SocketAddress remoteAddress = new InetSocketAddress("127.0.0.1", 3000); |
|
40 |
|
41 static final int[] bufferSizes = |
|
42 { 20, 49, 50, 51, 100, 101, 1024, 1025, 4095, 4096, 4097, 8191, 8192, 8193}; |
|
43 |
|
44 void test(String[] args) throws IOException { |
|
45 SocketAddress address = null; |
|
46 |
|
47 if (!Util.isSCTPSupported()) { |
|
48 out.println("SCTP protocol is not supported"); |
|
49 out.println("Test cannot be run"); |
|
50 return; |
|
51 } |
|
52 |
|
53 System.out.println("remote address: " + remoteAddress); |
|
54 System.out.println("Note, remote address should not be up"); |
|
55 |
|
56 /* combinations with various buffer sizes, and offsets */ |
|
57 for (int send=0; send < bufferSizes.length; send++) { |
|
58 for (int recv=0; recv < bufferSizes.length; recv++) { |
|
59 for (boolean direct : new boolean[] {true, false}) |
|
60 runWithManyOffsets(bufferSizes[send], bufferSizes[recv], direct); |
|
61 } |
|
62 } |
|
63 } |
|
64 |
|
65 void runWithManyOffsets(int sendBufferSize, int recvBufferSize, boolean direct) |
|
66 throws IOException |
|
67 { |
|
68 doTest(sendBufferSize, recvBufferSize, direct, 0); |
|
69 doTest(sendBufferSize, recvBufferSize, direct, 1); |
|
70 doTest(sendBufferSize, recvBufferSize, direct, 3); |
|
71 doTest(sendBufferSize, recvBufferSize, direct, 7); |
|
72 doTest(sendBufferSize, recvBufferSize, direct, 9); |
|
73 doTest(sendBufferSize, recvBufferSize, direct, 13); |
|
74 doTest(sendBufferSize, recvBufferSize, direct, 15); |
|
75 } |
|
76 |
|
77 void doTest(int sendBufferSize, int recvBufferSize, boolean direct, int offset) |
|
78 throws IOException |
|
79 { |
|
80 debug("%n--- Testing with send size:[%d], recv size:[%d], offset:[%d] " |
|
81 + ", direct [%s]. ", sendBufferSize, recvBufferSize, offset, direct); |
|
82 |
|
83 try (SctpMultiChannel channel = SctpMultiChannel.open()) { |
|
84 MessageInfo messageInfo = MessageInfo.createOutgoing(remoteAddress, 0); |
|
85 ByteBuffer sendBuffer = filledBuffer(sendBufferSize, direct); |
|
86 |
|
87 debug("%nAttempting to send to %s. ", remoteAddress); |
|
88 int sent = channel.send(sendBuffer, messageInfo); |
|
89 sendBuffer.flip(); |
|
90 |
|
91 SendFailedNotificationHandler handler = |
|
92 new SendFailedNotificationHandler(); |
|
93 ByteBuffer recvBuffer = direct ? allocateDirect(recvBufferSize) |
|
94 : allocate((recvBufferSize)); |
|
95 channel.receive(recvBuffer, null, handler); |
|
96 |
|
97 // verify sent buffer received by send failed notification |
|
98 ByteBuffer buffer = handler.getSendFailedByteBuffer(); |
|
99 check(buffer.remaining() == sent); |
|
100 check(buffer.position() == 0); |
|
101 check(buffer.limit() == sent); |
|
102 assertSameContent(sendBuffer, handler.getSendFailedByteBuffer()); |
|
103 } |
|
104 } |
|
105 |
|
106 class SendFailedNotificationHandler extends AbstractNotificationHandler<Object> |
|
107 { |
|
108 /** Reference to the buffer captured in send failed notification */ |
|
109 private ByteBuffer sentBuffer; |
|
110 |
|
111 @Override |
|
112 public HandlerResult handleNotification( |
|
113 Notification notification, Object attachment) { |
|
114 fail("Unknown notification type"); |
|
115 return HandlerResult.CONTINUE; |
|
116 } |
|
117 |
|
118 @Override |
|
119 public HandlerResult handleNotification( |
|
120 AssociationChangeNotification notification, Object attachment) { |
|
121 AssociationChangeNotification.AssocChangeEvent event = notification.event(); |
|
122 debug("%nAssociationChangeNotification"); |
|
123 debug("%n Association: %s. ", notification.association()); |
|
124 debug("%n Event: %s. ", event); |
|
125 return HandlerResult.CONTINUE; |
|
126 } |
|
127 |
|
128 @Override |
|
129 public HandlerResult handleNotification( |
|
130 SendFailedNotification notification, Object attachment) { |
|
131 debug("%nSendFailedNotification: %s. ", notification); |
|
132 sentBuffer = notification.buffer(); |
|
133 return HandlerResult.RETURN; |
|
134 } |
|
135 |
|
136 public ByteBuffer getSendFailedByteBuffer() { |
|
137 return sentBuffer; |
|
138 } |
|
139 |
|
140 @Override |
|
141 public HandlerResult handleNotification( |
|
142 PeerAddressChangeNotification pacn, Object attachment) |
|
143 { |
|
144 debug("%nPeerAddressChangeNotification: %s", pacn); |
|
145 return HandlerResult.CONTINUE; |
|
146 } |
|
147 |
|
148 @Override |
|
149 public HandlerResult handleNotification( |
|
150 ShutdownNotification notification, Object attachment) { |
|
151 debug("%nShutdownNotification"); |
|
152 debug("%n Association: %s. ", notification.association()); |
|
153 return HandlerResult.CONTINUE; |
|
154 } |
|
155 } |
|
156 |
|
157 static ByteBuffer filledBuffer(int size, boolean direct) { |
|
158 ByteBuffer buffer = direct ? allocateDirect(size) : allocate((size)); |
|
159 for (int i=0; i< size; i++) |
|
160 buffer.put((byte)i); |
|
161 buffer.flip(); |
|
162 return buffer; |
|
163 } |
|
164 |
|
165 static void assertSameContent(ByteBuffer bb1, ByteBuffer bb2) { |
|
166 if (!bb1.equals(bb2)) |
|
167 throw new RuntimeException("Buffers are not equal; bb1: " + bb1 + ", bb2: " + bb2); |
|
168 } |
|
169 |
|
170 //--------------------- Infrastructure --------------------------- |
|
171 boolean debug = true; |
|
172 volatile int passed = 0, failed = 0; |
|
173 void pass() {passed++;} |
|
174 void fail() {failed++; Thread.dumpStack();} |
|
175 void fail(String msg) {System.err.println(msg); fail();} |
|
176 void unexpected(Throwable t) {failed++; t.printStackTrace();} |
|
177 void check(boolean cond) {if (cond) pass(); else fail();} |
|
178 void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);} |
|
179 void debug(String message, Object... args) {if(debug) { out.printf(message, args); } } |
|
180 public static void main(String[] args) throws Throwable { |
|
181 Class<?> k = new Object(){}.getClass().getEnclosingClass(); |
|
182 try {k.getMethod("instanceMain",String[].class) |
|
183 .invoke( k.newInstance(), (Object) args);} |
|
184 catch (Throwable e) {throw e.getCause();}} |
|
185 public void instanceMain(String[] args) throws Throwable { |
|
186 try {test(args);} catch (Throwable t) {unexpected(t);} |
|
187 out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); |
|
188 if (failed > 0) throw new AssertionError("Some tests failed");} |
|
189 } |