1 /* 2 * Copyright (c) 2011, 2012, 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 env.put("com.sun.jndi.ldap.connect.timeout", "10"); 68 env.put("com.sun.jndi.ldap.read.timeout", "3000"); 69 70 InitialContext ctx = null; 71 try { 72 new LdapTimeoutTest().ldapReadTimeoutTest(env, false); 73 new LdapTimeoutTest().ldapReadTimeoutTest(env, true); 74 new LdapTimeoutTest().simpleAuthConnectTest(env); 75 } finally { 76 s.interrupt(); 77 LdapTimeoutTest.pool.shutdown(); 78 } 79 80 System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); 81 if (failed > 0) throw new AssertionError("Some tests failed"); 82 } 83 84 void ldapReadTimeoutTest(Hashtable env, boolean ssl) { 85 InitialContext ctx = null; 86 if (ssl) env.put(Context.SECURITY_PROTOCOL, "ssl"); 87 ScheduledFuture killer = killSwitch(); 88 long start = System.nanoTime(); 89 try { 90 ctx = new InitialDirContext(env); 91 SearchControls scl = new SearchControls(); 92 scl.setSearchScope(SearchControls.SUBTREE_SCOPE); 93 NamingEnumeration<SearchResult> answer = ((InitialDirContext)ctx) 94 .search("ou=People,o=JNDITutorial", "(objectClass=*)", scl); 95 // shouldn't reach here 96 fail(); 97 } catch (NamingException e) { 98 if (ssl) { 99 if (e.getCause() instanceof SocketTimeoutException) { 100 pass(); 101 } else if (e.getCause() instanceof InterruptedIOException) { 102 Thread.interrupted(); 103 fail(); 104 } 105 } else { 106 pass(); 107 } 108 } finally { 109 if (!shutItDown(killer, ctx)) fail(); 110 } 111 } 112 113 void simpleAuthConnectTest(Hashtable env) { 114 InitialContext ctx = null; 115 ScheduledFuture killer = killSwitch(); 116 long start = System.nanoTime(); 117 try { 118 ctx = new InitialDirContext(env); 119 // shouldn't reach here 120 System.err.println("Fail: InitialDirContext succeeded"); 121 fail(); 122 } catch (NamingException e) { 123 long end = System.nanoTime(); 124 if (e.getCause() instanceof SocketTimeoutException) { 125 if (TimeUnit.NANOSECONDS.toMillis(end - start) < 2900) { 126 pass(); 127 } else { 128 System.err.println("Fail: Waited too long"); 129 fail(); 130 } 131 } else if (e.getCause() instanceof InterruptedIOException) { 132 Thread.interrupted(); 133 fail(); 134 } else { 135 fail(); 136 } 137 } finally { 138 if (!shutItDown(killer, ctx)) fail(); 139 } 140 } 141 142 boolean shutItDown(ScheduledFuture killer, InitialContext ctx) { 143 killer.cancel(true); 144 try { 145 if (ctx != null) ctx.close(); 146 return true; 147 } catch (NamingException ex) { 148 return false; 149 } 150 } 151 152 ScheduledFuture killSwitch() { 153 final Thread current = Thread.currentThread(); 154 return LdapTimeoutTest.pool.schedule(new Callable<Void>() { 155 public Void call() throws Exception { 156 System.err.println("Fail: killSwitch()"); 157 current.interrupt(); 158 return null; 159 } 160 }, 5000, TimeUnit.MILLISECONDS); 161 } 162 163 static class Server extends Thread { 164 final ServerSocket serverSock; 165 166 Server(ServerSocket serverSock) { 167 this.serverSock = serverSock; 168 } 169 170 public void run() { 171 try { 172 Socket socket = serverSock.accept(); 173 } catch (IOException e) {} 174 } 175 } 176 } 177