1 /* 2 * Copyright (c) 2011, 2014, 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 7094377 8000487 6176036 7056489 27 * @summary Timeout tests for ldap 28 */ 29 30 import java.net.Socket; 31 import java.net.ServerSocket; 32 import java.net.SocketTimeoutException; 33 import java.io.*; 34 import javax.naming.*; 35 import javax.naming.directory.*; 36 import java.util.Hashtable; 37 import java.util.concurrent.Callable; 38 import java.util.concurrent.Executors; 39 import java.util.concurrent.ScheduledExecutorService; 40 import java.util.concurrent.ScheduledFuture; 41 import java.util.concurrent.TimeUnit; 42 43 public class LdapTimeoutTest { 44 private static final ScheduledExecutorService pool = 45 Executors.newScheduledThreadPool(1); 46 static volatile int passed = 0, failed = 0; 47 static void pass() {passed++;} 48 static void fail() {failed++; Thread.dumpStack();} 49 50 public static void main(String[] args) throws Exception { 51 ServerSocket serverSock = new ServerSocket(0); 52 Server s = new Server(serverSock); 53 s.start(); 54 Thread.sleep(200); 55 56 Hashtable env = new Hashtable(11); 57 env.put(Context.INITIAL_CONTEXT_FACTORY, 58 "com.sun.jndi.ldap.LdapCtxFactory"); 59 env.put(Context.PROVIDER_URL, "ldap://localhost:" + 60 serverSock.getLocalPort()); 61 62 env.put(Context.SECURITY_AUTHENTICATION,"simple"); 63 64 env.put(Context.SECURITY_PRINCIPAL, "user"); 65 env.put(Context.SECURITY_CREDENTIALS, "password"); 66 67 InitialContext ctx = null; 68 try { 69 new LdapTimeoutTest().deadServerNoTimeout(env); 70 71 env.put("com.sun.jndi.ldap.connect.timeout", "10"); 72 env.put("com.sun.jndi.ldap.read.timeout", "3000"); 73 new LdapTimeoutTest().ldapReadTimeoutTest(env, false); 74 new LdapTimeoutTest().ldapReadTimeoutTest(env, true); 75 new LdapTimeoutTest().simpleAuthConnectTest(env); 76 } finally { 77 s.interrupt(); 78 LdapTimeoutTest.pool.shutdown(); 79 } 80 81 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 82 if (failed > 0) throw new AssertionError("Some tests failed"); 83 } 84 85 void ldapReadTimeoutTest(Hashtable env, boolean ssl) { 86 InitialContext ctx = null; 87 if (ssl) env.put(Context.SECURITY_PROTOCOL, "ssl"); 88 ScheduledFuture killer = killSwitch(5000); 89 long start = System.nanoTime(); 90 try { 91 ctx = new InitialDirContext(env); 92 SearchControls scl = new SearchControls(); 93 scl.setSearchScope(SearchControls.SUBTREE_SCOPE); 94 NamingEnumeration<SearchResult> answer = ((InitialDirContext)ctx) 95 .search("ou=People,o=JNDITutorial", "(objectClass=*)", scl); 96 // shouldn't reach here 97 fail(); 98 } catch (NamingException e) { 99 if (ssl) { 100 if (e.getCause() instanceof SocketTimeoutException) { 101 pass(); 102 } else if (e.getCause() instanceof InterruptedIOException) { 103 Thread.interrupted(); 104 fail(); 105 } 106 } else { 107 pass(); 108 } 109 } finally { 110 if (!shutItDown(killer, ctx)) fail(); 111 } 112 } 113 114 void simpleAuthConnectTest(Hashtable env) { 115 InitialContext ctx = null; 116 ScheduledFuture killer = killSwitch(5000); 117 long start = System.nanoTime(); 118 try { 119 ctx = new InitialDirContext(env); 120 // shouldn't reach here 121 System.err.println("Fail: InitialDirContext succeeded"); 122 fail(); 123 } catch (NamingException e) { 124 long end = System.nanoTime(); 125 if (e.getCause() instanceof SocketTimeoutException) { 126 if (TimeUnit.NANOSECONDS.toMillis(end - start) < 2900) { 127 pass(); 128 } else { 129 System.err.println("Fail: Waited too long"); 130 fail(); 131 } 132 } else if (e.getCause() instanceof InterruptedIOException) { 133 Thread.interrupted(); 134 fail(); 135 } else { 136 fail(); 137 } 138 } finally { 139 if (!shutItDown(killer, ctx)) fail(); 140 } 141 } 142 143 void deadServerNoTimeout(Hashtable env) { 144 InitialContext ctx = null; 145 ScheduledFuture killer = killSwitch(30000); 146 long start = System.nanoTime(); 147 try { 148 ctx = new InitialDirContext(env); 149 SearchControls scl = new SearchControls(); 150 scl.setSearchScope(SearchControls.SUBTREE_SCOPE); 151 NamingEnumeration<SearchResult> answer = ((InitialDirContext)ctx) 152 .search("ou=People,o=JNDITutorial", "(objectClass=*)", scl); 153 // shouldn't reach here 154 fail(); 155 } catch (NamingException e) { 156 long end = System.nanoTime(); 157 if (TimeUnit.NANOSECONDS.toMillis(end - start) < 14000) { 158 System.err.println("fail: timeout should be at least 15 seconds, actual time: " 159 + TimeUnit.NANOSECONDS.toMillis(end - start)); 160 fail(); 161 } else { 162 pass(); 163 } 164 } finally { 165 if (!shutItDown(killer, ctx)) fail(); 166 } 167 } 168 169 boolean shutItDown(ScheduledFuture killer, InitialContext ctx) { 170 killer.cancel(true); 171 try { 172 if (ctx != null) ctx.close(); 173 return true; 174 } catch (NamingException ex) { 175 return false; 176 } 177 } 178 179 ScheduledFuture killSwitch(int ms) { 180 final Thread current = Thread.currentThread(); 181 return LdapTimeoutTest.pool.schedule(new Callable<Void>() { 182 public Void call() throws Exception { 183 System.err.println("Fail: killSwitch()"); 184 System.exit(0); 185 return null; 186 } 187 }, ms, TimeUnit.MILLISECONDS); 188 } 189 190 static class Server extends Thread { 191 final ServerSocket serverSock; 192 193 Server(ServerSocket serverSock) { 194 this.serverSock = serverSock; 195 } 196 197 public void run() { 198 try { 199 Socket socket = serverSock.accept(); 200 } catch (IOException e) {} 201 } 202 } 203 } 204