Package kilim.test

Source Code of kilim.test.TestIO$EchoServer

/* Copyright (c) 2006, Sriram Srinivasan
*
* You may distribute this software under the terms of the license
* specified in the file "License"
*/

package kilim.test;

import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

import junit.framework.TestCase;
import kilim.Pausable;
import kilim.Scheduler;
import kilim.nio.EndPoint;
import kilim.nio.NioSelectorScheduler;
import kilim.nio.SessionTask;

public class TestIO extends TestCase {
    static final int ITERS = 10;
    static final int NCLIENTS = 100;
    NioSelectorScheduler nio;
    int port;
   
    @Override
    protected void setUp() throws Exception {
        nio = new NioSelectorScheduler(); // Starts a single thread that manages the select loop
        port = nio.listen(0, EchoServer.class, Scheduler.getDefaultScheduler()); //
    }
   
    @Override
    protected void tearDown() throws Exception {
        nio.shutdown();
        Thread.sleep(500); // Allow the socket to be closed
    }
   
    /**
     * Launch many ping clients, each of which is paired with its own instance of {@link EchoServer}.
     * @throws IOException
     */
    public void testParallelEchoes() throws IOException {
        try {
            for (int i = 0; i < NCLIENTS; i++) {
                client(port);
            }
        } catch (IOException e) {
            e.printStackTrace();
            fail("IOException " + e.getClass() + ":" + e.getMessage());
        }
    }
   
    public void testDelay() throws IOException {
        SocketChannel sc = SocketChannel.open();
       
        try {
            sc.socket().connect(new InetSocketAddress("localhost", port));
            String s = "Iteration #0. DONE"; // Only because EchoServer checks for it.
            byte[] sbytes = s.getBytes();
            ByteArrayOutputStream baos = new ByteArrayOutputStream(100);
            DataOutputStream dos = new DataOutputStream(baos);
            dos.writeInt(sbytes.length);
            dos.write(sbytes);
           
            byte[] sendbuf = baos.toByteArray();
            // Now write the bytes in little dribs and drabs and delaying in between. This tests fill's yield.
            OutputStream os = sc.socket().getOutputStream();
            sendChunkWithDelay(os, sendbuf, 0, 1)// splitting the length prefix
            sendChunkWithDelay(os, sendbuf, 1, 2);
            sendChunkWithDelay(os, sendbuf, 3, 4);
            sendChunkWithDelay(os, sendbuf, 7, 3);
            sendChunkWithDelay(os, sendbuf, 10, sendbuf.length - 10); // the rest
           
            // Ideally, would like to simulate flow control on the rcv end as well, but would have to turn off
            // socket buffering on the EchoServer side of things. 
            String rs = rcv(sc);
            assertEquals(s, rs);
        } catch (IOException e) {
            e.printStackTrace();
            fail("IOException " + e.getClass() + ":" + e.getMessage());
        }
    }
   

    public void sendChunkWithDelay(OutputStream os, byte[] sendbuf, int offset, int len) throws IOException {
        os.write(sendbuf, offset, len);
        os.flush();
        try {Thread.sleep(100);} catch (InterruptedException ignore) {}
    }
    /**
     * test client side utility function. uses blocking Java I/O to send a length-prefixed string.
     */
    static void send(SocketChannel sc, String s) throws IOException {
        byte[] bytes = s.getBytes();
        int len = bytes.length;
        DataOutputStream dos = new DataOutputStream(sc.socket().getOutputStream());
        dos.writeInt(len);
        dos.write(bytes);
        dos.flush();
    }
       
    /**
     * test client side utility function. uses blocking Java I/O to rcv a length-prefixed string.
     */
    static String rcv(SocketChannel sc) throws IOException {
        // rcv
        DataInputStream dis = new DataInputStream(sc.socket().getInputStream());
        byte[] bytes = new byte[100];
        int len = dis.readInt();
        assertTrue(len < bytes.length);
        int offset = 0;
        while (len > 0) {
            int n = dis.read(bytes, offset, len);
            if (n == -1) {
                throw new IOException("Unexpected termination");
            }
            len -= n;
            offset += n;
        }
        return new String(bytes, 0, offset); // offset contains the length.
    }
   
   
    static void client(int port) throws IOException {
        SocketChannel sc = SocketChannel.open();
        try {
            // Client using regular JDK I/O API.
            sc.socket().connect(new InetSocketAddress("localhost", port));
            for (int i = 0 ; i < ITERS; i++) {
                String s = "Iteration #" + i;
                if (i == ITERS-1) {s += " DONE";}
                send(sc, s);
                String rs = rcv(sc);
                assertEquals(s, rs);
            }
        } finally {
            sc.close();
        }
    }
   

    public static class EchoServer extends SessionTask {
        @Override
        public void execute() throws Pausable, Exception {
            ByteBuffer buf = ByteBuffer.allocate(100);
            EndPoint ep = getEndPoint();
            while (true) {
                buf.clear();
                buf = ep.fillMessage(buf, 4, /*lengthIncludesItself*/ false);
                buf.flip();
                int strlen = buf.getInt();
                String s= new String(buf.array(), 4, strlen);
                //System.out.println ("Rcvd: " + s);
                if (!s.startsWith("Iteration #")) {
                    ep.close();
                    break;
                }
                buf.position(0); // reset read pos
                ep.write(buf); // echo.
                if (s.endsWith("DONE")) {
                    ep.close();
                    break;
                }
            }
        }
    }
}
TOP

Related Classes of kilim.test.TestIO$EchoServer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.