diff --git a/CMakeModules/testing_cpp.cmake b/CMakeModules/testing_cpp.cmake
index f30d6cf85696e32ab62f9ed234b543a780bb9b28..9eb9d55e6ef78ae6116f70968c1c9161bd13ac4c 100644
--- a/CMakeModules/testing_cpp.cmake
+++ b/CMakeModules/testing_cpp.cmake
@@ -18,6 +18,39 @@ if (BUILD_TESTS)
     endif ()
 endif ()
 
+#TODO: Call add_plain_unit_test in gtest
+function(add_plain_unit_test target test_source_files linktarget)
+    if (BUILD_TESTS)
+        include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
+        link_directories(${gtest_SOURCE_DIR}/lib)
+
+        add_executable(test-${target} ${test_source_files})
+
+        if (NOT ${libs} STREQUAL "")
+            target_link_libraries(test-${target} ${libs})
+        endif ()
+
+        IF (WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+            set(GTEST_LIBS gtestd gtest_maind gmockd)
+        ELSE ()
+            set(GTEST_LIBS gtest gmock gtest_main)
+        ENDIF (WIN32 AND ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+        target_link_libraries(test-${target} ${GTEST_LIBS} ${CMAKE_THREAD_LIBS_INIT})
+
+        GET_PROPERTY(HIDRA2_COMMON_IO_LIBRARIES GLOBAL PROPERTY HIDRA2_COMMON_IO_LIBRARIES)
+        message(STATUS "HIDRA2_COMMON_IO_LIBRARIES: '${HIDRA2_COMMON_IO_LIBRARIES}'")
+        target_link_libraries(test-${target} ${HIDRA2_COMMON_IO_LIBRARIES})
+
+        if (NOT ${test_libraries} STREQUAL "")
+            target_link_libraries(test-${target} ${test_libraries})
+        endif ()
+        add_test(NAME test-${target} COMMAND test-${target})
+        set_tests_properties(test-${target} PROPERTIES LABELS "unit;all")
+
+        message(STATUS "Added test 'test-${target}'")
+    endif()
+endfunction()
+
 function(gtest target test_source_files linktarget)
     if (BUILD_TESTS)
         include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
diff --git a/common/cpp/CMakeLists.txt b/common/cpp/CMakeLists.txt
index 8558a4592ef5fb3906b29e5eff3bda110bf2434e..2e79b345e35a1a91c74e90320c463f8f66b3800d 100644
--- a/common/cpp/CMakeLists.txt
+++ b/common/cpp/CMakeLists.txt
@@ -1,5 +1,7 @@
 add_subdirectory(src/system_io)
 
+add_subdirectory(src/common)
+
 add_subdirectory(src/json_parser)
 
 add_subdirectory(src/data_structs)
diff --git a/common/cpp/include/common/networking.h b/common/cpp/include/common/networking.h
index a2a44195df427b7586b5f72494bbbde1f6a0c005..32afc8d9639aab8ac744ebd40d840bf0fd76bdc0 100644
--- a/common/cpp/include/common/networking.h
+++ b/common/cpp/include/common/networking.h
@@ -20,6 +20,8 @@ enum NetworkErrorCode : uint16_t {
     NET_ERR__INTERNAL_SERVER_ERROR = 65535,
 };
 
+//TODO need to use an serialization framework to ensure struct consistency on different computers
+
 /**
  * @defgroup RPC
  * RPC always return a response to a corresponding request
diff --git a/common/cpp/src/common/CMakeLists.txt b/common/cpp/src/common/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..40873cfcf7dba8ba3fd88b3246a20a05687b2fcb
--- /dev/null
+++ b/common/cpp/src/common/CMakeLists.txt
@@ -0,0 +1,7 @@
+set(TARGET_NAME common)
+
+set(TEST_SOURCE_FILES ../../unittests/common/test_error.cpp)
+
+set(TEST_LIBRARIES "${TARGET_NAME};system_io")
+include_directories(${HIDRA2_CXX_COMMON_INCLUDE_DIR})
+add_plain_unit_test(${TARGET_NAME} "${TEST_SOURCE_FILES}" "${TEST_LIBRARIES}")
diff --git a/common/cpp/unittests/common/test_error.cpp b/common/cpp/unittests/common/test_error.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2c9d64f2b55ba104459c2d2f67bc5b8707b36bb
--- /dev/null
+++ b/common/cpp/unittests/common/test_error.cpp
@@ -0,0 +1,26 @@
+#include <gmock/gmock.h>
+#include <common/error.h>
+#include "gtest/gtest.h"
+
+using hidra2::Error;
+using ::testing::Eq;
+using ::testing::Ne;
+
+namespace {
+
+    TEST(ErrorTemplate, GenerateNoNullptr) {
+        Error error = hidra2::ErrorTemplates::kEndOfFile.Generate();
+        ASSERT_THAT(error, Ne(nullptr));
+    }
+
+    TEST(ErrorTemplate, EqCheck) {
+        Error error = hidra2::ErrorTemplates::kEndOfFile.Generate();
+        ASSERT_TRUE(hidra2::ErrorTemplates::kEndOfFile == error);
+    }
+
+
+    TEST(ErrorTemplate, NeCheck) {
+        Error error = hidra2::ErrorTemplates::kEndOfFile.Generate();
+        ASSERT_FALSE(hidra2::ErrorTemplates::kMemoryAllocationError == error);
+    }
+}
diff --git a/producer/api/include/producer/producer.h b/producer/api/include/producer/producer.h
index 486025abb2553b503b0a6f1a6a6cd18832a856be..d5049d86fec02a75a558e9c6b6b012eb178014c7 100644
--- a/producer/api/include/producer/producer.h
+++ b/producer/api/include/producer/producer.h
@@ -28,11 +28,21 @@ enum class ProducerStatus {
 class Producer {
   public:
     //! Creates a new producer
+    /*!
+     * @return A unique_ptr to a new producer instance
+     */
     static std::unique_ptr<Producer> create();
 
     virtual ~Producer() = default;
 
+    /*!
+     * @return The version of the producer
+     */
     virtual uint64_t GetVersion() const = 0;
+
+    /*!
+     * @return The current status of the producer
+     */
     virtual ProducerStatus GetStatus() const = 0;
 
     //! Connects to a receiver