diff options
Diffstat (limited to 'net/socket/socket_test_util.h')
-rw-r--r-- | net/socket/socket_test_util.h | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/net/socket/socket_test_util.h b/net/socket/socket_test_util.h new file mode 100644 index 0000000..4d3b569 --- /dev/null +++ b/net/socket/socket_test_util.h @@ -0,0 +1,204 @@ +// Copyright (c) 2009 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef NET_SOCKET_SOCKET_TEST_UTIL_H_ +#define NET_SOCKET_SOCKET_TEST_UTIL_H_ + +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "net/base/address_list.h" +#include "net/base/net_errors.h" +#include "net/base/ssl_config_service.h" +#include "net/socket/client_socket_factory.h" + +namespace net { + +class ClientSocket; +class SSLClientSocket; + +struct MockConnect { + // Asynchronous connection success. + MockConnect() : async(true), result(OK) { } + MockConnect(bool a, int r) : async(a), result(r) { } + + bool async; + int result; +}; + +struct MockRead { + // Read failure (no data). + MockRead(bool async, int result) : async(async) , result(result), data(NULL), + data_len(0) { } + + // Asynchronous read success (inferred data length). + explicit MockRead(const char* data) : async(true), result(0), data(data), + data_len(strlen(data)) { } + + // Read success (inferred data length). + MockRead(bool async, const char* data) : async(async), result(0), data(data), + data_len(strlen(data)) { } + + // Read success. + MockRead(bool async, const char* data, int data_len) : async(async), + result(0), data(data), data_len(data_len) { } + + bool async; + int result; + const char* data; + int data_len; +}; + +// MockWrite uses the same member fields as MockRead, but with different +// meanings. The expected input to MockTCPClientSocket::Write() is given +// by {data, data_len}, and the return value of Write() is controlled by +// {async, result}. +typedef MockRead MockWrite; + +struct MockWriteResult { + MockWriteResult(bool async, int result) : async(async), result(result) {} + + bool async; + int result; +}; + +class MockSocket { + public: + MockSocket() : unexpected_read_(true, ERR_UNEXPECTED) { + } + + virtual ~MockSocket() {} + virtual MockRead* GetNextRead() = 0; + virtual MockWriteResult OnWrite(const std::string& data) = 0; + virtual void Reset() = 0; + + MockConnect connect_data() const { return connect_; } + + protected: + MockRead* unexpected_read() { return &unexpected_read_; } + + private: + MockRead unexpected_read_; + MockConnect connect_; + + DISALLOW_COPY_AND_ASSIGN(MockSocket); +}; + +// MockSocket which responds based on static tables of mock reads and writes. +class StaticMockSocket : public MockSocket { + public: + StaticMockSocket() : reads_(NULL), read_index_(0), + writes_(NULL), write_index_(0) {} + StaticMockSocket(MockRead* r, MockWrite* w) : reads_(r), read_index_(0), + writes_(w), write_index_(0) {} + + // MockSocket methods: + virtual MockRead* GetNextRead(); + virtual MockWriteResult OnWrite(const std::string& data); + virtual void Reset(); + + private: + MockRead* reads_; + int read_index_; + MockWrite* writes_; + int write_index_; + + DISALLOW_COPY_AND_ASSIGN(StaticMockSocket); +}; + +// MockSocket which can make decisions about next mock reads based on +// received writes. It can also be used to enforce order of operations, +// for example that tested code must send the "Hello!" message before +// receiving response. This is useful for testing conversation-like +// protocols like FTP. +class DynamicMockSocket : public MockSocket { + public: + DynamicMockSocket(); + + // MockSocket methods: + virtual MockRead* GetNextRead(); + virtual MockWriteResult OnWrite(const std::string& data) = 0; + virtual void Reset(); + + protected: + // The next time there is a read from this socket, it will return |data|. + // Before calling SimulateRead next time, the previous data must be consumed. + void SimulateRead(const char* data); + + private: + MockRead read_; + bool has_read_; + bool consumed_read_; + + DISALLOW_COPY_AND_ASSIGN(DynamicMockSocket); +}; + +// MockSSLSockets only need to keep track of the return code from calls to +// Connect(). +struct MockSSLSocket { + MockSSLSocket(bool async, int result) : connect(async, result) { } + + MockConnect connect; +}; + +// Holds an array of Mock{SSL,}Socket elements. As Mock{TCP,SSL}ClientSocket +// objects get instantiated, they take their data from the i'th element of this +// array. +template<typename T> +class MockSocketArray { + public: + MockSocketArray() : next_index_(0) { + } + + T* GetNext() { + DCHECK(next_index_ < sockets_.size()); + return sockets_[next_index_++]; + } + + void Add(T* socket) { + DCHECK(socket); + sockets_.push_back(socket); + } + + void ResetNextIndex() { + next_index_ = 0; + } + + private: + // Index of the next |sockets| element to use. Not an iterator because those + // are invalidated on vector reallocation. + size_t next_index_; + + // Mock sockets to be returned. + std::vector<T*> sockets_; +}; + +// ClientSocketFactory which contains arrays of sockets of each type. +// You should first fill the arrays using AddMock{SSL,}Socket. When the factory +// is asked to create a socket, it takes next entry from appropriate array. +// You can use ResetNextMockIndexes to reset that next entry index for all mock +// socket types. +class MockClientSocketFactory : public ClientSocketFactory { + public: + void AddMockSocket(MockSocket* socket); + void AddMockSSLSocket(MockSSLSocket* socket); + void ResetNextMockIndexes(); + + // ClientSocketFactory + virtual ClientSocket* CreateTCPClientSocket(const AddressList& addresses); + virtual SSLClientSocket* CreateSSLClientSocket( + ClientSocket* transport_socket, + const std::string& hostname, + const SSLConfig& ssl_config); + + private: + MockSocketArray<MockSocket> mock_sockets_; + MockSocketArray<MockSSLSocket> mock_ssl_sockets_; +}; + +} // namespace net + +#endif // NET_SOCKET_SOCKET_TEST_UTIL_H_ |