8015595: Test sun/security/krb5/auto/Unreachable.java fails with Timeout error
Summary: Unreachable.java was getting timeout due to PortUnreachableException was not thrown
Reviewed-by: weijun
--- a/jdk/test/ProblemList.txt Wed Aug 31 14:20:02 2016 +0200
+++ b/jdk/test/ProblemList.txt Wed Aug 31 08:34:59 2016 -0700
@@ -213,8 +213,6 @@
sun/security/pkcs11/ec/TestKeyFactory.java 8026976 generic-all
-sun/security/krb5/auto/Unreachable.java 7164518 macosx-all
-
sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all
sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java 8026393 generic-all
--- a/jdk/test/sun/security/krb5/auto/Unreachable.java Wed Aug 31 14:20:02 2016 +0200
+++ b/jdk/test/sun/security/krb5/auto/Unreachable.java Wed Aug 31 08:34:59 2016 -0700
@@ -23,31 +23,108 @@
/*
* @test
- * @bug 7162687
+ * @bug 7162687 8015595
* @key intermittent
* @summary enhance KDC server availability detection
* @compile -XDignore.symbol.file Unreachable.java
- * @run main/othervm/timeout=10 Unreachable
+ * @run main/othervm Unreachable
*/
-
-import java.io.File;
+import java.net.PortUnreachableException;
+import java.net.SocketTimeoutException;
+import java.net.DatagramPacket;
+import java.net.DatagramSocket;
+import java.net.InetSocketAddress;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import java.util.concurrent.Executors;
import javax.security.auth.login.LoginException;
import sun.security.krb5.Config;
public class Unreachable {
+ // Wait for 20 second until unreachable KDC throws PortUnreachableException.
+ private static final int TIMEOUT = 20;
+ private static final String REALM = "RABBIT.HOLE";
+ private static final String HOST = "127.0.0.1";
+ private static final int PORT = 13434;
+ private static final String KRB_CONF = "unreachable.krb5.conf";
+
public static void main(String[] args) throws Exception {
- File f = new File(
- System.getProperty("test.src", "."), "unreachable.krb5.conf");
- System.setProperty("java.security.krb5.conf", f.getPath());
- Config.refresh();
- // If PortUnreachableException is not received, the login will consume
- // about 3*3*30 seconds and the test will timeout.
+ // - Only PortUnreachableException will allow to continue execution.
+ // - SocketTimeoutException may occur on Mac because it will not throw
+ // PortUnreachableException for unreachable port in which case the Test
+ // execution will be skipped.
+ // - For Reachable port, the Test execution will get skipped.
+ // - Any other Exception will be treated as Test failure.
+ if (!findPortUnreachableExc()) {
+ System.out.println(String.format("WARNING: Either a reachable "
+ + "connection found to %s:%s or SocketTimeoutException "
+ + "occured which means PortUnreachableException not thrown"
+ + " by the platform.", HOST, PORT));
+ return;
+ }
+ KDC kdc = KDC.existing(REALM, HOST, PORT);
+ KDC.saveConfig(KRB_CONF, kdc);
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Exception> future = executor.submit(new Callable<Exception>() {
+ @Override
+ public Exception call() {
+ System.setProperty("java.security.krb5.conf", KRB_CONF);
+ try {
+ Config.refresh();
+ // If PortUnreachableException is not received, the login
+ // will consume about 3*3*30 seconds and the test will
+ // timeout.
+ try {
+ Context.fromUserPass("name", "pass".toCharArray(), true);
+ } catch (LoginException le) {
+ // This is OK
+ }
+ System.out.println("Execution successful.");
+ } catch (Exception e) {
+ return e;
+ }
+ return null;
+ }
+ });
try {
- Context.fromUserPass("name", "pass".toCharArray(), true);
- } catch (LoginException le) {
- // This is OK
+ Exception ex = null;
+ if ((ex = future.get(TIMEOUT, TimeUnit.SECONDS)) != null) {
+ throw new RuntimeException(ex);
+ }
+ } catch (TimeoutException e) {
+ future.cancel(true);
+ throw new RuntimeException("PortUnreachableException not thrown.");
+ } finally {
+ executor.shutdownNow();
}
}
+
+ /**
+ * If the remote destination to which the socket is connected does not
+ * exist, or is otherwise unreachable, and if an ICMP destination unreachable
+ * packet has been received for that address, then a subsequent call to
+ * send or receive may throw a PortUnreachableException. Note, there is no
+ * guarantee that the exception will be thrown.
+ */
+ private static boolean findPortUnreachableExc() throws Exception {
+ try {
+ InetSocketAddress iaddr = new InetSocketAddress(HOST, PORT);
+ DatagramSocket dgSocket = new DatagramSocket();
+ dgSocket.setSoTimeout(5000);
+ dgSocket.connect(iaddr);
+ byte[] data = new byte[]{};
+ dgSocket.send(new DatagramPacket(data, data.length, iaddr));
+ dgSocket.receive(new DatagramPacket(data, data.length));
+ } catch (PortUnreachableException e) {
+ return true;
+ } catch (SocketTimeoutException e) {
+ return false;
+ }
+ return false;
+ }
}
--- a/jdk/test/sun/security/krb5/auto/unreachable.krb5.conf Wed Aug 31 14:20:02 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,9 +0,0 @@
-[libdefaults]
- default_realm = RABBIT.HOLE
-[realms]
-
-RABBIT.HOLE = {
- kdc = 127.0.0.1:13434
- kdc = 127.0.0.1:13435
- kdc = 127.0.0.1:13436
-}