Merge "fastboot: socket testing improvements."
am: f971b6a24b
* commit 'f971b6a24b2d785187cf98cb002b9aee9ab6b2a7':
fastboot: socket testing improvements.
This commit is contained in:
commit
fe12d889e4
6 changed files with 350 additions and 15 deletions
|
|
@ -106,7 +106,11 @@ include $(CLEAR_VARS)
|
||||||
LOCAL_MODULE := fastboot_test
|
LOCAL_MODULE := fastboot_test
|
||||||
LOCAL_MODULE_HOST_OS := darwin linux windows
|
LOCAL_MODULE_HOST_OS := darwin linux windows
|
||||||
|
|
||||||
LOCAL_SRC_FILES := socket.cpp socket_test.cpp
|
LOCAL_SRC_FILES := \
|
||||||
|
socket.cpp \
|
||||||
|
socket_mock.cpp \
|
||||||
|
socket_test.cpp \
|
||||||
|
|
||||||
LOCAL_STATIC_LIBRARIES := libbase libcutils
|
LOCAL_STATIC_LIBRARIES := libbase libcutils
|
||||||
|
|
||||||
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
|
LOCAL_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@
|
||||||
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
|
||||||
|
#include <android-base/errors.h>
|
||||||
#include <android-base/stringprintf.h>
|
#include <android-base/stringprintf.h>
|
||||||
|
|
||||||
Socket::Socket(cutils_socket_t sock) : sock_(sock) {}
|
Socket::Socket(cutils_socket_t sock) : sock_(sock) {}
|
||||||
|
|
@ -77,6 +78,10 @@ ssize_t Socket::ReceiveAll(void* data, size_t length, int timeout_ms) {
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Socket::GetLocalPort() {
|
||||||
|
return socket_get_local_port(sock_);
|
||||||
|
}
|
||||||
|
|
||||||
// Implements the Socket interface for UDP.
|
// Implements the Socket interface for UDP.
|
||||||
class UdpSocket : public Socket {
|
class UdpSocket : public Socket {
|
||||||
public:
|
public:
|
||||||
|
|
@ -210,3 +215,12 @@ std::unique_ptr<Socket> Socket::NewServer(Protocol protocol, int port) {
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Socket::GetErrorMessage() {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
DWORD error_code = WSAGetLastError();
|
||||||
|
#else
|
||||||
|
int error_code = errno;
|
||||||
|
#endif
|
||||||
|
return android::base::SystemErrorCodeToString(error_code);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,10 @@ class Socket {
|
||||||
public:
|
public:
|
||||||
enum class Protocol { kTcp, kUdp };
|
enum class Protocol { kTcp, kUdp };
|
||||||
|
|
||||||
|
// Returns the socket error message. This must be called immediately after a socket failure
|
||||||
|
// before any other system calls are made.
|
||||||
|
static std::string GetErrorMessage();
|
||||||
|
|
||||||
// Creates a new client connection. Clients are connected to a specific hostname/port and can
|
// Creates a new client connection. Clients are connected to a specific hostname/port and can
|
||||||
// only send to that destination.
|
// only send to that destination.
|
||||||
// On failure, |error| is filled (if non-null) and nullptr is returned.
|
// On failure, |error| is filled (if non-null) and nullptr is returned.
|
||||||
|
|
@ -78,6 +82,9 @@ class Socket {
|
||||||
// connected to the client on success, nullptr on failure.
|
// connected to the client on success, nullptr on failure.
|
||||||
virtual std::unique_ptr<Socket> Accept() { return nullptr; }
|
virtual std::unique_ptr<Socket> Accept() { return nullptr; }
|
||||||
|
|
||||||
|
// Returns the local port the Socket is bound to or -1 on error.
|
||||||
|
int GetLocalPort();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Protected constructor to force factory function use.
|
// Protected constructor to force factory function use.
|
||||||
Socket(cutils_socket_t sock);
|
Socket(cutils_socket_t sock);
|
||||||
|
|
|
||||||
132
fastboot/socket_mock.cpp
Normal file
132
fastboot/socket_mock.cpp
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "socket_mock.h"
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
SocketMock::SocketMock() : Socket(INVALID_SOCKET) {}
|
||||||
|
|
||||||
|
SocketMock::~SocketMock() {
|
||||||
|
if (!events_.empty()) {
|
||||||
|
ADD_FAILURE() << events_.size() << " event(s) were not handled";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t SocketMock::Send(const void* data, size_t length) {
|
||||||
|
if (events_.empty()) {
|
||||||
|
ADD_FAILURE() << "Send() was called when no message was expected";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events_.front().type != EventType::kSend) {
|
||||||
|
ADD_FAILURE() << "Send() was called out-of-order";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string message(reinterpret_cast<const char*>(data), length);
|
||||||
|
if (events_.front().message != message) {
|
||||||
|
ADD_FAILURE() << "Send() expected " << events_.front().message << ", but got " << message;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t return_value = events_.front().return_value;
|
||||||
|
events_.pop();
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t SocketMock::Receive(void* data, size_t length, int /*timeout_ms*/) {
|
||||||
|
if (events_.empty()) {
|
||||||
|
ADD_FAILURE() << "Receive() was called when no message was ready";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events_.front().type != EventType::kReceive) {
|
||||||
|
ADD_FAILURE() << "Receive() was called out-of-order";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events_.front().return_value > static_cast<ssize_t>(length)) {
|
||||||
|
ADD_FAILURE() << "Receive(): not enough bytes (" << length << ") for "
|
||||||
|
<< events_.front().message;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t return_value = events_.front().return_value;
|
||||||
|
if (return_value > 0) {
|
||||||
|
memcpy(data, events_.front().message.data(), return_value);
|
||||||
|
}
|
||||||
|
events_.pop();
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SocketMock::Close() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Socket> SocketMock::Accept() {
|
||||||
|
if (events_.empty()) {
|
||||||
|
ADD_FAILURE() << "Accept() was called when no socket was ready";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (events_.front().type != EventType::kAccept) {
|
||||||
|
ADD_FAILURE() << "Accept() was called out-of-order";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Socket> sock = std::move(events_.front().sock);
|
||||||
|
events_.pop();
|
||||||
|
return sock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketMock::ExpectSend(std::string message) {
|
||||||
|
ssize_t return_value = message.length();
|
||||||
|
events_.push(Event(EventType::kSend, std::move(message), return_value, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketMock::ExpectSendFailure(std::string message) {
|
||||||
|
events_.push(Event(EventType::kSend, std::move(message), -1, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketMock::AddReceive(std::string message) {
|
||||||
|
ssize_t return_value = message.length();
|
||||||
|
events_.push(Event(EventType::kReceive, std::move(message), return_value, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketMock::AddReceiveFailure() {
|
||||||
|
events_.push(Event(EventType::kReceive, "", -1, nullptr));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SocketMock::AddAccept(std::unique_ptr<Socket> sock) {
|
||||||
|
events_.push(Event(EventType::kAccept, "", 0, std::move(sock)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SocketMock::Event::Event(EventType _type, std::string _message, ssize_t _return_value,
|
||||||
|
std::unique_ptr<Socket> _sock)
|
||||||
|
: type(_type), message(_message), return_value(_return_value), sock(std::move(_sock)) {}
|
||||||
97
fastboot/socket_mock.h
Normal file
97
fastboot/socket_mock.h
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 The Android Open Source Project
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in
|
||||||
|
* the documentation and/or other materials provided with the
|
||||||
|
* distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||||
|
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||||
|
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||||
|
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||||
|
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SOCKET_MOCK_H_
|
||||||
|
#define SOCKET_MOCK_H_
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <queue>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <android-base/macros.h>
|
||||||
|
|
||||||
|
#include "socket.h"
|
||||||
|
|
||||||
|
// A mock Socket implementation to be used for testing. Tests can set expectations for messages
|
||||||
|
// to be sent and provide messages to be received in order to verify protocol behavior.
|
||||||
|
//
|
||||||
|
// Example: testing sending "foo" and receiving "bar".
|
||||||
|
// SocketMock mock;
|
||||||
|
// mock.ExpectSend("foo");
|
||||||
|
// mock.AddReceive("bar");
|
||||||
|
// EXPECT_TRUE(DoFooBar(&mock));
|
||||||
|
//
|
||||||
|
// Example: testing sending "foo" and expecting "bar", but receiving "baz" instead.
|
||||||
|
// SocketMock mock;
|
||||||
|
// mock.ExpectSend("foo");
|
||||||
|
// mock.AddReceive("baz");
|
||||||
|
// EXPECT_FALSE(DoFooBar(&mock));
|
||||||
|
class SocketMock : public Socket {
|
||||||
|
public:
|
||||||
|
SocketMock();
|
||||||
|
~SocketMock() override;
|
||||||
|
|
||||||
|
ssize_t Send(const void* data, size_t length) override;
|
||||||
|
ssize_t Receive(void* data, size_t length, int timeout_ms) override;
|
||||||
|
int Close() override;
|
||||||
|
virtual std::unique_ptr<Socket> Accept();
|
||||||
|
|
||||||
|
// Adds an expectation for Send().
|
||||||
|
void ExpectSend(std::string message);
|
||||||
|
|
||||||
|
// Adds an expectation for Send() that returns -1.
|
||||||
|
void ExpectSendFailure(std::string message);
|
||||||
|
|
||||||
|
// Adds data to provide for Receive().
|
||||||
|
void AddReceive(std::string message);
|
||||||
|
|
||||||
|
// Adds a Receive() failure.
|
||||||
|
void AddReceiveFailure();
|
||||||
|
|
||||||
|
// Adds a Socket to return from Accept().
|
||||||
|
void AddAccept(std::unique_ptr<Socket> sock);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class EventType { kSend, kReceive, kAccept };
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
Event(EventType _type, std::string _message, ssize_t _return_value,
|
||||||
|
std::unique_ptr<Socket> _sock);
|
||||||
|
|
||||||
|
EventType type;
|
||||||
|
std::string message;
|
||||||
|
ssize_t return_value;
|
||||||
|
std::unique_ptr<Socket> sock;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::queue<Event> events_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(SocketMock);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SOCKET_MOCK_H_
|
||||||
|
|
@ -14,33 +14,31 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Tests UDP functionality using loopback connections. Requires that kTestPort is available
|
// Tests socket functionality using loopback connections. The UDP tests assume that no packets are
|
||||||
// for loopback communication on the host. These tests also assume that no UDP packets are lost,
|
// lost, which should be the case for loopback communication, but is not guaranteed.
|
||||||
// which should be the case for loopback communication, but is not guaranteed.
|
//
|
||||||
|
// Also tests our SocketMock class to make sure it works as expected and reports errors properly
|
||||||
|
// if the mock expectations aren't met during a test.
|
||||||
|
|
||||||
#include "socket.h"
|
#include "socket.h"
|
||||||
|
#include "socket_mock.h"
|
||||||
|
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <gtest/gtest-spi.h>
|
||||||
|
|
||||||
enum {
|
enum { kTestTimeoutMs = 3000 };
|
||||||
// This port must be available for loopback communication.
|
|
||||||
kTestPort = 54321,
|
|
||||||
|
|
||||||
// Don't wait forever in a unit test.
|
|
||||||
kTestTimeoutMs = 3000,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Creates connected sockets |server| and |client|. Returns true on success.
|
// Creates connected sockets |server| and |client|. Returns true on success.
|
||||||
bool MakeConnectedSockets(Socket::Protocol protocol, std::unique_ptr<Socket>* server,
|
bool MakeConnectedSockets(Socket::Protocol protocol, std::unique_ptr<Socket>* server,
|
||||||
std::unique_ptr<Socket>* client, const std::string hostname = "localhost",
|
std::unique_ptr<Socket>* client,
|
||||||
int port = kTestPort) {
|
const std::string hostname = "localhost") {
|
||||||
*server = Socket::NewServer(protocol, port);
|
*server = Socket::NewServer(protocol, 0);
|
||||||
if (*server == nullptr) {
|
if (*server == nullptr) {
|
||||||
ADD_FAILURE() << "Failed to create server.";
|
ADD_FAILURE() << "Failed to create server.";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
*client = Socket::NewClient(protocol, hostname, port, nullptr);
|
*client = Socket::NewClient(protocol, hostname, (*server)->GetLocalPort(), nullptr);
|
||||||
if (*client == nullptr) {
|
if (*client == nullptr) {
|
||||||
ADD_FAILURE() << "Failed to create client.";
|
ADD_FAILURE() << "Failed to create client.";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -124,3 +122,86 @@ TEST(SocketTest, TestUdpReceiveOverflow) {
|
||||||
EXPECT_EQ(-1, bytes);
|
EXPECT_EQ(-1, bytes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestSendSuccess) {
|
||||||
|
SocketMock mock;
|
||||||
|
|
||||||
|
mock.ExpectSend("foo");
|
||||||
|
EXPECT_TRUE(SendString(&mock, "foo"));
|
||||||
|
|
||||||
|
mock.ExpectSend("abc");
|
||||||
|
mock.ExpectSend("123");
|
||||||
|
EXPECT_TRUE(SendString(&mock, "abc"));
|
||||||
|
EXPECT_TRUE(SendString(&mock, "123"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestSendFailure) {
|
||||||
|
SocketMock* mock = new SocketMock;
|
||||||
|
|
||||||
|
EXPECT_NONFATAL_FAILURE(SendString(mock, "foo"), "no message was expected");
|
||||||
|
|
||||||
|
mock->ExpectSend("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(SendString(mock, "bar"), "expected foo, but got bar");
|
||||||
|
EXPECT_TRUE(SendString(mock, "foo"));
|
||||||
|
|
||||||
|
mock->AddReceive("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(SendString(mock, "foo"), "called out-of-order");
|
||||||
|
EXPECT_TRUE(ReceiveString(mock, "foo"));
|
||||||
|
|
||||||
|
mock->ExpectSend("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestReceiveSuccess) {
|
||||||
|
SocketMock mock;
|
||||||
|
|
||||||
|
mock.AddReceive("foo");
|
||||||
|
EXPECT_TRUE(ReceiveString(&mock, "foo"));
|
||||||
|
|
||||||
|
mock.AddReceive("abc");
|
||||||
|
mock.AddReceive("123");
|
||||||
|
EXPECT_TRUE(ReceiveString(&mock, "abc"));
|
||||||
|
EXPECT_TRUE(ReceiveString(&mock, "123"));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestReceiveFailure) {
|
||||||
|
SocketMock* mock = new SocketMock;
|
||||||
|
|
||||||
|
EXPECT_NONFATAL_FAILURE(ReceiveString(mock, "foo"), "no message was ready");
|
||||||
|
|
||||||
|
mock->ExpectSend("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(ReceiveString(mock, "foo"), "called out-of-order");
|
||||||
|
EXPECT_TRUE(SendString(mock, "foo"));
|
||||||
|
|
||||||
|
char c;
|
||||||
|
mock->AddReceive("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(mock->Receive(&c, 1, 0), "not enough bytes (1) for foo");
|
||||||
|
EXPECT_TRUE(ReceiveString(mock, "foo"));
|
||||||
|
|
||||||
|
mock->AddReceive("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestAcceptSuccess) {
|
||||||
|
SocketMock mock;
|
||||||
|
|
||||||
|
SocketMock* mock_handler = new SocketMock;
|
||||||
|
mock.AddAccept(std::unique_ptr<SocketMock>(mock_handler));
|
||||||
|
EXPECT_EQ(mock_handler, mock.Accept().get());
|
||||||
|
|
||||||
|
mock.AddAccept(nullptr);
|
||||||
|
EXPECT_EQ(nullptr, mock.Accept().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(SocketMockTest, TestAcceptFailure) {
|
||||||
|
SocketMock* mock = new SocketMock;
|
||||||
|
|
||||||
|
EXPECT_NONFATAL_FAILURE(mock->Accept(), "no socket was ready");
|
||||||
|
|
||||||
|
mock->ExpectSend("foo");
|
||||||
|
EXPECT_NONFATAL_FAILURE(mock->Accept(), "called out-of-order");
|
||||||
|
EXPECT_TRUE(SendString(mock, "foo"));
|
||||||
|
|
||||||
|
mock->AddAccept(nullptr);
|
||||||
|
EXPECT_NONFATAL_FAILURE(delete mock, "1 event(s) were not handled");
|
||||||
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue