samedi 26 septembre 2015

Mocking asynchronous Boost Asio connections

For a few days I have been thinking about a mechanism to mock the asynchronous connections from boost::asio, but I couldn't come out with a solution (I am not sure if this is matter of design or implementation).

Basicly, it boils down to the following (I included only the important things, but I can add more details):

I have the Server class, that starts a Connection. The class Connection reads a binary block from a file, writes the block to a boost::asio::ip::tcp::socket and submits a new callback for the next block.

class Connection : public boost::enable_shared_from_this<Connection>
{
public:
    Connection(boost::asio::io_service &ioService) : socket_(ioService)
    {
        rawBuffer_.resize(MAX_BUFFER_LENGTH);
    }

    //...

    void HandleWriteBlock(const boost::system::error_code &errorCode,
        size_t bytesTransferred, int64_t iBlockIdx)
    {
        LOG_DEBUG << errorCode.message() << ", current block: " << iBlockIdx;

        //...
        inputFile_.read(rawBuffer_.data(), BLOCK_MAX_LENGTH);
        std::streamsize iBytesRead = inputFile_.gcount();
        //...

        boost::asio::async_write(socket_, boost::asio::buffer(rawBuffer_,
            iBytesRead), boost::bind(&Connection::HandleWriteBlock,
            shared_from_this(), boost::asio::placeholders::error,
            boost::asio::placeholders::bytes_transferred, ++iBlockIdx));
    }

private:
    boost::asio::ip::tcp::socket socket_;
    std::vector<char> rawBuffer_;
}

class Server
{
public:
    void Start()
    {
        boost::asio::io_service ioService;

        // Here, connection can be called from an intermediary class,
        // hence the need for boost::enable_shared_from_this
        boost::shared_ptr<Connection> connection(new Connection(ioService));
        //...

        ioService.run();
    }
}

How can I mock this mechanism (preferably using Google Mock, but I am open to any other alternatives) to abstract the network operations and to still read from file (file operations will be mocked later) and print the activity logs (i.e.: LOG_DEBUG)? I don't see how I can obtain a precise simulation of the real activity, given the fact that Boost manages its asynchronous callback mechanism under the hood.

From what I see (e.g.: this example), mocking is suitable for normal synchronous operations.

Is it even recommended to go that far in mocking only the actual network operations (i.e.: boost::asio::async_write)? If not, how else may I approach this challenge?

Aucun commentaire:

Enregistrer un commentaire