Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f971b6a2 authored by David Pursell's avatar David Pursell Committed by Gerrit Code Review
Browse files

Merge "fastboot: socket testing improvements."

parents d95ecfc4 c3a46696
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -106,7 +106,11 @@ include $(CLEAR_VARS)
LOCAL_MODULE := fastboot_test
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_CFLAGS += -Wall -Wextra -Werror -Wunreachable-code
+14 −0
Original line number Diff line number Diff line
@@ -28,6 +28,7 @@

#include "socket.h"

#include <android-base/errors.h>
#include <android-base/stringprintf.h>

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;
}

int Socket::GetLocalPort() {
    return socket_get_local_port(sock_);
}

// Implements the Socket interface for UDP.
class UdpSocket : public Socket {
  public:
@@ -210,3 +215,12 @@ std::unique_ptr<Socket> Socket::NewServer(Protocol protocol, int port) {

    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);
}
+7 −0
Original line number Diff line number Diff line
@@ -44,6 +44,10 @@ class Socket {
  public:
    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
    // only send to that destination.
    // 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.
    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 constructor to force factory function use.
    Socket(cutils_socket_t sock);
+132 −0
Original line number Diff line number Diff line
/*
 * 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)) {}

fastboot/socket_mock.h

0 → 100644
+97 −0
Original line number Diff line number Diff line
/*
 * 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_
Loading