blob: 769d95f6464cdfc4f4a797e6463683b2eaccbdf0 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2004--2011, Google Inc.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#ifndef TALK_BASE_TESTUTILS_H__
29#define TALK_BASE_TESTUTILS_H__
30
31// Utilities for testing talk_base infrastructure in unittests
32
33#include <map>
34#include <vector>
35#include "talk/base/asyncsocket.h"
36#include "talk/base/common.h"
37#include "talk/base/gunit.h"
38#include "talk/base/nethelpers.h"
39#include "talk/base/stream.h"
40#include "talk/base/stringencode.h"
41#include "talk/base/stringutils.h"
42#include "talk/base/thread.h"
43
44namespace testing {
45
46using namespace talk_base;
47
48///////////////////////////////////////////////////////////////////////////////
49// StreamSink - Monitor asynchronously signalled events from StreamInterface
50// or AsyncSocket (which should probably be a StreamInterface.
51///////////////////////////////////////////////////////////////////////////////
52
53// Note: Any event that is an error is treaded as SSE_ERROR instead of that
54// event.
55
56enum StreamSinkEvent {
57 SSE_OPEN = SE_OPEN,
58 SSE_READ = SE_READ,
59 SSE_WRITE = SE_WRITE,
60 SSE_CLOSE = SE_CLOSE,
61 SSE_ERROR = 16
62};
63
64class StreamSink : public sigslot::has_slots<> {
65 public:
66 void Monitor(StreamInterface* stream) {
67 stream->SignalEvent.connect(this, &StreamSink::OnEvent);
68 events_.erase(stream);
69 }
70 void Unmonitor(StreamInterface* stream) {
71 stream->SignalEvent.disconnect(this);
72 // In case you forgot to unmonitor a previous object with this address
73 events_.erase(stream);
74 }
75 bool Check(StreamInterface* stream, StreamSinkEvent event, bool reset = true) {
76 return DoCheck(stream, event, reset);
77 }
78 int Events(StreamInterface* stream, bool reset = true) {
79 return DoEvents(stream, reset);
80 }
81
82 void Monitor(AsyncSocket* socket) {
83 socket->SignalConnectEvent.connect(this, &StreamSink::OnConnectEvent);
84 socket->SignalReadEvent.connect(this, &StreamSink::OnReadEvent);
85 socket->SignalWriteEvent.connect(this, &StreamSink::OnWriteEvent);
86 socket->SignalCloseEvent.connect(this, &StreamSink::OnCloseEvent);
87 // In case you forgot to unmonitor a previous object with this address
88 events_.erase(socket);
89 }
90 void Unmonitor(AsyncSocket* socket) {
91 socket->SignalConnectEvent.disconnect(this);
92 socket->SignalReadEvent.disconnect(this);
93 socket->SignalWriteEvent.disconnect(this);
94 socket->SignalCloseEvent.disconnect(this);
95 events_.erase(socket);
96 }
97 bool Check(AsyncSocket* socket, StreamSinkEvent event, bool reset = true) {
98 return DoCheck(socket, event, reset);
99 }
100 int Events(AsyncSocket* socket, bool reset = true) {
101 return DoEvents(socket, reset);
102 }
103
104 private:
105 typedef std::map<void*,int> EventMap;
106
107 void OnEvent(StreamInterface* stream, int events, int error) {
108 if (error) {
109 events = SSE_ERROR;
110 }
111 AddEvents(stream, events);
112 }
113 void OnConnectEvent(AsyncSocket* socket) {
114 AddEvents(socket, SSE_OPEN);
115 }
116 void OnReadEvent(AsyncSocket* socket) {
117 AddEvents(socket, SSE_READ);
118 }
119 void OnWriteEvent(AsyncSocket* socket) {
120 AddEvents(socket, SSE_WRITE);
121 }
122 void OnCloseEvent(AsyncSocket* socket, int error) {
123 AddEvents(socket, (0 == error) ? SSE_CLOSE : SSE_ERROR);
124 }
125
126 void AddEvents(void* obj, int events) {
127 EventMap::iterator it = events_.find(obj);
128 if (events_.end() == it) {
129 events_.insert(EventMap::value_type(obj, events));
130 } else {
131 it->second |= events;
132 }
133 }
134 bool DoCheck(void* obj, StreamSinkEvent event, bool reset) {
135 EventMap::iterator it = events_.find(obj);
136 if ((events_.end() == it) || (0 == (it->second & event))) {
137 return false;
138 }
139 if (reset) {
140 it->second &= ~event;
141 }
142 return true;
143 }
144 int DoEvents(void* obj, bool reset) {
145 EventMap::iterator it = events_.find(obj);
146 if (events_.end() == it)
147 return 0;
148 int events = it->second;
149 if (reset) {
150 it->second = 0;
151 }
152 return events;
153 }
154
155 EventMap events_;
156};
157
158///////////////////////////////////////////////////////////////////////////////
159// StreamSource - Implements stream interface and simulates asynchronous
160// events on the stream, without a network. Also buffers written data.
161///////////////////////////////////////////////////////////////////////////////
162
163class StreamSource : public StreamInterface {
164public:
165 StreamSource() {
166 Clear();
167 }
168
169 void Clear() {
170 readable_data_.clear();
171 written_data_.clear();
172 state_ = SS_CLOSED;
173 read_block_ = 0;
174 write_block_ = SIZE_UNKNOWN;
175 }
176 void QueueString(const char* data) {
177 QueueData(data, strlen(data));
178 }
179 void QueueStringF(const char* format, ...) {
180 va_list args;
181 va_start(args, format);
182 char buffer[1024];
183 size_t len = vsprintfn(buffer, sizeof(buffer), format, args);
184 ASSERT(len < sizeof(buffer) - 1);
185 va_end(args);
186 QueueData(buffer, len);
187 }
188 void QueueData(const char* data, size_t len) {
189 readable_data_.insert(readable_data_.end(), data, data + len);
190 if ((SS_OPEN == state_) && (readable_data_.size() == len)) {
191 SignalEvent(this, SE_READ, 0);
192 }
193 }
194 std::string ReadData() {
195 std::string data;
196 // avoid accessing written_data_[0] if it is undefined
197 if (written_data_.size() > 0) {
198 data.insert(0, &written_data_[0], written_data_.size());
199 }
200 written_data_.clear();
201 return data;
202 }
203 void SetState(StreamState state) {
204 int events = 0;
205 if ((SS_OPENING == state_) && (SS_OPEN == state)) {
206 events |= SE_OPEN;
207 if (!readable_data_.empty()) {
208 events |= SE_READ;
209 }
210 } else if ((SS_CLOSED != state_) && (SS_CLOSED == state)) {
211 events |= SE_CLOSE;
212 }
213 state_ = state;
214 if (events) {
215 SignalEvent(this, events, 0);
216 }
217 }
218 // Will cause Read to block when there are pos bytes in the read queue.
219 void SetReadBlock(size_t pos) { read_block_ = pos; }
220 // Will cause Write to block when there are pos bytes in the write queue.
221 void SetWriteBlock(size_t pos) { write_block_ = pos; }
222
223 virtual StreamState GetState() const { return state_; }
224 virtual StreamResult Read(void* buffer, size_t buffer_len,
225 size_t* read, int* error) {
226 if (SS_CLOSED == state_) {
227 if (error) *error = -1;
228 return SR_ERROR;
229 }
230 if ((SS_OPENING == state_) || (readable_data_.size() <= read_block_)) {
231 return SR_BLOCK;
232 }
233 size_t count = _min(buffer_len, readable_data_.size() - read_block_);
234 memcpy(buffer, &readable_data_[0], count);
235 size_t new_size = readable_data_.size() - count;
236 // Avoid undefined access beyond the last element of the vector.
237 // This only happens when new_size is 0.
238 if (count < readable_data_.size()) {
239 memmove(&readable_data_[0], &readable_data_[count], new_size);
240 }
241 readable_data_.resize(new_size);
242 if (read) *read = count;
243 return SR_SUCCESS;
244 }
245 virtual StreamResult Write(const void* data, size_t data_len,
246 size_t* written, int* error) {
247 if (SS_CLOSED == state_) {
248 if (error) *error = -1;
249 return SR_ERROR;
250 }
251 if (SS_OPENING == state_) {
252 return SR_BLOCK;
253 }
254 if (SIZE_UNKNOWN != write_block_) {
255 if (written_data_.size() >= write_block_) {
256 return SR_BLOCK;
257 }
258 if (data_len > (write_block_ - written_data_.size())) {
259 data_len = write_block_ - written_data_.size();
260 }
261 }
262 if (written) *written = data_len;
263 const char* cdata = static_cast<const char*>(data);
264 written_data_.insert(written_data_.end(), cdata, cdata + data_len);
265 return SR_SUCCESS;
266 }
267 virtual void Close() { state_ = SS_CLOSED; }
268
269private:
270 typedef std::vector<char> Buffer;
271 Buffer readable_data_, written_data_;
272 StreamState state_;
273 size_t read_block_, write_block_;
274};
275
276///////////////////////////////////////////////////////////////////////////////
277// SocketTestClient
278// Creates a simulated client for testing. Works on real and virtual networks.
279///////////////////////////////////////////////////////////////////////////////
280
281class SocketTestClient : public sigslot::has_slots<> {
282public:
283 SocketTestClient() {
284 Init(NULL, AF_INET);
285 }
286 SocketTestClient(AsyncSocket* socket) {
287 Init(socket, socket->GetLocalAddress().family());
288 }
289 SocketTestClient(const SocketAddress& address) {
290 Init(NULL, address.family());
291 socket_->Connect(address);
292 }
293
294 AsyncSocket* socket() { return socket_.get(); }
295
296 void QueueString(const char* data) {
297 QueueData(data, strlen(data));
298 }
299 void QueueStringF(const char* format, ...) {
300 va_list args;
301 va_start(args, format);
302 char buffer[1024];
303 size_t len = vsprintfn(buffer, sizeof(buffer), format, args);
304 ASSERT(len < sizeof(buffer) - 1);
305 va_end(args);
306 QueueData(buffer, len);
307 }
308 void QueueData(const char* data, size_t len) {
309 send_buffer_.insert(send_buffer_.end(), data, data + len);
310 if (Socket::CS_CONNECTED == socket_->GetState()) {
311 Flush();
312 }
313 }
314 std::string ReadData() {
315 std::string data(&recv_buffer_[0], recv_buffer_.size());
316 recv_buffer_.clear();
317 return data;
318 }
319
320 bool IsConnected() const {
321 return (Socket::CS_CONNECTED == socket_->GetState());
322 }
323 bool IsClosed() const {
324 return (Socket::CS_CLOSED == socket_->GetState());
325 }
326
327private:
328 typedef std::vector<char> Buffer;
329
330 void Init(AsyncSocket* socket, int family) {
331 if (!socket) {
332 socket = Thread::Current()->socketserver()
333 ->CreateAsyncSocket(family, SOCK_STREAM);
334 }
335 socket_.reset(socket);
336 socket_->SignalConnectEvent.connect(this,
337 &SocketTestClient::OnConnectEvent);
338 socket_->SignalReadEvent.connect(this, &SocketTestClient::OnReadEvent);
339 socket_->SignalWriteEvent.connect(this, &SocketTestClient::OnWriteEvent);
340 socket_->SignalCloseEvent.connect(this, &SocketTestClient::OnCloseEvent);
341 }
342
343 void Flush() {
344 size_t sent = 0;
345 while (sent < send_buffer_.size()) {
346 int result = socket_->Send(&send_buffer_[sent],
347 send_buffer_.size() - sent);
348 if (result > 0) {
349 sent += result;
350 } else {
351 break;
352 }
353 }
354 size_t new_size = send_buffer_.size() - sent;
355 memmove(&send_buffer_[0], &send_buffer_[sent], new_size);
356 send_buffer_.resize(new_size);
357 }
358
359 void OnConnectEvent(AsyncSocket* socket) {
360 if (!send_buffer_.empty()) {
361 Flush();
362 }
363 }
364 void OnReadEvent(AsyncSocket* socket) {
365 char data[64 * 1024];
366 int result = socket_->Recv(data, ARRAY_SIZE(data));
367 if (result > 0) {
368 recv_buffer_.insert(recv_buffer_.end(), data, data + result);
369 }
370 }
371 void OnWriteEvent(AsyncSocket* socket) {
372 if (!send_buffer_.empty()) {
373 Flush();
374 }
375 }
376 void OnCloseEvent(AsyncSocket* socket, int error) {
377 }
378
379 scoped_ptr<AsyncSocket> socket_;
380 Buffer send_buffer_, recv_buffer_;
381};
382
383///////////////////////////////////////////////////////////////////////////////
384// SocketTestServer
385// Creates a simulated server for testing. Works on real and virtual networks.
386///////////////////////////////////////////////////////////////////////////////
387
388class SocketTestServer : public sigslot::has_slots<> {
389 public:
390 SocketTestServer(const SocketAddress& address)
391 : socket_(Thread::Current()->socketserver()
392 ->CreateAsyncSocket(address.family(), SOCK_STREAM))
393 {
394 socket_->SignalReadEvent.connect(this, &SocketTestServer::OnReadEvent);
395 socket_->Bind(address);
396 socket_->Listen(5);
397 }
398 virtual ~SocketTestServer() {
399 clear();
400 }
401
402 size_t size() const { return clients_.size(); }
403 SocketTestClient* client(size_t index) const { return clients_[index]; }
404 SocketTestClient* operator[](size_t index) const { return client(index); }
405
406 void clear() {
407 for (size_t i=0; i<clients_.size(); ++i) {
408 delete clients_[i];
409 }
410 clients_.clear();
411 }
412
413 private:
414 void OnReadEvent(AsyncSocket* socket) {
415 AsyncSocket* accepted =
416 static_cast<AsyncSocket*>(socket_->Accept(NULL));
417 if (!accepted)
418 return;
419 clients_.push_back(new SocketTestClient(accepted));
420 }
421
422 scoped_ptr<AsyncSocket> socket_;
423 std::vector<SocketTestClient*> clients_;
424};
425
426///////////////////////////////////////////////////////////////////////////////
427// Generic Utilities
428///////////////////////////////////////////////////////////////////////////////
429
430inline bool ReadFile(const char* filename, std::string* contents) {
431 FILE* fp = fopen(filename, "rb");
432 if (!fp)
433 return false;
434 char buffer[1024*64];
435 size_t read;
436 contents->clear();
437 while ((read = fread(buffer, 1, sizeof(buffer), fp))) {
438 contents->append(buffer, read);
439 }
440 bool success = (0 != feof(fp));
441 fclose(fp);
442 return success;
443}
444
445///////////////////////////////////////////////////////////////////////////////
446// Unittest predicates which are similar to STREQ, but for raw memory
447///////////////////////////////////////////////////////////////////////////////
448
449inline AssertionResult CmpHelperMemEq(const char* expected_expression,
450 const char* expected_length_expression,
451 const char* actual_expression,
452 const char* actual_length_expression,
453 const void* expected,
454 size_t expected_length,
455 const void* actual,
456 size_t actual_length)
457{
458 if ((expected_length == actual_length)
459 && (0 == memcmp(expected, actual, expected_length))) {
460 return AssertionSuccess();
461 }
462
463 Message msg;
464 msg << "Value of: " << actual_expression
465 << " [" << actual_length_expression << "]";
466 if (true) { //!actual_value.Equals(actual_expression)) {
467 size_t buffer_size = actual_length * 2 + 1;
468 char* buffer = STACK_ARRAY(char, buffer_size);
469 hex_encode(buffer, buffer_size,
470 reinterpret_cast<const char*>(actual), actual_length);
471 msg << "\n Actual: " << buffer << " [" << actual_length << "]";
472 }
473
474 msg << "\nExpected: " << expected_expression
475 << " [" << expected_length_expression << "]";
476 if (true) { //!expected_value.Equals(expected_expression)) {
477 size_t buffer_size = expected_length * 2 + 1;
478 char* buffer = STACK_ARRAY(char, buffer_size);
479 hex_encode(buffer, buffer_size,
480 reinterpret_cast<const char*>(expected), expected_length);
481 msg << "\nWhich is: " << buffer << " [" << expected_length << "]";
482 }
483
484 return AssertionFailure(msg);
485}
486
487inline AssertionResult CmpHelperFileEq(const char* expected_expression,
488 const char* expected_length_expression,
489 const char* actual_filename,
490 const void* expected,
491 size_t expected_length,
492 const char* filename)
493{
494 std::string contents;
495 if (!ReadFile(filename, &contents)) {
496 Message msg;
497 msg << "File '" << filename << "' could not be read.";
498 return AssertionFailure(msg);
499 }
500 return CmpHelperMemEq(expected_expression, expected_length_expression,
501 actual_filename, "",
502 expected, expected_length,
503 contents.c_str(), contents.size());
504}
505
506#define EXPECT_MEMEQ(expected, expected_length, actual, actual_length) \
507 EXPECT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \
508 actual, actual_length)
509
510#define ASSERT_MEMEQ(expected, expected_length, actual, actual_length) \
511 ASSERT_PRED_FORMAT4(::testing::CmpHelperMemEq, expected, expected_length, \
512 actual, actual_length)
513
514#define EXPECT_FILEEQ(expected, expected_length, filename) \
515 EXPECT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \
516 filename)
517
518#define ASSERT_FILEEQ(expected, expected_length, filename) \
519 ASSERT_PRED_FORMAT3(::testing::CmpHelperFileEq, expected, expected_length, \
520 filename)
521
522///////////////////////////////////////////////////////////////////////////////
523// Helpers for initializing constant memory with integers in a particular byte
524// order
525///////////////////////////////////////////////////////////////////////////////
526
527#define BYTE_CAST(x) static_cast<uint8>((x) & 0xFF)
528
529// Declare a N-bit integer as a little-endian sequence of bytes
530#define LE16(x) BYTE_CAST(((uint16)x) >> 0), BYTE_CAST(((uint16)x) >> 8)
531
532#define LE32(x) BYTE_CAST(((uint32)x) >> 0), BYTE_CAST(((uint32)x) >> 8), \
533 BYTE_CAST(((uint32)x) >> 16), BYTE_CAST(((uint32)x) >> 24)
534
535#define LE64(x) BYTE_CAST(((uint64)x) >> 0), BYTE_CAST(((uint64)x) >> 8), \
536 BYTE_CAST(((uint64)x) >> 16), BYTE_CAST(((uint64)x) >> 24), \
537 BYTE_CAST(((uint64)x) >> 32), BYTE_CAST(((uint64)x) >> 40), \
538 BYTE_CAST(((uint64)x) >> 48), BYTE_CAST(((uint64)x) >> 56)
539
540// Declare a N-bit integer as a big-endian (Internet) sequence of bytes
541#define BE16(x) BYTE_CAST(((uint16)x) >> 8), BYTE_CAST(((uint16)x) >> 0)
542
543#define BE32(x) BYTE_CAST(((uint32)x) >> 24), BYTE_CAST(((uint32)x) >> 16), \
544 BYTE_CAST(((uint32)x) >> 8), BYTE_CAST(((uint32)x) >> 0)
545
546#define BE64(x) BYTE_CAST(((uint64)x) >> 56), BYTE_CAST(((uint64)x) >> 48), \
547 BYTE_CAST(((uint64)x) >> 40), BYTE_CAST(((uint64)x) >> 32), \
548 BYTE_CAST(((uint64)x) >> 24), BYTE_CAST(((uint64)x) >> 16), \
549 BYTE_CAST(((uint64)x) >> 8), BYTE_CAST(((uint64)x) >> 0)
550
551// Declare a N-bit integer as a this-endian (local machine) sequence of bytes
552#ifndef BIG_ENDIAN
553#define BIG_ENDIAN 1
554#endif // BIG_ENDIAN
555
556#if BIG_ENDIAN
557#define TE16 BE16
558#define TE32 BE32
559#define TE64 BE64
560#else // !BIG_ENDIAN
561#define TE16 LE16
562#define TE32 LE32
563#define TE64 LE64
564#endif // !BIG_ENDIAN
565
566///////////////////////////////////////////////////////////////////////////////
567
568} // namespace testing
569
570#endif // TALK_BASE_TESTUTILS_H__