jdk/test/java/nio/channels/SocketChannel/Hangup.java
author duke
Sat, 01 Dec 2007 00:00:00 +0000
changeset 2 90ce3da70b43
child 5506 202f599c92aa
permissions -rw-r--r--
Initial load

/*
 * Copyright 2002 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/* @test
 * @bug 4617165
 * @summary Ensure that socket hangups are handled correctly
 * @library ..
 * @build TestUtil
 * @run main Hangup
 */

import java.io.*;
import java.net.*;
import java.nio.*;
import java.nio.channels.*;
import java.util.*;


public class Hangup {

    static PrintStream log = System.err;
    static int failures = 0;

    private static class Failure
        extends RuntimeException
    {

        Failure(String s) {
            super(s);
        }

    }

    static void doSelect(Selector sel, SelectionKey sk, int count)
        throws IOException
    {
        int n = sel.select();
        if (n != 1)
            throw new Failure("Select returned zero");
        Set sks = sel.selectedKeys();
        if (sks.size() != 1)
            throw new Failure("Wrong size for selected-key set: "
                              + sks.size());
        if (!sks.remove(sk))
            throw new Failure("Key not in selected-key set");
        log.println("S: Socket selected #" + count);
    }

    static void dally() {
        try {
            Thread.sleep(100);
        } catch (InterruptedException x) { }
    }

    static void test(boolean writeFromClient, boolean readAfterClose)
        throws IOException
    {

        ServerSocketChannel ssc = null;
        SocketChannel cl = null;        // client end
        SocketChannel sv = null;        // server end
        Selector sel = null;

        log.println();
        log.println("Test: writeFromClient = " + writeFromClient
                    + ", readAfterClose = " + readAfterClose);

        try {

            int ns = 0;                 // Number of selection operations done

            // Set up server socket
            ssc = ServerSocketChannel.open();
            SocketAddress sa = TestUtil.bindToRandomPort(ssc);
            log.println("S: Listening on port "
                        + ssc.socket().getLocalPort());

            // Connect client
            cl = SocketChannel.open(sa);
            log.println("C: Connected via port "
                        + cl.socket().getLocalPort());

            // Accept client connection
            sv = ssc.accept();
            log.println("S: Client connection accepted");

            // Create selector and register server side
            sel = Selector.open();
            sv.configureBlocking(false);
            SelectionKey sk = sv.register(sel, SelectionKey.OP_READ);

            ByteBuffer stuff = ByteBuffer.allocate(10);
            int n;

            if (writeFromClient) {

                // Write from client, read from server

                stuff.clear();
                if (cl.write(stuff) != stuff.capacity())
                    throw new Failure("Incorrect number of bytes written");
                log.println("C: Wrote stuff");
                dally();

                doSelect(sel, sk, ++ns);

                stuff.clear();
                if (sv.read(stuff) != stuff.capacity())
                    throw new Failure("Wrong number of bytes read");
                log.println("S: Read stuff");
            }

            // Close client side
            cl.close();
            log.println("C: Socket closed");
            dally();

            // Select again
            doSelect(sel, sk, ++ns);

            if (readAfterClose) {
                // Read from client after client has disconnected
                stuff.clear();
                if (sv.read(stuff) != -1)
                    throw new Failure("Wrong number of bytes read");
                log.println("S: Read EOF");
            }

            // Select a couple more times just to make sure we're doing
            // the right thing

            doSelect(sel, sk, ++ns);
            doSelect(sel, sk, ++ns);

        } finally {
            if (ssc != null)
                ssc.close();
            if (cl != null)
                cl.close();
            if (sv != null)
                sv.close();
            if (sel != null)
                sel.close();
        }

    }

    public static void main(String[] args) throws IOException {

        for (boolean writeFromClient = false;; writeFromClient = true) {
            for (boolean readAfterClose = false;; readAfterClose = true) {
                try {
                    test(writeFromClient, readAfterClose);
                } catch (Failure x) {
                    x.printStackTrace(log);
                    failures++;
                }
                if (readAfterClose)
                    break;
            }
            if (writeFromClient)
                break;
        }

        if (failures > 0) {
            log.println();
            throw new RuntimeException("Some tests failed");
        }

    }

}