Wed, 09 Sep 2020 14:19:14 -0400
8062947: Fix exception message to correctly represent LDAP connection failure
Reviewed-by: dfuchs, xyin, vtewari
zgu@14206 | 1 | /* |
zgu@14206 | 2 | * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. |
zgu@14206 | 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
zgu@14206 | 4 | * |
zgu@14206 | 5 | * This code is free software; you can redistribute it and/or modify it |
zgu@14206 | 6 | * under the terms of the GNU General Public License version 2 only, as |
zgu@14206 | 7 | * published by the Free Software Foundation. |
zgu@14206 | 8 | * |
zgu@14206 | 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
zgu@14206 | 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
zgu@14206 | 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
zgu@14206 | 12 | * version 2 for more details (a copy is included in the LICENSE file that |
zgu@14206 | 13 | * accompanied this code). |
zgu@14206 | 14 | * |
zgu@14206 | 15 | * You should have received a copy of the GNU General Public License version |
zgu@14206 | 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
zgu@14206 | 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
zgu@14206 | 18 | * |
zgu@14206 | 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
zgu@14206 | 20 | * or visit www.oracle.com if you need additional information or have any |
zgu@14206 | 21 | * questions. |
zgu@14206 | 22 | */ |
zgu@14206 | 23 | |
zgu@14206 | 24 | /* |
zgu@14206 | 25 | * @test |
zgu@14206 | 26 | * @bug 8062947 |
zgu@14206 | 27 | * @summary Test that NamingException message text matches the failure reason |
zgu@14206 | 28 | * @library lib/ |
zgu@14206 | 29 | * @library /lib/testlibrary |
zgu@14206 | 30 | * @run testng NamingExceptionMessageTest |
zgu@14206 | 31 | */ |
zgu@14206 | 32 | |
zgu@14206 | 33 | import javax.naming.Context; |
zgu@14206 | 34 | import javax.naming.NamingException; |
zgu@14206 | 35 | import javax.naming.directory.InitialDirContext; |
zgu@14206 | 36 | import java.io.IOException; |
zgu@14206 | 37 | import java.io.OutputStream; |
zgu@14206 | 38 | import java.net.InetAddress; |
zgu@14206 | 39 | import java.net.InetSocketAddress; |
zgu@14206 | 40 | import java.net.ServerSocket; |
zgu@14206 | 41 | import java.net.Socket; |
zgu@14206 | 42 | import java.util.Hashtable; |
zgu@14206 | 43 | import java.util.concurrent.CountDownLatch; |
zgu@14206 | 44 | import java.util.concurrent.TimeUnit; |
zgu@14206 | 45 | |
zgu@14206 | 46 | import org.testng.annotations.Test; |
zgu@14206 | 47 | import org.testng.Assert; |
zgu@14206 | 48 | import jdk.testlibrary.net.URIBuilder; |
zgu@14206 | 49 | |
zgu@14206 | 50 | public class NamingExceptionMessageTest { |
zgu@14206 | 51 | |
zgu@14206 | 52 | @Test |
zgu@14206 | 53 | public void timeoutMessageTest() throws Exception { |
zgu@14206 | 54 | try (TestLdapServer ldapServer = TestLdapServer.newInstance(false)) { |
zgu@14206 | 55 | ldapServer.start(); |
zgu@14206 | 56 | ldapServer.awaitStartup(); |
zgu@14206 | 57 | Hashtable<Object, Object> env = ldapServer.getInitialLdapCtxEnvironment(TIMEOUT_VALUE); |
zgu@14206 | 58 | Exception namingException = Assert.expectThrows(NamingException.class, () -> new InitialDirContext(env)); |
zgu@14206 | 59 | System.out.println("Got naming exception:" + namingException); |
zgu@14206 | 60 | Assert.assertEquals(namingException.getMessage(), EXPECTED_TIMEOUT_MESSAGE); |
zgu@14206 | 61 | } |
zgu@14206 | 62 | } |
zgu@14206 | 63 | |
zgu@14206 | 64 | @Test |
zgu@14206 | 65 | public void connectionClosureMessageTest() throws Exception { |
zgu@14206 | 66 | try (TestLdapServer ldapServer = TestLdapServer.newInstance(true)) { |
zgu@14206 | 67 | ldapServer.start(); |
zgu@14206 | 68 | ldapServer.awaitStartup(); |
zgu@14206 | 69 | Hashtable<Object, Object> env = ldapServer.getInitialLdapCtxEnvironment(0); |
zgu@14206 | 70 | Exception namingException = Assert.expectThrows(NamingException.class, () -> new InitialDirContext(env)); |
zgu@14206 | 71 | System.out.println("Got naming exception:" + namingException); |
zgu@14206 | 72 | Assert.assertEquals(namingException.getMessage(), EXPECTED_CLOSURE_MESSAGE); |
zgu@14206 | 73 | } |
zgu@14206 | 74 | } |
zgu@14206 | 75 | |
zgu@14206 | 76 | // Test LDAP server |
zgu@14206 | 77 | private static class TestLdapServer extends BaseLdapServer { |
zgu@14206 | 78 | |
zgu@14206 | 79 | private final boolean closeConnections; |
zgu@14206 | 80 | private final CountDownLatch startupLatch = new CountDownLatch(1); |
zgu@14206 | 81 | |
zgu@14206 | 82 | public Hashtable<Object, Object> getInitialLdapCtxEnvironment(int readTimeoutValue) { |
zgu@14206 | 83 | // Create environment for initial LDAP context |
zgu@14206 | 84 | Hashtable<Object, Object> env = new Hashtable<>(); |
zgu@14206 | 85 | |
zgu@14206 | 86 | // Activate LDAPv3 |
zgu@14206 | 87 | env.put("java.naming.ldap.version", "3"); |
zgu@14206 | 88 | |
zgu@14206 | 89 | // De-activate the ManageDsaIT control |
zgu@14206 | 90 | env.put(Context.REFERRAL, "follow"); |
zgu@14206 | 91 | env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); |
zgu@14206 | 92 | env.put(Context.PROVIDER_URL, getUrlString()); |
zgu@14206 | 93 | env.put(Context.SECURITY_AUTHENTICATION, "simple"); |
zgu@14206 | 94 | env.put(Context.SECURITY_PRINCIPAL, "name"); |
zgu@14206 | 95 | env.put(Context.SECURITY_CREDENTIALS, "pwd"); |
zgu@14206 | 96 | |
zgu@14206 | 97 | if (readTimeoutValue > 0) { |
zgu@14206 | 98 | env.put("com.sun.jndi.ldap.read.timeout", String.valueOf(readTimeoutValue)); |
zgu@14206 | 99 | env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(readTimeoutValue)); |
zgu@14206 | 100 | } |
zgu@14206 | 101 | |
zgu@14206 | 102 | return env; |
zgu@14206 | 103 | } |
zgu@14206 | 104 | |
zgu@14206 | 105 | private String getUrlString() { |
zgu@14206 | 106 | String url = URIBuilder.newBuilder() |
zgu@14206 | 107 | .scheme("ldap") |
zgu@14206 | 108 | .loopback() |
zgu@14206 | 109 | .port(getPort()) |
zgu@14206 | 110 | .buildUnchecked() |
zgu@14206 | 111 | .toString(); |
zgu@14206 | 112 | return url; |
zgu@14206 | 113 | } |
zgu@14206 | 114 | |
zgu@14206 | 115 | public static TestLdapServer newInstance(boolean closeConnections) throws IOException { |
zgu@14206 | 116 | ServerSocket srvSock = new ServerSocket(); |
zgu@14206 | 117 | srvSock.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); |
zgu@14206 | 118 | return new TestLdapServer(srvSock, closeConnections); |
zgu@14206 | 119 | } |
zgu@14206 | 120 | |
zgu@14206 | 121 | void awaitStartup() throws InterruptedException { |
zgu@14206 | 122 | startupLatch.await(); |
zgu@14206 | 123 | } |
zgu@14206 | 124 | |
zgu@14206 | 125 | private TestLdapServer(ServerSocket serverSocket, boolean closeConnections) { |
zgu@14206 | 126 | super(serverSocket); |
zgu@14206 | 127 | this.closeConnections = closeConnections; |
zgu@14206 | 128 | |
zgu@14206 | 129 | } |
zgu@14206 | 130 | |
zgu@14206 | 131 | @Override |
zgu@14206 | 132 | protected void beforeAcceptingConnections() { |
zgu@14206 | 133 | startupLatch.countDown(); |
zgu@14206 | 134 | } |
zgu@14206 | 135 | |
zgu@14206 | 136 | @Override |
zgu@14206 | 137 | protected void handleRequest(Socket socket, |
zgu@14206 | 138 | LdapMessage msg, |
zgu@14206 | 139 | OutputStream out) |
zgu@14206 | 140 | throws IOException { |
zgu@14206 | 141 | switch (msg.getOperation()) { |
zgu@14206 | 142 | case BIND_REQUEST: |
zgu@14206 | 143 | if (closeConnections) { |
zgu@14206 | 144 | closeSilently(socket); |
zgu@14206 | 145 | } else { |
zgu@14206 | 146 | try { |
zgu@14206 | 147 | TimeUnit.DAYS.sleep(Integer.MAX_VALUE); |
zgu@14206 | 148 | } catch (InterruptedException e) { |
zgu@14206 | 149 | Thread.currentThread().interrupt(); |
zgu@14206 | 150 | } |
zgu@14206 | 151 | } |
zgu@14206 | 152 | default: |
zgu@14206 | 153 | break; |
zgu@14206 | 154 | } |
zgu@14206 | 155 | } |
zgu@14206 | 156 | } |
zgu@14206 | 157 | |
zgu@14206 | 158 | // Expected message for case when connection is closed on server side |
zgu@14206 | 159 | private static final String EXPECTED_CLOSURE_MESSAGE = "LDAP connection has been closed"; |
zgu@14206 | 160 | // read and connect timeouts value |
zgu@14206 | 161 | private static final int TIMEOUT_VALUE = 129; |
zgu@14206 | 162 | // Expected message text when connection is timed-out |
zgu@14206 | 163 | private static final String EXPECTED_TIMEOUT_MESSAGE = String.format( |
zgu@14206 | 164 | "LDAP response read timed out, timeout used: %d ms.", TIMEOUT_VALUE); |
zgu@14206 | 165 | } |