/* * Copyright (C) 2009 Google Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.waveprotocol.wave.examples.fedone.rpc; import com.google.protobuf.UnknownFieldSet; import junit.framework.TestCase; import org.waveprotocol.wave.examples.fedone.waveserver.WaveClientRpc; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.security.SecureRandom; import java.util.Random; /** * Test the SequencedProtoChannel. * * */ public class SequencedProtoChannelTest extends TestCase { private Random random = new SecureRandom(); private ClientServerPipe connection = null; /** * A convenient container class to generate and store a pair of SocketChannel * instances connected to each other. */ class ClientServerPipe { public final SocketChannel serverSocket; public final SocketChannel clientSocket; ClientServerPipe() throws IOException { ServerSocketChannel server; server = ServerSocketChannel.open(); server.socket().bind(null); clientSocket = SocketChannel.open(); clientSocket.connect(server.socket().getLocalSocketAddress()); serverSocket = server.accept(); assertTrue(clientSocket.finishConnect()); assertTrue(clientSocket.isConnected()); assertTrue(serverSocket.isConnected()); // Confirm that this socket is working properly! clientSocket.write(ByteBuffer.wrap(new byte[] {'a'})); ByteBuffer dsts = ByteBuffer.allocate(1); assertEquals(1, serverSocket.read(dsts)); assertEquals('a', dsts.get(0)); clientSocket.configureBlocking(true); serverSocket.configureBlocking(true); } } @Override public void setUp() throws Exception { super.setUp(); connection = new ClientServerPipe(); } @Override public void tearDown() throws Exception { connection = null; super.tearDown(); } /** * Test a faux-RPC style request/response interface passing messages between a * server and client. */ public void testRequestResponse() throws Exception { final int MESSAGE_TIMEOUT = 5; FakeProtoChannelManager clientManager = new FakeProtoChannelManager(connection.clientSocket); FakeProtoChannelManager serverManager = new FakeProtoChannelManager(connection.serverSocket); // Notify both the server and client of the messages they should expect. serverManager.channel.expectMessage(WaveClientRpc.ProtocolOpenRequest.getDefaultInstance()); clientManager.channel.expectMessage(WaveClientRpc.ProtocolWaveletUpdate.getDefaultInstance()); // Generate and send a client message to the server. WaveClientRpc.ProtocolOpenRequest clientMessage = WaveClientRpc.ProtocolOpenRequest.newBuilder().setParticipantId("sam@google.com") .setWaveId("foowave").build(); assertTrue(clientMessage.isInitialized()); clientManager.channel.sendMessage(0, clientMessage); // Confirm that the server has received this message. assertEquals(FakeProtoChannelManager.SequencedObject.of(0, clientMessage), serverManager.waitForMessage(MESSAGE_TIMEOUT)); // Generate and send a server message to the client. WaveClientRpc.ProtocolWaveletUpdate serverMessage = WaveClientRpc.ProtocolWaveletUpdate.newBuilder().setWaveletName("foowave").build(); assertTrue(serverMessage.isInitialized()); serverManager.channel.sendMessage(0, serverMessage); // Confirm that the client has received this message. assertEquals(FakeProtoChannelManager.SequencedObject.of(0, serverMessage), clientManager.waitForMessage(MESSAGE_TIMEOUT)); } /** * Test that multiple messages are passed over a SequencedProtoChannel. */ public void testMultipleMessages() throws Exception { final int MESSAGE_TIMEOUT = 5; final int MESSAGES_TO_SEND = random.nextInt(10) + 10; // between 10-20 messages FakeProtoChannelManager clientManager = new FakeProtoChannelManager(connection.clientSocket); FakeProtoChannelManager serverManager = new FakeProtoChannelManager(connection.serverSocket); // Notify the client of the message it should expect. clientManager.channel.expectMessage(WaveClientRpc.ProtocolWaveletUpdate.getDefaultInstance()); // Generate and send multiple server messages to the client. for (int m = 0; m < MESSAGES_TO_SEND; ++m) { WaveClientRpc.ProtocolWaveletUpdate serverMessage = WaveClientRpc.ProtocolWaveletUpdate.newBuilder().setWaveletName("wave_" + m).build(); assertTrue(serverMessage.isInitialized()); serverManager.channel.sendMessage(m, serverMessage); } // Confirm that all messages are received by the client. for (int m = 0; m < MESSAGES_TO_SEND; ++m) { FakeProtoChannelManager.SequencedObject<?> response = clientManager.waitForMessage(MESSAGE_TIMEOUT); assertNotNull("Couldn't get message number " + m + "/" + MESSAGES_TO_SEND, response); assertTrue(response.message instanceof WaveClientRpc.ProtocolWaveletUpdate); WaveClientRpc.ProtocolWaveletUpdate waveletUpdate = (WaveClientRpc.ProtocolWaveletUpdate) response.message; assertEquals("wave_" + m, waveletUpdate.getWaveletName()); } } /** * Test that an unknown message is received properly, and that the correct * callback is invoked. */ public void testUnknownMessage() throws Exception { final int MESSAGE_TIMEOUT = 5; FakeProtoChannelManager clientManager = new FakeProtoChannelManager(connection.clientSocket); FakeProtoChannelManager serverManager = new FakeProtoChannelManager(connection.serverSocket); // Generate standard message, pass from server to client - who has not had // this type registered. WaveClientRpc.ProtocolWaveletUpdate serverMessage = WaveClientRpc.ProtocolWaveletUpdate.newBuilder().setWaveletName("foowave").build(); assertTrue(serverMessage.isInitialized()); serverManager.channel.sendMessage(1, serverMessage); assertEquals(UnknownFieldSet.class, clientManager.waitForMessage(MESSAGE_TIMEOUT).message .getClass()); } }