1 /* 2 * Copyright (c) 2002, 2018, 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 import javax.naming.CommunicationException; 25 import javax.naming.Context; 26 import javax.naming.directory.InitialDirContext; 27 import java.net.SocketTimeoutException; 28 import java.time.Duration; 29 import java.time.Instant; 30 31 /* 32 * @test 33 * @bug 8200151 34 * @summary Tests that we can set the initial UDP timeout interval and the 35 * number of retries. 36 * @library ../lib/ 37 * @modules java.base/sun.security.util 38 * @run main Timeout 39 */ 40 41 public class Timeout extends DNSTestBase { 42 // Host 10.0.0.0 is a bit bucket, used here to simulate a DNS server that 43 // doesn't respond. 10.0.0.0 server shouldn't be reachable. 44 // Ping to this address should not give any reply 45 private static final String HOST = "10.0.0.0"; 46 // Port 9 is a bit bucket, used here to simulate a DNS server that 47 // doesn't respond. 48 private static final int PORT = 9; 49 // initial timeout = 1/4 sec 50 private static final int TIMEOUT = 250; 51 // try 5 times per server 52 private static final int RETRIES = 5; 53 54 private Instant startTime; 55 56 public Timeout() { 57 setLocalServer(false); 58 } 59 60 public static void main(String[] args) throws Exception { 61 new Timeout().run(args); 62 } 63 64 /* 65 * Tests that we can set the initial UDP timeout interval and the 66 * number of retries. 67 */ 68 @Override 69 public void runTest() throws Exception { 70 String allQuietUrl = "dns://" + HOST + ":" + PORT; 71 env().put(Context.PROVIDER_URL, allQuietUrl); 72 env().put("com.sun.jndi.dns.timeout.initial", String.valueOf(TIMEOUT)); 73 env().put("com.sun.jndi.dns.timeout.retries", String.valueOf(RETRIES)); 74 setContext(new InitialDirContext(env())); 75 76 // Any request should fail after timeouts have expired. 77 startTime = Instant.now(); 78 context().getAttributes(""); 79 80 throw new RuntimeException( 81 "Failed: getAttributes succeeded unexpectedly"); 82 } 83 84 @Override 85 public boolean handleException(Exception e) { 86 if (e instanceof CommunicationException) { 87 Duration elapsedTime = Duration.between(startTime, Instant.now()); 88 if (!(((CommunicationException) e) 89 .getRootCause() instanceof SocketTimeoutException)) { 90 return false; 91 } 92 93 Duration expectedTime = Duration.ofMillis(TIMEOUT) 94 .multipliedBy((1 << RETRIES) - 1); 95 DNSTestUtils.debug("Elapsed (ms): " + elapsedTime.toMillis()); 96 DNSTestUtils.debug("Expected (ms): " + expectedTime.toMillis()); 97 98 // Check that elapsed time is as long as expected, and 99 // not more than 50% greater. 100 if (elapsedTime.compareTo(expectedTime) >= 0 && 101 elapsedTime.multipliedBy(2) 102 .compareTo(expectedTime.multipliedBy(3)) <= 0) { 103 System.out.println("elapsed time is as long as expected."); 104 return true; 105 } 106 throw new RuntimeException( 107 "Failed: timeout in " + elapsedTime.toMillis() 108 + " ms, expected" + expectedTime.toMillis() + "ms"); 109 } 110 111 return super.handleException(e); 112 } 113 }