ferencd@0: // ferencd@0: // VMime library (http://www.vmime.org) ferencd@0: // Copyright (C) 2002-2013 Vincent Richard ferencd@0: // ferencd@0: // This program is free software; you can redistribute it and/or ferencd@0: // modify it under the terms of the GNU General Public License as ferencd@0: // published by the Free Software Foundation; either version 3 of ferencd@0: // the License, or (at your option) any later version. ferencd@0: // ferencd@0: // This program is distributed in the hope that it will be useful, ferencd@0: // but WITHOUT ANY WARRANTY; without even the implied warranty of ferencd@0: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ferencd@0: // General Public License for more details. ferencd@0: // ferencd@0: // You should have received a copy of the GNU General Public License along ferencd@0: // with this program; if not, write to the Free Software Foundation, Inc., ferencd@0: // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ferencd@0: // ferencd@0: // Linking this library statically or dynamically with other modules is making ferencd@0: // a combined work based on this library. Thus, the terms and conditions of ferencd@0: // the GNU General Public License cover the whole combination. ferencd@0: // ferencd@0: ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: #include ferencd@0: ferencd@0: ferencd@0: // VMime ferencd@0: #include "vmime/vmime.hpp" ferencd@0: ferencd@0: ferencd@0: // CppUnit ferencd@0: #pragma GCC diagnostic ignored "-Wold-style-cast" ferencd@0: #include ferencd@0: #include ferencd@0: #pragma GCC diagnostic warning "-Wold-style-cast" ferencd@0: ferencd@0: #define VASSERT(msg, cond) \ ferencd@0: CPPUNIT_ASSERT_MESSAGE(std::string(msg), cond) ferencd@0: ferencd@0: #define VASSERT_TRUE(msg, cond) \ ferencd@0: VASSERT(msg, cond) ferencd@0: #define VASSERT_FALSE(msg, cond) \ ferencd@0: VASSERT(msg, !(cond)) ferencd@0: ferencd@0: #define VASSERT_NOT_NULL(msg, cond) \ ferencd@0: VASSERT(msg, cond != NULL) ferencd@0: #define VASSERT_NULL(msg, cond) \ ferencd@0: VASSERT(msg, cond == NULL) ferencd@0: ferencd@0: #define VASSERT_EQ(msg, expected, actual) \ ferencd@0: CPPUNIT_ASSERT_EQUAL_MESSAGE(std::string(msg), expected, actual) ferencd@0: #define VASSERT_NEQ(msg, expected, actual) \ ferencd@0: CPPUNIT_ASSERT_MESSAGE(std::string(msg), (expected) != (actual)) ferencd@0: ferencd@0: #define VASSERT_THROW(msg, expression, exceptionType) \ ferencd@0: CPPUNIT_ASSERT_THROW(expression, exceptionType) ferencd@0: #define VASSERT_NO_THROW(msg, expression) \ ferencd@0: CPPUNIT_ASSERT_NO_THROW(expression) ferencd@0: ferencd@0: #define VMIME_TEST_SUITE_BEGIN(testSuiteName) \ ferencd@0: class testSuiteName; \ ferencd@0: typedef testSuiteName VMIME_TEST_SUITE; \ ferencd@0: class testSuiteName : public CppUnit::TestFixture { public: ferencd@0: #define VMIME_TEST_SUITE_END \ ferencd@0: }; \ ferencd@0: \ ferencd@0: /*static CppUnit::AutoRegisterSuite (autoRegisterRegistry1);*/ \ ferencd@0: /*static CppUnit::AutoRegisterSuite (autoRegisterRegistry2)(VMIME_TEST_SUITE_MODULE);*/ \ ferencd@0: extern void registerTestModule(const char* name); \ ferencd@0: extern const char* getTestModuleNameFromSourceFile(const char *path); \ ferencd@0: template \ ferencd@0: struct AutoRegisterModule { \ ferencd@0: AutoRegisterModule() { \ ferencd@0: static const char* moduleName = getTestModuleNameFromSourceFile(__FILE__); \ ferencd@0: static CppUnit::AutoRegisterSuite (autoRegisterRegistry1); \ ferencd@0: static CppUnit::AutoRegisterSuite (autoRegisterRegistry2)(moduleName); \ ferencd@0: registerTestModule(moduleName); \ ferencd@0: } \ ferencd@0: }; \ ferencd@0: static AutoRegisterModule autoRegisterModule; ferencd@0: ferencd@0: #define VMIME_TEST_LIST_BEGIN CPPUNIT_TEST_SUITE(VMIME_TEST_SUITE); ferencd@0: #define VMIME_TEST_LIST_END CPPUNIT_TEST_SUITE_END(); public: ferencd@0: #define VMIME_TEST(name) CPPUNIT_TEST(name); ferencd@0: ferencd@0: ferencd@0: namespace CppUnit ferencd@0: { ferencd@0: // Work-around for comparing 'std::string' against 'char*' ferencd@0: inline void assertEquals(const char* expected, const std::string actual, ferencd@0: SourceLine sourceLine, const std::string &message) ferencd@0: { ferencd@0: assertEquals(std::string(expected), actual, sourceLine, message); ferencd@0: } ferencd@0: ferencd@0: template ferencd@0: void assertEquals(const X expected, const Y actual, ferencd@0: SourceLine sourceLine, const std::string &message) ferencd@0: { ferencd@0: assertEquals(static_cast (expected), actual, sourceLine, message); ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: ferencd@0: namespace std ferencd@0: { ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::charset& ch) ferencd@0: { ferencd@0: os << "[charset: " << ch.getName() << "]"; ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::word& w) ferencd@0: { ferencd@0: os << "[word: charset=" << w.getCharset().getName() ferencd@0: << ", buffer=" << w.getBuffer(); ferencd@0: ferencd@0: if (!w.getLanguage().empty()) ferencd@0: os << ", lang=" << w.getLanguage(); ferencd@0: ferencd@0: os << "]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::text& txt) ferencd@0: { ferencd@0: os << "[text: ["; ferencd@0: ferencd@0: for (size_t i = 0 ; i < txt.getWordCount() ; ++i) ferencd@0: { ferencd@0: const vmime::word& w = *txt.getWordAt(i); ferencd@0: ferencd@0: if (i != 0) ferencd@0: os << ","; ferencd@0: ferencd@0: os << w; ferencd@0: } ferencd@0: ferencd@0: os << "]]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::emailAddress& email) ferencd@0: { ferencd@0: os << email.generate(); ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::mailbox& mbox) ferencd@0: { ferencd@0: os << "[mailbox: name=" << mbox.getName() << ", email=" << mbox.getEmail() << "]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::mailboxGroup& group) ferencd@0: { ferencd@0: os << "[mailbox-group: name=" << group.getName() << ", list=["; ferencd@0: ferencd@0: for (size_t i = 0 ; i < group.getMailboxCount() ; ++i) ferencd@0: { ferencd@0: if (i != 0) ferencd@0: os << ","; ferencd@0: ferencd@0: os << *group.getMailboxAt(i); ferencd@0: } ferencd@0: ferencd@0: os << "]]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::addressList& list) ferencd@0: { ferencd@0: os << "[address-list: ["; ferencd@0: ferencd@0: for (size_t i = 0 ; i < list.getAddressCount() ; ++i) ferencd@0: { ferencd@0: const vmime::address& addr = *list.getAddressAt(i); ferencd@0: ferencd@0: if (i != 0) ferencd@0: os << ","; ferencd@0: ferencd@0: if (addr.isGroup()) ferencd@0: { ferencd@0: const vmime::mailboxGroup& group = ferencd@0: dynamic_cast (addr); ferencd@0: ferencd@0: os << group; ferencd@0: } ferencd@0: else ferencd@0: { ferencd@0: const vmime::mailbox& mbox = ferencd@0: dynamic_cast (addr); ferencd@0: ferencd@0: os << mbox; ferencd@0: } ferencd@0: } ferencd@0: ferencd@0: os << "]]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::datetime& d) ferencd@0: { ferencd@0: os << "[datetime: " << d.getYear() << "/" << d.getMonth() << "/" << d.getDay(); ferencd@0: os << " " << d.getHour() << ":" << d.getMinute() << ":" << d.getSecond(); ferencd@0: os << " #" << d.getZone() << "]"; ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: inline std::ostream& operator<<(std::ostream& os, const vmime::encoding& enc) ferencd@0: { ferencd@0: os << enc.generate(); ferencd@0: ferencd@0: return (os); ferencd@0: } ferencd@0: ferencd@0: ferencd@0: } ferencd@0: ferencd@0: ferencd@0: ferencd@0: // Used to test network features. ferencd@0: // ferencd@0: // This works like a local pipe: client reads and writes data using receive() ferencd@0: // and send(). Server reads incoming data with localReceive() and sends data ferencd@0: // to client with localSend(). ferencd@0: ferencd@0: class testSocket : public vmime::net::socket ferencd@0: { ferencd@0: public: ferencd@0: ferencd@0: void connect(const vmime::string& address, const vmime::port_t port); ferencd@0: void disconnect(); ferencd@0: ferencd@0: bool isConnected() const; ferencd@0: ferencd@0: bool waitForWrite(const int msecs = 30000); ferencd@0: bool waitForRead(const int msecs = 30000); ferencd@0: ferencd@0: void receive(vmime::string& buffer); ferencd@0: void send(const vmime::string& buffer); ferencd@0: void send(const char* str); ferencd@0: ferencd@0: size_t receiveRaw(vmime::byte_t* buffer, const size_t count); ferencd@0: void sendRaw(const vmime::byte_t* buffer, const size_t count); ferencd@0: size_t sendRawNonBlocking(const vmime::byte_t* buffer, const size_t count); ferencd@0: ferencd@0: size_t getBlockSize() const; ferencd@0: ferencd@0: unsigned int getStatus() const; ferencd@0: ferencd@0: const vmime::string getPeerName() const; ferencd@0: const vmime::string getPeerAddress() const; ferencd@0: ferencd@0: vmime::shared_ptr getTimeoutHandler(); ferencd@0: ferencd@0: void setTracer(vmime::shared_ptr tracer); ferencd@0: vmime::shared_ptr getTracer(); ferencd@0: ferencd@0: /** Send data to client. ferencd@0: * ferencd@0: * @param buffer data to send ferencd@0: */ ferencd@0: void localSend(const vmime::string& buffer); ferencd@0: ferencd@0: /** Receive data from client. ferencd@0: * ferencd@0: * @param buffer buffer in which to store received data ferencd@0: */ ferencd@0: void localReceive(vmime::string& buffer); ferencd@0: ferencd@0: /** Receive a line from client. ferencd@0: * ferencd@0: * @param buffer buffer in which to store received line ferencd@0: * @return true if a line has been read, or false otherwise ferencd@0: */ ferencd@0: bool localReceiveLine(vmime::string& buffer); ferencd@0: ferencd@0: /** Receive data from client. ferencd@0: * ferencd@0: * @param buffer buffer in which to store received data ferencd@0: * @param count number of bytes to receive ferencd@0: * @return number of bytes received ferencd@0: */ ferencd@0: vmime::size_t localReceiveRaw(vmime::byte_t* buffer, const size_t count); ferencd@0: ferencd@0: protected: ferencd@0: ferencd@0: /** Called when the client has sent some data. ferencd@0: */ ferencd@0: virtual void onDataReceived(); ferencd@0: ferencd@0: /** Called when the client has connected. ferencd@0: */ ferencd@0: virtual void onConnected(); ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: vmime::string m_address; ferencd@0: vmime::port_t m_port; ferencd@0: bool m_connected; ferencd@0: ferencd@0: vmime::string m_inBuffer; ferencd@0: vmime::string m_outBuffer; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: template ferencd@0: class testSocketFactory : public vmime::net::socketFactory ferencd@0: { ferencd@0: public: ferencd@0: ferencd@0: vmime::shared_ptr create() ferencd@0: { ferencd@0: return vmime::make_shared (); ferencd@0: } ferencd@0: ferencd@0: vmime::shared_ptr create(vmime::shared_ptr /* th */) ferencd@0: { ferencd@0: return vmime::make_shared (); ferencd@0: } ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: class lineBasedTestSocket : public testSocket ferencd@0: { ferencd@0: public: ferencd@0: ferencd@0: void onDataReceived(); ferencd@0: ferencd@0: const vmime::string getNextLine(); ferencd@0: bool haveMoreLines() const; ferencd@0: ferencd@0: virtual void processCommand() = 0; ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: std::vector m_lines; ferencd@0: std::string m_buffer; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: class testTimeoutHandler : public vmime::net::timeoutHandler ferencd@0: { ferencd@0: public: ferencd@0: ferencd@0: testTimeoutHandler(const unsigned long delay = 3); ferencd@0: ferencd@0: bool isTimeOut(); ferencd@0: void resetTimeOut(); ferencd@0: bool handleTimeOut(); ferencd@0: ferencd@0: private: ferencd@0: ferencd@0: unsigned long m_delay; ferencd@0: unsigned long m_start; ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: class testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory ferencd@0: { ferencd@0: public: ferencd@0: ferencd@0: vmime::shared_ptr create(); ferencd@0: }; ferencd@0: ferencd@0: ferencd@0: // Exception helper ferencd@0: std::ostream& operator<<(std::ostream& os, const vmime::exception& e); ferencd@0: ferencd@0: ferencd@0: // Conversion to hexadecimal for easier debugging ferencd@0: const vmime::string toHex(const vmime::string str);