--- /dev/null	2014-10-12 14:58:52.985358547 +0200
+++ new/test/javax/net/ssl/TLS/FallbackSCSV.java	2014-10-20 22:48:34.875358971 +0200
@@ -0,0 +1,284 @@
+/**
+ * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 only, as published by
+ * the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ * A PARTICULAR PURPOSE. See the GNU General Public License version 2 for more
+ * details (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version 2
+ * along with this work; if not, write to the Free Software Foundation, Inc., 51
+ * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA or
+ * visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.SocketException;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLParameters;
+import javax.net.ssl.SSLProtocolException;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
+import javax.net.ssl.TrustManager;
+
+/**
+ * @test
+ * @library ../../../../lib/testlibrary/
+ * @build jdk.testlibrary.Utils
+ * @compile CipherTestUtils.java
+ * @summary Test that TLS_FALLBACK_SCSV works in the client and server
+ * TLS code
+ */
+
+public final class FallbackSCSV {
+    public static void main(String[] args) throws Exception {
+        FallbackSCSV test = new FallbackSCSV();
+        test.test();
+        test.immediateConnect = true;
+        test.test();
+        test.cipherTest.checkResult(null);
+    }
+    
+    private static final String SSL_CONTEXT = "TLS";
+
+    final CipherTestUtils cipherTest;
+    private final MyX509KeyManager keyManager;
+
+    /**
+     * If true, the socket is connected by the factory.
+     */
+    private boolean immediateConnect;
+    
+    private FallbackSCSV() throws Exception {
+        cipherTest = CipherTestUtils.getInstance();
+        keyManager = new MyX509KeyManager(cipherTest.getClientKeyManager());
+    }
+    
+    private void test() throws Exception {
+        List<String> protocols = getProtocols();
+        String maxProtocol = protocols.get(protocols.size() - 1);
+
+        // Without TLS_FALLBACK_SCSV.
+        run(protocols, protocols, false, maxProtocol);
+        run(protocols.subList(0, protocols.size() - 1), protocols,
+                false, protocols.get(protocols.size() - 2));
+        run(protocols, protocols.subList(0, protocols.size() - 1),
+                false, protocols.get(protocols.size() - 2));
+
+        // With TLS_FALLBACK_SCSV.
+        run(protocols, protocols, true, maxProtocol);
+        run(protocols.subList(0, protocols.size() - 1), protocols,
+                true, null);
+        run(protocols, protocols.subList(0, protocols.size() - 1),
+                true, protocols.get(protocols.size() - 2));
+    }
+    
+    private List<String> getProtocols() throws Exception {
+        SSLContext ctx = SSLContext.getInstance(SSL_CONTEXT);
+        ctx.init(new KeyManager[]{cipherTest.getServerKeyManager()},
+                new TrustManager[]{cipherTest.getServerTrustManager()},
+                CipherTestUtils.secureRandom);
+        return Arrays.asList(ctx.getDefaultSSLParameters().getProtocols());
+    }
+
+    private void run(List<String> clientProtocols,
+            List<String> serverProtocols,
+            boolean fallbackSCSV, String expectedProtocol) throws Exception {
+        Server server = new Server(serverProtocols);
+        Thread serverThread = new Thread(server);
+        serverThread.start();
+        try {
+            runClient(server, clientProtocols, fallbackSCSV, expectedProtocol);
+        } catch (Exception e) {
+            CipherTestUtils.addFailure(e);
+            System.out.println("Exception:");
+            e.printStackTrace(System.err);
+        } finally {
+            try {
+                serverThread.interrupt();
+                server.close(); 
+                serverThread.join();
+            } catch (Exception e) {
+                CipherTestUtils.addFailure(e);
+                System.out.println("Exception:");
+                e.printStackTrace(System.err);
+            }
+        }
+    }
+    
+    private SSLSocket createClientSocket(
+            SSLSocketFactory factory, Server server) throws Exception {
+        if (immediateConnect) {
+            return (SSLSocket) factory.createSocket(
+                    server.getAddress().getAddress(),
+                    server.getAddress().getPort());
+        } else {
+            return (SSLSocket) factory.createSocket();
+        }
+    }
+
+    private void runClient(Server server, List<String> clientProtocols,
+            boolean fallbackSCSV, String expectedProtocol) throws Exception {
+        SSLContext ctx = SSLContext.getInstance(SSL_CONTEXT);
+        ctx.init(new KeyManager[]{keyManager},
+                new TrustManager[]{cipherTest.getClientTrustManager()},
+                CipherTestUtils.secureRandom);
+        SSLSocketFactory factory = (SSLSocketFactory) ctx.getSocketFactory();
+        try (SSLSocket socket = createClientSocket(factory, server)) {
+            socket.setEnabledProtocols(clientProtocols.toArray(
+                    new String[clientProtocols.size()]));
+            if (fallbackSCSV) {
+                SSLParameters params = socket.getSSLParameters();
+                params.setSendFallbackSCSV(true);
+                socket.setSSLParameters(params);
+                if (!socket.getSSLParameters().getSendFallbackSCSV()) {
+                    throw new Exception("SendFallbackSCSV not set");
+                }
+            } else {
+                if (socket.getSSLParameters().getSendFallbackSCSV()) {
+                    throw new Exception("SendFallbackSCSV set");
+                }
+            }
+            socket.setSoTimeout(CipherTestUtils.TIMEOUT);
+            socket.setTcpNoDelay(true);
+            if (!immediateConnect) {
+                socket.connect(server.getAddress());
+            }
+            if (expectedProtocol == null) {
+                try {
+                    socket.startHandshake();
+                } catch (SSLHandshakeException e) {
+                    if (!"Received fatal alert: inappropriate_fallback".equals(
+                            e.getMessage())) {
+                        CipherTestUtils.addFailure(e);
+                        System.out.println("Exception:");
+                        e.printStackTrace(System.err);
+                    }
+                    return;
+                }
+                throw new Exception("No exception for fallback to: "
+                        + socket.getSession().getProtocol());
+            }
+            byte[] buf = {1, 2, 3, 0};
+            try (OutputStream out = socket.getOutputStream()) {
+                out.write(buf, 0, 3);
+                try (InputStream in = socket.getInputStream()) {
+                    for (int i = 0; i < 4; ++i) {
+                        int b = in.read();
+                        int expected = (-(i + 1)) & 0xFF;
+                        if (i == 3) {
+                            expected = -1;
+                        }
+                        if (b != expected) {
+                            throw new Exception(String.format(
+                                    "byte mismatch at %d, got %d", i, b));
+                        }
+                    }
+                    
+                    if (!socket.getSession().getProtocol().equals(
+                            expectedProtocol)) {
+                        throw new Exception(String.format(
+                                "Protocol is %s, but expected %s",
+                                socket.getSession().getProtocol(),
+                                expectedProtocol));
+                    }
+                }
+            }
+        }
+    }
+
+    class Server implements Runnable {
+        private final SSLServerSocket serverSocket;
+
+        Server(List<String> protocols) throws Exception {
+            SSLContext ctx = SSLContext.getInstance(SSL_CONTEXT);
+            ctx.init(new KeyManager[]{cipherTest.getServerKeyManager()},
+                    new TrustManager[]{cipherTest.getServerTrustManager()},
+                    CipherTestUtils.secureRandom);
+            SSLServerSocketFactory factory =
+                    (SSLServerSocketFactory)ctx.getServerSocketFactory();
+            serverSocket =
+                    (SSLServerSocket) factory.createServerSocket(0);
+            serverSocket.setEnabledProtocols(
+                    protocols.toArray(new String[protocols.size()]));
+        }
+        
+        InetSocketAddress getAddress() {
+            return (InetSocketAddress) serverSocket.getLocalSocketAddress();
+        }
+        
+        void close() throws Exception {
+            serverSocket.close();
+        }
+        
+        @Override
+        public void run() {
+            while (!Thread.currentThread().isInterrupted()) {
+                try (SSLSocket socket = (SSLSocket) serverSocket.accept()) {
+                    socket.setSoTimeout(CipherTestUtils.TIMEOUT);
+                    socket.setTcpNoDelay(true);
+                    
+                    try {
+                        socket.startHandshake();
+                    } catch (SSLHandshakeException e) {
+                        if (!"Client protocol downgrade is not allowed".equals(
+                                e.getMessage())) {
+                            throw e;
+                        }
+                        continue;
+                    }
+
+                    try (InputStream in = socket.getInputStream();
+                            OutputStream out = socket.getOutputStream()) {
+                        for (int i = 0; i < 3; ++i) {
+                            int b = in.read();
+                            if (b < 0) {
+                                break;
+                            }
+                            out.write((-b) & 0xFF);
+                        }
+                        out.flush();
+                    } catch (Exception e) {
+                        CipherTestUtils.addFailure(e);
+                        System.out.println("Exception:");
+                        e.printStackTrace(System.err);
+                        return;
+                    }
+                } catch (Exception e) {
+                    if (e.getClass() == SocketException.class
+                            && "Socket closed".equals(e.getMessage())) {
+                        // Concurrent close by main thread.
+                        return;
+                    }
+                    CipherTestUtils.addFailure(e);
+                    System.out.println("Exception:");
+                    e.printStackTrace(System.err);
+                    return;
+                }
+            }
+            try {
+                serverSocket.close();
+            } catch (Exception e) {
+                CipherTestUtils.addFailure(e);
+            }
+        }
+    }
+}
