From 3dc5fd1d6efb88de686c3d961179c08da8347451 Mon Sep 17 00:00:00 2001 From: Dennis Klein Date: Mon, 8 May 2017 20:37:36 +0200 Subject: [PATCH] expose STL iterator interface for FairMQParts --- fairmq/FairMQParts.h | 31 ++++++--- fairmq/test/CMakeLists.txt | 9 +++ fairmq/test/parts/_iterator_interface.cxx | 82 +++++++++++++++++++++++ fairmq/test/parts/runner.cxx | 16 +++++ 4 files changed, 128 insertions(+), 10 deletions(-) create mode 100644 fairmq/test/parts/_iterator_interface.cxx create mode 100644 fairmq/test/parts/runner.cxx diff --git a/fairmq/FairMQParts.h b/fairmq/FairMQParts.h index 272e913b..69584a4f 100644 --- a/fairmq/FairMQParts.h +++ b/fairmq/FairMQParts.h @@ -9,16 +9,19 @@ #ifndef FAIRMQPARTS_H_ #define FAIRMQPARTS_H_ -#include -#include // unique_ptr - #include "FairMQTransportFactory.h" #include "FairMQMessage.h" +#include +#include // unique_ptr + /// FairMQParts is a lightweight convenience wrapper around a vector of unique pointers to FairMQMessage, used for sending multi-part messages class FairMQParts { + private: + using container = std::vector>; + public: /// Default constructor FairMQParts() : fParts() {}; @@ -33,7 +36,7 @@ class FairMQParts /// Adds part (FairMQMessage) to the container /// @param msg message pointer (for example created with NewMessage() method of FairMQDevice) - inline void AddPart(FairMQMessage* msg) + void AddPart(FairMQMessage* msg) { fParts.push_back(std::unique_ptr(msg)); } @@ -49,27 +52,35 @@ class FairMQParts /// Adds part (std::unique_ptr&) to the container (move) /// @param msg unique pointer to FairMQMessage /// rvalue ref (move required when passing argument) - inline void AddPart(std::unique_ptr&& msg) + void AddPart(std::unique_ptr&& msg) { fParts.push_back(std::move(msg)); } /// Get reference to part in the container at index (without bounds check) /// @param index container index - inline FairMQMessage& operator[](const int index) { return *(fParts[index]); } + FairMQMessage& operator[](const int index) { return *(fParts[index]); } /// Get reference to unique pointer to part in the container at index (with bounds check) /// @param index container index - inline std::unique_ptr& At(const int index) { return fParts.at(index); } + std::unique_ptr& At(const int index) { return fParts.at(index); } // ref version - inline FairMQMessage& AtRef(const int index) { return *(fParts.at(index)); } + FairMQMessage& AtRef(const int index) { return *(fParts.at(index)); } /// Get number of parts in the container /// @return number of parts in the container - inline int Size() const { return fParts.size(); } + int Size() const { return fParts.size(); } - std::vector> fParts; + container fParts; + + // forward container iterators + using iterator = container::iterator; + using const_iterator = container::const_iterator; + auto begin() -> decltype(fParts.begin()) { return fParts.begin(); } + auto end() -> decltype(fParts.end()) { return fParts.end(); } + auto cbegin() -> decltype(fParts.cbegin()) { return fParts.cbegin(); } + auto cend() -> decltype(fParts.cend()) { return fParts.cend(); } }; #endif /* FAIRMQPARTS_H_ */ diff --git a/fairmq/test/CMakeLists.txt b/fairmq/test/CMakeLists.txt index d2882d0b..a1c1f52a 100644 --- a/fairmq/test/CMakeLists.txt +++ b/fairmq/test/CMakeLists.txt @@ -50,6 +50,15 @@ add_testsuite(FairMQ.Protocols RUN_SERIAL ON ) +add_testsuite(FairMQ.Parts + SOURCES + parts/runner.cxx + parts/_iterator_interface.cxx + + LINKS FairMQ + INCLUDES ${CMAKE_CURRENT_SOURCE_DIR}/parts + TIMEOUT 5 +) ############################## # Aggregate all test targets # diff --git a/fairmq/test/parts/_iterator_interface.cxx b/fairmq/test/parts/_iterator_interface.cxx new file mode 100644 index 00000000..28e2845d --- /dev/null +++ b/fairmq/test/parts/_iterator_interface.cxx @@ -0,0 +1,82 @@ +/******************************************************************************** + * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include + +namespace +{ + +using namespace std; + +class RandomAccessIterator : public ::testing::Test { + protected: + FairMQParts mParts; + FairMQTransportFactoryZMQ mFactory; + const string mS1, mS2, mS3; + + RandomAccessIterator() + : mParts(FairMQParts{}), + mFactory(FairMQTransportFactoryZMQ{}), + mS1("1"), + mS2("2"), + mS3("3") + { + + mParts.AddPart(mFactory.CreateMessage(const_cast(mS1.c_str()), + mS1.length(), FairMQDevice::FairMQSimpleMsgCleanup)); + mParts.AddPart(mFactory.CreateMessage(const_cast(mS2.c_str()), + mS2.length(), FairMQDevice::FairMQSimpleMsgCleanup)); + mParts.AddPart(mFactory.CreateMessage(const_cast(mS3.c_str()), + mS3.length(), FairMQDevice::FairMQSimpleMsgCleanup)); + } +}; + +TEST_F(RandomAccessIterator, RangeForLoopConst) +{ + stringstream out; + for (const auto& part : mParts) { + out << string{static_cast(part->GetData()), part->GetSize()}; + } + + ASSERT_EQ(out.str(), "123"); +} + +TEST_F(RandomAccessIterator, RangeForLoopMutation) +{ + auto s = string{"4"}; + + for (auto&& part : mParts) { + part = mFactory.CreateMessage(const_cast(s.c_str()), + s.length(), FairMQDevice::FairMQSimpleMsgCleanup); + } + + stringstream out; + for (const auto& part : mParts) { + out << string{static_cast(part->GetData()), part->GetSize()}; + } + + ASSERT_EQ(out.str(), "444"); +} + +TEST_F(RandomAccessIterator, ForEachConst) +{ + stringstream out; + for_each(mParts.cbegin(), mParts.cend(), [&out](const FairMQMessagePtr& part) { + out << string{static_cast(part->GetData()), part->GetSize()}; + }); + + ASSERT_EQ(out.str(), "123"); +} + +} // namespace diff --git a/fairmq/test/parts/runner.cxx b/fairmq/test/parts/runner.cxx new file mode 100644 index 00000000..5442845e --- /dev/null +++ b/fairmq/test/parts/runner.cxx @@ -0,0 +1,16 @@ +/******************************************************************************** + * Copyright (C) 2017 GSI Helmholtzzentrum fuer Schwerionenforschung GmbH * + * * + * This software is distributed under the terms of the * + * GNU Lesser General Public Licence (LGPL) version 3, * + * copied verbatim in the file "LICENSE" * + ********************************************************************************/ + +#include + +auto main(int argc, char** argv) -> int +{ + ::testing::InitGoogleTest(&argc, argv); + ::testing::FLAGS_gtest_death_test_style = "threadsafe"; + return RUN_ALL_TESTS(); +}