expose STL iterator interface for FairMQParts

This commit is contained in:
Dennis Klein 2017-05-08 20:37:36 +02:00 committed by Mohammad Al-Turany
parent 0926a9a764
commit 3dc5fd1d6e
4 changed files with 128 additions and 10 deletions

View File

@ -9,16 +9,19 @@
#ifndef FAIRMQPARTS_H_
#define FAIRMQPARTS_H_
#include <vector>
#include <memory> // unique_ptr
#include "FairMQTransportFactory.h"
#include "FairMQMessage.h"
#include <vector>
#include <memory> // 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<std::unique_ptr<FairMQMessage>>;
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<FairMQMessage>(msg));
}
@ -49,27 +52,35 @@ class FairMQParts
/// Adds part (std::unique_ptr<FairMQMessage>&) to the container (move)
/// @param msg unique pointer to FairMQMessage
/// rvalue ref (move required when passing argument)
inline void AddPart(std::unique_ptr<FairMQMessage>&& msg)
void AddPart(std::unique_ptr<FairMQMessage>&& 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<FairMQMessage>& At(const int index) { return fParts.at(index); }
std::unique_ptr<FairMQMessage>& 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<std::unique_ptr<FairMQMessage>> 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_ */

View File

@ -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 #

View File

@ -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 <gtest/gtest.h>
#include <FairMQParts.h>
#include <FairMQDevice.h>
#include <zeromq/FairMQTransportFactoryZMQ.h>
#include <string>
#include <sstream>
#include <algorithm>
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<char*>(mS1.c_str()),
mS1.length(), FairMQDevice::FairMQSimpleMsgCleanup<string>));
mParts.AddPart(mFactory.CreateMessage(const_cast<char*>(mS2.c_str()),
mS2.length(), FairMQDevice::FairMQSimpleMsgCleanup<string>));
mParts.AddPart(mFactory.CreateMessage(const_cast<char*>(mS3.c_str()),
mS3.length(), FairMQDevice::FairMQSimpleMsgCleanup<string>));
}
};
TEST_F(RandomAccessIterator, RangeForLoopConst)
{
stringstream out;
for (const auto& part : mParts) {
out << string{static_cast<char*>(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<char*>(s.c_str()),
s.length(), FairMQDevice::FairMQSimpleMsgCleanup<string>);
}
stringstream out;
for (const auto& part : mParts) {
out << string{static_cast<char*>(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<char*>(part->GetData()), part->GetSize()};
});
ASSERT_EQ(out.str(), "123");
}
} // namespace

View File

@ -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 <gtest/gtest.h>
auto main(int argc, char** argv) -> int
{
::testing::InitGoogleTest(&argc, argv);
::testing::FLAGS_gtest_death_test_style = "threadsafe";
return RUN_ALL_TESTS();
}