|
ferencd@0
|
1 //
|
|
ferencd@0
|
2 // VMime library (http://www.vmime.org)
|
|
ferencd@0
|
3 // Copyright (C) 2002-2013 Vincent Richard <vincent@vmime.org>
|
|
ferencd@0
|
4 //
|
|
ferencd@0
|
5 // This program is free software; you can redistribute it and/or
|
|
ferencd@0
|
6 // modify it under the terms of the GNU General Public License as
|
|
ferencd@0
|
7 // published by the Free Software Foundation; either version 3 of
|
|
ferencd@0
|
8 // the License, or (at your option) any later version.
|
|
ferencd@0
|
9 //
|
|
ferencd@0
|
10 // This program is distributed in the hope that it will be useful,
|
|
ferencd@0
|
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
ferencd@0
|
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
ferencd@0
|
13 // General Public License for more details.
|
|
ferencd@0
|
14 //
|
|
ferencd@0
|
15 // You should have received a copy of the GNU General Public License along
|
|
ferencd@0
|
16 // with this program; if not, write to the Free Software Foundation, Inc.,
|
|
ferencd@0
|
17 // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
ferencd@0
|
18 //
|
|
ferencd@0
|
19 // Linking this library statically or dynamically with other modules is making
|
|
ferencd@0
|
20 // a combined work based on this library. Thus, the terms and conditions of
|
|
ferencd@0
|
21 // the GNU General Public License cover the whole combination.
|
|
ferencd@0
|
22 //
|
|
ferencd@0
|
23
|
|
ferencd@0
|
24 #include <ostream>
|
|
ferencd@0
|
25 #include <iostream>
|
|
ferencd@0
|
26 #include <sstream>
|
|
ferencd@0
|
27 #include <vector>
|
|
ferencd@0
|
28 #include <string>
|
|
ferencd@0
|
29
|
|
ferencd@0
|
30
|
|
ferencd@0
|
31 // VMime
|
|
ferencd@0
|
32 #include "vmime/vmime.hpp"
|
|
ferencd@0
|
33
|
|
ferencd@0
|
34
|
|
ferencd@0
|
35 // CppUnit
|
|
ferencd@0
|
36 #pragma GCC diagnostic ignored "-Wold-style-cast"
|
|
ferencd@0
|
37 #include <cppunit/TestAssert.h>
|
|
ferencd@0
|
38 #include <cppunit/extensions/HelperMacros.h>
|
|
ferencd@0
|
39 #pragma GCC diagnostic warning "-Wold-style-cast"
|
|
ferencd@0
|
40
|
|
ferencd@0
|
41 #define VASSERT(msg, cond) \
|
|
ferencd@0
|
42 CPPUNIT_ASSERT_MESSAGE(std::string(msg), cond)
|
|
ferencd@0
|
43
|
|
ferencd@0
|
44 #define VASSERT_TRUE(msg, cond) \
|
|
ferencd@0
|
45 VASSERT(msg, cond)
|
|
ferencd@0
|
46 #define VASSERT_FALSE(msg, cond) \
|
|
ferencd@0
|
47 VASSERT(msg, !(cond))
|
|
ferencd@0
|
48
|
|
ferencd@0
|
49 #define VASSERT_NOT_NULL(msg, cond) \
|
|
ferencd@0
|
50 VASSERT(msg, cond != NULL)
|
|
ferencd@0
|
51 #define VASSERT_NULL(msg, cond) \
|
|
ferencd@0
|
52 VASSERT(msg, cond == NULL)
|
|
ferencd@0
|
53
|
|
ferencd@0
|
54 #define VASSERT_EQ(msg, expected, actual) \
|
|
ferencd@0
|
55 CPPUNIT_ASSERT_EQUAL_MESSAGE(std::string(msg), expected, actual)
|
|
ferencd@0
|
56 #define VASSERT_NEQ(msg, expected, actual) \
|
|
ferencd@0
|
57 CPPUNIT_ASSERT_MESSAGE(std::string(msg), (expected) != (actual))
|
|
ferencd@0
|
58
|
|
ferencd@0
|
59 #define VASSERT_THROW(msg, expression, exceptionType) \
|
|
ferencd@0
|
60 CPPUNIT_ASSERT_THROW(expression, exceptionType)
|
|
ferencd@0
|
61 #define VASSERT_NO_THROW(msg, expression) \
|
|
ferencd@0
|
62 CPPUNIT_ASSERT_NO_THROW(expression)
|
|
ferencd@0
|
63
|
|
ferencd@0
|
64 #define VMIME_TEST_SUITE_BEGIN(testSuiteName) \
|
|
ferencd@0
|
65 class testSuiteName; \
|
|
ferencd@0
|
66 typedef testSuiteName VMIME_TEST_SUITE; \
|
|
ferencd@0
|
67 class testSuiteName : public CppUnit::TestFixture { public:
|
|
ferencd@0
|
68 #define VMIME_TEST_SUITE_END \
|
|
ferencd@0
|
69 }; \
|
|
ferencd@0
|
70 \
|
|
ferencd@0
|
71 /*static CppUnit::AutoRegisterSuite <VMIME_TEST_SUITE>(autoRegisterRegistry1);*/ \
|
|
ferencd@0
|
72 /*static CppUnit::AutoRegisterSuite <VMIME_TEST_SUITE>(autoRegisterRegistry2)(VMIME_TEST_SUITE_MODULE);*/ \
|
|
ferencd@0
|
73 extern void registerTestModule(const char* name); \
|
|
ferencd@0
|
74 extern const char* getTestModuleNameFromSourceFile(const char *path); \
|
|
ferencd@0
|
75 template <typename T> \
|
|
ferencd@0
|
76 struct AutoRegisterModule { \
|
|
ferencd@0
|
77 AutoRegisterModule() { \
|
|
ferencd@0
|
78 static const char* moduleName = getTestModuleNameFromSourceFile(__FILE__); \
|
|
ferencd@0
|
79 static CppUnit::AutoRegisterSuite <VMIME_TEST_SUITE>(autoRegisterRegistry1); \
|
|
ferencd@0
|
80 static CppUnit::AutoRegisterSuite <VMIME_TEST_SUITE>(autoRegisterRegistry2)(moduleName); \
|
|
ferencd@0
|
81 registerTestModule(moduleName); \
|
|
ferencd@0
|
82 } \
|
|
ferencd@0
|
83 }; \
|
|
ferencd@0
|
84 static AutoRegisterModule <VMIME_TEST_SUITE> autoRegisterModule;
|
|
ferencd@0
|
85
|
|
ferencd@0
|
86 #define VMIME_TEST_LIST_BEGIN CPPUNIT_TEST_SUITE(VMIME_TEST_SUITE);
|
|
ferencd@0
|
87 #define VMIME_TEST_LIST_END CPPUNIT_TEST_SUITE_END(); public:
|
|
ferencd@0
|
88 #define VMIME_TEST(name) CPPUNIT_TEST(name);
|
|
ferencd@0
|
89
|
|
ferencd@0
|
90
|
|
ferencd@0
|
91 namespace CppUnit
|
|
ferencd@0
|
92 {
|
|
ferencd@0
|
93 // Work-around for comparing 'std::string' against 'char*'
|
|
ferencd@0
|
94 inline void assertEquals(const char* expected, const std::string actual,
|
|
ferencd@0
|
95 SourceLine sourceLine, const std::string &message)
|
|
ferencd@0
|
96 {
|
|
ferencd@0
|
97 assertEquals(std::string(expected), actual, sourceLine, message);
|
|
ferencd@0
|
98 }
|
|
ferencd@0
|
99
|
|
ferencd@0
|
100 template <typename X, typename Y>
|
|
ferencd@0
|
101 void assertEquals(const X expected, const Y actual,
|
|
ferencd@0
|
102 SourceLine sourceLine, const std::string &message)
|
|
ferencd@0
|
103 {
|
|
ferencd@0
|
104 assertEquals(static_cast <Y>(expected), actual, sourceLine, message);
|
|
ferencd@0
|
105 }
|
|
ferencd@0
|
106 }
|
|
ferencd@0
|
107
|
|
ferencd@0
|
108
|
|
ferencd@0
|
109 namespace std
|
|
ferencd@0
|
110 {
|
|
ferencd@0
|
111
|
|
ferencd@0
|
112
|
|
ferencd@0
|
113 inline std::ostream& operator<<(std::ostream& os, const vmime::charset& ch)
|
|
ferencd@0
|
114 {
|
|
ferencd@0
|
115 os << "[charset: " << ch.getName() << "]";
|
|
ferencd@0
|
116 return (os);
|
|
ferencd@0
|
117 }
|
|
ferencd@0
|
118
|
|
ferencd@0
|
119
|
|
ferencd@0
|
120 inline std::ostream& operator<<(std::ostream& os, const vmime::word& w)
|
|
ferencd@0
|
121 {
|
|
ferencd@0
|
122 os << "[word: charset=" << w.getCharset().getName()
|
|
ferencd@0
|
123 << ", buffer=" << w.getBuffer();
|
|
ferencd@0
|
124
|
|
ferencd@0
|
125 if (!w.getLanguage().empty())
|
|
ferencd@0
|
126 os << ", lang=" << w.getLanguage();
|
|
ferencd@0
|
127
|
|
ferencd@0
|
128 os << "]";
|
|
ferencd@0
|
129
|
|
ferencd@0
|
130 return (os);
|
|
ferencd@0
|
131 }
|
|
ferencd@0
|
132
|
|
ferencd@0
|
133
|
|
ferencd@0
|
134 inline std::ostream& operator<<(std::ostream& os, const vmime::text& txt)
|
|
ferencd@0
|
135 {
|
|
ferencd@0
|
136 os << "[text: [";
|
|
ferencd@0
|
137
|
|
ferencd@0
|
138 for (size_t i = 0 ; i < txt.getWordCount() ; ++i)
|
|
ferencd@0
|
139 {
|
|
ferencd@0
|
140 const vmime::word& w = *txt.getWordAt(i);
|
|
ferencd@0
|
141
|
|
ferencd@0
|
142 if (i != 0)
|
|
ferencd@0
|
143 os << ",";
|
|
ferencd@0
|
144
|
|
ferencd@0
|
145 os << w;
|
|
ferencd@0
|
146 }
|
|
ferencd@0
|
147
|
|
ferencd@0
|
148 os << "]]";
|
|
ferencd@0
|
149
|
|
ferencd@0
|
150 return (os);
|
|
ferencd@0
|
151 }
|
|
ferencd@0
|
152
|
|
ferencd@0
|
153
|
|
ferencd@0
|
154 inline std::ostream& operator<<(std::ostream& os, const vmime::emailAddress& email)
|
|
ferencd@0
|
155 {
|
|
ferencd@0
|
156 os << email.generate();
|
|
ferencd@0
|
157
|
|
ferencd@0
|
158 return (os);
|
|
ferencd@0
|
159 }
|
|
ferencd@0
|
160
|
|
ferencd@0
|
161
|
|
ferencd@0
|
162 inline std::ostream& operator<<(std::ostream& os, const vmime::mailbox& mbox)
|
|
ferencd@0
|
163 {
|
|
ferencd@0
|
164 os << "[mailbox: name=" << mbox.getName() << ", email=" << mbox.getEmail() << "]";
|
|
ferencd@0
|
165
|
|
ferencd@0
|
166 return (os);
|
|
ferencd@0
|
167 }
|
|
ferencd@0
|
168
|
|
ferencd@0
|
169
|
|
ferencd@0
|
170 inline std::ostream& operator<<(std::ostream& os, const vmime::mailboxGroup& group)
|
|
ferencd@0
|
171 {
|
|
ferencd@0
|
172 os << "[mailbox-group: name=" << group.getName() << ", list=[";
|
|
ferencd@0
|
173
|
|
ferencd@0
|
174 for (size_t i = 0 ; i < group.getMailboxCount() ; ++i)
|
|
ferencd@0
|
175 {
|
|
ferencd@0
|
176 if (i != 0)
|
|
ferencd@0
|
177 os << ",";
|
|
ferencd@0
|
178
|
|
ferencd@0
|
179 os << *group.getMailboxAt(i);
|
|
ferencd@0
|
180 }
|
|
ferencd@0
|
181
|
|
ferencd@0
|
182 os << "]]";
|
|
ferencd@0
|
183
|
|
ferencd@0
|
184 return (os);
|
|
ferencd@0
|
185 }
|
|
ferencd@0
|
186
|
|
ferencd@0
|
187
|
|
ferencd@0
|
188 inline std::ostream& operator<<(std::ostream& os, const vmime::addressList& list)
|
|
ferencd@0
|
189 {
|
|
ferencd@0
|
190 os << "[address-list: [";
|
|
ferencd@0
|
191
|
|
ferencd@0
|
192 for (size_t i = 0 ; i < list.getAddressCount() ; ++i)
|
|
ferencd@0
|
193 {
|
|
ferencd@0
|
194 const vmime::address& addr = *list.getAddressAt(i);
|
|
ferencd@0
|
195
|
|
ferencd@0
|
196 if (i != 0)
|
|
ferencd@0
|
197 os << ",";
|
|
ferencd@0
|
198
|
|
ferencd@0
|
199 if (addr.isGroup())
|
|
ferencd@0
|
200 {
|
|
ferencd@0
|
201 const vmime::mailboxGroup& group =
|
|
ferencd@0
|
202 dynamic_cast <const vmime::mailboxGroup&>(addr);
|
|
ferencd@0
|
203
|
|
ferencd@0
|
204 os << group;
|
|
ferencd@0
|
205 }
|
|
ferencd@0
|
206 else
|
|
ferencd@0
|
207 {
|
|
ferencd@0
|
208 const vmime::mailbox& mbox =
|
|
ferencd@0
|
209 dynamic_cast <const vmime::mailbox&>(addr);
|
|
ferencd@0
|
210
|
|
ferencd@0
|
211 os << mbox;
|
|
ferencd@0
|
212 }
|
|
ferencd@0
|
213 }
|
|
ferencd@0
|
214
|
|
ferencd@0
|
215 os << "]]";
|
|
ferencd@0
|
216
|
|
ferencd@0
|
217 return (os);
|
|
ferencd@0
|
218 }
|
|
ferencd@0
|
219
|
|
ferencd@0
|
220
|
|
ferencd@0
|
221 inline std::ostream& operator<<(std::ostream& os, const vmime::datetime& d)
|
|
ferencd@0
|
222 {
|
|
ferencd@0
|
223 os << "[datetime: " << d.getYear() << "/" << d.getMonth() << "/" << d.getDay();
|
|
ferencd@0
|
224 os << " " << d.getHour() << ":" << d.getMinute() << ":" << d.getSecond();
|
|
ferencd@0
|
225 os << " #" << d.getZone() << "]";
|
|
ferencd@0
|
226
|
|
ferencd@0
|
227 return (os);
|
|
ferencd@0
|
228 }
|
|
ferencd@0
|
229
|
|
ferencd@0
|
230
|
|
ferencd@0
|
231 inline std::ostream& operator<<(std::ostream& os, const vmime::encoding& enc)
|
|
ferencd@0
|
232 {
|
|
ferencd@0
|
233 os << enc.generate();
|
|
ferencd@0
|
234
|
|
ferencd@0
|
235 return (os);
|
|
ferencd@0
|
236 }
|
|
ferencd@0
|
237
|
|
ferencd@0
|
238
|
|
ferencd@0
|
239 }
|
|
ferencd@0
|
240
|
|
ferencd@0
|
241
|
|
ferencd@0
|
242
|
|
ferencd@0
|
243 // Used to test network features.
|
|
ferencd@0
|
244 //
|
|
ferencd@0
|
245 // This works like a local pipe: client reads and writes data using receive()
|
|
ferencd@0
|
246 // and send(). Server reads incoming data with localReceive() and sends data
|
|
ferencd@0
|
247 // to client with localSend().
|
|
ferencd@0
|
248
|
|
ferencd@0
|
249 class testSocket : public vmime::net::socket
|
|
ferencd@0
|
250 {
|
|
ferencd@0
|
251 public:
|
|
ferencd@0
|
252
|
|
ferencd@0
|
253 void connect(const vmime::string& address, const vmime::port_t port);
|
|
ferencd@0
|
254 void disconnect();
|
|
ferencd@0
|
255
|
|
ferencd@0
|
256 bool isConnected() const;
|
|
ferencd@0
|
257
|
|
ferencd@0
|
258 bool waitForWrite(const int msecs = 30000);
|
|
ferencd@0
|
259 bool waitForRead(const int msecs = 30000);
|
|
ferencd@0
|
260
|
|
ferencd@0
|
261 void receive(vmime::string& buffer);
|
|
ferencd@0
|
262 void send(const vmime::string& buffer);
|
|
ferencd@0
|
263 void send(const char* str);
|
|
ferencd@0
|
264
|
|
ferencd@0
|
265 size_t receiveRaw(vmime::byte_t* buffer, const size_t count);
|
|
ferencd@0
|
266 void sendRaw(const vmime::byte_t* buffer, const size_t count);
|
|
ferencd@0
|
267 size_t sendRawNonBlocking(const vmime::byte_t* buffer, const size_t count);
|
|
ferencd@0
|
268
|
|
ferencd@0
|
269 size_t getBlockSize() const;
|
|
ferencd@0
|
270
|
|
ferencd@0
|
271 unsigned int getStatus() const;
|
|
ferencd@0
|
272
|
|
ferencd@0
|
273 const vmime::string getPeerName() const;
|
|
ferencd@0
|
274 const vmime::string getPeerAddress() const;
|
|
ferencd@0
|
275
|
|
ferencd@0
|
276 vmime::shared_ptr <vmime::net::timeoutHandler> getTimeoutHandler();
|
|
ferencd@0
|
277
|
|
ferencd@0
|
278 void setTracer(vmime::shared_ptr <vmime::net::tracer> tracer);
|
|
ferencd@0
|
279 vmime::shared_ptr <vmime::net::tracer> getTracer();
|
|
ferencd@0
|
280
|
|
ferencd@0
|
281 /** Send data to client.
|
|
ferencd@0
|
282 *
|
|
ferencd@0
|
283 * @param buffer data to send
|
|
ferencd@0
|
284 */
|
|
ferencd@0
|
285 void localSend(const vmime::string& buffer);
|
|
ferencd@0
|
286
|
|
ferencd@0
|
287 /** Receive data from client.
|
|
ferencd@0
|
288 *
|
|
ferencd@0
|
289 * @param buffer buffer in which to store received data
|
|
ferencd@0
|
290 */
|
|
ferencd@0
|
291 void localReceive(vmime::string& buffer);
|
|
ferencd@0
|
292
|
|
ferencd@0
|
293 /** Receive a line from client.
|
|
ferencd@0
|
294 *
|
|
ferencd@0
|
295 * @param buffer buffer in which to store received line
|
|
ferencd@0
|
296 * @return true if a line has been read, or false otherwise
|
|
ferencd@0
|
297 */
|
|
ferencd@0
|
298 bool localReceiveLine(vmime::string& buffer);
|
|
ferencd@0
|
299
|
|
ferencd@0
|
300 /** Receive data from client.
|
|
ferencd@0
|
301 *
|
|
ferencd@0
|
302 * @param buffer buffer in which to store received data
|
|
ferencd@0
|
303 * @param count number of bytes to receive
|
|
ferencd@0
|
304 * @return number of bytes received
|
|
ferencd@0
|
305 */
|
|
ferencd@0
|
306 vmime::size_t localReceiveRaw(vmime::byte_t* buffer, const size_t count);
|
|
ferencd@0
|
307
|
|
ferencd@0
|
308 protected:
|
|
ferencd@0
|
309
|
|
ferencd@0
|
310 /** Called when the client has sent some data.
|
|
ferencd@0
|
311 */
|
|
ferencd@0
|
312 virtual void onDataReceived();
|
|
ferencd@0
|
313
|
|
ferencd@0
|
314 /** Called when the client has connected.
|
|
ferencd@0
|
315 */
|
|
ferencd@0
|
316 virtual void onConnected();
|
|
ferencd@0
|
317
|
|
ferencd@0
|
318 private:
|
|
ferencd@0
|
319
|
|
ferencd@0
|
320 vmime::string m_address;
|
|
ferencd@0
|
321 vmime::port_t m_port;
|
|
ferencd@0
|
322 bool m_connected;
|
|
ferencd@0
|
323
|
|
ferencd@0
|
324 vmime::string m_inBuffer;
|
|
ferencd@0
|
325 vmime::string m_outBuffer;
|
|
ferencd@0
|
326 };
|
|
ferencd@0
|
327
|
|
ferencd@0
|
328
|
|
ferencd@0
|
329 template <typename T>
|
|
ferencd@0
|
330 class testSocketFactory : public vmime::net::socketFactory
|
|
ferencd@0
|
331 {
|
|
ferencd@0
|
332 public:
|
|
ferencd@0
|
333
|
|
ferencd@0
|
334 vmime::shared_ptr <vmime::net::socket> create()
|
|
ferencd@0
|
335 {
|
|
ferencd@0
|
336 return vmime::make_shared <T>();
|
|
ferencd@0
|
337 }
|
|
ferencd@0
|
338
|
|
ferencd@0
|
339 vmime::shared_ptr <vmime::net::socket> create(vmime::shared_ptr <vmime::net::timeoutHandler> /* th */)
|
|
ferencd@0
|
340 {
|
|
ferencd@0
|
341 return vmime::make_shared <T>();
|
|
ferencd@0
|
342 }
|
|
ferencd@0
|
343 };
|
|
ferencd@0
|
344
|
|
ferencd@0
|
345
|
|
ferencd@0
|
346 class lineBasedTestSocket : public testSocket
|
|
ferencd@0
|
347 {
|
|
ferencd@0
|
348 public:
|
|
ferencd@0
|
349
|
|
ferencd@0
|
350 void onDataReceived();
|
|
ferencd@0
|
351
|
|
ferencd@0
|
352 const vmime::string getNextLine();
|
|
ferencd@0
|
353 bool haveMoreLines() const;
|
|
ferencd@0
|
354
|
|
ferencd@0
|
355 virtual void processCommand() = 0;
|
|
ferencd@0
|
356
|
|
ferencd@0
|
357 private:
|
|
ferencd@0
|
358
|
|
ferencd@0
|
359 std::vector <vmime::string> m_lines;
|
|
ferencd@0
|
360 std::string m_buffer;
|
|
ferencd@0
|
361 };
|
|
ferencd@0
|
362
|
|
ferencd@0
|
363
|
|
ferencd@0
|
364 class testTimeoutHandler : public vmime::net::timeoutHandler
|
|
ferencd@0
|
365 {
|
|
ferencd@0
|
366 public:
|
|
ferencd@0
|
367
|
|
ferencd@0
|
368 testTimeoutHandler(const unsigned long delay = 3);
|
|
ferencd@0
|
369
|
|
ferencd@0
|
370 bool isTimeOut();
|
|
ferencd@0
|
371 void resetTimeOut();
|
|
ferencd@0
|
372 bool handleTimeOut();
|
|
ferencd@0
|
373
|
|
ferencd@0
|
374 private:
|
|
ferencd@0
|
375
|
|
ferencd@0
|
376 unsigned long m_delay;
|
|
ferencd@0
|
377 unsigned long m_start;
|
|
ferencd@0
|
378 };
|
|
ferencd@0
|
379
|
|
ferencd@0
|
380
|
|
ferencd@0
|
381 class testTimeoutHandlerFactory : public vmime::net::timeoutHandlerFactory
|
|
ferencd@0
|
382 {
|
|
ferencd@0
|
383 public:
|
|
ferencd@0
|
384
|
|
ferencd@0
|
385 vmime::shared_ptr <vmime::net::timeoutHandler> create();
|
|
ferencd@0
|
386 };
|
|
ferencd@0
|
387
|
|
ferencd@0
|
388
|
|
ferencd@0
|
389 // Exception helper
|
|
ferencd@0
|
390 std::ostream& operator<<(std::ostream& os, const vmime::exception& e);
|
|
ferencd@0
|
391
|
|
ferencd@0
|
392
|
|
ferencd@0
|
393 // Conversion to hexadecimal for easier debugging
|
|
ferencd@0
|
394 const vmime::string toHex(const vmime::string str);
|