11161d3e8SAdam Hornacek /* 21161d3e8SAdam Hornacek * CDDL HEADER START 31161d3e8SAdam Hornacek * 41161d3e8SAdam Hornacek * The contents of this file are subject to the terms of the 51161d3e8SAdam Hornacek * Common Development and Distribution License (the "License"). 61161d3e8SAdam Hornacek * You may not use this file except in compliance with the License. 71161d3e8SAdam Hornacek * 81161d3e8SAdam Hornacek * See LICENSE.txt included in this distribution for the specific 91161d3e8SAdam Hornacek * language governing permissions and limitations under the License. 101161d3e8SAdam Hornacek * 111161d3e8SAdam Hornacek * When distributing Covered Code, include this CDDL HEADER in each 121161d3e8SAdam Hornacek * file and include the License file at LICENSE.txt. 131161d3e8SAdam Hornacek * If applicable, add the following below this CDDL HEADER, with the 141161d3e8SAdam Hornacek * fields enclosed by brackets "[]" replaced with your own identifying 151161d3e8SAdam Hornacek * information: Portions Copyright [yyyy] [name of copyright owner] 161161d3e8SAdam Hornacek * 171161d3e8SAdam Hornacek * CDDL HEADER END 181161d3e8SAdam Hornacek */ 191161d3e8SAdam Hornacek 201161d3e8SAdam Hornacek /* 212f7dccc7SAdam Hornacek * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. 221161d3e8SAdam Hornacek */ 2314c8a3ffSVladimir Kotal package opengrok.auth.plugin; 2414c8a3ffSVladimir Kotal 2514c8a3ffSVladimir Kotal import opengrok.auth.plugin.ldap.LdapServer; 262f7dccc7SAdam Hornacek import org.junit.jupiter.api.Test; 2714c8a3ffSVladimir Kotal import org.mockito.Mockito; 28*cb97e878SVladimir Kotal import org.opengrok.web.api.v1.controller.PortChecker; 2914c8a3ffSVladimir Kotal 3014c8a3ffSVladimir Kotal import java.io.IOException; 3114c8a3ffSVladimir Kotal import java.net.InetAddress; 3214c8a3ffSVladimir Kotal import java.net.ServerSocket; 3314c8a3ffSVladimir Kotal import java.net.Socket; 3414c8a3ffSVladimir Kotal import java.net.URISyntaxException; 3514c8a3ffSVladimir Kotal import java.net.UnknownHostException; 36*cb97e878SVladimir Kotal import java.util.Random; 3714c8a3ffSVladimir Kotal 381161d3e8SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertEquals; 391161d3e8SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertFalse; 401161d3e8SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNotNull; 411161d3e8SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertNull; 421161d3e8SAdam Hornacek import static org.junit.jupiter.api.Assertions.assertTrue; 4314c8a3ffSVladimir Kotal import static org.mockito.ArgumentMatchers.any; 4414c8a3ffSVladimir Kotal import static org.mockito.Mockito.doReturn; 4514c8a3ffSVladimir Kotal 4614c8a3ffSVladimir Kotal public class LdapServerTest { 4714c8a3ffSVladimir Kotal 4814c8a3ffSVladimir Kotal @Test testInvalidURI()4914c8a3ffSVladimir Kotal public void testInvalidURI() { 5014c8a3ffSVladimir Kotal LdapServer server = new LdapServer("foo:/\\/\\foo.bar"); 5114c8a3ffSVladimir Kotal assertFalse(server.isReachable()); 5214c8a3ffSVladimir Kotal } 5314c8a3ffSVladimir Kotal 5414c8a3ffSVladimir Kotal @Test testGetPort()5514c8a3ffSVladimir Kotal public void testGetPort() throws URISyntaxException { 5614c8a3ffSVladimir Kotal LdapServer server = new LdapServer("ldaps://foo.bar"); 5714c8a3ffSVladimir Kotal assertEquals(636, server.getPort()); 5814c8a3ffSVladimir Kotal 5914c8a3ffSVladimir Kotal server = new LdapServer("ldap://foo.bar"); 6014c8a3ffSVladimir Kotal assertEquals(389, server.getPort()); 6114c8a3ffSVladimir Kotal 6214c8a3ffSVladimir Kotal server = new LdapServer("crumble://foo.bar"); 6314c8a3ffSVladimir Kotal assertEquals(-1, server.getPort()); 6414c8a3ffSVladimir Kotal } 6514c8a3ffSVladimir Kotal 6614c8a3ffSVladimir Kotal @Test testSetGetUsername()6714c8a3ffSVladimir Kotal public void testSetGetUsername() { 6814c8a3ffSVladimir Kotal LdapServer server = new LdapServer(); 6914c8a3ffSVladimir Kotal 7014c8a3ffSVladimir Kotal assertNull(server.getUsername()); 7114c8a3ffSVladimir Kotal assertNull(server.getPassword()); 7214c8a3ffSVladimir Kotal 7314c8a3ffSVladimir Kotal final String testUsername = "foo"; 7414c8a3ffSVladimir Kotal server.setUsername(testUsername); 7514c8a3ffSVladimir Kotal assertEquals(testUsername, server.getUsername()); 7614c8a3ffSVladimir Kotal 7714c8a3ffSVladimir Kotal final String testPassword = "bar"; 7814c8a3ffSVladimir Kotal server.setPassword(testPassword); 7914c8a3ffSVladimir Kotal assertEquals(testPassword, server.getPassword()); 8014c8a3ffSVladimir Kotal } 8114c8a3ffSVladimir Kotal 8214c8a3ffSVladimir Kotal @Test testIsReachable()8314c8a3ffSVladimir Kotal public void testIsReachable() throws IOException, InterruptedException, URISyntaxException { 84*cb97e878SVladimir Kotal final int testPortBase = 6336; // It has to be > 1024 to avoid BindException due to permission denied. 85*cb97e878SVladimir Kotal final int randomRange = 49152; 86*cb97e878SVladimir Kotal int triesCount = 0; 87*cb97e878SVladimir Kotal final int MAX_PORT_TRIES = 20; 88*cb97e878SVladimir Kotal Random rand = new Random(); 89*cb97e878SVladimir Kotal int testPort; 90*cb97e878SVladimir Kotal while (true) { 91*cb97e878SVladimir Kotal testPort = testPortBase + rand.nextInt(randomRange); 92*cb97e878SVladimir Kotal if (PortChecker.available(testPort)) { 93*cb97e878SVladimir Kotal break; 94*cb97e878SVladimir Kotal } 95*cb97e878SVladimir Kotal if (++triesCount > MAX_PORT_TRIES) { 96*cb97e878SVladimir Kotal throw new RuntimeException("Could not find an available port after " + 97*cb97e878SVladimir Kotal MAX_PORT_TRIES + " tries"); 98*cb97e878SVladimir Kotal } 99*cb97e878SVladimir Kotal } 100*cb97e878SVladimir Kotal 101*cb97e878SVladimir Kotal // Start simple TCP server on test port. 10214c8a3ffSVladimir Kotal InetAddress localhostAddr = InetAddress.getLocalHost(); 10314c8a3ffSVladimir Kotal ServerSocket serverSocket = new ServerSocket(testPort, 1, localhostAddr); 10414c8a3ffSVladimir Kotal Thread thread = new Thread(() -> { 10514c8a3ffSVladimir Kotal try { 10614c8a3ffSVladimir Kotal while (true) { 10714c8a3ffSVladimir Kotal Socket client = serverSocket.accept(); 10814c8a3ffSVladimir Kotal client.close(); 10914c8a3ffSVladimir Kotal } 11014c8a3ffSVladimir Kotal } catch (IOException e) { 11114c8a3ffSVladimir Kotal e.printStackTrace(); 11214c8a3ffSVladimir Kotal } 11314c8a3ffSVladimir Kotal }); 11414c8a3ffSVladimir Kotal 11514c8a3ffSVladimir Kotal thread.start(); 11614c8a3ffSVladimir Kotal Socket socket = null; 11714c8a3ffSVladimir Kotal for (int i = 0; i < 3; i++) { 11814c8a3ffSVladimir Kotal try { 11914c8a3ffSVladimir Kotal socket = new Socket(localhostAddr, testPort); 12014c8a3ffSVladimir Kotal } catch (IOException e) { 12114c8a3ffSVladimir Kotal Thread.sleep(1000); 12214c8a3ffSVladimir Kotal } 12314c8a3ffSVladimir Kotal } 12414c8a3ffSVladimir Kotal 12514c8a3ffSVladimir Kotal assertNotNull(socket); 12614c8a3ffSVladimir Kotal assertTrue(socket.isConnected()); 12714c8a3ffSVladimir Kotal 128*cb97e878SVladimir Kotal // Mock getAddresses() to return single localhost IP address and getPort() to return the test port. 12914c8a3ffSVladimir Kotal LdapServer server = new LdapServer("ldaps://foo.bar.com"); 13014c8a3ffSVladimir Kotal LdapServer serverSpy = Mockito.spy(server); 13114c8a3ffSVladimir Kotal Mockito.when(serverSpy.getAddresses(any())).thenReturn(new InetAddress[]{localhostAddr}); 13214c8a3ffSVladimir Kotal doReturn(testPort).when(serverSpy).getPort(); 13314c8a3ffSVladimir Kotal 13414c8a3ffSVladimir Kotal // Test reachability. 13514c8a3ffSVladimir Kotal boolean reachable = serverSpy.isReachable(); 13614c8a3ffSVladimir Kotal serverSocket.close(); 13714c8a3ffSVladimir Kotal thread.join(5000); 13814c8a3ffSVladimir Kotal thread.interrupt(); 13914c8a3ffSVladimir Kotal assertTrue(reachable); 14014c8a3ffSVladimir Kotal 14114c8a3ffSVladimir Kotal // Test non-reachability. 14214c8a3ffSVladimir Kotal reachable = serverSpy.isReachable(); 14314c8a3ffSVladimir Kotal assertFalse(reachable); 14414c8a3ffSVladimir Kotal } 14514c8a3ffSVladimir Kotal 14614c8a3ffSVladimir Kotal @Test testEmptyAddressArray()14714c8a3ffSVladimir Kotal public void testEmptyAddressArray() throws UnknownHostException { 14814c8a3ffSVladimir Kotal LdapServer server = new LdapServer("ldaps://foo.bar.com"); 14914c8a3ffSVladimir Kotal LdapServer serverSpy = Mockito.spy(server); 15014c8a3ffSVladimir Kotal Mockito.when(serverSpy.getAddresses(any())).thenReturn(new InetAddress[]{}); 15114c8a3ffSVladimir Kotal assertFalse(serverSpy.isReachable()); 15214c8a3ffSVladimir Kotal } 153d0624dbbSVladimir Kotal 154d0624dbbSVladimir Kotal @Test testToString()155d0624dbbSVladimir Kotal public void testToString() { 156d0624dbbSVladimir Kotal LdapServer server = new LdapServer("ldaps://foo.bar.com", "foo", "bar"); 157d0624dbbSVladimir Kotal server.setConnectTimeout(2000); 158d0624dbbSVladimir Kotal server.setReadTimeout(1000); 159d0624dbbSVladimir Kotal assertEquals("ldaps://foo.bar.com, connect timeout: 2000, read timeout: 1000, username: foo", 160d0624dbbSVladimir Kotal server.toString()); 161d0624dbbSVladimir Kotal } 16214c8a3ffSVladimir Kotal } 163