diff options
| author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 | 
|---|---|---|
| committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 | 
| commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
| tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/tests/net | |
| download | smtps-and-pop3s-console-program-master.tar.gz smtps-and-pop3s-console-program-master.zip | |
Diffstat (limited to 'vmime-master/tests/net')
18 files changed, 4742 insertions, 0 deletions
| diff --git a/vmime-master/tests/net/folderAttributesTest.cpp b/vmime-master/tests/net/folderAttributesTest.cpp new file mode 100644 index 0000000..da0e025 --- /dev/null +++ b/vmime-master/tests/net/folderAttributesTest.cpp @@ -0,0 +1,137 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/folderAttributes.hpp" + + +VMIME_TEST_SUITE_BEGIN(folderAttributesTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testConstruct) +		VMIME_TEST(testConstructCopy) +		VMIME_TEST(testSetType) +		VMIME_TEST(testSetFlags) +		VMIME_TEST(testHasFlag) +		VMIME_TEST(testSetUserFlags) +		VMIME_TEST(testHasUserFlag) +		VMIME_TEST(testSetSpecialUse) +	VMIME_TEST_LIST_END + + +	void testConstruct() { + +		vmime::net::folderAttributes attr; + +		// Default values +		VASSERT_EQ("type", vmime::net::folderAttributes::TYPE_CONTAINS_FOLDERS +			| vmime::net::folderAttributes::TYPE_CONTAINS_MESSAGES, attr.getType()); +		VASSERT_EQ("flags", 0, attr.getFlags()); +		VASSERT_EQ("user-flags", 0, attr.getUserFlags().size()); +		VASSERT_EQ("special-use", vmime::net::folderAttributes::SPECIALUSE_NONE, attr.getSpecialUse()); +	} + +	void testConstructCopy() { + +		std::vector <vmime::string> userFlags; +		userFlags.push_back("\\XMyFlag1"); +		userFlags.push_back("\\XMyFlag2"); +		userFlags.push_back("\\XMyFlag3"); + +		vmime::net::folderAttributes attr; + +		attr.setFlags(vmime::net::folderAttributes::FLAG_HAS_CHILDREN); +		attr.setUserFlags(userFlags); + +		vmime::net::folderAttributes attr2(attr); + +		VASSERT("flags", attr2.getFlags() == attr.getFlags()); +		VASSERT("user-flags", attr2.getUserFlags() == attr.getUserFlags()); +	} + +	void testSetType() { + +		vmime::net::folderAttributes attr; +		attr.setType(vmime::net::folderAttributes::TYPE_CONTAINS_FOLDERS); + +		VASSERT_EQ("eq", vmime::net::folderAttributes::TYPE_CONTAINS_FOLDERS, attr.getType()); +	} + +	void testSetFlags() { + +		vmime::net::folderAttributes attr; +		attr.setFlags(vmime::net::folderAttributes::FLAG_HAS_CHILDREN); + +		VASSERT_EQ("eq", vmime::net::folderAttributes::FLAG_HAS_CHILDREN, attr.getFlags()); +	} + +	void testHasFlag() { + +		vmime::net::folderAttributes attr; +		attr.setFlags(vmime::net::folderAttributes::FLAG_HAS_CHILDREN); + +		VASSERT("has", attr.hasFlag(vmime::net::folderAttributes::FLAG_HAS_CHILDREN)); +		VASSERT("has-not", !attr.hasFlag(vmime::net::folderAttributes::FLAG_NO_OPEN)); +	} + +	void testSetUserFlags() { + +		std::vector <vmime::string> userFlags; +		userFlags.push_back("\\XMyFlag1"); +		userFlags.push_back("\\XMyFlag2"); +		userFlags.push_back("\\XMyFlag3"); + +		vmime::net::folderAttributes attr; +		attr.setUserFlags(userFlags); + +		VASSERT("eq", attr.getUserFlags() == userFlags); +	} + +	void testHasUserFlag() { + +		std::vector <vmime::string> userFlags; +		userFlags.push_back("\\XMyFlag1"); +		userFlags.push_back("\\XMyFlag2"); +		userFlags.push_back("\\XMyFlag3"); + +		vmime::net::folderAttributes attr; +		attr.setUserFlags(userFlags); + +		VASSERT("has", attr.hasUserFlag("\\XMyFlag1")); +		VASSERT("has-casesensitive", !attr.hasUserFlag("\\xmyflag1")); +		VASSERT("has-not", !attr.hasUserFlag("\\XMyFlag4")); +	} + +	void testSetSpecialUse() { + +		const int use = vmime::net::folderAttributes::SPECIALUSE_JUNK +			| vmime::net::folderAttributes::SPECIALUSE_TRASH; + +		vmime::net::folderAttributes attr; +		attr.setSpecialUse(use); + +		VASSERT_EQ("eq", use, attr.getSpecialUse()); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPCommandTest.cpp b/vmime-master/tests/net/imap/IMAPCommandTest.cpp new file mode 100644 index 0000000..cf3446d --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPCommandTest.cpp @@ -0,0 +1,495 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/imap/IMAPCommand.hpp" +#include "vmime/net/imap/IMAPStore.hpp" +#include "vmime/net/imap/IMAPConnection.hpp" + + +using namespace vmime::net::imap; + + +VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testCreateCommand) +		VMIME_TEST(testCreateCommandParams) +		VMIME_TEST(testLOGIN) +		VMIME_TEST(testAUTHENTICATE) +		VMIME_TEST(testAUTHENTICATE_InitialResponse) +		VMIME_TEST(testLIST) +		VMIME_TEST(testSELECT) +		VMIME_TEST(testSTATUS) +		VMIME_TEST(testCREATE) +		VMIME_TEST(testDELETE) +		VMIME_TEST(testRENAME) +		VMIME_TEST(testFETCH) +		VMIME_TEST(testSTORE) +		VMIME_TEST(testAPPEND) +		VMIME_TEST(testCOPY) +		VMIME_TEST(testSEARCH) +		VMIME_TEST(testSTARTTLS) +		VMIME_TEST(testCAPABILITY) +		VMIME_TEST(testNOOP) +		VMIME_TEST(testEXPUNGE) +		VMIME_TEST(testCLOSE) +		VMIME_TEST(testLOGOUT) +		VMIME_TEST(testSend) +	VMIME_TEST_LIST_END + + +	void testCreateCommand() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::createCommand("MY_COMMAND"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); +	} + +	void testCreateCommandParams() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::createCommand("MY_COMMAND param1 param2"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); +	} + +	void testLOGIN() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LOGIN("username", "password"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "LOGIN username password", cmd->getText()); +		VASSERT_EQ("Trace Text", "LOGIN {username} {password}", cmd->getTraceText()); +	} + +	void testAUTHENTICATE() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::AUTHENTICATE("saslmechanism"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTHENTICATE saslmechanism", cmd->getText()); +	} + +	void testAUTHENTICATE_InitialResponse() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::AUTHENTICATE("saslmechanism", "initial-response"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTHENTICATE saslmechanism initial-response", cmd->getText()); +	} + +	void testLIST() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LIST("ref-name", "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "LIST ref-name mailbox-name", cmd->getText()); + +		vmime::shared_ptr <IMAPCommand> cmdQuote = IMAPCommand::LIST("ref name", "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "LIST \"ref name\" mailbox-name", cmdQuote->getText()); +	} + +	void testSELECT() { + +		std::vector <vmime::string> params; +		params.push_back("param-1"); +		params.push_back("param-2"); + + +		vmime::shared_ptr <IMAPCommand> cmdRO = IMAPCommand::SELECT( +			/* readOnly */ true, "mailbox-name", std::vector <vmime::string>() +		); + +		VASSERT_NOT_NULL("Not null", cmdRO); +		VASSERT_EQ("Text", "EXAMINE mailbox-name", cmdRO->getText()); + +		vmime::shared_ptr <IMAPCommand> cmdROQuote = IMAPCommand::SELECT( +			/* readOnly */ true, "mailbox name", std::vector <vmime::string>() +		); + +		VASSERT_NOT_NULL("Not null", cmdROQuote); +		VASSERT_EQ("Text", "EXAMINE \"mailbox name\"", cmdROQuote->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdRW = IMAPCommand::SELECT( +			/* readOnly */ false, "mailbox-name", std::vector <vmime::string>() +		); + +		VASSERT_NOT_NULL("Not null", cmdRW); +		VASSERT_EQ("Text", "SELECT mailbox-name", cmdRW->getText()); + +		vmime::shared_ptr <IMAPCommand> cmdRWParams = IMAPCommand::SELECT( +			/* readOnly */ false, "mailbox-name", params +		); + +		VASSERT_NOT_NULL("Not null", cmdRWParams); +		VASSERT_EQ("Text", "SELECT mailbox-name (param-1 param-2)", cmdRWParams->getText()); + +		vmime::shared_ptr <IMAPCommand> cmdRWQuote = IMAPCommand::SELECT( +			/* readOnly */ false, "mailbox name", std::vector <vmime::string>() +		); + +		VASSERT_NOT_NULL("Not null", cmdRWQuote); +		VASSERT_EQ("Text", "SELECT \"mailbox name\"", cmdRWQuote->getText()); +	} + +	void testSTATUS() { + +		std::vector <vmime::string> attribs; +		attribs.push_back("attrib-1"); +		attribs.push_back("attrib-2"); + + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::STATUS("mailbox-name", attribs); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "STATUS mailbox-name (attrib-1 attrib-2)", cmd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::STATUS("mailbox name", attribs); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "STATUS \"mailbox name\" (attrib-1 attrib-2)", cmdQuote->getText()); +	} + +	void testCREATE() { + +		std::vector <vmime::string> params; +		params.push_back("param-1"); +		params.push_back("param-2"); + + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::CREATE("mailbox-name", params); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "CREATE mailbox-name (param-1 param-2)", cmd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::CREATE("mailbox name", params); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "CREATE \"mailbox name\" (param-1 param-2)", cmdQuote->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdNoParam = +			IMAPCommand::CREATE("mailbox-name", std::vector <vmime::string>()); + +		VASSERT_NOT_NULL("Not null", cmdNoParam); +		VASSERT_EQ("Text", "CREATE mailbox-name", cmdNoParam->getText()); +	} + +	void testDELETE() { + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::DELETE("mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "DELETE mailbox-name", cmd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::DELETE("mailbox name"); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "DELETE \"mailbox name\"", cmdQuote->getText()); +	} + +	void testRENAME() { + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::RENAME("mailbox-name", "new-mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RENAME mailbox-name new-mailbox-name", cmd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::RENAME("mailbox name", "new mailbox name"); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "RENAME \"mailbox name\" \"new mailbox name\"", cmdQuote->getText()); +	} + +	void testFETCH() { + +		std::vector <vmime::string> params; +		params.push_back("param-1"); +		params.push_back("param-2"); + + +		vmime::shared_ptr <IMAPCommand> cmdNum = +			IMAPCommand::FETCH(vmime::net::messageSet::byNumber(42), params); + +		VASSERT_NOT_NULL("Not null", cmdNum); +		VASSERT_EQ("Text", "FETCH 42 (param-1 param-2)", cmdNum->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdNums = +			IMAPCommand::FETCH(vmime::net::messageSet::byNumber(42, 47), params); + +		VASSERT_NOT_NULL("Not null", cmdNums); +		VASSERT_EQ("Text", "FETCH 42:47 (param-1 param-2)", cmdNums->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUID = +			IMAPCommand::FETCH(vmime::net::messageSet::byUID(42), params); + +		VASSERT_NOT_NULL("Not null", cmdUID); +		VASSERT_EQ("Text", "UID FETCH 42 (param-1 param-2)", cmdUID->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUIDs = +			IMAPCommand::FETCH(vmime::net::messageSet::byUID(42, 47), params); + +		VASSERT_NOT_NULL("Not null", cmdUIDs); +		VASSERT_EQ("Text", "UID FETCH 42:47 (param-1 param-2)", cmdUIDs->getText()); +	} + +	void testSTORE() { + +		std::vector <vmime::string> flags; +		flags.push_back("flag-1"); +		flags.push_back("flag-2"); + + +		vmime::shared_ptr <IMAPCommand> cmdNum = IMAPCommand::STORE( +			vmime::net::messageSet::byNumber(42), vmime::net::message::FLAG_MODE_SET, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdNum); +		VASSERT_EQ("Text", "STORE 42 FLAGS (flag-1 flag-2)", cmdNum->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdNums = IMAPCommand::STORE( +			vmime::net::messageSet::byNumber(42, 47), vmime::net::message::FLAG_MODE_SET, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdNums); +		VASSERT_EQ("Text", "STORE 42:47 FLAGS (flag-1 flag-2)", cmdNums->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUID = IMAPCommand::STORE( +			vmime::net::messageSet::byUID(42), vmime::net::message::FLAG_MODE_SET, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdUID); +		VASSERT_EQ("Text", "UID STORE 42 FLAGS (flag-1 flag-2)", cmdUID->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUIDs = IMAPCommand::STORE( +			vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_SET, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdUIDs); +		VASSERT_EQ("Text", "UID STORE 42:47 FLAGS (flag-1 flag-2)", cmdUIDs->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdAdd = IMAPCommand::STORE( +			vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_ADD, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdAdd); +		VASSERT_EQ("Text", "UID STORE 42:47 +FLAGS (flag-1 flag-2)", cmdAdd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdRem = IMAPCommand::STORE( +			vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_REMOVE, flags +		); + +		VASSERT_NOT_NULL("Not null", cmdRem); +		VASSERT_EQ("Text", "UID STORE 42:47 -FLAGS (flag-1 flag-2)", cmdRem->getText()); +	} + +	void testAPPEND() { + +		std::vector <vmime::string> flags; +		flags.push_back("flag-1"); +		flags.push_back("flag-2"); + + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::APPEND("mailbox-name", flags, /* date */ NULL, 1234); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "APPEND mailbox-name (flag-1 flag-2) {1234}", cmd->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::APPEND("mailbox name", flags, /* date */ NULL, 1234); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "APPEND \"mailbox name\" (flag-1 flag-2) {1234}", cmdQuote->getText()); + + +		vmime::datetime date(2014, 3, 15, 23, 11, 47, vmime::datetime::GMT2); +		vmime::shared_ptr <IMAPCommand> cmdDate = +			IMAPCommand::APPEND("mailbox name", flags, &date, 1234); + +		VASSERT_NOT_NULL("Not null", cmdDate); +		VASSERT_EQ("Text", "APPEND \"mailbox name\" (flag-1 flag-2) \"15-Mar-2014 23:11:47 +0200\" {1234}", cmdDate->getText()); +	} + +	void testCOPY() { + +		vmime::shared_ptr <IMAPCommand> cmdNum = +			IMAPCommand::COPY(vmime::net::messageSet::byNumber(42), "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmdNum); +		VASSERT_EQ("Text", "COPY 42 mailbox-name", cmdNum->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdNums = +			IMAPCommand::COPY(vmime::net::messageSet::byNumber(42, 47), "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmdNums); +		VASSERT_EQ("Text", "COPY 42:47 mailbox-name", cmdNums->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUID = +			IMAPCommand::COPY(vmime::net::messageSet::byUID(42), "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmdUID); +		VASSERT_EQ("Text", "UID COPY 42 mailbox-name", cmdUID->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdUIDs = +			IMAPCommand::COPY(vmime::net::messageSet::byUID(42, 47), "mailbox-name"); + +		VASSERT_NOT_NULL("Not null", cmdUIDs); +		VASSERT_EQ("Text", "UID COPY 42:47 mailbox-name", cmdUIDs->getText()); + + +		vmime::shared_ptr <IMAPCommand> cmdQuote = +			IMAPCommand::COPY(vmime::net::messageSet::byNumber(42, 47), "mailbox name"); + +		VASSERT_NOT_NULL("Not null", cmdQuote); +		VASSERT_EQ("Text", "COPY 42:47 \"mailbox name\"", cmdQuote->getText()); +	} + +	void testSEARCH() { + +		std::vector <vmime::string> searchKeys; +		searchKeys.push_back("search-key-1"); +		searchKeys.push_back("search-key-2"); + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::SEARCH(searchKeys, /* charset */ NULL); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "SEARCH search-key-1 search-key-2", cmd->getText()); + + +		vmime::charset cset("test-charset"); + +		vmime::shared_ptr <IMAPCommand> cmdCset = +			IMAPCommand::SEARCH(searchKeys, &cset); + +		VASSERT_NOT_NULL("Not null", cmdCset); +		VASSERT_EQ("Text", "SEARCH CHARSET test-charset search-key-1 search-key-2", cmdCset->getText()); +	} + +	void testSTARTTLS() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::STARTTLS(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "STARTTLS", cmd->getText()); +	} + +	void testCAPABILITY() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::CAPABILITY(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "CAPABILITY", cmd->getText()); +	} + +	void testNOOP() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::NOOP(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "NOOP", cmd->getText()); +	} + +	void testEXPUNGE() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::EXPUNGE(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "EXPUNGE", cmd->getText()); +	} + +	void testCLOSE() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::CLOSE(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "CLOSE", cmd->getText()); +	} + +	void testLOGOUT() { + +		vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LOGOUT(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "LOGOUT", cmd->getText()); +	} + +	void testSend() { + +		vmime::shared_ptr <IMAPCommand> cmd = +			IMAPCommand::createCommand("MY_COMMAND param1 param2"); + +		vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::security::authenticator> auth = +			vmime::make_shared <vmime::security::defaultAuthenticator>(); + +		vmime::shared_ptr <IMAPStore> store = +			vmime::make_shared <IMAPStore>(sess, auth, /* secured */ false); + +		vmime::shared_ptr <IMAPConnection> conn = +			vmime::make_shared <IMAPConnection>(store, auth); + +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); +		conn->setSocket(sok); + +		cmd->send(conn); + +		vmime::string response; +		sok->localReceive(response); + +		VASSERT_EQ("Sent buffer", vmime::string(*conn->getTag()) + " MY_COMMAND param1 param2\r\n", response); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPParserTest.cpp b/vmime-master/tests/net/imap/IMAPParserTest.cpp new file mode 100644 index 0000000..60ce16d --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPParserTest.cpp @@ -0,0 +1,374 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/imap/IMAPTag.hpp" +#include "vmime/net/imap/IMAPParser.hpp" + + +VMIME_TEST_SUITE_BEGIN(IMAPParserTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testExtraSpaceInCapaResponse) +		VMIME_TEST(testContinueReqWithoutSpace) +		VMIME_TEST(testNILValueInBodyFldEnc) +		VMIME_TEST(testFETCHResponse_optional_body_fld_lang) +		VMIME_TEST(testFETCHBodyStructure_NIL_body_fld_param_value) +		VMIME_TEST(testFETCHBodyStructure_empty_body_fld_param_instead_of_NIL) +		VMIME_TEST(testPipelining) +		VMIME_TEST(testStarFlagWithoutBackslash) +	VMIME_TEST_LIST_END + + +	// For Apple iCloud IMAP server +	void testExtraSpaceInCapaResponse() { + +		const char* resp = +			"* CAPABILITY IMAP4rev1 AUTH=ATOKEN AUTH=PLAIN \r\n"  // extra space at end +			"a001 OK Capability completed.\r\n"; + +		// Strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(true); + +			VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +		} + +		// Non-strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(false); + +			VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); +		} +	} + +	// For Apple iCloud/Exchange IMAP server +	void testContinueReqWithoutSpace() { + +		// continue_req   ::= "+" SPACE (resp_text / base64) +		// +		// Some servers do not send SPACE when response text is empty. +		// IMAP parser should allow this in non-strict mode. +		// +		// Eg: +		// +		//   C: a002 AUTHENTICATE xxx[CR][LF] +		//   S: +[CR][LF] + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +				vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		socket->localSend("+\r\n"); + +		vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = +			vmime::make_shared <vmime::net::imap::IMAPParser>(); + +		parser->setSocket(socket); +		parser->setTimeoutHandler(toh); + +		parser->setStrict(false); +		VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + +		++(*tag); + +		socket->localSend("+\r\n"); + +		parser->setStrict(true); +		VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +	} + +	// When an IMAP4 client sends a FETCH (bodystructure) request to a server +	// that is running the Exchange Server 2007 IMAP4 service, a corrupted +	// response is sent as a reply +	// --> http://support.microsoft.com/kb/975918/en-us +	void testNILValueInBodyFldEnc() { + +		const char* resp = "* 7970 FETCH (UID 8036 FLAGS () BODYSTRUCTURE (\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL NIL 175501 1651 NIL NIL NIL NIL) RFC822.HEADER {3}\r\nx\r\n)\r\na001 OK FETCH complete\r\n"; + +		// Strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(true); + +			VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +		} + +		// Non-strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(false); + +			VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); +		} +	} + +	// "body_fld_lang" is optional after "body_fld_dsp" in "body_ext_mpart" (Yahoo) +	void testFETCHResponse_optional_body_fld_lang() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +			vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		const char* resp = "* 1 FETCH (UID 7 RFC822.SIZE 694142 BODYSTRUCTURE (((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 193 0 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"----=_Part_536_109505883.1410847112666\") NIL)(\"image\" \"jpeg\" NIL \"<4db20d0e-e9f8-729b-aaf7-688b5956d0bc@yahoo.com>\" NIL \"base64\" 351784 NIL (\"attachment\" (\"name\" \"att2\" \"filename\" \"9.jpg\")) NIL NIL)(\"image\" \"jpeg\" NIL \"<542417d7-c0ed-db72-f9fc-d9ab2c7e0a6f@yahoo.com>\" NIL \"base64\" 337676 NIL (\"attachment\" (\"name\" \"att3\" \"filename\" \"10.jpg\")) NIL NIL) \"mixed\" (\"boundary\" \"----=_Part_537_1371134700.1410847112668\") NIL) RFC822.HEADER {3}\r\nx\r\n)\r\na001 OK FETCH complete\r\n"; + +		socket->localSend(resp); + +		vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = +			vmime::make_shared <vmime::net::imap::IMAPParser>(); + +		parser->setSocket(socket); +		parser->setTimeoutHandler(toh); + +		VASSERT_NO_THROW("parse", parser->readResponse(*tag)); +	} + +	// Support for NIL boundary, for mail.ru IMAP server: +	// https://www.ietf.org/mail-archive/web/imapext/current/msg05442.html +	void testFETCHBodyStructure_NIL_body_fld_param_value() { + +		// ...("boundary" NIL)))... is an invalid syntax for a "body_fld_param_item" +		const char* resp = "* 1 FETCH (BODYSTRUCTURE ((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"8bit\" 536 0 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"8bit\" 7130 0 NIL NIL NIL NIL) \"alternative\" (\"boundary\" NIL)))\r\na001 OK FETCH complete\r\n"; + +		// Strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(true); + +			VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +		} + +		// Non-strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(false); + +			VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); +		} +	} + +	void testFETCHBodyStructure_empty_body_fld_param_instead_of_NIL() { + +		const char* resp = "* 1 FETCH (BODYSTRUCTURE ((\"text\" \"html\" (\"charset\" \"cp1251\") NIL NIL \"base64\" 84056 0 NIL (\"inline\" NIL) NIL NIL)(\"image\" \"gif\" () \"25b2b55b5d97f04e9ea939fe32a46a65.gif\" NIL \"base64\" 20776 NIL (\"inline\" NIL) NIL NIL) \"related\" (\"boundary\" NIL)))\r\na001 OK FETCH complete\r\n"; + +		// Strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(true); + +			VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +		} + +		// Non-strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); +			parser->setStrict(false); + +			VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); +		} +	} + +	// Test pipelined and out-of-order replies +	void testPipelining() { + +		/* +		[C] a001 SELECT "INBOX" +		[C] a002 UID FETCH 42 (INTERNALDATE) +		[C] a003 UID FETCH 43 (INTERNALDATE) +		[S] * NO Error for a001 +		[S] a001 NO Access denied +		[S] * NO Error for a003 +		[S] a003 BAD No mailbox selected +		[S] * NO Error for a002 +		[S] a002 BAD No mailbox selected +		*/ + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::net::imap::IMAPTag tag1;  // a001 +		vmime::net::imap::IMAPTag tag2(tag1);  // a002 +		++tag2; +		vmime::net::imap::IMAPTag tag3(tag2);  // a003 +		++tag3; + +		socket->localSend( +			"* NO Error for a001\r\n" +			"a001 NO Access denied\r\n" +			"* NO Error for a003\r\n" +			"a003 BAD No mailbox selected a003\r\n" +			"* NO Error for a002\r\n" +			"a002 BAD No mailbox selected a002\r\n" +		); + +		vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = +			vmime::make_shared <vmime::net::imap::IMAPParser>(); + +		parser->setSocket(socket); +		parser->setTimeoutHandler(toh); + +		// Test response a001 +		vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp1(parser->readResponse(tag1, /* literalHandler */ NULL)); +		VASSERT("a001 response", resp1); +		VASSERT("a001 response_done", resp1->response_done); +		VASSERT_EQ("a001 response tag", "a001", resp1->response_done->response_tagged->tag->tagString); +		VASSERT_EQ("a001 response text", "Access denied", resp1->response_done->response_tagged->resp_cond_state->resp_text->text); +		VASSERT_EQ("a001 resp_data.size()", 1, resp1->continue_req_or_response_data.size()); +		VASSERT("a001 resp_data[0]", resp1->continue_req_or_response_data[0]->response_data); +		VASSERT("a001 resp_cond_state", resp1->continue_req_or_response_data[0]->response_data->resp_cond_state); +		VASSERT_EQ("a001 resp_cond_state.text", "Error for a001", resp1->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); +		VASSERT_EQ("a001 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp1->continue_req_or_response_data[0]->response_data->resp_cond_state->status); + +		// Test response a002 +		vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp2(parser->readResponse(tag2, /* literalHandler */ NULL)); +		VASSERT("a002 response", resp2); +		VASSERT("a002 response_done", resp2->response_done); +		VASSERT_EQ("a002 response tag", "a002", resp2->response_done->response_tagged->tag->tagString); +		VASSERT_EQ("a002 response text", "No mailbox selected a002", resp2->response_done->response_tagged->resp_cond_state->resp_text->text); +		VASSERT_EQ("a002 resp_data.size()", 1, resp2->continue_req_or_response_data.size()); +		VASSERT("a002 resp_data[0]", resp2->continue_req_or_response_data[0]->response_data); +		VASSERT("a002 resp_cond_state", resp2->continue_req_or_response_data[0]->response_data->resp_cond_state); +		VASSERT_EQ("a002 resp_cond_state.text", "Error for a002", resp2->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); +		VASSERT_EQ("a002 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp2->continue_req_or_response_data[0]->response_data->resp_cond_state->status); + +		// Test response a003 +		vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp3(parser->readResponse(tag3, /* literalHandler */ NULL)); +		VASSERT("a003 response", resp3); +		VASSERT("a003 response_done", resp3->response_done); +		VASSERT_EQ("a003 response tag", "a003", resp3->response_done->response_tagged->tag->tagString); +		VASSERT_EQ("a003 response text", "No mailbox selected a003", resp3->response_done->response_tagged->resp_cond_state->resp_text->text); +		VASSERT_EQ("a003 resp_data.size()", 1, resp3->continue_req_or_response_data.size()); +		VASSERT("a003 resp_data[0]", resp3->continue_req_or_response_data[0]->response_data); +		VASSERT("a003 resp_cond_state", resp3->continue_req_or_response_data[0]->response_data->resp_cond_state); +		VASSERT_EQ("a003 resp_cond_state.text", "Error for a003", resp3->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); +		VASSERT_EQ("a003 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp3->continue_req_or_response_data[0]->response_data->resp_cond_state->status); +	} + +	// Some IMAP servers return "*" instead of "\*" in PERMANENTFLAGS +	void testStarFlagWithoutBackslash() { + +		const char* resp = +			"* OK [PERMANENTFLAGS (Answered Flagged Deleted Seen Draft *)] Flags permitted.\r\n" +			"a001 OK Completed.\r\n"; + +		// Strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			auto toh = vmime::make_shared <testTimeoutHandler>(); + +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(toh); +			parser->setStrict(true); + +			VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); +		} + +		// Non-strict mode +		{ +			auto socket = vmime::make_shared <testSocket>(); +			auto toh = vmime::make_shared <testTimeoutHandler>(); + +			auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + +			socket->localSend(resp); + +			auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + +			parser->setSocket(socket); +			parser->setTimeoutHandler(toh); +			parser->setStrict(false); + +			VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); +		} +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPTagTest.cpp b/vmime-master/tests/net/imap/IMAPTagTest.cpp new file mode 100644 index 0000000..c8e09b6 --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPTagTest.cpp @@ -0,0 +1,90 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/imap/IMAPTag.hpp" + + +VMIME_TEST_SUITE_BEGIN(imapTagTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testConstruct) +		VMIME_TEST(testIncrement) +		VMIME_TEST(testReset) +		VMIME_TEST(testNumber) +	VMIME_TEST_LIST_END + + +	void testConstruct() { + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +			vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		VASSERT_EQ("init", "a001", static_cast <vmime::string>(*tag)); +	} + +	void testIncrement() { + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +			vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		(*tag)++; +		VASSERT_EQ("init", "a002", static_cast <vmime::string>(*tag)); + +		(*tag)++; +		VASSERT_EQ("init", "a003", static_cast <vmime::string>(*tag)); + +		(*tag)++; +		VASSERT_EQ("init", "a004", static_cast <vmime::string>(*tag)); +	} + +	void testReset() { + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +			vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		for (int i = tag->number() ; i < tag->maximumNumber() ; ++i) { +			(*tag)++; +		} + +		VASSERT_EQ("last", "Z999", static_cast <vmime::string>(*tag)); + +		(*tag)++; + +		VASSERT_EQ("reset", "a001", static_cast <vmime::string>(*tag)); +	} + +	void testNumber() { + +		vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = +			vmime::make_shared <vmime::net::imap::IMAPTag>(); + +		for (int i = 0 ; i < 41 ; ++i) { +			(*tag)++; +		} + +		VASSERT_EQ("number", 42, tag->number()); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPUtilsTest.cpp b/vmime-master/tests/net/imap/IMAPUtilsTest.cpp new file mode 100644 index 0000000..b707fd0 --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPUtilsTest.cpp @@ -0,0 +1,283 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/imap/IMAPUtils.hpp" +#include "vmime/net/imap/IMAPParser.hpp" + + +using namespace vmime::net::imap; + + + +VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testQuoteString) +		VMIME_TEST(testToModifiedUTF7) +		VMIME_TEST(testFromModifiedUTF7) +		VMIME_TEST(testConvertAddressList) +		VMIME_TEST(testMessageFlagList) +		VMIME_TEST(testDateTime) +		VMIME_TEST(testPathToString) +		VMIME_TEST(testStringToPath) +		VMIME_TEST(testBuildFetchCommand) +	VMIME_TEST_LIST_END + + +	void testQuoteString() { + +		VASSERT_EQ("unquoted", "ascii", IMAPUtils::quoteString("ascii")); +		VASSERT_EQ("space", "\"ascii with space\"", IMAPUtils::quoteString("ascii with space")); + +		VASSERT_EQ("special1", "\"(\"", IMAPUtils::quoteString("(")); +		VASSERT_EQ("special2", "\")\"", IMAPUtils::quoteString(")")); +		VASSERT_EQ("special3", "\"{\"", IMAPUtils::quoteString("{")); +		VASSERT_EQ("special4", "\" \"", IMAPUtils::quoteString(" ")); +		VASSERT_EQ("special5", "\"%\"", IMAPUtils::quoteString("%")); +		VASSERT_EQ("special6", "\"*\"", IMAPUtils::quoteString("*")); +		VASSERT_EQ("special7", "\"\\\"\"", IMAPUtils::quoteString("\"")); +		VASSERT_EQ("special8", "\"\\\\\"", IMAPUtils::quoteString("\\")); +		VASSERT_EQ("special9", "\"\x7f\"", IMAPUtils::quoteString("\x7f")); + +	} + +	void testToModifiedUTF7() { + +		#define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + +		// Example strings from RFC-1642 (modified for IMAP UTF-7) +		VASSERT_EQ("1", "A&ImIDkQ-.", IMAPUtils::toModifiedUTF7('/', FC("A\xe2\x89\xa2\xce\x91."))); +		VASSERT_EQ("2", "Hi Mum &Jjo-!", IMAPUtils::toModifiedUTF7('/', FC("Hi Mum \xe2\x98\xba!"))); +		VASSERT_EQ("3", "&ZeVnLIqe-", IMAPUtils::toModifiedUTF7('/', FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"))); +		VASSERT_EQ("4", "Item 3 is &AKM- 1.", IMAPUtils::toModifiedUTF7('/', FC("Item 3 is \xc2\xa3 1."))); + +		VASSERT_EQ("escape char", "&-", IMAPUtils::toModifiedUTF7('/', FC("&"))); +		VASSERT_EQ("ascii", "plain ascii text", IMAPUtils::toModifiedUTF7('/', FC("plain ascii text"))); +		VASSERT_EQ("special", "!\"#$%*+-;<=>@[]^_`{|}", IMAPUtils::toModifiedUTF7('/', FC("!\"#$%*+-;<=>@[]^_`{|}"))); + +		#undef FC +	} + +	void testFromModifiedUTF7() { + +		#define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + +		// Example strings from RFC-1642 (modified for IMAP UTF-7) +		VASSERT_EQ("1", FC("A\xe2\x89\xa2\xce\x91."), IMAPUtils::fromModifiedUTF7("A&ImIDkQ-.")); +		VASSERT_EQ("2", FC("Hi Mum \xe2\x98\xba!"), IMAPUtils::fromModifiedUTF7("Hi Mum &Jjo-!")); +		VASSERT_EQ("3", FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"), IMAPUtils::fromModifiedUTF7("&ZeVnLIqe-")); +		VASSERT_EQ("4", FC("Item 3 is \xc2\xa3 1."), IMAPUtils::fromModifiedUTF7("Item 3 is &AKM- 1.")); + +		VASSERT_EQ("escape char", FC("&"), IMAPUtils::fromModifiedUTF7("&-")); +		VASSERT_EQ("ascii", FC("plain ascii text"), IMAPUtils::fromModifiedUTF7("plain ascii text")); +		VASSERT_EQ("special", FC("!\"#$%*+;<=>@[]^_`{|}"), IMAPUtils::fromModifiedUTF7("!\"#$%*+-;<=>@[]^_`{|}")); + +		#undef FC +	} + +	void testConvertAddressList() { + +		IMAPParser parser; +		IMAPParser::address_list addrList; + +		vmime::string line("((\"name\" NIL \"mailbox\" \"host\")(\"name2\" NIL \"mailbox2\" \"host2\"))"); +		vmime::size_t pos = 0; + +		VASSERT("parse", addrList.parseImpl(parser, line, &pos)); + +		vmime::mailboxList mboxList; +		IMAPUtils::convertAddressList(addrList, mboxList); + +		VASSERT_EQ("mbox-count", 2, mboxList.getMailboxCount()); +		VASSERT_EQ("mbox-1", "mailbox@host", mboxList.getMailboxAt(0)->getEmail().toString()); +		VASSERT_EQ("mbox-1", "name", mboxList.getMailboxAt(0)->getName().getWholeBuffer()); +		VASSERT_EQ("mbox-2", "mailbox2@host2", mboxList.getMailboxAt(1)->getEmail().toString()); +		VASSERT_EQ("mbox-2", "name2", mboxList.getMailboxAt(1)->getName().getWholeBuffer()); +	} + +	void testMessageFlagList() { + +		int flags = 0; +		std::vector <vmime::string> flagList; + +		// Test each flag +		flags = vmime::net::message::FLAG_REPLIED; +		flagList = IMAPUtils::messageFlagList(flags); +		VASSERT("replied", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); + +		flags = vmime::net::message::FLAG_MARKED; +		flagList = IMAPUtils::messageFlagList(flags); +		VASSERT("marked", std::find(flagList.begin(), flagList.end(), "\\Flagged") != flagList.end()); + +		flags = vmime::net::message::FLAG_DELETED; +		flagList = IMAPUtils::messageFlagList(flags); +		VASSERT("deleted", std::find(flagList.begin(), flagList.end(), "\\Deleted") != flagList.end()); + +		flags = vmime::net::message::FLAG_SEEN; +		flagList = IMAPUtils::messageFlagList(flags); +		VASSERT("seen", std::find(flagList.begin(), flagList.end(), "\\Seen") != flagList.end()); + +		flags = vmime::net::message::FLAG_DRAFT; +		flagList = IMAPUtils::messageFlagList(flags); +		VASSERT("draft", std::find(flagList.begin(), flagList.end(), "\\Draft") != flagList.end()); + +		// Multiple flags +		flags = vmime::net::message::FLAG_REPLIED; +		flagList = IMAPUtils::messageFlagList(flags); + +		VASSERT_EQ("1.size", 1, flagList.size()); +		VASSERT("1.found", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); + +		flags |= vmime::net::message::FLAG_SEEN; +		flagList = IMAPUtils::messageFlagList(flags); + +		VASSERT_EQ("2.size", 2, flagList.size()); +		VASSERT("2.found1", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); +		VASSERT("2.found2", std::find(flagList.begin(), flagList.end(), "\\Seen") != flagList.end()); +	} + +	void testDateTime() { + +		vmime::datetime dt(2014, 3, 17, 23, 26, 22, vmime::datetime::GMT2); +		VASSERT_EQ("datetime", "\"17-Mar-2014 23:26:22 +0200\"", IMAPUtils::dateTime(dt)); +	} + +	void testPathToString() { + +		#define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + +		vmime::net::folder::path path; +		path /= FC("Hi Mum \xe2\x98\xba!"); +		path /= FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"); + +		VASSERT_EQ("string", "Hi Mum &Jjo-!/&ZeVnLIqe-", IMAPUtils::pathToString('/', path)); + +		#undef FC +	} + +	void testStringToPath() { + +		#define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + +		vmime::net::folder::path path = IMAPUtils::stringToPath('/', "Hi Mum &Jjo-!/&ZeVnLIqe-"); + +		VASSERT_EQ("count", 2, path.getSize()); +		VASSERT_EQ("component1", FC("Hi Mum \xe2\x98\xba!"), path[0]); +		VASSERT_EQ("component2", FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"), path[1]); + +		#undef FC +	} + +	void testBuildFetchCommand() { + +		vmime::shared_ptr <IMAPConnection> cnt; +		vmime::net::messageSet msgs = vmime::net::messageSet::byNumber(42); + +		// SIZE +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::SIZE; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("size", "FETCH 42 RFC822.SIZE", cmd->getText()); +		} + +		// FLAGS +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::FLAGS; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("flags", "FETCH 42 FLAGS", cmd->getText()); +		} + +		// STRUCTURE +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::STRUCTURE; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("structure", "FETCH 42 BODYSTRUCTURE", cmd->getText()); +		} + +		// UID +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::UID; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("uid", "FETCH 42 UID", cmd->getText()); +		} + +		// ENVELOPE +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::ENVELOPE; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("envelope", "FETCH 42 ENVELOPE", cmd->getText()); +		} + +		// CONTENT_INFO +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::CONTENT_INFO; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("content", "FETCH 42 BODY[HEADER.FIELDS (CONTENT_TYPE)]", cmd->getText()); +		} + +		// IMPORTANCE +		{ +			vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::IMPORTANCE; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("importance", "FETCH 42 BODY[HEADER.FIELDS (IMPORTANCE X-PRIORITY)]", cmd->getText()); +		} + +		// Any header attribute + full header should give RFC822.HEADER +		{ +			vmime::net::fetchAttributes attribs; +			attribs.add(vmime::net::fetchAttributes::ENVELOPE); +			attribs.add(vmime::net::fetchAttributes::FULL_HEADER); + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("full-header", "FETCH 42 RFC822.HEADER", cmd->getText()); +		} + +		// Test custom header +		{ +			vmime::net::fetchAttributes attribs; +			attribs.add("X-MyHeader"); + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("custom-header", "FETCH 42 BODY[HEADER.FIELDS (x-myheader)]", cmd->getText()); +		} + +		// Test multiple flags +		{ +			vmime::net::fetchAttributes attribs = +				vmime::net::fetchAttributes::UID | vmime::net::fetchAttributes::FLAGS; + +			vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); +			VASSERT_EQ("multiple", "FETCH 42 (FLAGS UID)", cmd->getText()); +		} +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/maildir/maildirStoreTest.cpp b/vmime-master/tests/net/maildir/maildirStoreTest.cpp new file mode 100644 index 0000000..1f418e8 --- /dev/null +++ b/vmime-master/tests/net/maildir/maildirStoreTest.cpp @@ -0,0 +1,584 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/platform.hpp" + +#include "vmime/net/maildir/maildirStore.hpp" +#include "vmime/net/maildir/maildirFormat.hpp" + + +// Shortcuts and helpers +typedef vmime::utility::file::path fspath; +typedef vmime::utility::file::path::component fspathc; + +typedef vmime::net::folder::path fpath; +typedef vmime::net::folder::path::component fpathc; + + +const fpath operator/(const fpath& path, const std::string& c) { + +	return path / fpathc(c); +} + + +/** Test messages */ +static const vmime::string TEST_MESSAGE_1 = +	"From: <test@vmime.org>\r\n" +	"Subject: VMime Test\r\n" +	"Date: Thu, 01 Mar 2007 09:49:35 +0100\r\n" +	"\r\n" +	"Hello, world!"; + + +/** Maildir trees used in tests. +  * Structure: +  * +  *  . +  *  |-- Folder +  *  |   `-- SubFolder +  *  |       |-- SubSubFolder1 +  *  |       `-- SubSubFolder2 +  *  `-- Folder2 +  * +  */ + +// KMail format +static const vmime::string TEST_MAILDIR_KMAIL[] = {  // directories to create +	"/Folder", +	"/Folder/new", +	"/Folder/tmp", +	"/Folder/cur", +	"/.Folder.directory", +	"/.Folder.directory/SubFolder", +	"/.Folder.directory/SubFolder/new", +	"/.Folder.directory/SubFolder/tmp", +	"/.Folder.directory/SubFolder/cur", +	"/.Folder.directory/.SubFolder.directory", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder1", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder1/new", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder1/tmp", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder1/cur", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder2", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder2/new", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder2/tmp", +	"/.Folder.directory/.SubFolder.directory/SubSubFolder2/cur", +	"/Folder2", +	"/Folder2/new", +	"/Folder2/tmp", +	"/Folder2/cur", +	"*"  // end +}; + +static const vmime::string TEST_MAILDIRFILES_KMAIL[] = {  // files to create and their contents +	"/.Folder.directory/.SubFolder.directory/SubSubFolder2/cur/1043236113.351.EmqD:S", TEST_MESSAGE_1, +	"*"  // end +}; + +// Courier format +static const vmime::string TEST_MAILDIR_COURIER[] = {  // directories to create +	"/.Folder", +	"/.Folder/new", +	"/.Folder/tmp", +	"/.Folder/cur", +	"/.Folder.SubFolder", +	"/.Folder.SubFolder", +	"/.Folder.SubFolder/new", +	"/.Folder.SubFolder/tmp", +	"/.Folder.SubFolder/cur", +	"/.Folder.SubFolder.SubSubFolder1", +	"/.Folder.SubFolder.SubSubFolder1/new", +	"/.Folder.SubFolder.SubSubFolder1/tmp", +	"/.Folder.SubFolder.SubSubFolder1/cur", +	"/.Folder.SubFolder.SubSubFolder2", +	"/.Folder.SubFolder.SubSubFolder2/new", +	"/.Folder.SubFolder.SubSubFolder2/tmp", +	"/.Folder.SubFolder.SubSubFolder2/cur", +	"/.Folder2", +	"/.Folder2/new", +	"/.Folder2/tmp", +	"/.Folder2/cur", +	"*"  // end +}; + +static const vmime::string TEST_MAILDIRFILES_COURIER[] = {  // files to create and their contents +	"/.Folder/maildirfolder", "", +	"/.Folder.SubFolder/maildirfolder", "", +	"/.Folder.SubFolder.SubSubFolder1/maildirfolder", "", +	"/.Folder.SubFolder.SubSubFolder2/maildirfolder", "", +	"/.Folder.SubFolder.SubSubFolder2/cur/1043236113.351.EmqD:S", TEST_MESSAGE_1, +	"/.Folder2/maildirfolder", "", +	"*"  // end +}; + + + +VMIME_TEST_SUITE_BEGIN(maildirStoreTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testDetectFormat_KMail) +		VMIME_TEST(testDetectFormat_Courier) + +		VMIME_TEST(testListRootFolders_KMail) +		VMIME_TEST(testListAllFolders_KMail) + +		VMIME_TEST(testListRootFolders_Courier) +		VMIME_TEST(testListAllFolders_Courier) + +		VMIME_TEST(testListMessages_KMail) +		VMIME_TEST(testListMessages_Courier) + +		VMIME_TEST(testRenameFolder_KMail) +		VMIME_TEST(testRenameFolder_Courier) + +		VMIME_TEST(testDestroyFolder_KMail) +		VMIME_TEST(testDestroyFolder_Courier) + +		VMIME_TEST(testFolderExists_KMail) +		VMIME_TEST(testFolderExists_Courier) + +		VMIME_TEST(testCreateFolder_KMail) +		VMIME_TEST(testCreateFolder_Courier) +	VMIME_TEST_LIST_END + + +public: + +	maildirStoreTest() { + +		// Temporary directory +		m_tempPath = fspath() / fspathc("tmp")   // Use /tmp +			/ fspathc("vmime" + vmime::utility::stringUtils::toString(std::time(NULL)) +				+ vmime::utility::stringUtils::toString(std::rand())); +	} + +	void tearDown() { + +		// In case of an uncaught exception +		destroyMaildir(); +	} + +	void testDetectFormat_KMail() { + +		createMaildir(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); + +		vmime::shared_ptr <vmime::net::maildir::maildirStore> store = +			vmime::dynamicCast <vmime::net::maildir::maildirStore>(createAndConnectStore()); + +		VASSERT_EQ("*", "kmail", store->getFormat()->getName()); + +		destroyMaildir(); +	} + +	void testDetectFormat_Courier() { + +		createMaildir(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); + +		vmime::shared_ptr <vmime::net::maildir::maildirStore> store = +			vmime::dynamicCast <vmime::net::maildir::maildirStore>(createAndConnectStore()); + +		VASSERT_EQ("*", "courier", store->getFormat()->getName()); + +		destroyMaildir(); +	} + + +	void testListRootFolders_KMail() { + +		testListRootFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testListRootFolders_Courier() { + +		testListRootFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testListRootFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		// Connect to store +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		// Get root folders, not recursive +		const std::vector <vmime::shared_ptr <vmime::net::folder> > +			rootFolders = rootFolder->getFolders(false); + +		VASSERT_EQ("1", 2, rootFolders.size()); +		VASSERT("2", findFolder(rootFolders, fpath() / "Folder") != NULL); +		VASSERT("3", findFolder(rootFolders, fpath() / "Folder2") != NULL); + +		destroyMaildir(); +	} + + +	void testListAllFolders_KMail() { + +		testListAllFoldersImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testListAllFolders_Courier() { + +		testListAllFoldersImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testListAllFoldersImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		// Connect to store +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		// Get all folders, recursive +		const std::vector <vmime::shared_ptr <vmime::net::folder> > +			allFolders = rootFolder->getFolders(true); + +		VASSERT_EQ("1", 5, allFolders.size()); +		VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL); +		VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") != NULL); +		VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") != NULL); +		VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") != NULL); +		VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL); + +		destroyMaildir(); +	} + + +	void testListMessages_KMail() { + +		testListMessagesImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testListMessages_Courier() { + +		testListMessagesImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testListMessagesImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		vmime::shared_ptr <vmime::net::folder> folder = store->getFolder( +			fpath() / "Folder" / "SubFolder" / "SubSubFolder2" +		); + +		vmime::size_t count, unseen; +		folder->status(count, unseen); + +		VASSERT_EQ("Message count", 1, count); + +		folder->open(vmime::net::folder::MODE_READ_ONLY); + +		vmime::shared_ptr <vmime::net::message> msg = folder->getMessage(1); + +		folder->fetchMessage(msg, vmime::net::fetchAttributes::SIZE); + +		VASSERT_EQ("Message size", TEST_MESSAGE_1.length(), msg->getSize()); + +		std::ostringstream oss; +		vmime::utility::outputStreamAdapter os(oss); +		msg->extract(os); + +		VASSERT_EQ("Message contents", TEST_MESSAGE_1, oss.str()); + +		folder->close(false); + +		destroyMaildir(); +	} + + +	void testRenameFolder_KMail() { + +		try { + +			testRenameFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); + +		} catch (vmime::exception& e) { + +			std::cerr << e; +			throw e; +		} +	} + +	void testRenameFolder_Courier() +	{ +		try { + +			testRenameFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); + +		} catch (vmime::exception& e) { + +			std::cerr << e; +			throw e; +		} +	} + +	void testRenameFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		// Rename "Folder/SubFolder" to "Folder/foo" +		vmime::shared_ptr <vmime::net::folder> folder = +			store->getFolder(fpath() / "Folder" / "SubFolder"); + +		folder->rename(fpath() / "Folder" / "foo"); + +		// Ensure folder and its subfolders have been renamed +		const std::vector <vmime::shared_ptr <vmime::net::folder> > +			allFolders = rootFolder->getFolders(true); + +		VASSERT_EQ("1", 5, allFolders.size()); +		VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL); +		VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") == NULL); +		VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") == NULL); +		VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") == NULL); +		VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL); +		VASSERT("7", findFolder(allFolders, fpath() / "Folder" / "foo") != NULL); +		VASSERT("8", findFolder(allFolders, fpath() / "Folder" / "foo" / "SubSubFolder1") != NULL); +		VASSERT("9", findFolder(allFolders, fpath() / "Folder" / "foo" / "SubSubFolder2") != NULL); + +		destroyMaildir(); +	} + + +	void testDestroyFolder_KMail() { + +		testDestroyFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testDestroyFolder_Courier() { + +		testDestroyFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testDestroyFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		// Destroy "Folder/SubFolder" (total: 3 folders) +		vmime::shared_ptr <vmime::net::folder> folder = +			store->getFolder(fpath() / "Folder" / "SubFolder"); + +		folder->destroy(); + +		// Ensure folder and its subfolders have been deleted and other folders still exist +		const std::vector <vmime::shared_ptr <vmime::net::folder> > +			allFolders = rootFolder->getFolders(true); + +		VASSERT_EQ("1", 2, allFolders.size()); +		VASSERT("2", findFolder(allFolders, fpath() / "Folder") != NULL); +		VASSERT("3", findFolder(allFolders, fpath() / "Folder" / "SubFolder") == NULL); +		VASSERT("4", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder1") == NULL); +		VASSERT("5", findFolder(allFolders, fpath() / "Folder" / "SubFolder" / "SubSubFolder2") == NULL); +		VASSERT("6", findFolder(allFolders, fpath() / "Folder2") != NULL); + +		destroyMaildir(); +	} + + +	void testFolderExists_KMail() { + +		testFolderExistsImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testFolderExists_Courier() { + +		testFolderExistsImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testFolderExistsImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		VASSERT("1",  store->getFolder(fpath() / "Folder" / "SubFolder")->exists()); +		VASSERT("2", !store->getFolder(fpath() / "Folder" / "SubSubFolder1")->exists()); +		VASSERT("3",  store->getFolder(fpath() / "Folder2")->exists()); +		VASSERT("4",  store->getFolder(fpath() / "Folder" / "SubFolder" / "SubSubFolder2")->exists()); + +		destroyMaildir(); +	} + + +	void testCreateFolder_KMail() { + +		testCreateFolderImpl(TEST_MAILDIR_KMAIL, TEST_MAILDIRFILES_KMAIL); +	} + +	void testCreateFolder_Courier() { + +		testCreateFolderImpl(TEST_MAILDIR_COURIER, TEST_MAILDIRFILES_COURIER); +	} + +	void testCreateFolderImpl(const vmime::string* const dirs, const vmime::string* const files) { + +		createMaildir(dirs, files); + +		vmime::shared_ptr <vmime::net::store> store = createAndConnectStore(); +		vmime::shared_ptr <vmime::net::folder> rootFolder = store->getRootFolder(); + +		VASSERT("Before", !store->getFolder(fpath() / "Folder" / "NewFolder")->exists()); + +		vmime::net::folderAttributes attribs; +		attribs.setType(vmime::net::folderAttributes::TYPE_CONTAINS_MESSAGES); + +		VASSERT_NO_THROW("Creation", store->getFolder(fpath() / "Folder" / "NewFolder")->create(attribs)); + +		VASSERT("After", store->getFolder(fpath() / "Folder" / "NewFolder")->exists()); + +		destroyMaildir(); +	} + +private: + +	vmime::utility::file::path m_tempPath; + + +	vmime::shared_ptr <vmime::net::store> createAndConnectStore() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::store> store = +			session->getStore(getStoreURL()); + +		store->connect(); + +		return store; +	} + +	const vmime::shared_ptr <vmime::net::folder> findFolder( +		const std::vector <vmime::shared_ptr <vmime::net::folder> >& folders, +		const vmime::net::folder::path& path +	) { + +		for (size_t i = 0, n = folders.size() ; i < n ; ++i) { + +			if (folders[i]->getFullPath() == path) { +				return folders[i]; +			} +		} + +		return vmime::null; +	} + +	const vmime::utility::url getStoreURL() { + +		vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf = +			vmime::platform::getHandler()->getFileSystemFactory(); + +		vmime::utility::url url(std::string("maildir://localhost") +			+ fsf->pathToString(m_tempPath)); + +		return url; +	} + +	void createMaildir(const vmime::string* const dirs, const vmime::string* const files) { + +		vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf = +			vmime::platform::getHandler()->getFileSystemFactory(); + +		vmime::shared_ptr <vmime::utility::file> rootDir = fsf->create(m_tempPath); +		rootDir->createDirectory(false); + +		for (vmime::string const* dir = dirs ; *dir != "*" ; ++dir) { + +			vmime::shared_ptr <vmime::utility::file> fdir = fsf->create(m_tempPath / fsf->stringToPath(*dir)); +			fdir->createDirectory(false); +		} + +		for (vmime::string const* file = files ; *file != "*" ; file += 2) { + +			const vmime::string& contents = *(file + 1); + +			vmime::shared_ptr <vmime::utility::file> ffile = fsf->create(m_tempPath / fsf->stringToPath(*file)); +			ffile->createFile(); + +			vmime::shared_ptr <vmime::utility::fileWriter> fileWriter = ffile->getFileWriter(); +			vmime::shared_ptr <vmime::utility::outputStream> os = fileWriter->getOutputStream(); + +			os->write(contents.data(), contents.length()); +			os->flush(); + +			fileWriter = vmime::null; +		} + +	} + +	void destroyMaildir() { + +		vmime::shared_ptr <vmime::utility::fileSystemFactory> fsf = +			vmime::platform::getHandler()->getFileSystemFactory(); + +		recursiveDelete(fsf->create(m_tempPath)); +	} + +	void recursiveDelete(vmime::shared_ptr <vmime::utility::file> dir) { + +		if (!dir->exists() || !dir->isDirectory()) { +			return; +		} + +		vmime::shared_ptr <vmime::utility::fileIterator> files = dir->getFiles(); + +		// First, delete files and subdirectories in this directory +		while (files->hasMoreElements()) { + +			vmime::shared_ptr <vmime::utility::file> file = files->nextElement(); + +			if (file->isDirectory()) { + +				recursiveDelete(file); + +			} else { + +				try { +					file->remove(); +				} catch (vmime::exceptions::filesystem_exception&) { +					// Ignore +				} +			} +		} + +		// Then, delete this (empty) directory +		try { +			dir->remove(); +		} catch (vmime::exceptions::filesystem_exception&) { +			// Ignore +		} +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/maildir/maildirUtilsTest.cpp b/vmime-master/tests/net/maildir/maildirUtilsTest.cpp new file mode 100644 index 0000000..9deeebf --- /dev/null +++ b/vmime-master/tests/net/maildir/maildirUtilsTest.cpp @@ -0,0 +1,54 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/maildir/maildirUtils.hpp" + + +using namespace vmime::net::maildir; + + +VMIME_TEST_SUITE_BEGIN(maildirUtilsTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testMessageSetToNumberList) +	VMIME_TEST_LIST_END + + +	void testMessageSetToNumberList() { + +		const std::vector <size_t> msgNums = +			maildirUtils::messageSetToNumberList( +				vmime::net::messageSet::byNumber(5, -1), +				/* msgCount */ 8 +			); + +		VASSERT_EQ("Count", 4, msgNums.size()); +		VASSERT_EQ("1", 5, msgNums[0]); +		VASSERT_EQ("2", 6, msgNums[1]); +		VASSERT_EQ("3", 7, msgNums[2]); +		VASSERT_EQ("4", 8, msgNums[3]); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/messageSetTest.cpp b/vmime-master/tests/net/messageSetTest.cpp new file mode 100644 index 0000000..dee5dc8 --- /dev/null +++ b/vmime-master/tests/net/messageSetTest.cpp @@ -0,0 +1,229 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/messageSet.hpp" + + +VMIME_TEST_SUITE_BEGIN(messageSetTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testNumberSet_Single) +		VMIME_TEST(testNumberSet_Range) +		VMIME_TEST(testNumberSet_InvalidRange) +		VMIME_TEST(testNumberSet_InvalidFirst) +		VMIME_TEST(testNumberSet_InfiniteRange) +		VMIME_TEST(testNumberSet_Multiple) +		VMIME_TEST(testUIDSet_Single) +		VMIME_TEST(testUIDSet_Range) +		VMIME_TEST(testUIDSet_InfiniteRange) +		VMIME_TEST(testUIDSet_MultipleNumeric) +		VMIME_TEST(testUIDSet_MultipleNonNumeric) +		VMIME_TEST(testIsNumberSet) +		VMIME_TEST(testIsUIDSet) +		VMIME_TEST(testMixedRanges) +	VMIME_TEST_LIST_END + + +	class messageSetStringEnumerator : public vmime::net::messageSetEnumerator { + +	public: + +		messageSetStringEnumerator() +			: m_first(true) { + +		} + +		void enumerateNumberMessageRange(const vmime::net::numberMessageRange& range) { + +			if (!m_first) { +				m_oss << ","; +			} + +			if (range.getFirst() == range.getLast()) { +				m_oss << range.getFirst(); +			} else if (range.getLast() == size_t(-1)) { +				m_oss << range.getFirst() << ":(LAST)"; +			} else { +				m_oss << range.getFirst() << ":" << range.getLast(); +			} + +			m_first = false; +		} + +		void enumerateUIDMessageRange(const vmime::net::UIDMessageRange& range) { + +			if (!m_first) { +				m_oss << ","; +			} + +			if (range.getFirst() == range.getLast()) { +				m_oss << range.getFirst(); +			} else if (range.getLast() == size_t(-1)) { +				m_oss << range.getFirst() << ":(LAST)"; +			} else { +				m_oss << range.getFirst() << ":" << range.getLast(); +			} + +			m_first = false; +		} + +		const std::string str() const { + +			return m_oss.str(); +		} + +	private: + +		std::ostringstream m_oss; +		bool m_first; +	}; + + +	const std::string enumerateAsString(const vmime::net::messageSet& set) { + +		messageSetStringEnumerator en; +		set.enumerate(en); + +		return en.str(); +	} + + +	void testNumberSet_Single() { + +		VASSERT_EQ("str", "42", enumerateAsString(vmime::net::messageSet::byNumber(42))); +	} + +	void testNumberSet_Range() { + +		VASSERT_EQ("str", "42:100", enumerateAsString(vmime::net::messageSet::byNumber(42, 100))); +	} + +	void testNumberSet_InvalidRange() { + +		VASSERT_THROW("first > last", vmime::net::messageSet::byNumber(100, 42), std::invalid_argument); +	} + +	void testNumberSet_InvalidFirst() { + +		VASSERT_THROW("first == -1", vmime::net::messageSet::byNumber(-1, 42), std::invalid_argument); +	} + +	void testNumberSet_InfiniteRange() { + +		VASSERT_EQ("str", "42:(LAST)", enumerateAsString(vmime::net::messageSet::byNumber(42, -1))); +	} + +	void testNumberSet_Multiple() { + +		std::vector <vmime::size_t> numbers; +		numbers.push_back(1);    // test grouping 1:3 +		numbers.push_back(89);   // test sorting +		numbers.push_back(2); +		numbers.push_back(3); +		numbers.push_back(42); +		numbers.push_back(53);   // test grouping 53:57 +		numbers.push_back(54); +		numbers.push_back(55); +		numbers.push_back(56); +		numbers.push_back(56);   // test duplicates +		numbers.push_back(57); +		numbers.push_back(99); + +		VASSERT_EQ("str", "1:3,42,53:57,89,99", enumerateAsString(vmime::net::messageSet::byNumber(numbers))); +	} + + +	void testUIDSet_Single() { + +		VASSERT_EQ("str", "abcdef", enumerateAsString(vmime::net::messageSet::byUID("abcdef"))); +	} + +	void testUIDSet_Range() { + +		VASSERT_EQ("str", "abc:def", enumerateAsString(vmime::net::messageSet::byUID("abc:def"))); +	} + +	void testUIDSet_InfiniteRange() { + +		VASSERT_EQ("str", "abc:*", enumerateAsString(vmime::net::messageSet::byUID("abc", "*"))); +	} + +	void testUIDSet_MultipleNumeric() { + +		std::vector <vmime::net::message::uid> uids; +		uids.push_back("1");    // test grouping 1:3 +		uids.push_back("89");   // test sorting +		uids.push_back("2"); +		uids.push_back("3"); +		uids.push_back("42"); +		uids.push_back("53");   // test grouping 53:57 +		uids.push_back("54"); +		uids.push_back("55"); +		uids.push_back("56"); +		uids.push_back("56");   // test duplicates +		uids.push_back("57"); +		uids.push_back("99"); + +		VASSERT_EQ("str", "1:3,42,53:57,89,99", enumerateAsString(vmime::net::messageSet::byUID(uids))); +	} + +	void testUIDSet_MultipleNonNumeric() { + +		std::vector <vmime::net::message::uid> uids; +		uids.push_back("12"); +		uids.push_back("34"); +		uids.push_back("ab56"); +		uids.push_back("78cd"); + +		VASSERT_EQ("str", "12,34,ab56,78cd", enumerateAsString(vmime::net::messageSet::byUID(uids))); +	} + +	void testIsNumberSet() { + +		VASSERT_TRUE("number1", vmime::net::messageSet::byNumber(42).isNumberSet()); +		VASSERT_FALSE("uid1", vmime::net::messageSet::byUID("42").isNumberSet()); + +		VASSERT_TRUE("number2", vmime::net::messageSet::byNumber(42, -1).isNumberSet()); +		VASSERT_FALSE("uid2", vmime::net::messageSet::byUID("42", "*").isNumberSet()); +	} + +	void testIsUIDSet() { + +		VASSERT_FALSE("number1", vmime::net::messageSet::byNumber(42).isUIDSet()); +		VASSERT_TRUE("uid1", vmime::net::messageSet::byUID("42").isUIDSet()); + +		VASSERT_FALSE("number2", vmime::net::messageSet::byNumber(42, -1).isUIDSet()); +		VASSERT_TRUE("uid2", vmime::net::messageSet::byUID("42", "*").isUIDSet()); +	} + +	void testMixedRanges() { + +		vmime::net::messageSet set = vmime::net::messageSet::byNumber(1, 5); +		set.addRange(vmime::net::numberMessageRange(6, 8)); + +		VASSERT_THROW("mixed ranges", set.addRange(vmime::net::UIDMessageRange("123")), std::invalid_argument); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/pop3/POP3CommandTest.cpp b/vmime-master/tests/net/pop3/POP3CommandTest.cpp new file mode 100644 index 0000000..3ed579e --- /dev/null +++ b/vmime-master/tests/net/pop3/POP3CommandTest.cpp @@ -0,0 +1,241 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 "tests/net/pop3/POP3TestUtils.hpp" + +#include "vmime/net/pop3/POP3Command.hpp" + + +using namespace vmime::net::pop3; + + +VMIME_TEST_SUITE_BEGIN(POP3CommandTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testCreateCommand) +		VMIME_TEST(testCreateCommandParams) +		VMIME_TEST(testCAPA) +		VMIME_TEST(testNOOP) +		VMIME_TEST(testAUTH) +		VMIME_TEST(testAUTH_InitialResponse) +		VMIME_TEST(testSTLS) +		VMIME_TEST(testAPOP) +		VMIME_TEST(testUSER) +		VMIME_TEST(testPASS) +		VMIME_TEST(testSTAT) +		VMIME_TEST(testLIST) +		VMIME_TEST(testLISTMessage) +		VMIME_TEST(testUIDL) +		VMIME_TEST(testUIDLMessage) +		VMIME_TEST(testDELE) +		VMIME_TEST(testRETR) +		VMIME_TEST(testTOP) +		VMIME_TEST(testRSET) +		VMIME_TEST(testQUIT) +		VMIME_TEST(testWriteToSocket) +	VMIME_TEST_LIST_END + + +	void testCreateCommand() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::createCommand("MY_COMMAND"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); +	} + +	void testCreateCommandParams() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::createCommand("MY_COMMAND param1 param2"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); +	} + +	void testCAPA() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::CAPA(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "CAPA", cmd->getText()); +	} + +	void testNOOP() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::NOOP(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "NOOP", cmd->getText()); +	} + +	void testAUTH() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::AUTH("saslmechanism"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText()); +	} + +	void testAUTH_InitialResponse() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::AUTH("saslmechanism", "initial-response"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText()); +	} + +	void testSTLS() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::STLS(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "STLS", cmd->getText()); +	} + +	void testAPOP() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::APOP("user", "digest"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "APOP user digest", cmd->getText()); +	} + +	void testUSER() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::USER("user"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "USER user", cmd->getText()); +	} + +	void testPASS() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::PASS("pass"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "PASS pass", cmd->getText()); +	} + +	void testSTAT() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::STAT(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "STAT", cmd->getText()); +	} + +	void testLIST() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::LIST(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "LIST", cmd->getText()); +	} + +	void testLISTMessage() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::LIST(42); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "LIST 42", cmd->getText()); +	} + +	void testUIDL() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::UIDL(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "UIDL", cmd->getText()); +	} + +	void testUIDLMessage() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::UIDL(42); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "UIDL 42", cmd->getText()); +	} + +	void testDELE() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::DELE(42); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "DELE 42", cmd->getText()); +	} + +	void testRETR() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::RETR(42); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RETR 42", cmd->getText()); +	} + +	void testTOP() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::TOP(42, 567); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "TOP 42 567", cmd->getText()); +	} + +	void testRSET() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::RSET(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RSET", cmd->getText()); +	} + +	void testQUIT() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::QUIT(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "QUIT", cmd->getText()); +	} + +	void testWriteToSocket() { + +		vmime::shared_ptr <POP3Command> cmd = POP3Command::createCommand("MY_COMMAND param1 param2"); + +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(sok), +				vmime::shared_ptr <vmime::net::timeoutHandler>() +			); + +		cmd->send(conn); + +		vmime::string response; +		sok->localReceive(response); + +		VASSERT_EQ("Sent buffer", "MY_COMMAND param1 param2\r\n", response); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/pop3/POP3ResponseTest.cpp b/vmime-master/tests/net/pop3/POP3ResponseTest.cpp new file mode 100644 index 0000000..8fecb74 --- /dev/null +++ b/vmime-master/tests/net/pop3/POP3ResponseTest.cpp @@ -0,0 +1,244 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 "tests/net/pop3/POP3TestUtils.hpp" + +#include "vmime/net/pop3/POP3Response.hpp" + + +using namespace vmime::net::pop3; + + +VMIME_TEST_SUITE_BEGIN(POP3ResponseTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testSingleLineResponseOK) +		VMIME_TEST(testSingleLineResponseERR) +		VMIME_TEST(testSingleLineResponseReady) +		VMIME_TEST(testSingleLineResponseInvalid) +		VMIME_TEST(testSingleLineResponseLF) +		VMIME_TEST(testMultiLineResponse) +		VMIME_TEST(testMultiLineResponseLF) +		VMIME_TEST(testLargeResponse) +	VMIME_TEST_LIST_END + + +	void testSingleLineResponseOK() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Response Text\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode()); +		VASSERT_TRUE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +		VASSERT_EQ("First Line", "+OK Response Text", resp->getFirstLine()); +	} + +	void testSingleLineResponseERR() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("-ERR Response Text\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode()); +		VASSERT_FALSE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +		VASSERT_EQ("First Line", "-ERR Response Text", resp->getFirstLine()); +	} + +	void testSingleLineResponseReady() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+ challenge_string\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_READY, resp->getCode()); +		VASSERT_FALSE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "challenge_string", resp->getText()); +		VASSERT_EQ("First Line", "+ challenge_string", resp->getFirstLine()); +	} + +	void testSingleLineResponseInvalid() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = vmime::make_shared <POP3ConnectionTest> +			(vmime::dynamicCast <vmime::net::socket>(socket), toh); + +		socket->localSend("Invalid Response Text\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_ERR, resp->getCode()); +		VASSERT_FALSE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +		VASSERT_EQ("First Line", "Invalid Response Text", resp->getFirstLine()); +	} + +	void testSingleLineResponseLF() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Response terminated by LF\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode()); +		VASSERT_TRUE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "Response terminated by LF", resp->getText()); +		VASSERT_EQ("First Line", "+OK Response terminated by LF", resp->getFirstLine()); +	} + +	void testMultiLineResponse() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Response Text\r\n"); +		socket->localSend("Line 1\r\n"); +		socket->localSend("Line 2\r\n"); +		socket->localSend(".\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readMultilineResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode()); +		VASSERT_TRUE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 2, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +		VASSERT_EQ("First Line", "+OK Response Text", resp->getFirstLine()); +		VASSERT_EQ("Line 1", "Line 1", resp->getLineAt(0)); +		VASSERT_EQ("Line 2", "Line 2", resp->getLineAt(1)); +	} + +	void testMultiLineResponseLF() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Response Text\n"); +		socket->localSend("Line 1\n"); +		socket->localSend("Line 2\n"); +		socket->localSend(".\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readMultilineResponse(conn); + +		VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode()); +		VASSERT_TRUE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 2, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +		VASSERT_EQ("First Line", "+OK Response Text", resp->getFirstLine()); +		VASSERT_EQ("Line 1", "Line 1", resp->getLineAt(0)); +		VASSERT_EQ("Line 2", "Line 2", resp->getLineAt(1)); +	} + +	void testLargeResponse() { + +		std::ostringstream data; + +		for (unsigned int i = 0 ; i < 5000 ; ++i) { +			data << "VMIME.VMIME\nVMIME\r\nVMIME_VMIME"; +		} + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Large Response Follows\n"); +		socket->localSend(data.str()); +		socket->localSend("\r\n.\r\n"); + +		vmime::string receivedData; +		vmime::utility::outputStreamStringAdapter receivedDataStream(receivedData); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readLargeResponse(conn, receivedDataStream, NULL, 0); + +		VASSERT_EQ("Code", POP3Response::CODE_OK, resp->getCode()); +		VASSERT_TRUE("Success", resp->isSuccess()); +		VASSERT_EQ("Lines", 0, resp->getLineCount()); +		VASSERT_EQ("Text", "Large Response Follows", resp->getText()); +		VASSERT_EQ("Data Length", data.str().length(), receivedData.length()); +		VASSERT_EQ("Data Bytes", data.str(), receivedData); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/pop3/POP3StoreTest.cpp b/vmime-master/tests/net/pop3/POP3StoreTest.cpp new file mode 100644 index 0000000..5d9e3c2 --- /dev/null +++ b/vmime-master/tests/net/pop3/POP3StoreTest.cpp @@ -0,0 +1,67 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 "tests/net/pop3/POP3TestUtils.hpp" + +#include "vmime/net/pop3/POP3Store.hpp" +#include "vmime/net/pop3/POP3SStore.hpp" + + +VMIME_TEST_SUITE_BEGIN(POP3StoreTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testCreateFromURL) +		VMIME_TEST(testConnectToInvalidServer) +	VMIME_TEST_LIST_END + + +	void testCreateFromURL() { + +		vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +		// POP3 +		vmime::utility::url url("pop3://pop3.vmime.org"); +		vmime::shared_ptr <vmime::net::store> store = sess->getStore(url); + +		VASSERT_TRUE("pop3", typeid(*store) == typeid(vmime::net::pop3::POP3Store)); + +		// POP3S +		vmime::utility::url url2("pop3s://pop3s.vmime.org"); +		vmime::shared_ptr <vmime::net::store> store2 = sess->getStore(url2); + +		VASSERT_TRUE("pop3s", typeid(*store2) == typeid(vmime::net::pop3::POP3SStore)); +	} + +	void testConnectToInvalidServer() { + +		vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +		vmime::utility::url url("pop3://invalid-pop3-server"); +		vmime::shared_ptr <vmime::net::store> store = sess->getStore(url); + +		VASSERT_THROW("connect", store->connect(), vmime::exceptions::connection_error); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/pop3/POP3TestUtils.hpp b/vmime-master/tests/net/pop3/POP3TestUtils.hpp new file mode 100644 index 0000000..24efb8b --- /dev/null +++ b/vmime-master/tests/net/pop3/POP3TestUtils.hpp @@ -0,0 +1,69 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 "vmime/net/pop3/POP3Connection.hpp" +#include "vmime/net/pop3/POP3Store.hpp" + + +class POP3TestStore : public vmime::net::pop3::POP3Store { + +public: + +	POP3TestStore() +		: POP3Store(vmime::net::session::create(), +		            vmime::shared_ptr <vmime::security::authenticator>()) { + +	} +}; + + +class POP3ConnectionTest : public vmime::net::pop3::POP3Connection { + +public: + +	POP3ConnectionTest( +		vmime::shared_ptr <vmime::net::socket> socket, +		vmime::shared_ptr <vmime::net::timeoutHandler> timeoutHandler +	) +		: POP3Connection(vmime::make_shared <POP3TestStore>(), +		                 vmime::shared_ptr <vmime::security::authenticator>()), +		  m_socket(socket), +		  m_timeoutHandler(timeoutHandler) { + +	} + +	vmime::shared_ptr <vmime::net::socket> getSocket() { + +		return m_socket; +	} + +	vmime::shared_ptr <vmime::net::timeoutHandler> getTimeoutHandler() { + +		return m_timeoutHandler; +	} + +private: + +	vmime::shared_ptr <vmime::net::socket> m_socket; +	vmime::shared_ptr <vmime::net::timeoutHandler> m_timeoutHandler; +}; diff --git a/vmime-master/tests/net/pop3/POP3UtilsTest.cpp b/vmime-master/tests/net/pop3/POP3UtilsTest.cpp new file mode 100644 index 0000000..1cded39 --- /dev/null +++ b/vmime-master/tests/net/pop3/POP3UtilsTest.cpp @@ -0,0 +1,88 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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 "tests/net/pop3/POP3TestUtils.hpp" + +#include "vmime/net/pop3/POP3Utils.hpp" +#include "vmime/net/pop3/POP3Response.hpp" + + +using namespace vmime::net::pop3; + + +VMIME_TEST_SUITE_BEGIN(POP3UtilsTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testParseMultiListOrUidlResponse) +		VMIME_TEST(testMessageSetToNumberList) +	VMIME_TEST_LIST_END + + +	void testParseMultiListOrUidlResponse() { + +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		vmime::shared_ptr <POP3ConnectionTest> conn = +			vmime::make_shared <POP3ConnectionTest>( +				vmime::dynamicCast <vmime::net::socket>(socket), toh +			); + +		socket->localSend("+OK Response Text\r\n"); +		socket->localSend("1 abcdef\r\n"); +		socket->localSend("23    ghijkl\r\n"); +		socket->localSend("4\tmnopqr\r\n"); +		socket->localSend("567xx\tstuvwx\r\n"); +		socket->localSend("8 yz   \r\n"); +		socket->localSend(".\r\n"); + +		vmime::shared_ptr <POP3Response> resp = +			POP3Response::readMultilineResponse(conn); + +		std::map <vmime::size_t, vmime::string> result; +		POP3Utils::parseMultiListOrUidlResponse(resp, result); + +		VASSERT_EQ("Count", 5, result.size()); +		VASSERT_EQ("1", "abcdef", result[1]); +		VASSERT_EQ("2 (multiple spaces)", "ghijkl", result[23]); +		VASSERT_EQ("3 (with tab)", "mnopqr", result[4]); +		VASSERT_EQ("4 (with invalid digit)", "stuvwx", result[567]); +		VASSERT_EQ("5 (with extra space)", "yz", result[8]); +	} + +	void testMessageSetToNumberList() { + +		const std::vector <size_t> msgNums = POP3Utils::messageSetToNumberList( +			vmime::net::messageSet::byNumber(5, -1), /* msgCount */ 8 +		); + +		VASSERT_EQ("Count", 4, msgNums.size()); +		VASSERT_EQ("1", 5, msgNums[0]); +		VASSERT_EQ("2", 6, msgNums[1]); +		VASSERT_EQ("3", 7, msgNums[2]); +		VASSERT_EQ("4", 8, msgNums[3]); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/smtp/SMTPCommandSetTest.cpp b/vmime-master/tests/net/smtp/SMTPCommandSetTest.cpp new file mode 100644 index 0000000..7ea3578 --- /dev/null +++ b/vmime-master/tests/net/smtp/SMTPCommandSetTest.cpp @@ -0,0 +1,181 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/SMTPCommandSet.hpp" +#include "vmime/net/smtp/SMTPCommand.hpp" + + +using namespace vmime::net::smtp; + + +VMIME_TEST_SUITE_BEGIN(SMTPCommandSetTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testCreate) +		VMIME_TEST(testCreatePipeline) +		VMIME_TEST(testAddCommand) +		VMIME_TEST(testAddCommandPipeline) +		VMIME_TEST(testWriteToSocket) +		VMIME_TEST(testWriteToSocketPipeline) +		VMIME_TEST(testGetLastCommandSent) +		VMIME_TEST(testGetLastCommandSentPipeline) +	VMIME_TEST_LIST_END + + +	void testCreate() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); + +		VASSERT_NOT_NULL("Not null", cset); +		VASSERT_FALSE("Finished", cset->isFinished()); +	} + +	void testCreatePipeline() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); + +		VASSERT_NOT_NULL("Not null", cset); +		VASSERT_FALSE("Finished", cset->isFinished()); +	} + +	void testAddCommand() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); + +		VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); +		VASSERT_EQ("Text", "MY_COMMAND1\r\n", cset->getText()); +		VASSERT_NO_THROW("No throw 2", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"))); +		VASSERT_EQ("Text", "MY_COMMAND1\r\nMY_COMMAND2\r\n", cset->getText()); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + +		cset->writeToSocket(sok, tracer); +		VASSERT_FALSE("Finished", cset->isFinished()); + +		// Can't add commands when writing to socket has started +		VASSERT_THROW("Throw", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND3")), std::runtime_error); + +		cset->writeToSocket(sok, tracer); +		VASSERT_TRUE("Finished", cset->isFinished()); +	} + +	void testAddCommandPipeline() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); + +		VASSERT_NO_THROW("No throw 1", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1"))); +		VASSERT_EQ("Text", "MY_COMMAND1\r\n", cset->getText()); +		VASSERT_NO_THROW("No throw 2", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2"))); +		VASSERT_EQ("Text", "MY_COMMAND1\r\nMY_COMMAND2\r\n", cset->getText()); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); +		vmime::string response; + +		cset->writeToSocket(sok, tracer); +		VASSERT_TRUE("Finished", cset->isFinished()); + +		sok->localReceive(response); +		VASSERT_EQ("Receive cmds", "MY_COMMAND1\r\nMY_COMMAND2\r\n", response); + +		// Can't add commands when writing to socket has started +		VASSERT_THROW("Throw", cset->addCommand(SMTPCommand::createCommand("MY_COMMAND3")), std::runtime_error); +	} + +	void testWriteToSocket() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); + +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); +		vmime::string response; + +		cset->writeToSocket(sok, tracer); + +		sok->localReceive(response); +		VASSERT_EQ("Receive cmd 1", "MY_COMMAND1\r\n", response); + +		cset->writeToSocket(sok, tracer); + +		sok->localReceive(response); +		VASSERT_EQ("Receive cmd 2", "MY_COMMAND2\r\n", response); +	} + +	void testWriteToSocketPipeline() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); + +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); +		vmime::string response; + +		cset->writeToSocket(sok, tracer); + +		sok->localReceive(response); +		VASSERT_EQ("Receive cmds", "MY_COMMAND1\r\nMY_COMMAND2\r\n", response); +	} + +	void testGetLastCommandSent() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ false); + +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + +		cset->writeToSocket(sok, tracer); +		VASSERT_EQ("Cmd 1", "MY_COMMAND1", cset->getLastCommandSent()->getText()); + +		cset->writeToSocket(sok, tracer); +		VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText()); +	} + +	void testGetLastCommandSentPipeline() { + +		vmime::shared_ptr <SMTPCommandSet> cset = SMTPCommandSet::create(/* pipelining */ true); + +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND1")); +		cset->addCommand(SMTPCommand::createCommand("MY_COMMAND2")); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + +		cset->writeToSocket(sok, tracer); +		VASSERT_EQ("Cmd 1", "MY_COMMAND1", cset->getLastCommandSent()->getText()); + +		cset->writeToSocket(sok, tracer); +		VASSERT_EQ("Cmd 2", "MY_COMMAND2", cset->getLastCommandSent()->getText()); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/smtp/SMTPCommandTest.cpp b/vmime-master/tests/net/smtp/SMTPCommandTest.cpp new file mode 100644 index 0000000..ecaf292 --- /dev/null +++ b/vmime-master/tests/net/smtp/SMTPCommandTest.cpp @@ -0,0 +1,252 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/SMTPCommand.hpp" + + +using namespace vmime::net::smtp; + + +VMIME_TEST_SUITE_BEGIN(SMTPCommandTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testCreateCommand) +		VMIME_TEST(testCreateCommandParams) +		VMIME_TEST(testHELO) +		VMIME_TEST(testEHLO) +		VMIME_TEST(testAUTH) +		VMIME_TEST(testAUTH_InitialResponse) +		VMIME_TEST(testSTARTTLS) +		VMIME_TEST(testMAIL) +		VMIME_TEST(testMAIL_Encoded) +		VMIME_TEST(testMAIL_UTF8) +		VMIME_TEST(testMAIL_SIZE) +		VMIME_TEST(testMAIL_SIZE_UTF8) +		VMIME_TEST(testRCPT) +		VMIME_TEST(testRCPT_Encoded) +		VMIME_TEST(testRCPT_UTF8) +		VMIME_TEST(testRSET) +		VMIME_TEST(testDATA) +		VMIME_TEST(testBDAT) +		VMIME_TEST(testNOOP) +		VMIME_TEST(testQUIT) +		VMIME_TEST(testWriteToSocket) +	VMIME_TEST_LIST_END + + +	void testCreateCommand() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); +	} + +	void testCreateCommandParams() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); +	} + +	void testHELO() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::HELO("hostname"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "HELO hostname", cmd->getText()); +	} + +	void testEHLO() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::EHLO("hostname"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "EHLO hostname", cmd->getText()); +	} + +	void testAUTH() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::AUTH("saslmechanism"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTH saslmechanism", cmd->getText()); +	} + +	void testAUTH_InitialResponse() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::AUTH("saslmechanism", "initial-response"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "AUTH saslmechanism initial-response", cmd->getText()); +	} + +	void testSTARTTLS() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::STARTTLS(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "STARTTLS", cmd->getText()); +	} + +	void testMAIL() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL(vmime::mailbox("me@vmime.org"), false, "FULL", "dsn-unique-id"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MAIL FROM:<me@vmime.org> RET=FULL ENVID=<dsn-unique-id>", cmd->getText()); +	} + +	void testMAIL_Encoded() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( +			vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false, "FULL", "dsn-unique-id" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MAIL FROM:<mailtest@xn--r8jz45g.xn--zckzah> RET=FULL ENVID=<dsn-unique-id>", cmd->getText()); +	} + +	void testMAIL_UTF8() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( +			vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, "FULL", "dsn-unique-id" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MAIL FROM:<mailtest@例え.テスト> RET=FULL ENVID=<dsn-unique-id> SMTPUTF8", cmd->getText()); +	} + +	void testMAIL_SIZE() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( +			vmime::mailbox("me@vmime.org"), false, 123456789, "FULL", "dsn-unique-id" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MAIL FROM:<me@vmime.org> RET=FULL ENVID=<dsn-unique-id> SIZE=123456789", cmd->getText()); +	} + +	void testMAIL_SIZE_UTF8() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::MAIL( +			vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, 123456789, "FULL", "dsn-unique-id" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "MAIL FROM:<mailtest@例え.テスト> RET=FULL ENVID=<dsn-unique-id> SMTPUTF8 SIZE=123456789", cmd->getText()); +	} + +	void testRCPT() { + +		vmime::shared_ptr <SMTPCommand> cmd = +			SMTPCommand::RCPT(vmime::mailbox("someone@vmime.org"), false, "NEVER"); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RCPT TO:<someone@vmime.org> NOTIFY=NEVER", cmd->getText()); +	} + +	void testRCPT_Encoded() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT( +			vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), false, "NEVER" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RCPT TO:<mailtest@xn--r8jz45g.xn--zckzah> NOTIFY=NEVER", cmd->getText()); +	} + +	void testRCPT_UTF8() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RCPT( +			vmime::mailbox(vmime::emailAddress("mailtest", "例え.テスト")), true, "NEVER" +		); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RCPT TO:<mailtest@例え.テスト> NOTIFY=NEVER", cmd->getText()); +	} + +	void testRSET() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::RSET(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "RSET", cmd->getText()); +	} + +	void testDATA() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::DATA(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "DATA", cmd->getText()); +	} + +	void testBDAT() { + +		vmime::shared_ptr <SMTPCommand> cmd1 = SMTPCommand::BDAT(12345, false); + +		VASSERT_NOT_NULL("Not null", cmd1); +		VASSERT_EQ("Text", "BDAT 12345", cmd1->getText()); + +		vmime::shared_ptr <SMTPCommand> cmd2 = SMTPCommand::BDAT(67890, true); + +		VASSERT_NOT_NULL("Not null", cmd2); +		VASSERT_EQ("Text", "BDAT 67890 LAST", cmd2->getText()); +	} + +	void testNOOP() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::NOOP(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "NOOP", cmd->getText()); +	} + +	void testQUIT() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::QUIT(); + +		VASSERT_NOT_NULL("Not null", cmd); +		VASSERT_EQ("Text", "QUIT", cmd->getText()); +	} + +	void testWriteToSocket() { + +		vmime::shared_ptr <SMTPCommand> cmd = SMTPCommand::createCommand("MY_COMMAND param1 param2"); + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + +		cmd->writeToSocket(sok, tracer); + +		vmime::string response; +		sok->localReceive(response); + +		VASSERT_EQ("Sent buffer", "MY_COMMAND param1 param2\r\n", response); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/smtp/SMTPResponseTest.cpp b/vmime-master/tests/net/smtp/SMTPResponseTest.cpp new file mode 100644 index 0000000..f899a82 --- /dev/null +++ b/vmime-master/tests/net/smtp/SMTPResponseTest.cpp @@ -0,0 +1,238 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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" + + +VMIME_TEST_SUITE_BEGIN(SMTPResponseTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testSingleLineResponse) +		VMIME_TEST(testSingleLineResponseLF) +		VMIME_TEST(testMultiLineResponse) +		VMIME_TEST(testMultiLineResponseDifferentCode) +		VMIME_TEST(testIncompleteMultiLineResponse) +		VMIME_TEST(testNoResponseText) +		VMIME_TEST(testEnhancedStatusCode) +		VMIME_TEST(testNoEnhancedStatusCode) +		VMIME_TEST(testInvalidEnhancedStatusCode) +	VMIME_TEST_LIST_END + + +	void testSingleLineResponse() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend("123 Response Text\r\n"); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 123, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +	} + +	void testSingleLineResponseLF() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend("123 Response Text\n"); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 123, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "Response Text", resp->getText()); +	} + +	void testMultiLineResponse() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend( +			"123-Response\r\n" +			"123 Text\r\n" +		); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		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::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend( +			"123-Response\r\n" +			"456 Text\r\n" +		); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		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::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(1); + +		socket->localSend( +			"123-Response\r\n" +			"123-Text\r\n" +			// Missing data +		); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		VASSERT_THROW( +			"Incomplete response", +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState), +			vmime::exceptions::operation_timed_out +		); +	} + +	void testNoResponseText() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(1); + +		socket->localSend( +			"250\r\n" +		); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 250, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "", resp->getText()); +	} + +	void testEnhancedStatusCode() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend("250 2.1.5 OK fu13sm4720601wic.7 - gsmtp\r\n"); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 250, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "2.1.5 OK fu13sm4720601wic.7 - gsmtp", resp->getText()); +		VASSERT_EQ("Enh.class", 2, resp->getEnhancedCode().klass); +		VASSERT_EQ("Enh.subject", 1, resp->getEnhancedCode().subject); +		VASSERT_EQ("Enh.detail", 5, resp->getEnhancedCode().detail); +	} + +	void testNoEnhancedStatusCode() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend("354  Go ahead fu13sm4720601wic.7 - gsmtp\r\n"); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 354, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "Go ahead fu13sm4720601wic.7 - gsmtp", resp->getText()); +		VASSERT_EQ("Enh.class", 0, resp->getEnhancedCode().klass); +		VASSERT_EQ("Enh.subject", 0, resp->getEnhancedCode().subject); +		VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail); +	} + +	void testInvalidEnhancedStatusCode() { + +		vmime::shared_ptr <vmime::net::tracer> tracer; +		vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); +		vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + +		socket->localSend("250 4.2 xxx\r\n"); + +		vmime::net::smtp::SMTPResponse::state responseState; + +		vmime::shared_ptr <vmime::net::smtp::SMTPResponse> resp = +			vmime::net::smtp::SMTPResponse::readResponse(tracer, socket, toh, responseState); + +		VASSERT_EQ("Code", 250, resp->getCode()); +		VASSERT_EQ("Lines", 1, resp->getLineCount()); +		VASSERT_EQ("Text", "4.2 xxx", resp->getText()); +		VASSERT_EQ("Enh.class", 0, resp->getEnhancedCode().klass); +		VASSERT_EQ("Enh.subject", 0, resp->getEnhancedCode().subject); +		VASSERT_EQ("Enh.detail", 0, resp->getEnhancedCode().detail); +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/smtp/SMTPTransportTest.cpp b/vmime-master/tests/net/smtp/SMTPTransportTest.cpp new file mode 100644 index 0000000..8ea4ba7 --- /dev/null +++ b/vmime-master/tests/net/smtp/SMTPTransportTest.cpp @@ -0,0 +1,324 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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/SMTPTransport.hpp" +#include "vmime/net/smtp/SMTPChunkingOutputStreamAdapter.hpp" +#include "vmime/net/smtp/SMTPExceptions.hpp" + +#include "SMTPTransportTestUtils.hpp" + + +VMIME_TEST_SUITE_BEGIN(SMTPTransportTest) + +	VMIME_TEST_LIST_BEGIN +		VMIME_TEST(testConnectToInvalidServer) +		VMIME_TEST(testGreetingError) +		VMIME_TEST(testMAILandRCPT) +		VMIME_TEST(testChunking) +		VMIME_TEST(testSize_Chunking) +		VMIME_TEST(testSize_NoChunking) +		VMIME_TEST(testSMTPUTF8_available) +		VMIME_TEST(testSMTPUTF8_notAvailable) +	VMIME_TEST_LIST_END + + +	void testConnectToInvalidServer() { + +		vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + +		vmime::utility::url url("smtp://invalid-smtp-server"); +		vmime::shared_ptr <vmime::net::transport> store = sess->getTransport(url); + +		VASSERT_THROW("connect", store->connect(), vmime::exceptions::connection_error); +	} + +	void testGreetingError() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::transport> tr = +			session->getTransport(vmime::utility::url("smtp://localhost")); + +		tr->setSocketFactory(vmime::make_shared <testSocketFactory <greetingErrorSMTPTestSocket> >()); +		tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +		VASSERT_THROW( +			"Connection", +			tr->connect(), +			vmime::exceptions::connection_greeting_error +		); +	} + +	void testMAILandRCPT() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::transport> tr = +			session->getTransport(vmime::utility::url("smtp://localhost")); + +		tr->setSocketFactory(vmime::make_shared <testSocketFactory <MAILandRCPTSMTPTestSocket> >()); +		tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +		VASSERT_NO_THROW("Connection", tr->connect()); + +		vmime::mailbox exp("expeditor@test.vmime.org"); + +		vmime::mailboxList recips; +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient1@test.vmime.org")); +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient2@test.vmime.org")); +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient3@test.vmime.org")); + +		vmime::string data("Message data"); +		vmime::utility::inputStreamStringAdapter is(data); + +		tr->send(exp, recips, is, 0); +	} + +	void testChunking() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::transport> tr = +			session->getTransport(vmime::utility::url("smtp://localhost")); + +		tr->setSocketFactory(vmime::make_shared <testSocketFactory <chunkingSMTPTestSocket> >()); +		tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +		tr->connect(); + +		VASSERT( +			"Test server should report it supports the CHUNKING extension!", +			vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("CHUNKING") +		); + +		vmime::mailbox exp("expeditor@test.vmime.org"); + +		vmime::mailboxList recips; +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient@test.vmime.org")); + +		vmime::shared_ptr <vmime::message> msg = vmime::make_shared <SMTPTestMessage>(); + +		tr->send(msg, exp, recips); +	} + +	void testSize_Chunking() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::transport> tr = +			session->getTransport(vmime::utility::url("smtp://localhost")); + +		tr->setSocketFactory(vmime::make_shared <testSocketFactory <bigMessageSMTPTestSocket <true> > >()); +		tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +		tr->connect(); + +		VASSERT( +			"Test server should report it supports the SIZE extension!", +			vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE") +		); + +		vmime::mailbox exp("expeditor@test.vmime.org"); + +		vmime::mailboxList recips; +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient@test.vmime.org")); + +		vmime::shared_ptr <vmime::message> msg = vmime::make_shared <SMTPBigTestMessage4MB>(); + +		VASSERT_THROW( +			"Max size limit exception", +			tr->send(msg, exp, recips), +			vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException +		); +	} + +	void testSize_NoChunking() { + +		vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +		vmime::shared_ptr <vmime::net::transport> tr = +			session->getTransport(vmime::utility::url("smtp://localhost")); + +		tr->setSocketFactory(vmime::make_shared <testSocketFactory <bigMessageSMTPTestSocket <false> > >()); +		tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +		tr->connect(); + +		VASSERT( +			"Test server should report it supports the SIZE extension!", +			vmime::dynamicCast <vmime::net::smtp::SMTPTransport>(tr)->getConnection()->hasExtension("SIZE") +		); + +		vmime::mailbox exp("expeditor@test.vmime.org"); + +		vmime::mailboxList recips; +		recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient@test.vmime.org")); + +		vmime::shared_ptr <vmime::message> msg = vmime::make_shared <SMTPBigTestMessage4MB>(); + +		VASSERT_THROW( +			"Max size limit exception", +			tr->send(msg, exp, recips), +			vmime::net::smtp::SMTPMessageSizeExceedsMaxLimitsException +		); +	} + +	void testSMTPUTF8_available() { + +		// Test with UTF8 sender +		{ +			vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +			vmime::shared_ptr <vmime::net::transport> tr = +				session->getTransport(vmime::utility::url("smtp://localhost")); + +			tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <true> > >()); +			tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +			VASSERT_NO_THROW("Connection", tr->connect()); + +			vmime::mailbox exp( +				vmime::emailAddress( +					vmime::word("expéditeur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			); + +			vmime::mailboxList recips; +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient1@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient2@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>( +				vmime::emailAddress( +					vmime::word("récepteur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			)); + +			vmime::string data("Message data"); +			vmime::utility::inputStreamStringAdapter is(data); + +			tr->send(exp, recips, is, 0); +		} + +		// Test with UTF8 recipient only +		{ +			vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +			vmime::shared_ptr <vmime::net::transport> tr = +				session->getTransport(vmime::utility::url("smtp://localhost")); + +			tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <true> > >()); +			tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +			VASSERT_NO_THROW("Connection", tr->connect()); + +			vmime::mailbox exp("expediteur@test.vmime.org"); + +			vmime::mailboxList recips; +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient1@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient2@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>( +				vmime::emailAddress( +					vmime::word("récepteur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			)); + +			vmime::string data("Message data"); +			vmime::utility::inputStreamStringAdapter is(data); + +			tr->send(exp, recips, is, 0); +		} +	} + +	void testSMTPUTF8_notAvailable() { + +		// Test with UTF8 sender +		{ +			vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +			vmime::shared_ptr <vmime::net::transport> tr = +				session->getTransport(vmime::utility::url("smtp://localhost")); + +			tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <false> > >()); +			tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +			VASSERT_NO_THROW("Connection", tr->connect()); + +			vmime::mailbox exp( +				vmime::emailAddress( +					vmime::word("expéditeur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			); + +			vmime::mailboxList recips; +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient1@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient2@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>( +				vmime::emailAddress( +					vmime::word("récepteur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			)); + +			vmime::string data("Message data"); +			vmime::utility::inputStreamStringAdapter is(data); + +			tr->send(exp, recips, is, 0); +		} + +		// Test with UTF8 recipient only +		{ +			vmime::shared_ptr <vmime::net::session> session = vmime::net::session::create(); + +			vmime::shared_ptr <vmime::net::transport> tr = +				session->getTransport(vmime::utility::url("smtp://localhost")); + +			tr->setSocketFactory(vmime::make_shared <testSocketFactory <UTF8SMTPTestSocket <false> > >()); +			tr->setTimeoutHandlerFactory(vmime::make_shared <testTimeoutHandlerFactory>()); + +			VASSERT_NO_THROW("Connection", tr->connect()); + +			vmime::mailbox exp("expediteur@test.vmime.org"); + +			vmime::mailboxList recips; +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient1@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>("recipient2@test.vmime.org")); +			recips.appendMailbox(vmime::make_shared <vmime::mailbox>( +				vmime::emailAddress( +					vmime::word("récepteur", vmime::charsets::UTF_8), +					vmime::word("test.vmime.org") +				) +			)); + +			vmime::string data("Message data"); +			vmime::utility::inputStreamStringAdapter is(data); + +			tr->send(exp, recips, is, 0); +		} +	} + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/smtp/SMTPTransportTestUtils.hpp b/vmime-master/tests/net/smtp/SMTPTransportTestUtils.hpp new file mode 100644 index 0000000..8710639 --- /dev/null +++ b/vmime-master/tests/net/smtp/SMTPTransportTestUtils.hpp @@ -0,0 +1,792 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// 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 3 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. +// + + +/** 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; +		m_ehloSent = m_heloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; +	} + +	~MAILandRCPTSMTPTestSocket() { + +		VASSERT("Client must send the DATA command", m_dataSent); +		VASSERT("Client must send the QUIT command", m_quitSent); +	} + +	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 == "EHLO") { + +				localSend("502 Command not implemented\r\n"); + +				m_ehloSent = true; + +			} else if (cmd == "HELO") { + +				VASSERT("Client must send the EHLO command before HELO", m_ehloSent); + +				localSend("250 OK\r\n"); + +				m_heloSent = true; + +			} else if (cmd == "MAIL") { + +				VASSERT("Client must send the HELO command", m_heloSent); +				VASSERT("The MAIL command must be sent only one time", !m_mailSent); + +				VASSERT_EQ("MAIL", std::string("MAIL FROM:<expeditor@test.vmime.org>"), line); + +				localSend("250 OK\r\n"); + +				m_mailSent = true; + +			} else if (cmd == "RCPT") { + +				const vmime::size_t lt = line.find('<'); +				const vmime::size_t 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"); + +				m_rcptSent = true; + +			} else if (cmd == "DATA") { + +				VASSERT("Client must send the MAIL command", m_mailSent); +				VASSERT("Client must send the RCPT command", m_rcptSent); +				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(); + +				m_dataSent = true; + +			} else if (cmd == "NOOP") { + +				localSend("250 Completed\r\n"); + +			} else if (cmd == "QUIT") { + +				m_quitSent = true; + +				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; + +	bool m_ehloSent, m_heloSent, m_mailSent, m_rcptSent, +	     m_dataSent, m_quitSent; +}; + + + +/** SMTP test server 2. +  * +  * Test CHUNKING extension/BDAT command. +  */ +class chunkingSMTPTestSocket : public testSocket { + +public: + +	chunkingSMTPTestSocket() { + +		m_state = STATE_NOT_CONNECTED; +		m_bdatChunkCount = 0; +		m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; +	} + +	~chunkingSMTPTestSocket() { + +		VASSERT_EQ("BDAT chunk count", 3, m_bdatChunkCount); +		VASSERT("Client must send the QUIT command", m_quitSent); +	} + +	void onConnected() { + +		localSend("220 test.vmime.org Service ready\r\n"); +		processCommand(); + +		m_state = STATE_COMMAND; +	} + +	void onDataReceived() { + +		if (m_state == STATE_DATA) { + +			if (m_bdatChunkReceived != m_bdatChunkSize) { + +				const size_t remaining = m_bdatChunkSize - m_bdatChunkReceived; +				const size_t received = localReceiveRaw(NULL, remaining); + +				m_bdatChunkReceived += received; +			} + +			if (m_bdatChunkReceived == m_bdatChunkSize) { + +				m_state = STATE_COMMAND; +			} +		} + +		processCommand(); +	} + +	void processCommand() { + +		vmime::string line; + +		if (!localReceiveLine(line)) { +			return; +		} + +		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 == "EHLO") { + +				localSend("250-test.vmime.org says hello\r\n"); +				localSend("250 CHUNKING\r\n"); + +				m_ehloSent = true; + +			} else if (cmd == "HELO") { + +				VASSERT("Client must not send the HELO command, as EHLO succeeded", false); + +			} else if (cmd == "MAIL") { + +				VASSERT("The MAIL command must be sent only one time", !m_mailSent); + +				localSend("250 OK\r\n"); + +				m_mailSent = true; + +			} else if (cmd == "RCPT") { + +				localSend("250 OK, recipient accepted\r\n"); + +				m_rcptSent = true; + +			} else if (cmd == "DATA") { + +				VASSERT("BDAT must be used here!", false); + +			} else if (cmd == "BDAT") { + +				VASSERT("Client must send the MAIL command", m_mailSent); +				VASSERT("Client must send the RCPT command", m_rcptSent); + +				unsigned long chunkSize = 0; +				iss >> chunkSize; + +				std::string last; +				iss >> last; + +				if (m_bdatChunkCount == 0) { + +					VASSERT_EQ("BDAT chunk1 size", 262144, chunkSize); +					VASSERT_EQ("BDAT chunk1 last", "", last); + +				} else if (m_bdatChunkCount == 1) { + +					VASSERT_EQ("BDAT chunk2 size", 262144, chunkSize); +					VASSERT_EQ("BDAT chunk2 last", "", last); + +				} else if (m_bdatChunkCount == 2) { + +					VASSERT_EQ("BDAT chunk3 size", 4712, chunkSize); +					VASSERT_EQ("BDAT chunk3 last", "LAST", last); + +				} else { + +					VASSERT("No more BDAT command should be issued!", false); +				} + +				m_bdatChunkSize = chunkSize; +				m_bdatChunkReceived = 0; +				m_bdatChunkCount++; +				m_state = STATE_DATA; + +				localSend("250 chunk received\r\n"); + +			} else if (cmd == "NOOP") { + +				localSend("250 Completed\r\n"); + +			} else if (cmd == "QUIT") { + +				localSend("221 test.vmime.org Service closing transmission channel\r\n"); + +				m_quitSent = true; + +			} else { + +				localSend("502 Command not implemented\r\n"); +			} + +			break; +		} + +		} + +		processCommand(); +	} + +private: + +	enum State { +		STATE_NOT_CONNECTED, +		STATE_COMMAND, +		STATE_DATA +	}; + +	int m_state; +	int m_bdatChunkCount; +	size_t m_bdatChunkSize, m_bdatChunkReceived; + +	bool m_ehloSent, m_mailSent, m_rcptSent, m_quitSent; +}; + + +class SMTPTestMessage : public vmime::message { + +public: + +	vmime::size_t getChunkBufferSize() const { + +		static vmime::net::smtp::SMTPChunkingOutputStreamAdapter chunkStream(vmime::null, 0, NULL); +		return chunkStream.getBlockSize(); +	} + +	const std::vector <vmime::string>& getChunks() const { + +		static std::vector <vmime::string> chunks; + +		if (chunks.size() == 0) { +			chunks.push_back(vmime::string(1000, 'A')); +			chunks.push_back(vmime::string(3000, 'B')); +			chunks.push_back(vmime::string(500000, 'C')); +			chunks.push_back(vmime::string(25000, 'D')); +		} + +		return chunks; +	} + +	void generateImpl( +		const vmime::generationContext& /* ctx */, +		vmime::utility::outputStream& outputStream, +		const size_t /* curLinePos */ = 0, +		size_t* /* newLinePos */ = NULL +	) const { + +		for (size_t i = 0, n = getChunks().size() ; i < n ; ++i) { + +			const vmime::string& chunk = getChunks()[i]; +			outputStream.write(chunk.data(), chunk.size()); +		} +	} +}; + + + +/** SMTP test server 3. +  * +  * Test SIZE extension. +  */ +template <bool WITH_CHUNKING> +class bigMessageSMTPTestSocket : public testSocket { + +public: + +	bigMessageSMTPTestSocket() { + +		m_state = STATE_NOT_CONNECTED; +		m_ehloSent = m_mailSent = m_rcptSent = m_quitSent = false; +	} + +	~bigMessageSMTPTestSocket() { + +		VASSERT("Client must send the QUIT command", m_quitSent); +	} + +	void onConnected() { + +		localSend("220 test.vmime.org Service ready\r\n"); +		processCommand(); + +		m_state = STATE_COMMAND; +	} + +	void onDataReceived() { + +		processCommand(); +	} + +	void processCommand() { + +		vmime::string line; + +		if (!localReceiveLine(line)) { +			return; +		} + +		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 == "EHLO") { + +				localSend("250-test.vmime.org says hello\r\n"); + +				if (WITH_CHUNKING) { +					localSend("250-CHUNKING\r\n"); +				} + +				localSend("250 SIZE 1000000\r\n"); + +				m_ehloSent = true; + +			} else if (cmd == "HELO") { + +				VASSERT("Client must not send the HELO command, as EHLO succeeded", false); + +			} else if (cmd == "MAIL") { + +				VASSERT("The MAIL command must be sent only one time", !m_mailSent); + +				std::string address; +				iss >> address; + +				VASSERT_EQ("MAIL/address", "FROM:<expeditor@test.vmime.org>", address); + +				std::string option; +				iss >> option; + +				VASSERT_EQ("MAIL/size", "SIZE=4194304", option); + +				localSend("552 Channel size limit exceeded\r\n"); + +				m_mailSent = true; + +			} else if (cmd == "NOOP") { + +				localSend("250 Completed\r\n"); + +			} else if (cmd == "QUIT") { + +				localSend("221 test.vmime.org Service closing transmission channel\r\n"); + +				m_quitSent = true; + +			} else { + +				VASSERT("No other command should be sent", false); + +				localSend("502 Command not implemented\r\n"); +			} + +			break; +		} + +		} + +		processCommand(); +	} + +private: + +	enum State { +		STATE_NOT_CONNECTED, +		STATE_COMMAND, +		STATE_DATA +	}; + +	int m_state; + +	bool m_ehloSent, m_mailSent, m_rcptSent, m_quitSent; +}; + + +template <unsigned long SIZE> +class SMTPBigTestMessage : public vmime::message { + +public: + +	size_t getGeneratedSize(const vmime::generationContext& /* ctx */) { + +		return SIZE; +	} + +	void generateImpl( +		const vmime::generationContext& /* ctx */, +		vmime::utility::outputStream& outputStream, +		const vmime::size_t /* curLinePos */ = 0, +		vmime::size_t* /* newLinePos */ = NULL +	) const { + +		for (unsigned int i = 0, n = SIZE ; i < n ; ++i) { +			outputStream.write("X", 1); +		} +	} +}; + +typedef SMTPBigTestMessage <4194304> SMTPBigTestMessage4MB; + + + +/** SMTP test server for SMTPUTF8 extension. +  */ +template <bool SUPPORTS_UTF8> +class UTF8SMTPTestSocket : public lineBasedTestSocket { + +public: + +	UTF8SMTPTestSocket() { + +		if (SUPPORTS_UTF8) { + +			m_rcptLines.insert("RCPT TO:<recipient1@test.vmime.org>"); +			m_rcptLines.insert("RCPT TO:<recipient2@test.vmime.org>"); +			m_rcptLines.insert("RCPT TO:<récepteur@test.vmime.org>"); + +		} else { + +			m_rcptLines.insert("RCPT TO:<recipient1@test.vmime.org>"); +			m_rcptLines.insert("RCPT TO:<recipient2@test.vmime.org>"); +			m_rcptLines.insert("RCPT TO:<=?utf-8?Q?r=C3=A9cepteur?=@test.vmime.org>"); +		} + +		m_state = STATE_NOT_CONNECTED; +		m_ehloSent = m_mailSent = m_rcptSent = m_dataSent = m_quitSent = false; +	} + +	~UTF8SMTPTestSocket() { + +	} + +	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 == "EHLO") { + +				if (SUPPORTS_UTF8) { + +					localSend("250-test.vmime.org\r\n"); +					localSend("250 SMTPUTF8\r\n"); + +				} else { + +					localSend("250 test.vmime.org\r\n"); +				} + +				m_ehloSent = true; + +			} else if (cmd == "HELO") { + +				VASSERT("Client must not send the HELO command, as EHLO succeeded", false); + +			} else if (cmd == "MAIL") { + +				VASSERT("Client must send the EHLO command", m_ehloSent); +				VASSERT("The MAIL command must be sent only one time", !m_mailSent); + +				if (SUPPORTS_UTF8) { + +					VASSERT( +						"MAIL", +						   std::string("MAIL FROM:<expediteur@test.vmime.org> SMTPUTF8") == line +						|| std::string("MAIL FROM:<expéditeur@test.vmime.org> SMTPUTF8") == line +					); + +				} else { + +					VASSERT( +						"MAIL", +						   std::string("MAIL FROM:<expediteur@test.vmime.org>") == line +						|| std::string("MAIL FROM:<=?utf-8?Q?exp=C3=A9diteur?=@test.vmime.org>") == line +					); +				} + +				localSend("250 OK\r\n"); + +				m_mailSent = true; + +			} else if (cmd == "RCPT") { + +				std::set <vmime::string>::iterator it = m_rcptLines.find(line); + +				VASSERT(std::string("RCPT not found: '") + line + "'", it != m_rcptLines.end()); + +				m_rcptLines.erase(it); + +				localSend("250 OK, recipient accepted\r\n"); + +				m_rcptSent = true; + +			} else if (cmd == "DATA") { + +				VASSERT("Client must send the MAIL command", m_mailSent); +				VASSERT("Client must send the RCPT command", m_rcptSent); +				VASSERT("All recipients", m_rcptLines.empty()); + +				localSend("354 Ready to accept data; end with <CRLF>.<CRLF>\r\n"); + +				m_state = STATE_DATA; +				m_msgData.clear(); + +				m_dataSent = true; + +			} else if (cmd == "NOOP") { + +				localSend("250 Completed\r\n"); + +			} else if (cmd == "QUIT") { + +				m_quitSent = true; + +				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_rcptLines; + +	std::string m_msgData; + +	bool m_ehloSent, m_mailSent, m_rcptSent, m_dataSent, m_quitSent; +}; | 
