blob: 694cd3d34fa91a99e690c0692e3e7fbcb3501255 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.
*/
#include "ServerSocketTest.h"
#include <decaf/net/Socket.h>
#include <decaf/net/ServerSocket.h>
#include <decaf/lang/System.h>
#include <decaf/lang/Thread.h>
using namespace decaf;
using namespace decaf::net;
using namespace decaf::io;
using namespace decaf::lang;
using namespace decaf::lang::exceptions;
////////////////////////////////////////////////////////////////////////////////
namespace {
class SocketClient : public Runnable {
public:
std::auto_ptr<Socket> clientS;
int port;
SocketClient(int port) : Runnable(), clientS(NULL), port(port) {
}
virtual void run() {
try {
Thread::sleep(1000);
this->clientS.reset(new Socket("127.0.0.1", port));
Thread::sleep(1000);
} catch (InterruptedException& ex) {
} catch (Exception& ex) {
ex.printStackTrace();
}
}
};
SocketClient* client = NULL;
}
////////////////////////////////////////////////////////////////////////////////
ServerSocketTest::ServerSocketTest() : ssconn(), theThread() {
}
////////////////////////////////////////////////////////////////////////////////
ServerSocketTest::~ServerSocketTest() {
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::setUp() {
this->ssconn = NULL;
this->theThread = NULL;
// Clear global client value
client = NULL;
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::tearDown() {
if( this->theThread != NULL ) {
this->theThread->join( 3000 );
}
delete this->theThread;
if( this->ssconn != NULL ) {
ssconn->close();
delete ssconn;
}
// Delete the global client if it exists.
delete client;
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testConstructor() {
try {
ServerSocket s( 0, 10 );
//s.setSoTimeout( 20000 );
startClient( s.getLocalPort() );
this->ssconn = s.accept();
this->ssconn->close();
} catch( InterruptedException& ex ) {
} catch( Exception& ex ) {
ex.printStackTrace();
throw ex;
}
try{
ServerSocket s1(0);
// No idea why but windows seems to let two sockets listen on the same port.
#ifndef WIN32
CPPUNIT_ASSERT_THROW_MESSAGE(
"Should throw an IOException",
ServerSocket s2( s1.getLocalPort() ),
IOException );
#endif
} catch( Exception& ex ) {
ex.printStackTrace();
throw ex;
}
ServerSocket s2(0);
int port = s2.getLocalPort();
s2.close();
ServerSocket s3( port );
s3.close();
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testClose() {
ServerSocket s(0);
s.close();
CPPUNIT_ASSERT_THROW_MESSAGE(
"Should throw an IOException",
s.accept(),
IOException );
}
////////////////////////////////////////////////////////////////////////////////
namespace{
class TestAcceptRunnable : public Runnable {
private:
bool* interrupted;
ServerSocket* ss;
private:
TestAcceptRunnable(const TestAcceptRunnable&);
TestAcceptRunnable& operator= (const TestAcceptRunnable&);
public:
TestAcceptRunnable(bool* interrupted, ServerSocket* ss) : interrupted(interrupted), ss(ss) {}
virtual void run() {
try{
std::auto_ptr<Socket> socket( ss->accept() );
} catch( IOException& ex ) {
*interrupted = true;
} catch(...) {
}
}
};
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testAccept() {
ServerSocket s(0);
try {
//s.setSoTimeout( 10000 );
startClient( s.getLocalPort() );
this->ssconn = s.accept();
int localPort1 = s.getLocalPort();
int localPort2 = this->ssconn->getLocalPort();
this->ssconn->close();
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Bad local port value", localPort1, localPort2 );
} catch(...) {
s.close();
}
// try {
// bool interrupted = false;
// ServerSocket ss(0);
// ss.setSoTimeout(12000);
// TestAcceptRunnable runnable( &interrupted, &ss );
// Thread thread( &runnable );
// thread.start();
//
// try {
// do {
// Thread::sleep( 500 );
// } while( !thread.isAlive() );
// } catch( InterruptedException& e ) {
// }
//
// ss.close();
//
// int c = 0;
// do {
// try {
// Thread::sleep( 500 );
// } catch( InterruptedException& e ) {
// }
//
// if( interrupted ) {
// CPPUNIT_FAIL( "accept interrupted" );
// }
// if( ++c > 4 ) {
// CPPUNIT_FAIL( "accept call did not exit" );
// }
// } while( thread.isAlive() );
//
// interrupted = false;
//
// ServerSocket ss2(0);
// ss2.setSoTimeout( 500 );
// long long start = System::currentTimeMillis();
//
// try {
// ss2.accept();
// } catch( IOException& e ) {
// interrupted = true;
// }
//
// CPPUNIT_ASSERT_MESSAGE( "accept not interrupted", interrupted );
// long long finish = System::currentTimeMillis();
// int delay = (int)( finish - start );
// CPPUNIT_ASSERT_MESSAGE( "timeout too soon: ", delay >= 490);
// ss2.close();
//
// } catch( IOException& e ) {
// CPPUNIT_FAIL( "Unexpected IOException : " + e.getMessage() );
// }
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testGetLocalPort() {
int port = 23232;
int actual = 0;
// Try the selected port, if it doesn't work don't complain just give up.
try{
ServerSocket s( port );
actual = s.getLocalPort();
} catch( IOException& ex ) {
return;
}
CPPUNIT_ASSERT_EQUAL( port, actual );
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testGetSoTimeout() {
ServerSocket s(0);
s.setSoTimeout( 100 );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "SO_TIMEOUT doesnt match what was set.", 100, s.getSoTimeout() );
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testGetReuseAddress() {
try{
ServerSocket s;
s.setReuseAddress( true );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Reuse Address doesnt match what was set.", true, s.getReuseAddress() );
s.setReuseAddress( false );
CPPUNIT_ASSERT_EQUAL_MESSAGE( "Reuse Address doesnt match what was set.", false, s.getReuseAddress() );
} catch( Exception& ex ) {
ex.printStackTrace();
throw ex;
}
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::testGetReceiveBufferSize() {
try{
ServerSocket s;
// CPPUNIT_ASSERT_MESSAGE( "Receive Buffer should never be zero.", 0 != s.getReceiveBufferSize() );
// CPPUNIT_ASSERT_MESSAGE( "Receive Buffer should never be negative.", 0 < s.getReceiveBufferSize() );
} catch( Exception& ex ) {
ex.printStackTrace();
throw ex;
}
}
////////////////////////////////////////////////////////////////////////////////
void ServerSocketTest::startClient( int port ) {
client = new SocketClient( port );
theThread = new Thread( client );
theThread->start();
try {
Thread::sleep( 1000 );
} catch( InterruptedException& e ) {
CPPUNIT_FAIL( std::string( "Exception during startClinet()" ) + e.getMessage() );
}
}