summaryrefslogtreecommitdiff
path: root/test/basicserver
diff options
context:
space:
mode:
authorReinhard Tartler <siretart@tauware.de>2007-02-14 09:01:45 +0100
committerReinhard Tartler <siretart@tauware.de>2007-02-14 09:01:45 +0100
commitaa2943800f9c00823720af98da036813ebf5cd2c (patch)
tree099cc0264d32a36ab89aa3f48cbf34612c3cd225 /test/basicserver
initial commit
Diffstat (limited to 'test/basicserver')
-rw-r--r--test/basicserver/Makefile.extra21
-rw-r--r--test/basicserver/TestCommands.cpp137
-rw-r--r--test/basicserver/TestContext.cpp54
-rw-r--r--test/basicserver/TestContext.h45
-rw-r--r--test/basicserver/testbasicserver.cpp667
-rw-r--r--test/basicserver/testfiles/clientCerts.pem14
-rw-r--r--test/basicserver/testfiles/clientPrivKey.pem15
-rw-r--r--test/basicserver/testfiles/clientReq.pem11
-rw-r--r--test/basicserver/testfiles/clientTrustedCAs.pem14
-rw-r--r--test/basicserver/testfiles/key-creation.txt83
-rw-r--r--test/basicserver/testfiles/root.pem29
-rw-r--r--test/basicserver/testfiles/root.srl1
-rw-r--r--test/basicserver/testfiles/rootcert.pem14
-rw-r--r--test/basicserver/testfiles/rootkey.pem15
-rw-r--r--test/basicserver/testfiles/rootreq.pem11
-rw-r--r--test/basicserver/testfiles/serverCerts.pem14
-rw-r--r--test/basicserver/testfiles/serverPrivKey.pem15
-rw-r--r--test/basicserver/testfiles/serverReq.pem11
-rw-r--r--test/basicserver/testfiles/serverTrustedCAs.pem14
-rw-r--r--test/basicserver/testfiles/srv1.conf6
-rw-r--r--test/basicserver/testfiles/srv1b.conf6
-rw-r--r--test/basicserver/testfiles/srv2.conf6
-rw-r--r--test/basicserver/testfiles/srv3.conf9
-rw-r--r--test/basicserver/testfiles/srv4.conf6
-rw-r--r--test/basicserver/testprotocol.txt42
25 files changed, 1260 insertions, 0 deletions
diff --git a/test/basicserver/Makefile.extra b/test/basicserver/Makefile.extra
new file mode 100644
index 00000000..51280db9
--- /dev/null
+++ b/test/basicserver/Makefile.extra
@@ -0,0 +1,21 @@
+
+MAKEPROTOCOL = ../../lib/server/makeprotocol.pl
+
+GEN_CMD_SRV = $(MAKEPROTOCOL) Server testprotocol.txt
+GEN_CMD_CLI = $(MAKEPROTOCOL) Client testprotocol.txt
+
+# AUTOGEN SEEDING
+autogen_TestProtocolServer.cpp: $(MAKEPROTOCOL) testprotocol.txt
+ perl $(GEN_CMD_SRV)
+
+autogen_TestProtocolServer.h: $(MAKEPROTOCOL) testprotocol.txt
+ perl $(GEN_CMD_SRV)
+
+
+# AUTOGEN SEEDING
+autogen_TestProtocolClient.cpp: $(MAKEPROTOCOL) testprotocol.txt
+ perl $(GEN_CMD_CLI)
+
+autogen_TestProtocolClient.h: $(MAKEPROTOCOL) testprotocol.txt
+ perl $(GEN_CMD_CLI)
+
diff --git a/test/basicserver/TestCommands.cpp b/test/basicserver/TestCommands.cpp
new file mode 100644
index 00000000..d879ff9d
--- /dev/null
+++ b/test/basicserver/TestCommands.cpp
@@ -0,0 +1,137 @@
+// distribution boxbackup-0.10 (svn version: 494)
+//
+// Copyright (c) 2003 - 2006
+// Ben Summers and contributors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. All use of this software and associated advertising materials must
+// display the following acknowledgment:
+// This product includes software developed by Ben Summers.
+// 4. The names of the Authors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// [Where legally impermissible the Authors do not disclaim liability for
+// direct physical injury or death caused solely by defects in the software
+// unless it is modified by a third party.]
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+//
+
+#include "Box.h"
+
+#include <syslog.h>
+
+#include "autogen_TestProtocolServer.h"
+#include "CollectInBufferStream.h"
+
+#include "MemLeakFindOn.h"
+
+
+std::auto_ptr<ProtocolObject> TestProtocolServerHello::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ if(mNumber32 != 41 || mNumber16 != 87 || mNumber8 != 11 || mText != "pingu")
+ {
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerError(0, 0));
+ }
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerHello(12,89,22,std::string("Hello world!")));
+}
+
+std::auto_ptr<ProtocolObject> TestProtocolServerLists::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerListsReply(mLotsOfText.size()));
+}
+
+std::auto_ptr<ProtocolObject> TestProtocolServerQuit::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerQuit);
+}
+
+std::auto_ptr<ProtocolObject> TestProtocolServerSimple::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerSimpleReply(mValue+1));
+}
+
+class UncertainBufferStream : public CollectInBufferStream
+{
+public:
+ // make the collect in buffer stream pretend not to know how many bytes are left
+ pos_type BytesLeftToRead()
+ {
+ return IOStream::SizeOfStreamUnknown;
+ }
+};
+
+std::auto_ptr<ProtocolObject> TestProtocolServerGetStream::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ // make a new stream object
+ CollectInBufferStream *pstream = mUncertainSize?(new UncertainBufferStream):(new CollectInBufferStream);
+
+ // Data.
+ int values[24273];
+ int v = mStartingValue;
+ for(int l = 0; l < 3; ++l)
+ {
+ for(int x = 0; x < 24273; ++x)
+ {
+ values[x] = v++;
+ }
+ pstream->Write(values, sizeof(values));
+ }
+
+ // Finished
+ pstream->SetForReading();
+
+ // Get it to be sent
+ rProtocol.SendStreamAfterCommand(pstream);
+
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerGetStream(mStartingValue, mUncertainSize));
+}
+
+std::auto_ptr<ProtocolObject> TestProtocolServerSendStream::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ if(mValue != 0x73654353298ffLL)
+ {
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerError(0, 0));
+ }
+
+ // Get a stream
+ std::auto_ptr<IOStream> stream(rProtocol.ReceiveStream());
+ bool uncertain = (stream->BytesLeftToRead() == IOStream::SizeOfStreamUnknown);
+
+ // Count how many bytes in it
+ int bytes = 0;
+ char buffer[125];
+ while(stream->StreamDataLeft())
+ {
+ bytes += stream->Read(buffer, sizeof(buffer));
+ }
+
+ // tell the caller how many bytes there were
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerGetStream(bytes, uncertain));
+}
+
+std::auto_ptr<ProtocolObject> TestProtocolServerString::DoCommand(TestProtocolServer &rProtocol, TestContext &rContext)
+{
+ return std::auto_ptr<ProtocolObject>(new TestProtocolServerString(mTest));
+}
+
diff --git a/test/basicserver/TestContext.cpp b/test/basicserver/TestContext.cpp
new file mode 100644
index 00000000..8c99dde7
--- /dev/null
+++ b/test/basicserver/TestContext.cpp
@@ -0,0 +1,54 @@
+// distribution boxbackup-0.10 (svn version: 494)
+//
+// Copyright (c) 2003 - 2006
+// Ben Summers and contributors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. All use of this software and associated advertising materials must
+// display the following acknowledgment:
+// This product includes software developed by Ben Summers.
+// 4. The names of the Authors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// [Where legally impermissible the Authors do not disclaim liability for
+// direct physical injury or death caused solely by defects in the software
+// unless it is modified by a third party.]
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+//
+
+#include "Box.h"
+#include "Test.h"
+#include "TestContext.h"
+
+#include "MemLeakFindOn.h"
+
+TestContext::TestContext()
+{
+}
+
+TestContext::~TestContext()
+{
+}
+
+
diff --git a/test/basicserver/TestContext.h b/test/basicserver/TestContext.h
new file mode 100644
index 00000000..27663e95
--- /dev/null
+++ b/test/basicserver/TestContext.h
@@ -0,0 +1,45 @@
+// distribution boxbackup-0.10 (svn version: 494)
+//
+// Copyright (c) 2003 - 2006
+// Ben Summers and contributors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. All use of this software and associated advertising materials must
+// display the following acknowledgment:
+// This product includes software developed by Ben Summers.
+// 4. The names of the Authors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// [Where legally impermissible the Authors do not disclaim liability for
+// direct physical injury or death caused solely by defects in the software
+// unless it is modified by a third party.]
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+//
+
+class TestContext
+{
+public:
+ TestContext();
+ ~TestContext();
+};
diff --git a/test/basicserver/testbasicserver.cpp b/test/basicserver/testbasicserver.cpp
new file mode 100644
index 00000000..9045b34b
--- /dev/null
+++ b/test/basicserver/testbasicserver.cpp
@@ -0,0 +1,667 @@
+// distribution boxbackup-0.10 (svn version: 494)
+//
+// Copyright (c) 2003 - 2006
+// Ben Summers and contributors. All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+// 3. All use of this software and associated advertising materials must
+// display the following acknowledgment:
+// This product includes software developed by Ben Summers.
+// 4. The names of the Authors may not be used to endorse or promote
+// products derived from this software without specific prior written
+// permission.
+//
+// [Where legally impermissible the Authors do not disclaim liability for
+// direct physical injury or death caused solely by defects in the software
+// unless it is modified by a third party.]
+//
+// THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR
+// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY DIRECT,
+// INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+// ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+// POSSIBILITY OF SUCH DAMAGE.
+//
+//
+//
+// --------------------------------------------------------------------------
+//
+// File
+// Name: testbasicserver.cpp
+// Purpose: Test basic server classes
+// Created: 2003/07/29
+//
+// --------------------------------------------------------------------------
+
+
+#include "Box.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+#include <typeinfo>
+
+#include "Test.h"
+#include "Daemon.h"
+#include "Configuration.h"
+#include "ServerStream.h"
+#include "SocketStream.h"
+#include "IOStreamGetLine.h"
+#include "ServerTLS.h"
+#include "CollectInBufferStream.h"
+
+#include "TestContext.h"
+#include "autogen_TestProtocolClient.h"
+#include "autogen_TestProtocolServer.h"
+
+#include "MemLeakFindOn.h"
+
+
+#define SERVER_LISTEN_PORT 2003
+
+// in ms
+#define COMMS_READ_TIMEOUT 4
+#define COMMS_SERVER_WAIT_BEFORE_REPLYING 40
+
+class basicdaemon : public Daemon
+{
+public:
+basicdaemon() {};
+~basicdaemon() {}
+virtual void Run();
+};
+
+void basicdaemon::Run()
+{
+ // Write a file to check it's done...
+ const Configuration &c(GetConfiguration());
+
+ FILE *f = fopen(c.GetKeyValue("TestFile").c_str(), "w");
+ fclose(f);
+
+ while(!StopRun())
+ {
+ ::sleep(10);
+ }
+}
+
+void testservers_pause_before_reply()
+{
+ struct timespec t;
+ t.tv_sec = 0;
+ t.tv_nsec = COMMS_SERVER_WAIT_BEFORE_REPLYING * 1000 * 1000; // convert to ns
+ ::nanosleep(&t, NULL);
+}
+
+#define LARGE_DATA_BLOCK_SIZE 19870
+#define LARGE_DATA_SIZE (LARGE_DATA_BLOCK_SIZE*1000)
+
+void testservers_connection(SocketStream &rStream)
+{
+ IOStreamGetLine getline(rStream);
+
+ if(typeid(rStream) == typeid(SocketStreamTLS))
+ {
+ // need to wait for some data before sending stuff, otherwise timeout test doesn't work
+ std::string line;
+ while(!getline.GetLine(line))
+ ;
+ SocketStreamTLS &rtls = (SocketStreamTLS&)rStream;
+ std::string line1("CONNECTED:");
+ line1 += rtls.GetPeerCommonName();
+ line1 += '\n';
+ testservers_pause_before_reply();
+ rStream.Write(line1.c_str(), line1.size());
+ }
+
+ while(!getline.IsEOF())
+ {
+ std::string line;
+ while(!getline.GetLine(line))
+ ;
+ if(line == "QUIT")
+ {
+ break;
+ }
+ if(line == "LARGEDATA")
+ {
+ {
+ // Send lots of data
+ char data[LARGE_DATA_BLOCK_SIZE];
+ for(unsigned int y = 0; y < sizeof(data); y++)
+ {
+ data[y] = y & 0xff;
+ }
+ for(int s = 0; s < (LARGE_DATA_SIZE / LARGE_DATA_BLOCK_SIZE); ++s)
+ {
+ rStream.Write(data, sizeof(data));
+ }
+ }
+ {
+ // Receive lots of data
+ char buf[1024];
+ int total = 0;
+ int r = 0;
+ while(total < LARGE_DATA_SIZE && (r = rStream.Read(buf, sizeof(buf))) != 0)
+ {
+ total += r;
+ }
+ TEST_THAT(total == LARGE_DATA_SIZE);
+ }
+
+ // next!
+ continue;
+ }
+ std::string backwards;
+ for(std::string::const_reverse_iterator i(line.end()); i != std::string::const_reverse_iterator(line.begin()); ++i)
+ {
+ backwards += (*i);
+ }
+ backwards += '\n';
+ testservers_pause_before_reply();
+ rStream.Write(backwards.c_str(), backwards.size());
+ }
+ rStream.Shutdown();
+ rStream.Close();
+}
+
+
+
+class testserver : public ServerStream<SocketStream, SERVER_LISTEN_PORT>
+{
+public:
+ testserver() {}
+ ~testserver() {}
+
+ void Connection(SocketStream &rStream);
+
+ virtual const char *DaemonName() const
+ {
+ return "test-srv2";
+ }
+ const ConfigurationVerify *GetConfigVerify() const;
+
+};
+
+const ConfigurationVerify *testserver::GetConfigVerify() const
+{
+ static ConfigurationVerifyKey verifyserverkeys[] =
+ {
+ SERVERSTREAM_VERIFY_SERVER_KEYS(0) // no default addresses
+ };
+
+ static ConfigurationVerify verifyserver[] =
+ {
+ {
+ "Server",
+ 0,
+ verifyserverkeys,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ }
+ };
+
+ static ConfigurationVerify verify =
+ {
+ "root",
+ verifyserver,
+ 0,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ };
+
+ return &verify;
+}
+
+void testserver::Connection(SocketStream &rStream)
+{
+ testservers_connection(rStream);
+}
+
+class testProtocolServer : public testserver
+{
+public:
+ testProtocolServer() {}
+ ~testProtocolServer() {}
+
+ void Connection(SocketStream &rStream);
+
+ virtual const char *DaemonName() const
+ {
+ return "test-srv4";
+ }
+};
+
+void testProtocolServer::Connection(SocketStream &rStream)
+{
+ TestProtocolServer server(rStream);
+ TestContext context;
+ server.DoServer(context);
+}
+
+
+class testTLSserver : public ServerTLS<SERVER_LISTEN_PORT>
+{
+public:
+ testTLSserver() {}
+ ~testTLSserver() {}
+
+ void Connection(SocketStreamTLS &rStream);
+
+ virtual const char *DaemonName() const
+ {
+ return "test-srv3";
+ }
+ const ConfigurationVerify *GetConfigVerify() const;
+
+};
+
+const ConfigurationVerify *testTLSserver::GetConfigVerify() const
+{
+ static ConfigurationVerifyKey verifyserverkeys[] =
+ {
+ SERVERTLS_VERIFY_SERVER_KEYS(0) // no default listen addresses
+ };
+
+ static ConfigurationVerify verifyserver[] =
+ {
+ {
+ "Server",
+ 0,
+ verifyserverkeys,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ }
+ };
+
+ static ConfigurationVerify verify =
+ {
+ "root",
+ verifyserver,
+ 0,
+ ConfigTest_Exists | ConfigTest_LastEntry,
+ 0
+ };
+
+ return &verify;
+}
+
+void testTLSserver::Connection(SocketStreamTLS &rStream)
+{
+ testservers_connection(rStream);
+}
+
+
+void Srv2TestConversations(const std::vector<IOStream *> &conns)
+{
+ const static char *tosend[] = {
+ "test 1\n", "carrots\n", "pineapples\n", "booo!\n", 0
+ };
+ const static char *recieve[] = {
+ "1 tset", "storrac", "selppaenip", "!ooob", 0
+ };
+
+ IOStreamGetLine **getline = new IOStreamGetLine*[conns.size()];
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ getline[c] = new IOStreamGetLine(*conns[c]);
+
+ bool hadTimeout = false;
+ if(typeid(*conns[c]) == typeid(SocketStreamTLS))
+ {
+ SocketStreamTLS *ptls = (SocketStreamTLS *)conns[c];
+ printf("Connected to '%s'\n", ptls->GetPeerCommonName().c_str());
+
+ // Send some data, any data, to get the first response.
+ conns[c]->Write("Hello\n", 6);
+
+ std::string line1;
+ while(!getline[c]->GetLine(line1, false, COMMS_READ_TIMEOUT))
+ hadTimeout = true;
+ TEST_THAT(line1 == "CONNECTED:CLIENT");
+ TEST_THAT(hadTimeout)
+ }
+ }
+
+ for(int q = 0; tosend[q] != 0; ++q)
+ {
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ //printf("%d: %s", c, tosend[q]);
+ conns[c]->Write(tosend[q], strlen(tosend[q]));
+ std::string rep;
+ bool hadTimeout = false;
+ while(!getline[c]->GetLine(rep, false, COMMS_READ_TIMEOUT))
+ hadTimeout = true;
+ TEST_THAT(rep == recieve[q]);
+ TEST_THAT(hadTimeout)
+ }
+ }
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ conns[c]->Write("LARGEDATA\n", 10);
+ }
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ // Receive lots of data
+ char buf[1024];
+ int total = 0;
+ int r = 0;
+ while(total < LARGE_DATA_SIZE && (r = conns[c]->Read(buf, sizeof(buf))) != 0)
+ {
+ total += r;
+ }
+ TEST_THAT(total == LARGE_DATA_SIZE);
+ }
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ // Send lots of data
+ char data[LARGE_DATA_BLOCK_SIZE];
+ for(unsigned int y = 0; y < sizeof(data); y++)
+ {
+ data[y] = y & 0xff;
+ }
+ for(int s = 0; s < (LARGE_DATA_SIZE / LARGE_DATA_BLOCK_SIZE); ++s)
+ {
+ conns[c]->Write(data, sizeof(data));
+ }
+ }
+
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ conns[c]->Write("QUIT\n", 5);
+ }
+
+ for(unsigned int c = 0; c < conns.size(); ++c)
+ {
+ if ( getline[c] ) delete getline[c];
+ getline[c] = 0;
+ }
+ if ( getline ) delete [] getline;
+ getline = 0;
+}
+
+void TestStreamReceive(TestProtocolClient &protocol, int value, bool uncertainstream)
+{
+ std::auto_ptr<TestProtocolClientGetStream> reply(protocol.QueryGetStream(value, uncertainstream));
+ TEST_THAT(reply->GetStartingValue() == value);
+
+ // Get a stream
+ std::auto_ptr<IOStream> stream(protocol.ReceiveStream());
+
+ // check uncertainty
+ TEST_THAT(uncertainstream == (stream->BytesLeftToRead() == IOStream::SizeOfStreamUnknown));
+
+ printf("stream is %s\n", uncertainstream?"uncertain size":"fixed size");
+
+ // Then check the contents
+ int values[998];
+ int v = value;
+ int count = 0;
+ int bytesleft = 0;
+ int bytessofar = 0;
+ while(stream->StreamDataLeft())
+ {
+ // Read some data
+ int bytes = stream->Read(((char*)values) + bytesleft, sizeof(values) - bytesleft);
+ bytessofar += bytes;
+ bytes += bytesleft;
+ int n = bytes / 4;
+ //printf("read %d, n = %d, so far = %d\n", bytes, n, bytessofar);
+ for(int t = 0; t < n; ++t)
+ {
+ if(values[t] != v) printf("%d, %d, %d\n", t, values[t], v);
+ TEST_THAT(values[t] == v++);
+ }
+ count += n;
+ bytesleft = bytes - (n*4);
+ if(bytesleft) ::memmove(values, ((char*)values) + bytes - bytesleft, bytesleft);
+ }
+
+ TEST_THAT(bytesleft == 0);
+ TEST_THAT(count == (24273*3)); // over 64 k of data, definately
+}
+
+
+int test(int argc, const char *argv[])
+{
+ // Server launching stuff
+ if(argc >= 2)
+ {
+ if(strcmp(argv[1], "srv1") == 0)
+ {
+ // Run very basic daemon
+ basicdaemon daemon;
+ return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ }
+ else if(strcmp(argv[1], "srv2") == 0)
+ {
+ // Run daemon which accepts connections
+ testserver daemon;
+ return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ }
+ else if(strcmp(argv[1], "srv3") == 0)
+ {
+ testTLSserver daemon;
+ return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ }
+ else if(strcmp(argv[1], "srv4") == 0)
+ {
+ testProtocolServer daemon;
+ return daemon.Main("doesnotexist", argc - 1, argv + 1);
+ }
+ }
+
+//printf("SKIPPING TESTS------------------------\n");
+//goto protocolserver;
+
+ // Launch a basic server
+ {
+ int pid = LaunchServer("./test srv1 testfiles/srv1.conf", "testfiles/srv1.pid");
+ TEST_THAT(pid != -1 && pid != 0);
+ if(pid > 0)
+ {
+ // Check that it's written the expected file
+ TEST_THAT(TestFileExists("testfiles/srv1.test1"));
+ TEST_THAT(ServerIsAlive(pid));
+ // Move the config file over
+ TEST_THAT(::rename("testfiles/srv1b.conf", "testfiles/srv1.conf") != -1);
+ // Get it to reread the config file
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Check that new file exists
+ TEST_THAT(TestFileExists("testfiles/srv1.test2"));
+ // Kill it off
+ TEST_THAT(KillServer(pid));
+ TestRemoteProcessMemLeaks("generic-daemon.memleaks");
+ }
+ }
+
+ // Launch a test forking server
+ {
+ int pid = LaunchServer("./test srv2 testfiles/srv2.conf", "testfiles/srv2.pid");
+ TEST_THAT(pid != -1 && pid != 0);
+ if(pid > 0)
+ {
+ // Will it restart?
+ TEST_THAT(ServerIsAlive(pid));
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Make some connections
+ {
+ SocketStream conn1;
+ conn1.Open(Socket::TypeINET, "localhost", 2003);
+ SocketStream conn2;
+ conn2.Open(Socket::TypeUNIX, "testfiles/srv2.sock");
+ SocketStream conn3;
+ conn3.Open(Socket::TypeINET, "localhost", 2003);
+ // Quick check that reconnections fail
+ TEST_CHECK_THROWS(conn1.Open(Socket::TypeUNIX, "testfiles/srv2.sock");, ServerException, SocketAlreadyOpen);
+ // Stuff some data around
+ std::vector<IOStream *> conns;
+ conns.push_back(&conn1);
+ conns.push_back(&conn2);
+ conns.push_back(&conn3);
+ Srv2TestConversations(conns);
+ // Implicit close
+ }
+ // HUP again
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Kill it
+ TEST_THAT(KillServer(pid));
+ ::sleep(1);
+ TEST_THAT(!ServerIsAlive(pid));
+ TestRemoteProcessMemLeaks("test-srv2.memleaks");
+ }
+ }
+
+ // Launch a test SSL server
+ {
+ int pid = LaunchServer("./test srv3 testfiles/srv3.conf", "testfiles/srv3.pid");
+ TEST_THAT(pid != -1 && pid != 0);
+ if(pid > 0)
+ {
+ // Will it restart?
+ TEST_THAT(ServerIsAlive(pid));
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Make some connections
+ {
+ // SSL library
+ SSLLib::Initialise();
+
+ // Context first
+ TLSContext context;
+ context.Initialise(false /* client */,
+ "testfiles/clientCerts.pem",
+ "testfiles/clientPrivKey.pem",
+ "testfiles/clientTrustedCAs.pem");
+
+ SocketStreamTLS conn1;
+ conn1.Open(context, Socket::TypeINET, "localhost", 2003);
+ SocketStreamTLS conn2;
+ conn2.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");
+ SocketStreamTLS conn3;
+ conn3.Open(context, Socket::TypeINET, "localhost", 2003);
+ // Quick check that reconnections fail
+ TEST_CHECK_THROWS(conn1.Open(context, Socket::TypeUNIX, "testfiles/srv3.sock");, ServerException, SocketAlreadyOpen);
+ // Stuff some data around
+ std::vector<IOStream *> conns;
+ conns.push_back(&conn1);
+ conns.push_back(&conn2);
+ conns.push_back(&conn3);
+ Srv2TestConversations(conns);
+ // Implicit close
+ }
+ // HUP again
+ TEST_THAT(HUPServer(pid));
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+ // Kill it
+ TEST_THAT(KillServer(pid));
+ ::sleep(1);
+ TEST_THAT(!ServerIsAlive(pid));
+ TestRemoteProcessMemLeaks("test-srv3.memleaks");
+ }
+ }
+
+//protocolserver:
+ // Launch a test protocol handling server
+ {
+ int pid = LaunchServer("./test srv4 testfiles/srv4.conf", "testfiles/srv4.pid");
+ TEST_THAT(pid != -1 && pid != 0);
+ if(pid > 0)
+ {
+ ::sleep(1);
+ TEST_THAT(ServerIsAlive(pid));
+
+ // Open a connection to it
+ SocketStream conn;
+ conn.Open(Socket::TypeUNIX, "testfiles/srv4.sock");
+
+ // Create a protocol
+ TestProtocolClient protocol(conn);
+
+ // Simple query
+ {
+ std::auto_ptr<TestProtocolClientSimpleReply> reply(protocol.QuerySimple(41));
+ TEST_THAT(reply->GetValuePlusOne() == 42);
+ }
+ {
+ std::auto_ptr<TestProtocolClientSimpleReply> reply(protocol.QuerySimple(809));
+ TEST_THAT(reply->GetValuePlusOne() == 810);
+ }
+
+ // Streams, twice, both uncertain and certain sizes
+ TestStreamReceive(protocol, 374, false);
+ TestStreamReceive(protocol, 23983, true);
+ TestStreamReceive(protocol, 12098, false);
+ TestStreamReceive(protocol, 4342, true);
+
+ // Try to send a stream
+ {
+ CollectInBufferStream s;
+ char buf[1663];
+ s.Write(buf, sizeof(buf));
+ s.SetForReading();
+ std::auto_ptr<TestProtocolClientGetStream> reply(protocol.QuerySendStream(0x73654353298ffLL, s));
+ TEST_THAT(reply->GetStartingValue() == sizeof(buf));
+ }
+
+ // Lots of simple queries
+ for(int q = 0; q < 514; q++)
+ {
+ std::auto_ptr<TestProtocolClientSimpleReply> reply(protocol.QuerySimple(q));
+ TEST_THAT(reply->GetValuePlusOne() == (q+1));
+ }
+ // Send a list of strings to it
+ {
+ std::vector<std::string> strings;
+ strings.push_back(std::string("test1"));
+ strings.push_back(std::string("test2"));
+ strings.push_back(std::string("test3"));
+ std::auto_ptr<TestProtocolClientListsReply> reply(protocol.QueryLists(strings));
+ TEST_THAT(reply->GetNumberOfStrings() == 3);
+ }
+
+ // And another
+ {
+ std::auto_ptr<TestProtocolClientHello> reply(protocol.QueryHello(41,87,11,std::string("pingu")));
+ TEST_THAT(reply->GetNumber32() == 12);
+ TEST_THAT(reply->GetNumber16() == 89);
+ TEST_THAT(reply->GetNumber8() == 22);
+ TEST_THAT(reply->GetText() == "Hello world!");
+ }
+
+ // Quit query to finish
+ protocol.QueryQuit();
+
+ // Kill it
+ TEST_THAT(KillServer(pid));
+ ::sleep(1);
+ TEST_THAT(!ServerIsAlive(pid));
+ TestRemoteProcessMemLeaks("test-srv4.memleaks");
+ }
+ }
+
+ return 0;
+}
+
diff --git a/test/basicserver/testfiles/clientCerts.pem b/test/basicserver/testfiles/clientCerts.pem
new file mode 100644
index 00000000..81d4c5cc
--- /dev/null
+++ b/test/basicserver/testfiles/clientCerts.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICOTCCAaICAQUwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNDQz
+WhcNMzEwMTIyMTYyNDQzWjBmMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjEPMA0GA1UEAxMGQ0xJRU5UMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQC7AJDQJdGHi4HO7VXZJdi/3C8rQx1uTxMO6QHBFep0wQZ6I37Zcr+TRrHk
+Q8CelymIBx2ZfQXMLKsoB8FScIp0zIT/drK0AghuWE5UPU6dntPlrA65y417qk5z
+NjiOy6coWl+7ktZ0ItCuy7VHWrTmHRbNZeXKub7fjuccDJdiywIDAQABMA0GCSqG
+SIb3DQEBBQUAA4GBACYkSYlrKNv1v6lrES4j68S8u8SNlnSM+Z4pTHF/7K7SQeIn
+SKVV8EI8CLR5jIsQRRHKB9rYgYS4kB8SFbPyrsH8VKngjIUcjmTKLq9zpAt2zDNo
+m+y5SMXsaJF6Xbtbz+MSxXZZ6YBBuseY+Wkpz4ZGSVlQrHxjsuYdBFHIguM3
+-----END CERTIFICATE-----
diff --git a/test/basicserver/testfiles/clientPrivKey.pem b/test/basicserver/testfiles/clientPrivKey.pem
new file mode 100644
index 00000000..a4797b66
--- /dev/null
+++ b/test/basicserver/testfiles/clientPrivKey.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQC7AJDQJdGHi4HO7VXZJdi/3C8rQx1uTxMO6QHBFep0wQZ6I37Z
+cr+TRrHkQ8CelymIBx2ZfQXMLKsoB8FScIp0zIT/drK0AghuWE5UPU6dntPlrA65
+y417qk5zNjiOy6coWl+7ktZ0ItCuy7VHWrTmHRbNZeXKub7fjuccDJdiywIDAQAB
+AoGAF92enbH158KaMnp/tlLqMrI7It5R5z4YRJLgMnBFl9j6pqPZEI9ge79N/L/Y
+2WSZXE7sLCaUktYwkc9LkOXkBYQI7EIOonLdmSsNCMbSBVbeczdM77dBscuCTKva
+nvre/2+hlmuWBNINqXlprBkvd5YF4Q/yeXzoXPuMIQ0tROECQQDqifOZOfCle8uA
+CgdHT9pO638PwrrldMHmZSK3gUmHmFe7ziGpNGCfKZ+wkSIvDg9INQvEXvQfLZiV
+n4J78IOHAkEAzB0SoUU0cL+wK3OQTTOlx4cgxaxgtsuvccIhqTh4Jp1Aj9iMKiPW
+yXvbGhDBTZP2IL5HoqSLc3SxfXgvn6O/nQJBALgJMYWdalBf2GoK9HUnmpTsw1I5
+qe/c8z13RIubvnfQuZ8be1xLRjn+LlkdOSaVMLanMSmQnJxOafmWJYxdSMcCQFBc
+5ffe8n2tyyPgdSEgQ5YiatHJQ67U1Te50lz44b16TnAUN2NkBu3/OM2zaRgtOEu9
+/yBXHpyPhk47Iqz84LUCQQCIDIKluoughLVjJS2eD28UJHM9Z+OvmyIE0fF0Q0vi
+E+Rn/+iWCoEJYa7WP5AEo/aeVXiCeHONXGF1AI8a8gb5
+-----END RSA PRIVATE KEY-----
diff --git a/test/basicserver/testfiles/clientReq.pem b/test/basicserver/testfiles/clientReq.pem
new file mode 100644
index 00000000..14e2c6df
--- /dev/null
+++ b/test/basicserver/testfiles/clientReq.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBpjCCAQ8CAQAwZjELMAkGA1UEBhMCR0IxDzANBgNVBAgTBkxvbmRvbjEPMA0G
+A1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYDVQQLEwxiYXNpYyBzZXJ2
+ZXIxDzANBgNVBAMTBkNMSUVOVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+uwCQ0CXRh4uBzu1V2SXYv9wvK0Mdbk8TDukBwRXqdMEGeiN+2XK/k0ax5EPAnpcp
+iAcdmX0FzCyrKAfBUnCKdMyE/3aytAIIblhOVD1OnZ7T5awOucuNe6pOczY4jsun
+KFpfu5LWdCLQrsu1R1q05h0WzWXlyrm+347nHAyXYssCAwEAAaAAMA0GCSqGSIb3
+DQEBBQUAA4GBAKV3H/yWrYep6yfEDQp61zn60tEnJOS5LVbuV7ivNjAue0/09wBT
+PGzTblwx116AT9GbTcbERK/ll549+tziTLT9NUT12ZcvaRezYP2PpaD8fiDKHs3D
+vSwpFoihLmUnDeMWE9Vbt+b0Fl/mdsH6sm3Mo0COG/DkolOVsydOj2Hp
+-----END CERTIFICATE REQUEST-----
diff --git a/test/basicserver/testfiles/clientTrustedCAs.pem b/test/basicserver/testfiles/clientTrustedCAs.pem
new file mode 100644
index 00000000..d72b70e5
--- /dev/null
+++ b/test/basicserver/testfiles/clientTrustedCAs.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaACAQAwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNDA4
+WhcNMzEwMTIyMTYyNDA4WjBkMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjENMAsGA1UEAxMEUk9PVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzGFyfiCNApPYnK8A3hspnWdwIe0Tpgt9i6Ut7EFXIUHe+djuLYMk1D+neO6y
+3TNsbFY3UR3m/QA/g1a8wzUVq7T2MUDMoz4V8HkM/48MQMlUHcmBCFJHnGAL1g8K
+bfX+sxeSKXKurnZMbRNyRwp0d9RDltQnHLfqcoPCgYI95FMCAwEAATANBgkqhkiG
+9w0BAQUFAAOBgQDIAhGUvs47CQeKiF6GDxFfSseCk6UWB1lFe154ZpexgMTp8Dgu
+leJOvnZPmkywovIcxr2YZAM33e+3+rKDJEy9PJ9mGLsrZMHSi4v3U0e9bBDGCkKH
+1sSrbEGIc02HIo8m3PGUdrNJ8GNJdcYUghtoZbe01sIqVmWWLA8XXDQmOQ==
+-----END CERTIFICATE-----
diff --git a/test/basicserver/testfiles/key-creation.txt b/test/basicserver/testfiles/key-creation.txt
new file mode 100644
index 00000000..51f4eb77
--- /dev/null
+++ b/test/basicserver/testfiles/key-creation.txt
@@ -0,0 +1,83 @@
+$ openssl genrsa -out rootkey.pem 1024
+
+$ openssl req -new -key rootkey.pem -sha1 -out rootreq.pem
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) []:GB
+State or Province Name (full name) []:London
+Locality Name (eg, city) []:London
+Organization Name (eg, company) []:Test
+Organizational Unit Name (eg, section) []:basic server
+Common Name (eg, fully qualified host name) []:ROOT
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+
+$ openssl x509 -req -in rootreq.pem -sha1 -extensions v3_ca -signkey rootkey.pem -out rootcert.pem -days 10000
+Signature ok
+subject=/C=GB/ST=London/L=London/O=Test/OU=basic server/CN=ROOT
+Getting Private key
+
+$ cp rootcert.pem serverTrustedCAs.pem
+$ cp rootcert.pem clientTrustedCAs.pem
+
+$ openssl genrsa -out clientPrivKey.pem 1024
+$ openssl req -new -key clientPrivKey.pem -sha1 -out clientReq.pem
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) []:GB
+State or Province Name (full name) []:London
+Locality Name (eg, city) []:London
+Organization Name (eg, company) []:Test
+Organizational Unit Name (eg, section) []:basic server
+Common Name (eg, fully qualified host name) []:CLIENT
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+
+$ cat rootcert.pem rootkey.pem > root.pem
+
+$ echo 01 > root.srl
+
+$ openssl x509 -req -in clientReq.pem -sha1 -extensions usr_crt -CA root.pem -CAkey root.pem -out clientCerts.pem -days 10000
+
+$ openssl genrsa -out serverPrivKey.pem 1024
+$ openssl req -new -key serverPrivKey.pem -sha1 -out serverReq.pem
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+-----
+Country Name (2 letter code) []:GB
+State or Province Name (full name) []:London
+Locality Name (eg, city) []:London
+Organization Name (eg, company) []:Test
+Organizational Unit Name (eg, section) []:basic server
+Common Name (eg, fully qualified host name) []:SERVER
+Email Address []:
+
+Please enter the following 'extra' attributes
+to be sent with your certificate request
+A challenge password []:
+An optional company name []:
+
+$ openssl x509 -req -in serverReq.pem -sha1 -extensions usr_crt -CA root.pem -CAkey root.pem -out serverCerts.pem -days 10000
+
diff --git a/test/basicserver/testfiles/root.pem b/test/basicserver/testfiles/root.pem
new file mode 100644
index 00000000..020c25c3
--- /dev/null
+++ b/test/basicserver/testfiles/root.pem
@@ -0,0 +1,29 @@
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaACAQAwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNDA4
+WhcNMzEwMTIyMTYyNDA4WjBkMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjENMAsGA1UEAxMEUk9PVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzGFyfiCNApPYnK8A3hspnWdwIe0Tpgt9i6Ut7EFXIUHe+djuLYMk1D+neO6y
+3TNsbFY3UR3m/QA/g1a8wzUVq7T2MUDMoz4V8HkM/48MQMlUHcmBCFJHnGAL1g8K
+bfX+sxeSKXKurnZMbRNyRwp0d9RDltQnHLfqcoPCgYI95FMCAwEAATANBgkqhkiG
+9w0BAQUFAAOBgQDIAhGUvs47CQeKiF6GDxFfSseCk6UWB1lFe154ZpexgMTp8Dgu
+leJOvnZPmkywovIcxr2YZAM33e+3+rKDJEy9PJ9mGLsrZMHSi4v3U0e9bBDGCkKH
+1sSrbEGIc02HIo8m3PGUdrNJ8GNJdcYUghtoZbe01sIqVmWWLA8XXDQmOQ==
+-----END CERTIFICATE-----
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDMYXJ+II0Ck9icrwDeGymdZ3Ah7ROmC32LpS3sQVchQd752O4t
+gyTUP6d47rLdM2xsVjdRHeb9AD+DVrzDNRWrtPYxQMyjPhXweQz/jwxAyVQdyYEI
+UkecYAvWDwpt9f6zF5Ipcq6udkxtE3JHCnR31EOW1Ccct+pyg8KBgj3kUwIDAQAB
+AoGAFsGO3u4+5ReTGbb+kLxTgNwghxZ/hpBm9SJ6H4ES83gDHKyDsHuWoS9JNVTW
+g3yTSOi8lgKPUoIxkC0bLVz+wYF0UWysOzhxbTqq43CdJM/HDuHbFGHs2MAKyvdm
+ai7ccJMISDATN6XT7BLRBE5AAVqDhNllvmr92niZS51yzJECQQD4LQWdK9IUjsja
+pYEeQKZENmC2pstAVYDyd3wuXaE8wiiTG86L/5zVRfEVpbD3rKPZVjcZKx+VZoIw
+iyW9WntbAkEA0tL2fSeBC1V9Jcj8TOuMmEaoPMclJLUBDLJPxFmHCguwvcH8cgTb
+Nr08FFqz62gZxudcrl5nISw3G0Rm3UGkaQJALRfhIUHJFjsre67+2wRcMaC/yfBc
+lf/zQhs70SDqHyQYQ0KWMRHs6UOgHpLQqPARhXgI4uXXA0pw9WkTHmjGaQJBAJ1x
+fTEkQmPjeS2xtnH/ayUBh3y0QJH0Nw9zTszVC1s+NcTQzSWdaNStZ+PPhRQlzzJS
+8E0sJRqJ+bF8WNGdxxkCQQCTpEUpqsVykhucZ3GsCTlI4o3HNmYFarKDDEHgppLS
+GKoUzTX2UMPJgeRITwacIh3lFhAily2PMFmlF+B7b5ep
+-----END RSA PRIVATE KEY-----
diff --git a/test/basicserver/testfiles/root.srl b/test/basicserver/testfiles/root.srl
new file mode 100644
index 00000000..2c7456e3
--- /dev/null
+++ b/test/basicserver/testfiles/root.srl
@@ -0,0 +1 @@
+07
diff --git a/test/basicserver/testfiles/rootcert.pem b/test/basicserver/testfiles/rootcert.pem
new file mode 100644
index 00000000..d72b70e5
--- /dev/null
+++ b/test/basicserver/testfiles/rootcert.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaACAQAwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNDA4
+WhcNMzEwMTIyMTYyNDA4WjBkMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjENMAsGA1UEAxMEUk9PVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzGFyfiCNApPYnK8A3hspnWdwIe0Tpgt9i6Ut7EFXIUHe+djuLYMk1D+neO6y
+3TNsbFY3UR3m/QA/g1a8wzUVq7T2MUDMoz4V8HkM/48MQMlUHcmBCFJHnGAL1g8K
+bfX+sxeSKXKurnZMbRNyRwp0d9RDltQnHLfqcoPCgYI95FMCAwEAATANBgkqhkiG
+9w0BAQUFAAOBgQDIAhGUvs47CQeKiF6GDxFfSseCk6UWB1lFe154ZpexgMTp8Dgu
+leJOvnZPmkywovIcxr2YZAM33e+3+rKDJEy9PJ9mGLsrZMHSi4v3U0e9bBDGCkKH
+1sSrbEGIc02HIo8m3PGUdrNJ8GNJdcYUghtoZbe01sIqVmWWLA8XXDQmOQ==
+-----END CERTIFICATE-----
diff --git a/test/basicserver/testfiles/rootkey.pem b/test/basicserver/testfiles/rootkey.pem
new file mode 100644
index 00000000..4eb0f59d
--- /dev/null
+++ b/test/basicserver/testfiles/rootkey.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDMYXJ+II0Ck9icrwDeGymdZ3Ah7ROmC32LpS3sQVchQd752O4t
+gyTUP6d47rLdM2xsVjdRHeb9AD+DVrzDNRWrtPYxQMyjPhXweQz/jwxAyVQdyYEI
+UkecYAvWDwpt9f6zF5Ipcq6udkxtE3JHCnR31EOW1Ccct+pyg8KBgj3kUwIDAQAB
+AoGAFsGO3u4+5ReTGbb+kLxTgNwghxZ/hpBm9SJ6H4ES83gDHKyDsHuWoS9JNVTW
+g3yTSOi8lgKPUoIxkC0bLVz+wYF0UWysOzhxbTqq43CdJM/HDuHbFGHs2MAKyvdm
+ai7ccJMISDATN6XT7BLRBE5AAVqDhNllvmr92niZS51yzJECQQD4LQWdK9IUjsja
+pYEeQKZENmC2pstAVYDyd3wuXaE8wiiTG86L/5zVRfEVpbD3rKPZVjcZKx+VZoIw
+iyW9WntbAkEA0tL2fSeBC1V9Jcj8TOuMmEaoPMclJLUBDLJPxFmHCguwvcH8cgTb
+Nr08FFqz62gZxudcrl5nISw3G0Rm3UGkaQJALRfhIUHJFjsre67+2wRcMaC/yfBc
+lf/zQhs70SDqHyQYQ0KWMRHs6UOgHpLQqPARhXgI4uXXA0pw9WkTHmjGaQJBAJ1x
+fTEkQmPjeS2xtnH/ayUBh3y0QJH0Nw9zTszVC1s+NcTQzSWdaNStZ+PPhRQlzzJS
+8E0sJRqJ+bF8WNGdxxkCQQCTpEUpqsVykhucZ3GsCTlI4o3HNmYFarKDDEHgppLS
+GKoUzTX2UMPJgeRITwacIh3lFhAily2PMFmlF+B7b5ep
+-----END RSA PRIVATE KEY-----
diff --git a/test/basicserver/testfiles/rootreq.pem b/test/basicserver/testfiles/rootreq.pem
new file mode 100644
index 00000000..6da1e428
--- /dev/null
+++ b/test/basicserver/testfiles/rootreq.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBpDCCAQ0CAQAwZDELMAkGA1UEBhMCR0IxDzANBgNVBAgTBkxvbmRvbjEPMA0G
+A1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYDVQQLEwxiYXNpYyBzZXJ2
+ZXIxDTALBgNVBAMTBFJPT1QwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMxh
+cn4gjQKT2JyvAN4bKZ1ncCHtE6YLfYulLexBVyFB3vnY7i2DJNQ/p3just0zbGxW
+N1Ed5v0AP4NWvMM1Fau09jFAzKM+FfB5DP+PDEDJVB3JgQhSR5xgC9YPCm31/rMX
+kilyrq52TG0TckcKdHfUQ5bUJxy36nKDwoGCPeRTAgMBAAGgADANBgkqhkiG9w0B
+AQUFAAOBgQCmy4L/D/m1Q23y+WB1Ub2u1efl0sb7zMWNzHsD/IR1CXSvXmAfPpr2
+hpJQj118ccaTqkRhA8gwhktMTBuGH5KiOLHYXRlniKo3G0yr0+fHWnjclZ+m6Bg1
+9HjJZYqIWRMQ78+wTpLCxliX6yp0JxMdx/v6/7jx3BtXz8cyU8ANAw==
+-----END CERTIFICATE REQUEST-----
diff --git a/test/basicserver/testfiles/serverCerts.pem b/test/basicserver/testfiles/serverCerts.pem
new file mode 100644
index 00000000..f61c554e
--- /dev/null
+++ b/test/basicserver/testfiles/serverCerts.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICOTCCAaICAQYwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNTA0
+WhcNMzEwMTIyMTYyNTA0WjBmMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjEPMA0GA1UEAxMGU0VSVkVSMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQDLR7tFaeNvCdvC5nQgfYggFHxZM5NcsxJSYcF27GhPylHE40XsmCEdHnDl
+AjWs48GrYN7tfTa7/JEFM9s7sgF9Oxj+tshMTNZvx25uih8gHFCg0RrYaQkgME2O
+mPuPtFcA/isTMCKO7D/aG2SapjY8/Xke0TseKO3jfP9LtxZz7QIDAQABMA0GCSqG
+SIb3DQEBBQUAA4GBALgh7u/7GZUMjzOPGuIenkdrsP0Gbst7wuXrLaMrAMlAaWMH
+E9AgU/6Q9+2yFxisgAzRmyKydNP4E4YomsE8rbx08vGw/6Rc7L19/UsFJxeNC5Ue
+6hziI9boB9LL5em4N8v+z4yhGvj2CrKzBxLNy8MYPi2S3KfQ69FdipvRQRp/
+-----END CERTIFICATE-----
diff --git a/test/basicserver/testfiles/serverPrivKey.pem b/test/basicserver/testfiles/serverPrivKey.pem
new file mode 100644
index 00000000..f2d73fd4
--- /dev/null
+++ b/test/basicserver/testfiles/serverPrivKey.pem
@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXQIBAAKBgQDLR7tFaeNvCdvC5nQgfYggFHxZM5NcsxJSYcF27GhPylHE40Xs
+mCEdHnDlAjWs48GrYN7tfTa7/JEFM9s7sgF9Oxj+tshMTNZvx25uih8gHFCg0RrY
+aQkgME2OmPuPtFcA/isTMCKO7D/aG2SapjY8/Xke0TseKO3jfP9LtxZz7QIDAQAB
+AoGBAJSH7zAC9OmXXHoGhWeQEbzO+yT6aHxdY8/KGeBZUMasYB7qqZb8eYWbToYm
+nS2cpVAh0gHZcfrdyuDwSQpPQIIA8gAPFHqR8T8VGrpChxgetYzkoPDapmcqKU4H
+YobFVA1gypK1IM5z3Z5kargqGmmzRIxX8BwWr6FGmFPp2+NBAkEA7A17g4JewNtY
+vtpM0NhIyw+7HN3ljf+pAvHM2pMw1Wk8TrbPJNQ20ZWnhGMdIvP0m25zna6pShL6
+0laf5EUWFQJBANx1SJ+Xb3P9IyrIlyMhrsYvAveezh6wimjAFFNYWmGEZ6uuHM5P
+eBSc3P0x0LbFKlGQWomxMb3ULwpjEueX9HkCQDMf0GpxJ/h5CUV8njp1PX7NT2c3
+H+qbPo2mtQl564+tFSSvLzn4xE6sLPXdSYgycf3f9CZol721UqGPpV2ZIOkCQQCQ
+trxxZmrW7LgFAZ+UhCvCFGISQcB0DNcOY+fzve+2S7/xxl1KYIgmn8HAws6K62oY
+GHYWJKbOQVaPrvFd7TWhAkA8VQPjDSRkdg2fU5RDTRfOQBczgc8aHTiqAv/S2g47
+lpsw8CLitobBvi3e5XuBKNIbnjeoZMbHcBZ+RXAAZe/Q
+-----END RSA PRIVATE KEY-----
diff --git a/test/basicserver/testfiles/serverReq.pem b/test/basicserver/testfiles/serverReq.pem
new file mode 100644
index 00000000..ce510fae
--- /dev/null
+++ b/test/basicserver/testfiles/serverReq.pem
@@ -0,0 +1,11 @@
+-----BEGIN CERTIFICATE REQUEST-----
+MIIBpjCCAQ8CAQAwZjELMAkGA1UEBhMCR0IxDzANBgNVBAgTBkxvbmRvbjEPMA0G
+A1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYDVQQLEwxiYXNpYyBzZXJ2
+ZXIxDzANBgNVBAMTBlNFUlZFUjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA
+y0e7RWnjbwnbwuZ0IH2IIBR8WTOTXLMSUmHBduxoT8pRxONF7JghHR5w5QI1rOPB
+q2De7X02u/yRBTPbO7IBfTsY/rbITEzWb8duboofIBxQoNEa2GkJIDBNjpj7j7RX
+AP4rEzAijuw/2htkmqY2PP15HtE7Hijt43z/S7cWc+0CAwEAAaAAMA0GCSqGSIb3
+DQEBBQUAA4GBAGdUCS76aBzPw4zcU999r6gE7/F8/bYlT/tr2SEyKzF+vC0widZN
+P3bg9IaNAWi84vw8WEB+j2wM3TPB5/kSKFpO2MxOHPERX+aOXh6JkN6a/ay5CDOT
+r/wCERRkqY2gphU5m3/S0Gd7wLbH/neBgNsHUzbNwwQ+uqkF2NRGg0V/
+-----END CERTIFICATE REQUEST-----
diff --git a/test/basicserver/testfiles/serverTrustedCAs.pem b/test/basicserver/testfiles/serverTrustedCAs.pem
new file mode 100644
index 00000000..d72b70e5
--- /dev/null
+++ b/test/basicserver/testfiles/serverTrustedCAs.pem
@@ -0,0 +1,14 @@
+-----BEGIN CERTIFICATE-----
+MIICNzCCAaACAQAwDQYJKoZIhvcNAQEFBQAwZDELMAkGA1UEBhMCR0IxDzANBgNV
+BAgTBkxvbmRvbjEPMA0GA1UEBxMGTG9uZG9uMQ0wCwYDVQQKEwRUZXN0MRUwEwYD
+VQQLEwxiYXNpYyBzZXJ2ZXIxDTALBgNVBAMTBFJPT1QwHhcNMDMwOTA2MTYyNDA4
+WhcNMzEwMTIyMTYyNDA4WjBkMQswCQYDVQQGEwJHQjEPMA0GA1UECBMGTG9uZG9u
+MQ8wDQYDVQQHEwZMb25kb24xDTALBgNVBAoTBFRlc3QxFTATBgNVBAsTDGJhc2lj
+IHNlcnZlcjENMAsGA1UEAxMEUk9PVDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkC
+gYEAzGFyfiCNApPYnK8A3hspnWdwIe0Tpgt9i6Ut7EFXIUHe+djuLYMk1D+neO6y
+3TNsbFY3UR3m/QA/g1a8wzUVq7T2MUDMoz4V8HkM/48MQMlUHcmBCFJHnGAL1g8K
+bfX+sxeSKXKurnZMbRNyRwp0d9RDltQnHLfqcoPCgYI95FMCAwEAATANBgkqhkiG
+9w0BAQUFAAOBgQDIAhGUvs47CQeKiF6GDxFfSseCk6UWB1lFe154ZpexgMTp8Dgu
+leJOvnZPmkywovIcxr2YZAM33e+3+rKDJEy9PJ9mGLsrZMHSi4v3U0e9bBDGCkKH
+1sSrbEGIc02HIo8m3PGUdrNJ8GNJdcYUghtoZbe01sIqVmWWLA8XXDQmOQ==
+-----END CERTIFICATE-----
diff --git a/test/basicserver/testfiles/srv1.conf b/test/basicserver/testfiles/srv1.conf
new file mode 100644
index 00000000..ee68704e
--- /dev/null
+++ b/test/basicserver/testfiles/srv1.conf
@@ -0,0 +1,6 @@
+Server
+{
+ PidFile = testfiles/srv1.pid
+}
+
+TestFile = testfiles/srv1.test1
diff --git a/test/basicserver/testfiles/srv1b.conf b/test/basicserver/testfiles/srv1b.conf
new file mode 100644
index 00000000..d6d6eebd
--- /dev/null
+++ b/test/basicserver/testfiles/srv1b.conf
@@ -0,0 +1,6 @@
+Server
+{
+ PidFile = testfiles/srv1.pid
+}
+
+TestFile = testfiles/srv1.test2
diff --git a/test/basicserver/testfiles/srv2.conf b/test/basicserver/testfiles/srv2.conf
new file mode 100644
index 00000000..ef1d7c49
--- /dev/null
+++ b/test/basicserver/testfiles/srv2.conf
@@ -0,0 +1,6 @@
+Server
+{
+ PidFile = testfiles/srv2.pid
+ ListenAddresses = inet:localhost,unix:testfiles/srv2.sock
+}
+
diff --git a/test/basicserver/testfiles/srv3.conf b/test/basicserver/testfiles/srv3.conf
new file mode 100644
index 00000000..e2211553
--- /dev/null
+++ b/test/basicserver/testfiles/srv3.conf
@@ -0,0 +1,9 @@
+Server
+{
+ PidFile = testfiles/srv3.pid
+ ListenAddresses = inet:localhost,unix:testfiles/srv3.sock
+ CertificateFile = testfiles/serverCerts.pem
+ PrivateKeyFile = testfiles/serverPrivKey.pem
+ TrustedCAsFile = testfiles/serverTrustedCAs.pem
+}
+
diff --git a/test/basicserver/testfiles/srv4.conf b/test/basicserver/testfiles/srv4.conf
new file mode 100644
index 00000000..b4c5627c
--- /dev/null
+++ b/test/basicserver/testfiles/srv4.conf
@@ -0,0 +1,6 @@
+Server
+{
+ PidFile = testfiles/srv4.pid
+ ListenAddresses = unix:testfiles/srv4.sock
+}
+
diff --git a/test/basicserver/testprotocol.txt b/test/basicserver/testprotocol.txt
new file mode 100644
index 00000000..5bca9f49
--- /dev/null
+++ b/test/basicserver/testprotocol.txt
@@ -0,0 +1,42 @@
+# test protocol file
+
+Name Test
+IdentString Test-0.00
+ServerContextClass TestContext TestContext.h
+
+BEGIN_OBJECTS
+
+Error 0 IsError(Type,SubType) Reply
+ int32 Type
+ int32 SubType
+
+Hello 1 Command(Hello) Reply
+ int32 Number32
+ int16 Number16
+ int8 Number8
+ string Text
+
+Lists 2 Command(ListsReply)
+ vector<string> LotsOfText
+
+ListsReply 3 Reply
+ int32 NumberOfStrings
+
+Quit 4 Command(Quit) Reply EndsConversation
+
+Simple 5 Command(SimpleReply)
+ int32 Value
+
+SimpleReply 6 Reply
+ int32 ValuePlusOne
+
+GetStream 7 Command(GetStream) Reply
+ int32 StartingValue
+ bool UncertainSize
+
+SendStream 8 Command(GetStream) StreamWithCommand
+ int64 Value
+
+String 9 Command(String) Reply
+ string Test
+