3996N/A/*
3996N/A * Copyright (c) 2011 Oracle and/or its affiliates. All rights reserved.
3996N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
3996N/A *
3996N/A * This code is free software; you can redistribute it and/or modify it
3996N/A * under the terms of the GNU General Public License version 2 only, as
3996N/A * published by the Free Software Foundation.
3996N/A *
3996N/A * This code is distributed in the hope that it will be useful, but WITHOUT
3996N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
3996N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
3996N/A * version 2 for more details (a copy is included in the LICENSE file that
3996N/A * accompanied this code).
3996N/A *
3996N/A * You should have received a copy of the GNU General Public License version
3996N/A * 2 along with this work; if not, write to the Free Software Foundation,
3996N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
3996N/A *
3996N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
3996N/A * or visit www.oracle.com if you need additional information or have any
3996N/A * questions.
3996N/A */
3996N/A
3996N/A
3996N/A/* @test
3996N/A * @summary Test chat server chatserver test
3996N/A *
3996N/A * @library ../../../src/share/sample/nio/chatserver
3996N/A * @build ChatTest ChatServer Client ClientReader DataReader MessageReader NameReader
3996N/A * @run main ChatTest
3996N/A */
3996N/A
3996N/Aimport java.io.*;
3996N/Aimport java.net.InetSocketAddress;
3996N/Aimport java.net.Socket;
3996N/Aimport java.util.ArrayList;
3996N/Aimport java.util.Collections;
3996N/Aimport java.util.List;
3996N/Aimport java.util.concurrent.CyclicBarrier;
3996N/A
3996N/Apublic class ChatTest {
3996N/A public static int listeningPort = 0;
3996N/A
3996N/A public static void main(String[] args) throws Throwable {
3996N/A testStartStop();
3996N/A testPortOpen();
3996N/A testAsksForName();
3996N/A testUseName();
3996N/A testConnectDisconnectConnect();
3996N/A testUsernameAndMessage();
3996N/A testDontReceiveMessageInNameState();
3996N/A }
3996N/A
3996N/A private static ChatServer startServer() throws IOException {
3996N/A ChatServer server = new ChatServer(0);
3996N/A InetSocketAddress address = (InetSocketAddress) server.getSocketAddress();
3996N/A listeningPort = address.getPort();
3996N/A server.run();
3996N/A return server;
3996N/A }
3996N/A
3996N/A public static void testStartStop() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A server.shutdown();
3996N/A }
3996N/A
3996N/A public static void testPortOpen() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A Socket socket = new Socket("localhost", listeningPort);
3996N/A if (!socket.isConnected()) {
3996N/A throw new RuntimeException("Failed to connect to server: port not open");
3996N/A }
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A public static void testAsksForName() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A Socket socket = new Socket("localhost", listeningPort);
3996N/A
3996N/A Reader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
3996N/A String string = readAvailableString(reader);
3996N/A if (!string.equals("Name: ")) {
3996N/A throw new RuntimeException("Server doesn't send Name: ");
3996N/A }
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A public static void testUseName() throws Throwable {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A performTestUseName();
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A public static void testConnectDisconnectConnect() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A performTestConnectDisconnectConnect();
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A public static void testUsernameAndMessage() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A performTestUsernameAndMessage();
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A public static void testDontReceiveMessageInNameState() throws Exception {
3996N/A ChatServer server = startServer();
3996N/A try {
3996N/A performDontReceiveMessageInNameState();
3996N/A } finally {
3996N/A server.shutdown();
3996N/A }
3996N/A }
3996N/A
3996N/A private static void assertEqual(List<Exception> exception, Object value, Object expected) {
3996N/A if (expected == value) {
3996N/A return;
3996N/A }
3996N/A if (expected == null) {
3996N/A exception.add(new RuntimeException("Expected null, but was: " + value));
3996N/A return;
3996N/A }
3996N/A if (!expected.equals(value)) {
3996N/A exception.add(new RuntimeException("Expected: " + expected + " but was: " + value));
3996N/A return;
3996N/A }
3996N/A }
3996N/A
3996N/A private static void performDontReceiveMessageInNameState() throws Exception {
3996N/A final CyclicBarrier barrier1 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier2 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier3 = new CyclicBarrier(2);
3996N/A final List<Exception> exceptions = Collections.synchronizedList(new ArrayList<Exception>());
3996N/A
3996N/A ChatConnection chatConnection = new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "Name: ");
3996N/A writer.write("testClient1\n");
3996N/A waitForJoin(reader, "testClient1");
3996N/A barrier1.await();
3996N/A writer.write("Ignore this!\n");
3996N/A barrier2.await();
3996N/A barrier3.await();
3996N/A }
3996N/A };
3996N/A
3996N/A Thread client2 = new Thread(new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A barrier1.await();
3996N/A barrier2.await();
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "Name: ");
3996N/A string = readAvailableString(reader, true);
3996N/A assertEqual(exceptions, string, null);
3996N/A writer.write("testClient2\n");
3996N/A barrier3.await();
3996N/A }
3996N/A });
3996N/A
3996N/A client2.start();
3996N/A chatConnection.run();
3996N/A if (!exceptions.isEmpty()) {
3996N/A throw exceptions.get(0);
3996N/A }
3996N/A
3996N/A }
3996N/A
3996N/A private static void waitForJoin(BufferedReader reader, String s) throws IOException {
3996N/A String joined;
3996N/A do {
3996N/A joined = readAvailableString(reader);
3996N/A } while (!(joined != null && joined.contains("Welcome " + s)));
3996N/A }
3996N/A
3996N/A private static void performTestUsernameAndMessage() throws Exception {
3996N/A final CyclicBarrier barrier1 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier2 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier3 = new CyclicBarrier(2);
3996N/A final List<Exception> exceptions = Collections.synchronizedList(new ArrayList<Exception>());
3996N/A
3996N/A ChatConnection chatConnection = new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "Name: ");
3996N/A writer.write("testClient1\n");
3996N/A waitForJoin(reader, "testClient1");
3996N/A barrier1.await();
3996N/A barrier2.await();
3996N/A string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "testClient2: Hello world!\n");
3996N/A barrier3.await();
3996N/A }
3996N/A };
3996N/A
3996N/A Thread client2 = new Thread(new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "Name: ");
3996N/A barrier1.await();
3996N/A writer.write("testClient2\nHello world!\n");
3996N/A barrier2.await();
3996N/A barrier3.await();
3996N/A }
3996N/A });
3996N/A
3996N/A client2.start();
3996N/A chatConnection.run();
3996N/A if (!exceptions.isEmpty()) {
3996N/A throw exceptions.get(0);
3996N/A }
3996N/A }
3996N/A
3996N/A private static void performTestConnectDisconnectConnect() throws Exception {
3996N/A final CyclicBarrier barrier1 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier2 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier3 = new CyclicBarrier(2);
3996N/A final List<Exception> exceptions = new ArrayList<Exception>();
3996N/A
3996N/A ChatConnection chatConnection = new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "Name: ");
3996N/A writer.write("testClient1\n");
3996N/A }
3996N/A };
3996N/A
3996N/A ChatConnection chatConnection2 = new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A readAvailableString(reader);
3996N/A writer.write("testClient1\n");
3996N/A waitForJoin(reader, "testClient1");
3996N/A barrier1.await();
3996N/A writer.write("Good morning!\n");
3996N/A barrier2.await();
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "testClient2: Hello world!\n");
3996N/A barrier3.await();
3996N/A }
3996N/A };
3996N/A
3996N/A Thread client2 = new Thread(new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A readAvailableString(reader);
3996N/A writer.write("testClient2\n");
3996N/A waitForJoin(reader, "testClient2");
3996N/A barrier1.await();
3996N/A writer.write("Hello world!\n");
3996N/A barrier2.await();
3996N/A String string = readAvailableString(reader);
3996N/A assertEqual(exceptions, string, "testClient1: Good morning!\n");
3996N/A barrier3.await();
3996N/A }
3996N/A });
3996N/A
3996N/A client2.start();
3996N/A chatConnection.run();
3996N/A chatConnection2.run();
3996N/A if (!exceptions.isEmpty()) {
3996N/A throw exceptions.get(0);
3996N/A }
3996N/A }
3996N/A
3996N/A private static void performTestUseName() throws Exception {
3996N/A final CyclicBarrier barrier1 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier2 = new CyclicBarrier(2);
3996N/A final CyclicBarrier barrier3 = new CyclicBarrier(2);
3996N/A final List<Exception> exceptions = new ArrayList<Exception>();
3996N/A
3996N/A ChatConnection chatConnection = new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A if (!"Name: ".equals(string)) {
3996N/A exceptions.add(new RuntimeException("Expected Name: "));
3996N/A }
3996N/A writer.write("testClient1\n");
3996N/A waitForJoin(reader, "testClient1");
3996N/A barrier1.await();
3996N/A barrier2.await();
3996N/A string = readAvailableString(reader);
3996N/A if (!"testClient2: Hello world!\n".equals(string)) {
3996N/A exceptions.add(new RuntimeException("testClient2: Hello world!\n"));
3996N/A }
3996N/A barrier3.await();
3996N/A }
3996N/A };
3996N/A
3996N/A Thread client2 = new Thread(new ChatConnection() {
3996N/A @Override
3996N/A public void run(Socket socket, BufferedReader reader, Writer writer) throws Exception {
3996N/A String string = readAvailableString(reader);
3996N/A if (!"Name: ".equals(string)) {
3996N/A exceptions.add(new RuntimeException("Expected Name: "));
3996N/A }
3996N/A writer.write("testClient2\n");
3996N/A waitForJoin(reader, "testClient2");
3996N/A barrier1.await();
3996N/A writer.write("Hello world!\n");
3996N/A barrier2.await();
3996N/A barrier3.await();
3996N/A }
3996N/A });
3996N/A
3996N/A client2.start();
3996N/A chatConnection.run();
3996N/A if (!exceptions.isEmpty()) {
3996N/A throw exceptions.get(0);
3996N/A }
3996N/A }
3996N/A
3996N/A private static String readAvailableString(Reader reader) throws IOException {
3996N/A return readAvailableString(reader, false);
3996N/A }
3996N/A
3996N/A private static String readAvailableString(Reader reader, boolean now) throws IOException {
3996N/A StringBuilder builder = new StringBuilder();
3996N/A int bytes;
3996N/A if (now && !reader.ready()) {
3996N/A return null;
3996N/A }
3996N/A do {
3996N/A char[] buf = new char[256];
3996N/A bytes = reader.read(buf);
3996N/A builder.append(buf, 0, bytes);
3996N/A } while (bytes == 256);
3996N/A return builder.toString();
3996N/A }
3996N/A
3996N/A private abstract static class ChatConnection implements Runnable {
3996N/A public Exception exception;
3996N/A
3996N/A @Override
3996N/A public void run() {
3996N/A try (Socket socket = new Socket("localhost", listeningPort);
3996N/A BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
3996N/A Writer writer = new FlushingWriter(new OutputStreamWriter(socket.getOutputStream()))) {
3996N/A socket.setTcpNoDelay(true);
3996N/A
3996N/A run(socket, reader, writer);
3996N/A } catch (Exception e) {
3996N/A exception = e;
3996N/A }
3996N/A }
3996N/A
3996N/A public abstract void run(Socket socket, BufferedReader reader, Writer writer) throws Exception;
3996N/A }
3996N/A
3996N/A private static class FlushingWriter extends Writer {
3996N/A public final Writer delegate;
3996N/A
3996N/A private FlushingWriter(Writer delegate) {
3996N/A this.delegate = delegate;
3996N/A }
3996N/A
3996N/A @Override
3996N/A public void write(char[] cbuf, int off, int len) throws IOException {
3996N/A delegate.write(cbuf, off, len);
3996N/A }
3996N/A
3996N/A @Override
3996N/A public void flush() throws IOException {
3996N/A delegate.flush();
3996N/A }
3996N/A
3996N/A @Override
3996N/A public void close() throws IOException {
3996N/A delegate.close();
3996N/A }
3996N/A
3996N/A @Override
3996N/A public void write(String str) throws IOException {
3996N/A super.write(str);
3996N/A flush();
3996N/A }
3996N/A }
3996N/A}