Home | History | Annotate | Download | only in base
      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