Unit tests for SMTP.
This commit is contained in:
parent
4579f8f95a
commit
2791e5d41e
@ -333,6 +333,7 @@ libvmimetest_common = [
|
|||||||
|
|
||||||
libvmimetest_sources = [
|
libvmimetest_sources = [
|
||||||
'tests/testRunner.cpp',
|
'tests/testRunner.cpp',
|
||||||
|
'tests/testUtils.cpp',
|
||||||
# ============================== Parser ==============================
|
# ============================== Parser ==============================
|
||||||
'tests/parser/attachmentHelperTest.cpp',
|
'tests/parser/attachmentHelperTest.cpp',
|
||||||
'tests/parser/bodyPartTest.cpp',
|
'tests/parser/bodyPartTest.cpp',
|
||||||
@ -360,7 +361,10 @@ libvmimetest_sources = [
|
|||||||
'tests/misc/importanceHelperTest.cpp',
|
'tests/misc/importanceHelperTest.cpp',
|
||||||
# ============================= Security =============================
|
# ============================= Security =============================
|
||||||
'tests/security/digest/md5Test.cpp',
|
'tests/security/digest/md5Test.cpp',
|
||||||
'tests/security/digest/sha1Test.cpp'
|
'tests/security/digest/sha1Test.cpp',
|
||||||
|
# =============================== Net ================================
|
||||||
|
'tests/net/smtp/SMTPTransportTest.cpp',
|
||||||
|
'tests/net/smtp/SMTPResponseTest.cpp'
|
||||||
]
|
]
|
||||||
|
|
||||||
libvmime_autotools = [
|
libvmime_autotools = [
|
||||||
|
189
tests/net/smtp/SMTPResponseTest.cpp
Normal file
189
tests/net/smtp/SMTPResponseTest.cpp
Normal file
@ -0,0 +1,189 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2006 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "tests/testUtils.hpp"
|
||||||
|
|
||||||
|
#include "vmime/net/smtp/SMTPResponse.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#define VMIME_TEST_SUITE SMTPResponseTest
|
||||||
|
#define VMIME_TEST_SUITE_MODULE "Net/SMTP"
|
||||||
|
|
||||||
|
|
||||||
|
VMIME_TEST_SUITE_BEGIN
|
||||||
|
|
||||||
|
VMIME_TEST_LIST_BEGIN
|
||||||
|
VMIME_TEST(testSingleLineResponse)
|
||||||
|
VMIME_TEST(testSingleLineResponseLF)
|
||||||
|
VMIME_TEST(testMultiLineResponse)
|
||||||
|
VMIME_TEST(testMultiLineResponseDifferentCode)
|
||||||
|
VMIME_TEST(testIncompleteMultiLineResponse)
|
||||||
|
VMIME_TEST(testIntermediateResponse)
|
||||||
|
VMIME_TEST(testNoResponseText)
|
||||||
|
VMIME_TEST_LIST_END
|
||||||
|
|
||||||
|
|
||||||
|
void testSingleLineResponse()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
socket->localSend("123 Response Text\r\n");
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "Response Text", resp->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testSingleLineResponseLF()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
socket->localSend("123 Response Text\n");
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "Response Text", resp->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMultiLineResponse()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
socket->localSend
|
||||||
|
(
|
||||||
|
"123-Response\r\n"
|
||||||
|
"123 Text\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 2, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "Response\nText", resp->getText());
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getLineAt(0).getCode());
|
||||||
|
VASSERT_EQ("Text", "Response", resp->getLineAt(0).getText());
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getLineAt(1).getCode());
|
||||||
|
VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMultiLineResponseDifferentCode()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>();
|
||||||
|
|
||||||
|
socket->localSend
|
||||||
|
(
|
||||||
|
"123-Response\r\n"
|
||||||
|
"456 Text\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 0, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 2, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "Response\nText", resp->getText());
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 123, resp->getLineAt(0).getCode());
|
||||||
|
VASSERT_EQ("Text", "Response", resp->getLineAt(0).getText());
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 456, resp->getLineAt(1).getCode());
|
||||||
|
VASSERT_EQ("Text", "Text", resp->getLineAt(1).getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testIncompleteMultiLineResponse()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>(1);
|
||||||
|
|
||||||
|
socket->localSend
|
||||||
|
(
|
||||||
|
"123-Response\r\n"
|
||||||
|
"123-Text\r\n"
|
||||||
|
// Missing data
|
||||||
|
);
|
||||||
|
|
||||||
|
VASSERT_THROW("Incomplete response",
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh),
|
||||||
|
vmime::exceptions::operation_timed_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testIntermediateResponse()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>(1);
|
||||||
|
|
||||||
|
socket->localSend
|
||||||
|
(
|
||||||
|
"334\r\n"
|
||||||
|
"More information\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 334, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "More information", resp->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
void testNoResponseText()
|
||||||
|
{
|
||||||
|
vmime::ref <testSocket> socket = vmime::create <testSocket>();
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> toh =
|
||||||
|
vmime::create <testTimeoutHandler>(1);
|
||||||
|
|
||||||
|
socket->localSend
|
||||||
|
(
|
||||||
|
"250\r\n"
|
||||||
|
);
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::smtp::SMTPResponse> resp =
|
||||||
|
vmime::net::smtp::SMTPResponse::readResponse(socket, toh);
|
||||||
|
|
||||||
|
VASSERT_EQ("Code", 250, resp->getCode());
|
||||||
|
VASSERT_EQ("Lines", 1, resp->getLineCount());
|
||||||
|
VASSERT_EQ("Text", "", resp->getText());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
VMIME_TEST_SUITE_END
|
||||||
|
|
256
tests/net/smtp/SMTPTransportTest.cpp
Normal file
256
tests/net/smtp/SMTPTransportTest.cpp
Normal file
@ -0,0 +1,256 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2006 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "tests/testUtils.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
#define VMIME_TEST_SUITE SMTPTransportTest
|
||||||
|
#define VMIME_TEST_SUITE_MODULE "Net/SMTP"
|
||||||
|
|
||||||
|
|
||||||
|
class greetingErrorSMTPTestSocket;
|
||||||
|
class MAILandRCPTSMTPTestSocket;
|
||||||
|
|
||||||
|
|
||||||
|
VMIME_TEST_SUITE_BEGIN
|
||||||
|
|
||||||
|
VMIME_TEST_LIST_BEGIN
|
||||||
|
VMIME_TEST(testGreetingError)
|
||||||
|
VMIME_TEST(testMAILandRCPT)
|
||||||
|
VMIME_TEST_LIST_END
|
||||||
|
|
||||||
|
|
||||||
|
void testGreetingError()
|
||||||
|
{
|
||||||
|
vmime::ref <vmime::net::session> session =
|
||||||
|
vmime::create <vmime::net::session>();
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::transport> tr = session->getTransport
|
||||||
|
(vmime::utility::url("smtp://localhost"));
|
||||||
|
|
||||||
|
tr->setSocketFactory(vmime::create <testSocketFactory <greetingErrorSMTPTestSocket> >());
|
||||||
|
tr->setTimeoutHandlerFactory(vmime::create <testTimeoutHandlerFactory>());
|
||||||
|
|
||||||
|
VASSERT_THROW("Connection", tr->connect(),
|
||||||
|
vmime::exceptions::connection_greeting_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testMAILandRCPT()
|
||||||
|
{
|
||||||
|
vmime::ref <vmime::net::session> session =
|
||||||
|
vmime::create <vmime::net::session>();
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::transport> tr = session->getTransport
|
||||||
|
(vmime::utility::url("smtp://localhost"));
|
||||||
|
|
||||||
|
tr->setSocketFactory(vmime::create <testSocketFactory <MAILandRCPTSMTPTestSocket> >());
|
||||||
|
tr->setTimeoutHandlerFactory(vmime::create <testTimeoutHandlerFactory>());
|
||||||
|
|
||||||
|
VASSERT_NO_THROW("Connection", tr->connect());
|
||||||
|
|
||||||
|
vmime::mailbox exp("expeditor@test.vmime.org");
|
||||||
|
|
||||||
|
vmime::mailboxList recips;
|
||||||
|
recips.appendMailbox(vmime::create <vmime::mailbox>("recipient1@test.vmime.org"));
|
||||||
|
recips.appendMailbox(vmime::create <vmime::mailbox>("recipient2@test.vmime.org"));
|
||||||
|
recips.appendMailbox(vmime::create <vmime::mailbox>("recipient3@test.vmime.org"));
|
||||||
|
|
||||||
|
vmime::string data("Message data");
|
||||||
|
vmime::utility::inputStreamStringAdapter is(data);
|
||||||
|
|
||||||
|
tr->send(exp, recips, is, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
VMIME_TEST_SUITE_END
|
||||||
|
|
||||||
|
|
||||||
|
/** Accepts connection and fails on greeting.
|
||||||
|
*/
|
||||||
|
class greetingErrorSMTPTestSocket : public lineBasedTestSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void onConnected()
|
||||||
|
{
|
||||||
|
localSend("421 test.vmime.org Service not available, closing transmission channel\r\n");
|
||||||
|
disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
void processCommand()
|
||||||
|
{
|
||||||
|
if (!haveMoreLines())
|
||||||
|
return;
|
||||||
|
|
||||||
|
getNextLine();
|
||||||
|
|
||||||
|
localSend("502 Command not implemented\r\n");
|
||||||
|
processCommand();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/** SMTP test server 1.
|
||||||
|
*
|
||||||
|
* Test send().
|
||||||
|
* Ensure MAIL and RCPT commands are sent correctly.
|
||||||
|
*/
|
||||||
|
class MAILandRCPTSMTPTestSocket : public lineBasedTestSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MAILandRCPTSMTPTestSocket()
|
||||||
|
{
|
||||||
|
m_recipients.insert("recipient1@test.vmime.org");
|
||||||
|
m_recipients.insert("recipient2@test.vmime.org");
|
||||||
|
m_recipients.insert("recipient3@test.vmime.org");
|
||||||
|
|
||||||
|
m_state = STATE_NOT_CONNECTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void onConnected()
|
||||||
|
{
|
||||||
|
localSend("220 test.vmime.org Service ready\r\n");
|
||||||
|
processCommand();
|
||||||
|
|
||||||
|
m_state = STATE_COMMAND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void processCommand()
|
||||||
|
{
|
||||||
|
if (!haveMoreLines())
|
||||||
|
return;
|
||||||
|
|
||||||
|
vmime::string line = getNextLine();
|
||||||
|
std::istringstream iss(line);
|
||||||
|
|
||||||
|
switch (m_state)
|
||||||
|
{
|
||||||
|
case STATE_NOT_CONNECTED:
|
||||||
|
|
||||||
|
localSend("451 Requested action aborted: invalid state\r\n");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case STATE_COMMAND:
|
||||||
|
{
|
||||||
|
std::string cmd;
|
||||||
|
iss >> cmd;
|
||||||
|
|
||||||
|
if (cmd.empty())
|
||||||
|
{
|
||||||
|
localSend("500 Syntax error, command unrecognized\r\n");
|
||||||
|
}
|
||||||
|
else if (cmd == "HELO")
|
||||||
|
{
|
||||||
|
localSend("250 OK\r\n");
|
||||||
|
}
|
||||||
|
else if (cmd == "MAIL")
|
||||||
|
{
|
||||||
|
VASSERT_EQ("MAIL", std::string("MAIL FROM: <expeditor@test.vmime.org>"), line);
|
||||||
|
|
||||||
|
localSend("250 OK\r\n");
|
||||||
|
}
|
||||||
|
else if (cmd == "RCPT")
|
||||||
|
{
|
||||||
|
const vmime::string::size_type lt = line.find('<');
|
||||||
|
const vmime::string::size_type gt = line.find('>');
|
||||||
|
|
||||||
|
VASSERT("RCPT <", lt != vmime::string::npos);
|
||||||
|
VASSERT("RCPT >", gt != vmime::string::npos);
|
||||||
|
VASSERT("RCPT ><", gt >= lt);
|
||||||
|
|
||||||
|
const vmime::string recip = vmime::string
|
||||||
|
(line.begin() + lt + 1, line.begin() + gt);
|
||||||
|
|
||||||
|
std::set <vmime::string>::iterator it =
|
||||||
|
m_recipients.find(recip);
|
||||||
|
|
||||||
|
VASSERT(std::string("Recipient not found: '") + recip + "'",
|
||||||
|
it != m_recipients.end());
|
||||||
|
|
||||||
|
m_recipients.erase(it);
|
||||||
|
|
||||||
|
localSend("250 OK, recipient accepted\r\n");
|
||||||
|
}
|
||||||
|
else if (cmd == "DATA")
|
||||||
|
{
|
||||||
|
VASSERT("All recipients", m_recipients.empty());
|
||||||
|
|
||||||
|
localSend("354 Ready to accept data; end with <CRLF>.<CRLF>\r\n");
|
||||||
|
|
||||||
|
m_state = STATE_DATA;
|
||||||
|
m_msgData.clear();
|
||||||
|
}
|
||||||
|
else if (cmd == "NOOP")
|
||||||
|
{
|
||||||
|
localSend("250 Completed\r\n");
|
||||||
|
}
|
||||||
|
else if (cmd == "QUIT")
|
||||||
|
{
|
||||||
|
localSend("221 test.vmime.org Service closing transmission channel\r\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
localSend("502 Command not implemented\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case STATE_DATA:
|
||||||
|
{
|
||||||
|
if (line == ".")
|
||||||
|
{
|
||||||
|
VASSERT_EQ("Data", "Message data\r\n", m_msgData);
|
||||||
|
|
||||||
|
localSend("250 Message accepted for delivery\r\n");
|
||||||
|
m_state = STATE_COMMAND;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_msgData += line + "\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
processCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
enum State
|
||||||
|
{
|
||||||
|
STATE_NOT_CONNECTED,
|
||||||
|
STATE_COMMAND,
|
||||||
|
STATE_DATA
|
||||||
|
};
|
||||||
|
|
||||||
|
int m_state;
|
||||||
|
|
||||||
|
std::set <vmime::string> m_recipients;
|
||||||
|
|
||||||
|
std::string m_msgData;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
@ -210,7 +210,7 @@ int main(int argc, char* argv[])
|
|||||||
// Run the tests
|
// Run the tests
|
||||||
if (xmlOutput)
|
if (xmlOutput)
|
||||||
{
|
{
|
||||||
// Get the test suites from the registry and add them to the list of test to run
|
// Get the test suites from the registry and add them to the list of tests to run
|
||||||
CppUnit::TestRunner runner;
|
CppUnit::TestRunner runner;
|
||||||
|
|
||||||
for (unsigned int i = 0 ; i < getTestModules().size() ; ++i)
|
for (unsigned int i = 0 ; i < getTestModules().size() ; ++i)
|
||||||
@ -231,7 +231,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
xmlListener->output(std::cout);
|
xmlListener->output(std::cout);
|
||||||
|
|
||||||
// Return error code 1 if the one of test failed
|
// Return error code 1 if a test failed
|
||||||
return result.wasSuccessful() ? 0 : 1;
|
return result.wasSuccessful() ? 0 : 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
183
tests/testUtils.cpp
Normal file
183
tests/testUtils.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
//
|
||||||
|
// VMime library (http://www.vmime.org)
|
||||||
|
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License as
|
||||||
|
// published by the Free Software Foundation; either version 2 of
|
||||||
|
// the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
// General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License along
|
||||||
|
// with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
//
|
||||||
|
// Linking this library statically or dynamically with other modules is making
|
||||||
|
// a combined work based on this library. Thus, the terms and conditions of
|
||||||
|
// the GNU General Public License cover the whole combination.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "testUtils.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// testSocket
|
||||||
|
|
||||||
|
void testSocket::connect(const vmime::string& address, const vmime::port_t port)
|
||||||
|
{
|
||||||
|
m_address = address;
|
||||||
|
m_port = port;
|
||||||
|
m_connected = true;
|
||||||
|
|
||||||
|
onConnected();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::disconnect()
|
||||||
|
{
|
||||||
|
m_address.clear();
|
||||||
|
m_port = 0;
|
||||||
|
m_connected = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool testSocket::isConnected() const
|
||||||
|
{
|
||||||
|
return m_connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::receive(vmime::string& buffer)
|
||||||
|
{
|
||||||
|
buffer = m_inBuffer;
|
||||||
|
m_inBuffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::send(const vmime::string& buffer)
|
||||||
|
{
|
||||||
|
m_outBuffer += buffer;
|
||||||
|
|
||||||
|
onDataReceived();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const int testSocket::receiveRaw(char* buffer, const int count)
|
||||||
|
{
|
||||||
|
const int n = std::min(count, static_cast <int>(m_inBuffer.size()));
|
||||||
|
|
||||||
|
std::copy(m_inBuffer.begin(), m_inBuffer.begin() + n, buffer);
|
||||||
|
m_inBuffer.erase(m_inBuffer.begin(), m_inBuffer.begin() + n);
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::sendRaw(const char* buffer, const int count)
|
||||||
|
{
|
||||||
|
send(vmime::string(buffer, count));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::localSend(const vmime::string& buffer)
|
||||||
|
{
|
||||||
|
m_inBuffer += buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::localReceive(vmime::string& buffer)
|
||||||
|
{
|
||||||
|
buffer = m_outBuffer;
|
||||||
|
m_outBuffer.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::onDataReceived()
|
||||||
|
{
|
||||||
|
// Override
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testSocket::onConnected()
|
||||||
|
{
|
||||||
|
// Override
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// lineBasedTestSocket
|
||||||
|
|
||||||
|
void lineBasedTestSocket::onDataReceived()
|
||||||
|
{
|
||||||
|
vmime::string chunk;
|
||||||
|
localReceive(chunk);
|
||||||
|
|
||||||
|
m_buffer += chunk;
|
||||||
|
|
||||||
|
vmime::string::size_type eol;
|
||||||
|
|
||||||
|
while ((eol = m_buffer.find('\n')) != vmime::string::npos)
|
||||||
|
{
|
||||||
|
vmime::string line(std::string(m_buffer.begin(), m_buffer.begin() + eol));
|
||||||
|
|
||||||
|
if (!line.empty() && line[line.length() - 1] == '\r')
|
||||||
|
line.erase(line.end() - 1, line.end());
|
||||||
|
|
||||||
|
m_lines.push_back(line);
|
||||||
|
m_buffer.erase(m_buffer.begin(), m_buffer.begin() + eol + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!m_lines.empty())
|
||||||
|
processCommand();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const vmime::string lineBasedTestSocket::getNextLine()
|
||||||
|
{
|
||||||
|
const vmime::string line = m_lines.front();
|
||||||
|
m_lines.erase(m_lines.begin(), m_lines.begin() + 1);
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool lineBasedTestSocket::haveMoreLines() const
|
||||||
|
{
|
||||||
|
return !m_lines.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// testTimeoutHandler
|
||||||
|
|
||||||
|
testTimeoutHandler::testTimeoutHandler(const unsigned int delay)
|
||||||
|
: m_delay(delay), m_start(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool testTimeoutHandler::isTimeOut()
|
||||||
|
{
|
||||||
|
return (vmime::platformDependant::getHandler()->getUnixTime() - m_start) >= m_delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void testTimeoutHandler::resetTimeOut()
|
||||||
|
{
|
||||||
|
m_start = vmime::platformDependant::getHandler()->getUnixTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const bool testTimeoutHandler::handleTimeOut()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> testTimeoutHandlerFactory::create()
|
||||||
|
{
|
||||||
|
return vmime::create <testTimeoutHandler>();
|
||||||
|
}
|
||||||
|
|
@ -193,3 +193,113 @@ inline std::ostream& operator<<(std::ostream& os, const vmime::datetime& d)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// Used to test network features.
|
||||||
|
//
|
||||||
|
// This works like a local pipe: client reads and writes data using receive()
|
||||||
|
// and send(). Server reads incoming data with localReceive() and sends data
|
||||||
|
// to client with localSend().
|
||||||
|
|
||||||
|
class testSocket : public vmime::net::socket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void connect(const vmime::string& address, const vmime::port_t port);
|
||||||
|
void disconnect();
|
||||||
|
|
||||||
|
const bool isConnected() const;
|
||||||
|
|
||||||
|
void receive(vmime::string& buffer);
|
||||||
|
void send(const vmime::string& buffer);
|
||||||
|
|
||||||
|
const int receiveRaw(char* buffer, const int count);
|
||||||
|
void sendRaw(const char* buffer, const int count);
|
||||||
|
|
||||||
|
/** Send data to client.
|
||||||
|
*
|
||||||
|
* @buffer data to send
|
||||||
|
*/
|
||||||
|
void localSend(const vmime::string& buffer);
|
||||||
|
|
||||||
|
/** Receive data from client.
|
||||||
|
*
|
||||||
|
* @buffer buffer in which to store received data
|
||||||
|
*/
|
||||||
|
void localReceive(vmime::string& buffer);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
|
||||||
|
/** Called when the client has sent some data.
|
||||||
|
*/
|
||||||
|
virtual void onDataReceived();
|
||||||
|
|
||||||
|
/** Called when the client has connected.
|
||||||
|
*/
|
||||||
|
virtual void onConnected();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
vmime::string m_address;
|
||||||
|
vmime::port_t m_port;
|
||||||
|
bool m_connected;
|
||||||
|
|
||||||
|
vmime::string m_inBuffer;
|
||||||
|
vmime::string m_outBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class testSocketFactory : public vmime::net::socketFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::socket> create()
|
||||||
|
{
|
||||||
|
return vmime::create <T>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class lineBasedTestSocket : public testSocket
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
void onDataReceived();
|
||||||
|
|
||||||
|
const vmime::string getNextLine();
|
||||||
|
const bool haveMoreLines() const;
|
||||||
|
|
||||||
|
virtual void processCommand() = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
std::vector <vmime::string> m_lines;
|
||||||
|
std::string m_buffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class testTimeoutHandler : public vmime::net::timeoutHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
testTimeoutHandler(const unsigned int delay = 3);
|
||||||
|
|
||||||
|
const bool isTimeOut();
|
||||||
|
void resetTimeOut();
|
||||||
|
const bool handleTimeOut();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned int m_delay;
|
||||||
|
unsigned int m_start;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
vmime::ref <vmime::net::timeoutHandler> create();
|
||||||
|
};
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user