From c3e9cf11164cec031373f0dae344ac4a3d971e8a Mon Sep 17 00:00:00 2001
From: Sergey Yakubov <sergey.yakubov@desy.de>
Date: Fri, 23 Mar 2018 12:55:57 +0100
Subject: [PATCH] finish with request

---
 common/cpp/include/system_wrappers/io.h |  5 ++
 receiver/CMakeLists.txt                 |  2 -
 receiver/src/connection.cpp             | 51 ++++++++-------
 receiver/src/connection.h               |  1 +
 receiver/src/receiver_error.h           |  1 -
 receiver/src/request.cpp                | 55 ++++++++++------
 receiver/src/request.h                  | 14 +++--
 receiver/src/request_handler.cpp        |  9 ---
 receiver/src/request_handler.h          |  5 +-
 receiver/src/send_data_request.cpp      | 10 ---
 receiver/src/send_data_request.h        | 20 ------
 receiver/unittests/test_connection.cpp  | 78 +++++++++++++++++++++--
 receiver/unittests/test_request.cpp     | 83 ++++++++++++++-----------
 13 files changed, 209 insertions(+), 125 deletions(-)
 delete mode 100644 receiver/src/request_handler.cpp
 delete mode 100644 receiver/src/send_data_request.cpp
 delete mode 100644 receiver/src/send_data_request.h

diff --git a/common/cpp/include/system_wrappers/io.h b/common/cpp/include/system_wrappers/io.h
index a329ad379..39dd23ccb 100644
--- a/common/cpp/include/system_wrappers/io.h
+++ b/common/cpp/include/system_wrappers/io.h
@@ -69,6 +69,11 @@ class IOErrorTemplate : public SimpleErrorTemplate {
     }
 };
 
+static inline std::ostream& operator<<(std::ostream& os, const IOErrorTemplate& err) {
+    return os << err.Text();
+}
+
+
 namespace IOErrorTemplates {
 auto const kUnknownIOError = IOErrorTemplate{"Unknown Error", IOErrorType::kUnknownIOError};
 
diff --git a/receiver/CMakeLists.txt b/receiver/CMakeLists.txt
index 309848b3d..cd5c8d620 100644
--- a/receiver/CMakeLists.txt
+++ b/receiver/CMakeLists.txt
@@ -4,8 +4,6 @@ set(SOURCE_FILES
         src/connection.h src/connection.cpp
         src/receiver_error.h
         src/request.cpp
-        src/request_handler.cpp
-        src/send_data_request.cpp
         )
 
 
diff --git a/receiver/src/connection.cpp b/receiver/src/connection.cpp
index db6155366..5afed3c2a 100644
--- a/receiver/src/connection.cpp
+++ b/receiver/src/connection.cpp
@@ -20,16 +20,32 @@ uint64_t Connection::GetId() const noexcept {
     return connection_id_;
 }
 
-void Connection::Listen() const noexcept {
+NetworkErrorCode GetNetworkCodeFromError(const Error& err) {
+    if(err) {
+        if(err == IOErrorTemplates::kFileAlreadyExists) {
+            return NetworkErrorCode::kNetErrorFileIdAlreadyInUse;
+        } else {
+            return NetworkErrorCode::kNetErrorInternalServerError;
+        }
+    }
+    return NetworkErrorCode::kNetErrorNoError;
+
+}
+
+Error Connection::ProcessRequest(const std::unique_ptr<Request>& request) const noexcept {
+    Error err;
+    err = request->Handle();
+    GenericNetworkResponse generic_response;
+    generic_response.error_code = GetNetworkCodeFromError(err);
+    if(err) {
+        std::cerr << "[" << GetId() << "] Error while handling request: " << err << std::endl;
+    }
+    io__->Send(socket_fd_, &generic_response, sizeof(GenericNetworkResponse), &err);
+    return err;
+}
 
-    /*    std::unique_ptr<GenericNetworkResponse> generic_response_buffer;
-        try {
-            generic_response_buffer.reset(reinterpret_cast<GenericNetworkResponse*> (new uint8_t[kRequestHandlerMaxBufferSize]));
-        } catch(...) {
-            std::cerr << "Failed to allocate buffer space for request and response" << std::endl;
-            return;
-        }*/
 
+void Connection::Listen() const noexcept {
     while(true) {
         Error err;
         auto request = WaitForNewRequest(&err);
@@ -38,9 +54,9 @@ void Connection::Listen() const noexcept {
             break;
         }
         if (!request) continue; //no error, but timeout
-        err = request->Handle();
+        err = ProcessRequest(request);
         if(err) {
-            std::cerr << "[" << GetId() << "] Error while handling request: " << err << std::endl;
+            std::cerr << "[" << GetId() << "] Error sending response: " << err << std::endl;
             break;
         }
     }
@@ -50,23 +66,16 @@ void Connection::Listen() const noexcept {
 
 
 std::unique_ptr<Request> Connection::WaitForNewRequest(Error* err) const noexcept {
-    std::unique_ptr<GenericNetworkRequestHeader> generic_request_buffer;
-    try {
-        generic_request_buffer.reset(reinterpret_cast<GenericNetworkRequestHeader*> (new
-                                     uint8_t[kRequestHandlerMaxBufferSize]));
-    } catch(...) {
-        *err = ErrorTemplates::kMemoryAllocationError.Generate();
-        return nullptr;
-    }
-
-    io__->ReceiveWithTimeout(socket_fd_, generic_request_buffer.get(), sizeof(GenericNetworkRequestHeader), 50, err);
+    //TODO: to be overwritten with MessagePack (or similar)
+    GenericNetworkRequestHeader generic_request_header;
+    io__->ReceiveWithTimeout(socket_fd_, &generic_request_header, sizeof(GenericNetworkRequestHeader), 50, err);
     if(*err) {
         if(*err == IOErrorTemplates::kTimeout) {
             *err = nullptr;//Not an error in this case
         }
         return nullptr;
     }
-    return request_factory__->GenerateRequest(generic_request_buffer, socket_fd_, err);
+    return request_factory__->GenerateRequest(generic_request_header, socket_fd_, err);
 }
 
 
diff --git a/receiver/src/connection.h b/receiver/src/connection.h
index 6c2d348ed..23e66b199 100644
--- a/receiver/src/connection.h
+++ b/receiver/src/connection.h
@@ -38,6 +38,7 @@ class Connection {
 
   private:
     std::unique_ptr<Request> WaitForNewRequest(Error* err) const noexcept;
+    Error ProcessRequest(const std::unique_ptr<Request>& request) const noexcept;
 };
 
 }
diff --git a/receiver/src/receiver_error.h b/receiver/src/receiver_error.h
index daf1b723d..2e74565b3 100644
--- a/receiver/src/receiver_error.h
+++ b/receiver/src/receiver_error.h
@@ -49,7 +49,6 @@ class ReceiverErrorTemplate : public SimpleErrorTemplate {
 
 namespace ReceiverErrorTemplates {
 auto const kInvalidOpCode = ReceiverErrorTemplate{"Invalid Opcode", ReceiverErrorType::kInvalidOpCode};
-auto const kConnectionError = SimpleErrorTemplate{"ConnectionError"};
 };
 }
 
diff --git a/receiver/src/request.cpp b/receiver/src/request.cpp
index 9cf4ec59c..74d0b5984 100644
--- a/receiver/src/request.cpp
+++ b/receiver/src/request.cpp
@@ -1,43 +1,62 @@
 #include "request.h"
-#include "send_data_request.h"
 #include "system_wrappers/system_io.h"
 
 namespace hidra2 {
 
-Request::Request(const std::unique_ptr<GenericNetworkRequestHeader>& header,
-                 SocketDescriptor socket_fd) : io__{new SystemIO}, request_header_{*header}, socket_fd_{socket_fd} {
+Request::Request(const GenericNetworkRequestHeader& header,
+                 SocketDescriptor socket_fd) : io__{new SystemIO}, request_header_{header}, socket_fd_{socket_fd} {
 }
 
+Error Request::AllocateDataBuffer() {
+    try {
+        data_buffer_.reset(new uint8_t[request_header_.data_size]);
+    } catch(std::exception& e) {
+        auto err = ErrorTemplates::kMemoryAllocationError.Generate();
+        err->Append(e.what());
+        return err;
+    }
+    return nullptr;
+}
+
+Error Request::ReceiveData() {
+    auto err = AllocateDataBuffer();
+    if (err) {
+        return err;
+    }
+    io__->Receive(socket_fd_, data_buffer_.get(), request_header_.data_size, &err);
+    return err;
+}
+
+
 Error Request::Handle() {
     Error err;
-
     if (request_header_.data_size != 0) {
-        try {
-            data_buffer_.reset(new uint8_t[request_header_.data_size]);
-        } catch(std::exception& e) {
-            err = ErrorTemplates::kMemoryAllocationError.Generate();
-            err->Append(e.what());
+        auto err = ReceiveData();
+        if (err) {
             return err;
         }
-
-        io__->Receive(socket_fd_, data_buffer_.get(), request_header_.data_size, &err);
+    }
+    for (auto handler : handlers_) {
+        auto err = handler->ProcessRequest(*this);
         if (err) {
-            auto recv_err = ReceiverErrorTemplates::kConnectionError.Generate();
-            recv_err->Append(err->Explain());
-            return recv_err;
+            return err;
         }
-
     }
     return nullptr;
 }
 
-std::unique_ptr<Request> RequestFactory::GenerateRequest(const std::unique_ptr<GenericNetworkRequestHeader>&
+void Request::AddHandler(const RequestHandler* handler) {
+    handlers_.emplace_back(handler);
+}
+
+
+std::unique_ptr<Request> RequestFactory::GenerateRequest(const GenericNetworkRequestHeader&
         request_header, SocketDescriptor socket_fd,
         Error* err) const noexcept {
     *err = nullptr;
-    switch (request_header->op_code) {
+    switch (request_header.op_code) {
     case Opcode::kNetOpcodeSendData:
-        return std::unique_ptr<Request> {new SendDataRequest{request_header, socket_fd}};
+        return std::unique_ptr<Request> {new Request{request_header, socket_fd}};
     default:
         *err = ReceiverErrorTemplates::kInvalidOpCode.Generate();
         return nullptr;
diff --git a/receiver/src/request.h b/receiver/src/request.h
index 7cbd7cb5e..c2da48398 100644
--- a/receiver/src/request.h
+++ b/receiver/src/request.h
@@ -4,24 +4,30 @@
 #include "receiver_error.h"
 #include "common/networking.h"
 #include "system_wrappers/io.h"
-
+#include "request_handler.h"
 namespace hidra2 {
 
+class RequestHandler;
+
 class Request {
   public:
     virtual Error Handle();
-    ~Request() = default;
-    Request(const std::unique_ptr<GenericNetworkRequestHeader>& request_header, SocketDescriptor socket_fd);
+    virtual ~Request() = default;
+    Request(const GenericNetworkRequestHeader& request_header, SocketDescriptor socket_fd);
+    void AddHandler(const RequestHandler*);
     std::unique_ptr<IO> io__;
   private:
+    Error AllocateDataBuffer();
+    Error ReceiveData();
     const GenericNetworkRequestHeader request_header_;
     const SocketDescriptor socket_fd_;
     FileData data_buffer_;
+    std::vector<const RequestHandler*> handlers_;
 };
 
 class RequestFactory {
   public:
-    virtual std::unique_ptr<Request> GenerateRequest(const std::unique_ptr<GenericNetworkRequestHeader>& request_header,
+    virtual std::unique_ptr<Request> GenerateRequest(const GenericNetworkRequestHeader& request_header,
                                                      SocketDescriptor socket_fd, Error* err) const noexcept ;
 };
 
diff --git a/receiver/src/request_handler.cpp b/receiver/src/request_handler.cpp
deleted file mode 100644
index 2c68d7afb..000000000
--- a/receiver/src/request_handler.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
-//
-// Created by yakubov on 20/03/18.
-//
-
-#include "request_handler.h"
-
-namespace hidra2 {
-
-}
\ No newline at end of file
diff --git a/receiver/src/request_handler.h b/receiver/src/request_handler.h
index 2dea83399..a136c40eb 100644
--- a/receiver/src/request_handler.h
+++ b/receiver/src/request_handler.h
@@ -6,9 +6,12 @@
 
 namespace hidra2 {
 
+class Request;
 
 class RequestHandler {
-    virtual Error ProcessRequest(const Request& request) = 0;
+  public:
+    virtual Error ProcessRequest(const Request& request) const = 0;
+  private:
 };
 
 }
diff --git a/receiver/src/send_data_request.cpp b/receiver/src/send_data_request.cpp
deleted file mode 100644
index ab9d65172..000000000
--- a/receiver/src/send_data_request.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "send_data_request.h"
-
-namespace hidra2 {
-
-SendDataRequest::SendDataRequest(const std::unique_ptr<GenericNetworkRequestHeader>& header,
-                                 SocketDescriptor socket_fd) : Request(header, socket_fd) {
-
-}
-
-}
\ No newline at end of file
diff --git a/receiver/src/send_data_request.h b/receiver/src/send_data_request.h
deleted file mode 100644
index 09b2f1405..000000000
--- a/receiver/src/send_data_request.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#ifndef HIDRA2_SEND_DATA_REQUEST_H
-#define HIDRA2_SEND_DATA_REQUEST_H
-
-#include "request.h"
-#include "common/networking.h"
-#include "system_wrappers/io.h"
-
-namespace hidra2 {
-
-class SendDataRequest : public Request {
-  public:
-    SendDataRequest(const std::unique_ptr<GenericNetworkRequestHeader>& request_header, SocketDescriptor socket_fd);
-
-  private:
-    GenericNetworkRequestHeader request_header_;
-};
-
-}
-
-#endif //HIDRA2_SEND_DATA_REQUEST_H
diff --git a/receiver/unittests/test_connection.cpp b/receiver/unittests/test_connection.cpp
index ef7802b4c..2343553e3 100644
--- a/receiver/unittests/test_connection.cpp
+++ b/receiver/unittests/test_connection.cpp
@@ -14,6 +14,8 @@ using ::testing::Gt;
 using ::testing::Eq;
 using ::testing::Mock;
 using ::testing::NiceMock;
+using ::testing::SaveArg;
+using ::testing::SaveArgPointee;
 using ::testing::InSequence;
 using ::testing::SetArgPointee;
 using ::hidra2::Error;
@@ -33,7 +35,7 @@ namespace {
 
 class MockRequest: public Request {
   public:
-    MockRequest(const std::unique_ptr<GenericNetworkRequestHeader>& request_header, SocketDescriptor socket_fd):
+    MockRequest(const GenericNetworkRequestHeader& request_header, SocketDescriptor socket_fd):
         Request(request_header, socket_fd) {};
     Error Handle() override {
         return Error{Handle_t()};
@@ -43,7 +45,7 @@ class MockRequest: public Request {
 
 class MockRequestFactory: public hidra2::RequestFactory {
   public:
-    std::unique_ptr<Request> GenerateRequest(const std::unique_ptr<GenericNetworkRequestHeader>& request_header,
+    std::unique_ptr<Request> GenerateRequest(const GenericNetworkRequestHeader& request_header,
                                              SocketDescriptor socket_fd,
                                              Error* err) const noexcept override {
         ErrorInterface* error = nullptr;
@@ -52,7 +54,7 @@ class MockRequestFactory: public hidra2::RequestFactory {
         return std::unique_ptr<Request> {res};
     }
 
-    MOCK_CONST_METHOD3(GenerateRequest_t, Request * (const std::unique_ptr<GenericNetworkRequestHeader>&,
+    MOCK_CONST_METHOD3(GenerateRequest_t, Request * (const GenericNetworkRequestHeader&,
                                                      SocketDescriptor socket_fd,
                                                      ErrorInterface**));
 
@@ -94,8 +96,65 @@ TEST_F(ConnectionTests, ErrorWaitForNewRequest) {
     connection.Listen();
 }
 
+ACTION_P(SaveArg1ToGenericNetworkResponse, value) {
+    auto resp =  *static_cast<const GenericNetworkResponse*>(arg1);
+    value->error_code = resp.error_code;
+}
+
+
 TEST_F(ConnectionTests, CallsHandleRequest) {
-    std::unique_ptr<GenericNetworkRequestHeader> header{new GenericNetworkRequestHeader};
+
+    GenericNetworkRequestHeader header;
+    auto request = new MockRequest{header, 1};
+
+    EXPECT_CALL(mock_io, ReceiveWithTimeout_t(_, _, _, _, _));
+
+    EXPECT_CALL(mock_factory, GenerateRequest_t(_, _, _)).WillOnce(
+        Return(request)
+    );
+
+    EXPECT_CALL(*request, Handle_t()).WillOnce(
+        Return(new hidra2::SimpleError{""})
+    );
+
+    EXPECT_CALL(mock_io, Send_t(_, _, _, _)).WillOnce(
+        DoAll(SetArgPointee<3>(new hidra2::IOError("Test Send Error", hidra2::IOErrorType::kUnknownIOError)),
+              Return(0)
+             ));
+
+
+    connection.Listen();
+}
+
+TEST_F(ConnectionTests, SendsNoErrorToProducer) {
+
+    GenericNetworkRequestHeader header;
+    auto request = new MockRequest{header, 1};
+
+    EXPECT_CALL(mock_io, ReceiveWithTimeout_t(_, _, _, _, _));
+
+    EXPECT_CALL(mock_factory, GenerateRequest_t(_, _, _)).WillOnce(
+        Return(request)
+    );
+
+    EXPECT_CALL(*request, Handle_t()).WillOnce(
+        Return(nullptr)
+    );
+    GenericNetworkResponse response;
+    EXPECT_CALL(mock_io, Send_t(_, _, sizeof(GenericNetworkResponse), _)).WillOnce(
+        DoAll(SetArgPointee<3>(new hidra2::IOError("Test Send Error", hidra2::IOErrorType::kUnknownIOError)),
+              SaveArg1ToGenericNetworkResponse(&response),
+              Return(0)
+             ));
+
+    connection.Listen();
+
+    ASSERT_THAT(response.error_code, Eq(hidra2::NetworkErrorCode::kNetErrorNoError));
+}
+
+TEST_F(ConnectionTests, SendsErrorToProducer) {
+
+    GenericNetworkRequestHeader header;
     auto request = new MockRequest{header, 1};
 
     EXPECT_CALL(mock_io, ReceiveWithTimeout_t(_, _, _, _, _));
@@ -108,9 +167,20 @@ TEST_F(ConnectionTests, CallsHandleRequest) {
         Return(new hidra2::SimpleError{""})
     );
 
+    GenericNetworkResponse response;
+    EXPECT_CALL(mock_io, Send_t(_, _, sizeof(GenericNetworkResponse), _)).WillOnce(
+        DoAll(SetArgPointee<3>(new hidra2::IOError("Test Send Error", hidra2::IOErrorType::kUnknownIOError)),
+              SaveArg1ToGenericNetworkResponse(&response),
+              Return(0)
+             ));
+
     connection.Listen();
+
+    ASSERT_THAT(response.error_code, Eq(hidra2::NetworkErrorCode::kNetErrorInternalServerError));
+
 }
 
+
 /*
 TEST(Constructor, CheckGetAddress) {
     std::string expected_address = "somehost:1234";
diff --git a/receiver/unittests/test_request.cpp b/receiver/unittests/test_request.cpp
index 2091231d1..0fafb5fda 100644
--- a/receiver/unittests/test_request.cpp
+++ b/receiver/unittests/test_request.cpp
@@ -4,7 +4,7 @@
 #include "../src/connection.h"
 #include "../src/receiver_error.h"
 #include "../src/request.h"
-#include "../src/send_data_request.h"
+#include "../src/request_handler.h"
 
 using ::testing::Test;
 using ::testing::Return;
@@ -33,11 +33,21 @@ using hidra2::Request;
 
 namespace {
 
+class MockReqestHandler : public hidra2::RequestHandler {
+  public:
+    Error ProcessRequest(const Request& request) const override {
+        return Error{ProcessRequest_t(request)};
+    }
+
+    MOCK_CONST_METHOD1(ProcessRequest_t, ErrorInterface * (const Request& request));
+
+};
+
 class FactoryTests : public Test {
   public:
     hidra2::RequestFactory factory;
     Error err{nullptr};
-    std::unique_ptr<GenericNetworkRequestHeader> generic_request_buffer{new GenericNetworkRequestHeader};
+    GenericNetworkRequestHeader generic_request_header;
     void SetUp() override {
     }
     void TearDown() override {
@@ -45,37 +55,36 @@ class FactoryTests : public Test {
 };
 
 TEST_F(FactoryTests, ErrorOnWrongCode) {
-    generic_request_buffer->op_code = hidra2::Opcode::kNetOpcodeUnknownOp;
-    auto request = factory.GenerateRequest(generic_request_buffer, 1, &err);
+    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeUnknownOp;
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
 
     ASSERT_THAT(err, Ne(nullptr));
 }
 
 TEST_F(FactoryTests, ReturnsSendDataRequestOnkNetOpcodeSendDataCode) {
-    generic_request_buffer->op_code = hidra2::Opcode::kNetOpcodeSendData;
-    auto request = factory.GenerateRequest(generic_request_buffer, 1, &err);
+    generic_request_header.op_code = hidra2::Opcode::kNetOpcodeSendData;
+    auto request = factory.GenerateRequest(generic_request_header, 1, &err);
 
     ASSERT_THAT(err, Eq(nullptr));
-    ASSERT_THAT(dynamic_cast<hidra2::SendDataRequest*>(request.get()), Ne(nullptr));
+    ASSERT_THAT(dynamic_cast<hidra2::Request*>(request.get()), Ne(nullptr));
 }
 
 
 class RequestTests : public Test {
   public:
-    std::unique_ptr<GenericNetworkRequestHeader> generic_request_buffer{new GenericNetworkRequestHeader};
+    GenericNetworkRequestHeader generic_request_header;
     hidra2::SocketDescriptor socket_fd_{1};
     uint64_t data_size_ {100};
     std::unique_ptr<Request> request;
-    MockIO mock_io;
+    NiceMock<MockIO> mock_io;
     void SetUp() override {
-        generic_request_buffer->data_size = data_size_;
-        request.reset(new Request{generic_request_buffer, socket_fd_});
-        request->io__ = std::unique_ptr<hidra2::IO> {&mock_io};;
-//      ON_CALL(mock_io, ReceiveWithTimeout_t(_, _, _, _, _)).
-//          WillByDefault(DoAll(testing::SetArgPointee<4>(nullptr),
-//                              testing::Return(0)));
-//      EXPECT_CALL(mock_io, CloseSocket_t(_, _));
-
+        generic_request_header.data_size = data_size_;
+        request.reset(new Request{generic_request_header, socket_fd_});
+        request->io__ = std::unique_ptr<hidra2::IO> {&mock_io};
+        ON_CALL(mock_io, Receive_t(socket_fd_, _, data_size_, _)).WillByDefault(
+            DoAll(SetArgPointee<3>(nullptr),
+                  Return(0)
+                 ));
     }
     void TearDown() override {
         request->io__.release();
@@ -83,20 +92,10 @@ class RequestTests : public Test {
 
 };
 
-TEST_F(RequestTests, HandleReturnsErrorOnMemoryAllocation) {
-    generic_request_buffer->data_size = -1;
-    request->io__.release();
-    request.reset(new Request{generic_request_buffer, socket_fd_});
-    auto err = request->Handle();
-
-    ASSERT_THAT(err, Eq(hidra2::ErrorTemplates::kMemoryAllocationError));
-
-}
-
 TEST_F(RequestTests, HandleDoesNotReceiveEmptyData) {
-    generic_request_buffer->data_size = 0;
+    generic_request_header.data_size = 0;
     request->io__.release();
-    request.reset(new Request{generic_request_buffer, socket_fd_});
+    request.reset(new Request{generic_request_header, socket_fd_});
     request->io__ = std::unique_ptr<hidra2::IO> {&mock_io};;
 
     EXPECT_CALL(mock_io, Receive_t(_, _, _, _)).Times(0);
@@ -106,20 +105,34 @@ TEST_F(RequestTests, HandleDoesNotReceiveEmptyData) {
     ASSERT_THAT(err, Eq(nullptr));
 }
 
-
-
 TEST_F(RequestTests, HandleReturnsErrorOnDataReceive) {
     EXPECT_CALL(mock_io, Receive_t(socket_fd_, _, data_size_, _)).WillOnce(
-        DoAll(SetArgPointee<3>(new hidra2::IOError("", hidra2::IOErrorType::kReadError)),
+        DoAll(SetArgPointee<3>(new hidra2::IOError("Test Read Error", hidra2::IOErrorType::kReadError)),
               Return(0)
              ));
 
     auto err = request->Handle();
+    ASSERT_THAT(err, Eq(hidra2::IOErrorTemplates::kReadError));
+}
+
+
+TEST_F(RequestTests, HandleProcessesRequests) {
 
-    //socket_fd_
-//    EXPECT_CALL(mock_io, Send_t(size_t(SocketDescriptor socket_fd, const void* buf, size_t length, ErrorInterface** err));
-    ASSERT_THAT(err, Eq(hidra2::ReceiverErrorTemplates::kConnectionError));
+    MockReqestHandler mock_request_handler;
 
+    EXPECT_CALL(mock_request_handler, ProcessRequest_t(_)).WillOnce(
+        Return(nullptr)
+    ).WillOnce(
+        Return(new hidra2::IOError("Test Send Error", hidra2::IOErrorType::kUnknownIOError))
+    );;
+
+    request->AddHandler(&mock_request_handler);
+    request->AddHandler(&mock_request_handler);
+
+    auto err = request->Handle();
+
+    ASSERT_THAT(err, Eq(hidra2::IOErrorTemplates::kUnknownIOError));
 }
 
+
 }
-- 
GitLab