1 /* 2 * Copyright (c) 2020, 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 * @bug 8239355 27 * @summary Check that new SO_SNDBUF limit on macOS is adhered to 28 * @library /test/lib 29 * @build jdk.test.lib.net.IPSupport 30 * @requires os.family == "mac" 31 * @run testng/othervm MinSendBufferSize 32 * @run testng/othervm -Djava.net.preferIPv4Stack=true MinSendBufferSize 33 */ 34 35 import org.testng.annotations.AfterTest; 36 import org.testng.annotations.BeforeTest; 37 import org.testng.annotations.DataProvider; 38 import org.testng.annotations.Test; 39 40 import java.io.IOException; 41 import java.net.DatagramSocket; 42 import java.net.InetAddress; 43 import java.net.ProtocolFamily; 44 import java.nio.ByteBuffer; 45 import java.nio.channels.DatagramChannel; 46 import java.util.ArrayList; 47 import java.util.List; 48 49 import static java.net.StandardSocketOptions.SO_SNDBUF; 50 import static jdk.test.lib.net.IPSupport.hasIPv4; 51 import static jdk.test.lib.net.IPSupport.hasIPv6; 52 import static jdk.test.lib.net.IPSupport.preferIPv4Stack; 53 import static java.net.StandardProtocolFamily.INET; 54 import static java.net.StandardProtocolFamily.INET6; 55 import static org.testng.Assert.assertTrue; 56 import static org.testng.Assert.expectThrows; 57 58 public class MinSendBufferSize { 59 private int EXPECTED_SNDBUF; 60 private DatagramChannel datagramChannel, datagramChannelIPv4, 61 datagramChannelIPv6; 62 63 private final static int IPV4_SNDBUF = 65507; 64 private final static int IPV6_SNDBUF = 65527; 65 private final static Class<IOException> IOE = IOException.class; 66 67 @BeforeTest setUp()68 public void setUp() throws IOException { 69 datagramChannel = DatagramChannel.open(); 70 if (hasIPv4()) 71 datagramChannelIPv4 = DatagramChannel.open(INET); 72 if (hasIPv6()) 73 datagramChannelIPv6 = DatagramChannel.open(INET6); 74 75 EXPECTED_SNDBUF = hasIPv6() && !preferIPv4Stack() 76 ? IPV6_SNDBUF : IPV4_SNDBUF; 77 } 78 populateDataProvider(List<Object[]> testcases, DatagramChannel datagramChannel, int payloadSize, ProtocolFamily family)79 private void populateDataProvider(List<Object[]> testcases, 80 DatagramChannel datagramChannel, 81 int payloadSize, 82 ProtocolFamily family) { 83 84 testcases.add(new Object[]{datagramChannel, payloadSize - 1, 85 family, null}); 86 testcases.add(new Object[]{datagramChannel, payloadSize, 87 family, null}); 88 testcases.add(new Object[]{datagramChannel, payloadSize + 1, 89 family, IOE}); 90 } 91 92 @DataProvider(name = "testGetOptionProvider") providerIO()93 public Object[][] providerIO() { 94 var testcases = new ArrayList<Object[]>(); 95 96 testcases.add(new Object[]{datagramChannel, EXPECTED_SNDBUF}); 97 if (hasIPv4()) 98 testcases.add(new Object[]{datagramChannelIPv4, IPV4_SNDBUF}); 99 if (hasIPv6()) 100 testcases.add(new Object[]{datagramChannelIPv6, IPV6_SNDBUF}); 101 102 return testcases.toArray(Object[][]::new); 103 } 104 105 @DataProvider(name = "testSendPayloadProvider") providerIO_Payload()106 public Object[][] providerIO_Payload() { 107 var testcases = new ArrayList<Object[]>(); 108 109 if (hasIPv4()) 110 populateDataProvider(testcases, datagramChannel, 111 IPV4_SNDBUF, INET); 112 if (hasIPv6() && !preferIPv4Stack()) 113 populateDataProvider(testcases, datagramChannel, 114 IPV6_SNDBUF, INET6); 115 116 if (hasIPv4()) 117 populateDataProvider(testcases, datagramChannelIPv4, 118 IPV4_SNDBUF, INET); 119 if (hasIPv6()) 120 populateDataProvider(testcases, datagramChannelIPv6, 121 IPV6_SNDBUF, INET6); 122 123 return testcases.toArray(Object[][]::new); 124 } 125 126 @Test(dataProvider = "testGetOptionProvider") testGetOption(DatagramChannel channel, int sendBuf)127 public void testGetOption(DatagramChannel channel, int sendBuf) 128 throws IOException { 129 130 assertTrue(channel.getOption(SO_SNDBUF) >= sendBuf); 131 } 132 133 @Test(dataProvider = "testSendPayloadProvider") testSend(DatagramChannel channel, int sendBuf, ProtocolFamily family, Class<? extends Throwable> exception)134 public void testSend(DatagramChannel channel, int sendBuf, 135 ProtocolFamily family, 136 Class<? extends Throwable> exception) 137 throws IOException { 138 139 InetAddress targetAddress; 140 assert family != null; 141 if (family == INET) { 142 targetAddress = InetAddress.getByName("127.0.0.1"); 143 } else { 144 targetAddress = InetAddress.getByName("::1"); 145 } 146 147 try (var receiver = new DatagramSocket(0, targetAddress)) { 148 var buf = ByteBuffer.allocate(sendBuf); 149 var addr = receiver.getLocalSocketAddress(); 150 if (exception != null) { 151 expectThrows(exception, () -> channel.send(buf, addr)); 152 } else { 153 channel.send(buf, addr); 154 } 155 } 156 } 157 158 @AfterTest tearDown()159 public void tearDown() throws IOException { 160 datagramChannel.close(); 161 if (hasIPv4()) 162 datagramChannelIPv4.close(); 163 if (hasIPv6()) 164 datagramChannelIPv6.close(); 165 } 166 } 167