1 /* 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 44 namespace testing { 45 46 using 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 56 enum 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 64 class 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 163 class StreamSource : public StreamInterface { 164 public: 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 269 private: 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 281 class SocketTestClient : public sigslot::has_slots<> { 282 public: 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 327 private: 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 388 class 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 430 inline 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 449 inline 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 487 inline 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__ 571