FairMQ: Fix various errors from CI

* move Plugins::Version to fair::mq::tools
* fix Parser interface
* make device a shared pointer in main
* provide std::hash template specialization
* fix FairMQ.Plugins/FairMQ.PluginsStatic when run with ctest
* fix MQ/serialization example
* add --no-as-needed flag
* GCC 4 does not support member refs, move to pointer types
This commit is contained in:
Dennis Klein 2017-06-30 16:29:52 +02:00 committed by Mohammad Al-Turany
parent ad0f050c99
commit a26925cbf5
20 changed files with 153 additions and 104 deletions

View File

@ -95,6 +95,7 @@ set(FAIRMQ_HEADER_FILES
tools/Network.h
tools/runSimpleMQStateMachine.h
tools/Strings.h
tools/Version.h
zeromq/FairMQMessageZMQ.h
zeromq/FairMQPollerZMQ.h
zeromq/FairMQSocketZMQ.h

View File

@ -854,7 +854,7 @@ int FairMQDevice::GetProperty(const int key, const int default_ /*= 0*/)
shared_ptr<FairMQTransportFactory> FairMQDevice::AddTransport(const string& transport)
{
unordered_map<FairMQ::Transport, shared_ptr<FairMQTransportFactory>>::const_iterator i = fTransports.find(FairMQ::TransportTypes.at(transport));
auto i = fTransports.find(FairMQ::TransportTypes.at(transport));
if (i == fTransports.end())
{

View File

@ -8,6 +8,7 @@
#ifndef FAIRMQTRANSPORTS_H_
#define FAIRMQTRANSPORTS_H_
#include <fairmq/Tools.h>
#include <string>
#include <unordered_map>
@ -22,6 +23,7 @@ enum class Transport
SHM
};
static std::unordered_map<std::string, Transport> TransportTypes {
{ "default", Transport::DEFAULT },
{ "zeromq", Transport::ZMQ },
@ -34,14 +36,9 @@ static std::unordered_map<std::string, Transport> TransportTypes {
namespace std
{
template <>
struct hash<FairMQ::Transport>
{
size_t operator()(const FairMQ::Transport& v) const
{
return hash<int>()(static_cast<int>(v));
}
};
template<>
struct hash<FairMQ::Transport> : fair::mq::tools::HashEnum<FairMQ::Transport> {};
} /* namespace std */
}
#endif /* FAIRMQTRANSPORTS_H_ */

View File

@ -11,9 +11,9 @@
using namespace std;
fair::mq::Plugin::Plugin(const string name, const Version version, const string maintainer, const string homepage, PluginServices& pluginServices)
fair::mq::Plugin::Plugin(const string name, const Version version, const string maintainer, const string homepage, PluginServices* pluginServices)
: fkName{name}
, fkVersion{version}
, fkVersion(version)
, fkMaintainer{maintainer}
, fkHomepage{homepage}
, fPluginServices{pluginServices}

View File

@ -38,21 +38,10 @@ class Plugin
using ProgOptions = boost::optional<boost::program_options::options_description>;
struct Version
{
const int fkMajor, fkMinor, fkPatch;
friend auto operator< (const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) < std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); }
friend auto operator> (const Version& lhs, const Version& rhs) -> bool { return rhs < lhs; }
friend auto operator<=(const Version& lhs, const Version& rhs) -> bool { return !(lhs > rhs); }
friend auto operator>=(const Version& lhs, const Version& rhs) -> bool { return !(lhs < rhs); }
friend auto operator==(const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) == std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); }
friend auto operator!=(const Version& lhs, const Version& rhs) -> bool { return !(lhs == rhs); }
friend auto operator<<(std::ostream& os, const Version& v) -> std::ostream& { return os << v.fkMajor << "." << v.fkMinor << "." << v.fkPatch; }
};
using Version = tools::Version;
Plugin() = delete;
Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices& pluginServices);
Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices* pluginServices);
virtual ~Plugin();
auto GetName() const -> const std::string& { return fkName; }
@ -75,24 +64,24 @@ class Plugin
// see <fairmq/PluginServices.h> for docs
using DeviceState = fair::mq::PluginServices::DeviceState;
using DeviceStateTransition = fair::mq::PluginServices::DeviceStateTransition;
auto ToDeviceState(const std::string& state) const -> fair::mq::PluginServices::DeviceState { return fPluginServices.ToDeviceState(state); }
auto ToStr(fair::mq::PluginServices::DeviceState state) const -> std::string { return fPluginServices.ToStr(state); }
auto GetCurrentDeviceState() const -> fair::mq::PluginServices::DeviceState { return fPluginServices.GetCurrentDeviceState(); }
auto ChangeDeviceState(const fair::mq::PluginServices::DeviceStateTransition next) -> void { fPluginServices.ChangeDeviceState(next); }
auto SubscribeToDeviceStateChange(std::function<void(fair::mq::PluginServices::DeviceState)> callback) -> void { fPluginServices.SubscribeToDeviceStateChange(fkName, callback); }
auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices.UnsubscribeFromDeviceStateChange(fkName); }
auto ToDeviceState(const std::string& state) const -> DeviceState { return fPluginServices->ToDeviceState(state); }
auto ToStr(DeviceState state) const -> std::string { return fPluginServices->ToStr(state); }
auto GetCurrentDeviceState() const -> DeviceState { return fPluginServices->GetCurrentDeviceState(); }
auto ChangeDeviceState(const DeviceStateTransition next) -> void { fPluginServices->ChangeDeviceState(next); }
auto SubscribeToDeviceStateChange(std::function<void(DeviceState)> callback) -> void { fPluginServices->SubscribeToDeviceStateChange(fkName, callback); }
auto UnsubscribeFromDeviceStateChange() -> void { fPluginServices->UnsubscribeFromDeviceStateChange(fkName); }
// device config API
// see <fairmq/PluginServices.h> for docs
template<typename T>
auto SetProperty(const std::string& key, T val) -> void { fPluginServices.SetProperty(key, val); }
auto SetProperty(const std::string& key, T val) -> void { fPluginServices->SetProperty(key, val); }
template<typename T>
auto GetProperty(const std::string& key) const -> T { return fPluginServices.GetProperty<T>(key); }
auto GetPropertyAsString(const std::string& key) const -> std::string { return fPluginServices.GetPropertyAsString(key); }
template<typename T>
auto SubscribeToPropertyChange(std::function<void(const std::string& /*key*/, const T /*newValue*/)> callback) const -> void { fPluginServices.SubscribeToPropertyChange(fkName, callback); }
template<typename T>
auto UnsubscribeFromPropertyChange() -> void { fPluginServices.UnsubscribeFromPropertyChange<T>(fkName); }
auto GetProperty(const std::string& key) const -> T { return fPluginServices->GetProperty<T>(key); }
auto GetPropertyAsString(const std::string& key) const -> std::string { return fPluginServices->GetPropertyAsString(key); }
// template<typename T>
// auto SubscribeToPropertyChange(std::function<void(const std::string& [>key*/, const T /*newValue<])> callback) const -> void { fPluginServices.SubscribeToPropertyChange(fkName, callback); }
// template<typename T>
// auto UnsubscribeFromPropertyChange() -> void { fPluginServices.UnsubscribeFromPropertyChange<T>(fkName); }
private:
@ -100,7 +89,7 @@ class Plugin
const Version fkVersion;
const std::string fkMaintainer;
const std::string fkHomepage;
PluginServices& fPluginServices;
PluginServices* fPluginServices;
}; /* class Plugin */
@ -108,7 +97,7 @@ class Plugin
} /* namespace fair */
#define REGISTER_FAIRMQ_PLUGIN(KLASS, NAME, VERSION, MAINTAINER, HOMEPAGE, PROGOPTIONS) \
static auto Make_##NAME##_Plugin(fair::mq::PluginServices& pluginServices) -> std::shared_ptr<KLASS> \
static auto Make_##NAME##_Plugin(fair::mq::PluginServices* pluginServices) -> std::shared_ptr<KLASS> \
{ \
return std::make_shared<KLASS>(std::string{#NAME}, VERSION, std::string{MAINTAINER}, std::string{HOMEPAGE}, pluginServices); \
} \

View File

@ -8,7 +8,7 @@
#include <fairmq/PluginServices.h>
using fair::mq::PluginServices;
using namespace fair::mq;
const std::unordered_map<std::string, PluginServices::DeviceState> PluginServices::fkDeviceStateStrMap = {
{"OK", DeviceState::Ok},
@ -24,7 +24,7 @@ const std::unordered_map<std::string, PluginServices::DeviceState> PluginService
{"RESETTING DEVICE", DeviceState::ResettingDevice},
{"EXITING", DeviceState::Exiting}
};
const std::unordered_map<PluginServices::DeviceState, std::string> PluginServices::fkStrDeviceStateMap = {
const std::unordered_map<PluginServices::DeviceState, std::string, tools::HashEnum<PluginServices::DeviceState>> PluginServices::fkStrDeviceStateMap = {
{DeviceState::Ok, "OK"},
{DeviceState::Error, "ERROR"},
{DeviceState::Idle, "IDLE"},
@ -49,7 +49,7 @@ const std::unordered_map<std::string, PluginServices::DeviceStateTransition> Plu
{"END", DeviceStateTransition::End},
{"ERROR FOUND", DeviceStateTransition::ErrorFound},
};
const std::unordered_map<PluginServices::DeviceStateTransition, std::string> PluginServices::fkStrDeviceStateTransitionMap = {
const std::unordered_map<PluginServices::DeviceStateTransition, std::string, tools::HashEnum<PluginServices::DeviceStateTransition>> PluginServices::fkStrDeviceStateTransitionMap = {
{DeviceStateTransition::InitDevice, "INIT DEVICE"},
{DeviceStateTransition::InitTask, "INIT TASK"},
{DeviceStateTransition::Run, "RUN"},
@ -60,7 +60,7 @@ const std::unordered_map<PluginServices::DeviceStateTransition, std::string> Plu
{DeviceStateTransition::End, "END"},
{DeviceStateTransition::ErrorFound, "ERROR FOUND"},
};
const std::unordered_map<FairMQDevice::State, PluginServices::DeviceState> PluginServices::fkDeviceStateMap = {
const std::unordered_map<FairMQDevice::State, PluginServices::DeviceState, fair::mq::tools::HashEnum<FairMQDevice::State>> PluginServices::fkDeviceStateMap = {
{FairMQDevice::OK, DeviceState::Ok},
{FairMQDevice::ERROR, DeviceState::Error},
{FairMQDevice::IDLE, DeviceState::Idle},
@ -74,7 +74,7 @@ const std::unordered_map<FairMQDevice::State, PluginServices::DeviceState> Plugi
{FairMQDevice::RESETTING_DEVICE, DeviceState::ResettingDevice},
{FairMQDevice::EXITING, DeviceState::Exiting}
};
const std::unordered_map<PluginServices::DeviceStateTransition, FairMQDevice::Event> PluginServices::fkDeviceStateTransitionMap = {
const std::unordered_map<PluginServices::DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<PluginServices::DeviceStateTransition>> PluginServices::fkDeviceStateTransitionMap = {
{DeviceStateTransition::InitDevice, FairMQDevice::INIT_DEVICE},
{DeviceStateTransition::InitTask, FairMQDevice::INIT_TASK},
{DeviceStateTransition::Run, FairMQDevice::RUN},

View File

@ -32,8 +32,15 @@ class PluginServices
{
public:
PluginServices() = delete;
PluginServices(FairMQProgOptions* config, std::shared_ptr<FairMQDevice> device)
: fDevice{device}
, fConfig{config}
{
}
/// See https://github.com/FairRootGroup/FairRoot/blob/dev/fairmq/docs/Device.md#13-state-machine
enum class DeviceState
enum class DeviceState : int
{
Ok,
Error,
@ -48,7 +55,8 @@ class PluginServices
ResettingDevice,
Exiting
};
enum class DeviceStateTransition // transition event between DeviceStates
enum class DeviceStateTransition : int // transition event between DeviceStates
{
InitDevice,
InitTask,
@ -61,13 +69,6 @@ class PluginServices
ErrorFound
};
PluginServices() = delete;
PluginServices(FairMQProgOptions& config, FairMQDevice& device)
: fDevice{device}
, fConfig{config}
{
}
// Control API
/// @brief Convert string to DeviceState
@ -86,23 +87,24 @@ class PluginServices
/// @param state to convert
/// @return string representation of DeviceState enum entry
static auto ToStr(DeviceState state) -> std::string { return fkStrDeviceStateMap.at(state); }
friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); }
/// @brief Convert DeviceStateTransition to string
/// @param transition to convert
/// @return string representation of DeviceStateTransition enum entry
static auto ToStr(DeviceStateTransition transition) -> std::string { return fkStrDeviceStateTransitionMap.at(transition); }
friend auto operator<<(std::ostream& os, const DeviceState& state) -> std::ostream& { return os << ToStr(state); }
friend auto operator<<(std::ostream& os, const DeviceStateTransition& transition) -> std::ostream& { return os << ToStr(transition); }
/// @return current device state
auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<FairMQDevice::State>(fDevice.GetCurrentState())); }
auto GetCurrentDeviceState() const -> DeviceState { return fkDeviceStateMap.at(static_cast<FairMQDevice::State>(fDevice->GetCurrentState())); }
/// @brief Request a device state transition
/// @param next state transition
///
/// The state transition may not happen immediately, but when the current state evaluates the
/// pending transition event and terminates. In other words, the device states are scheduled cooperatively.
auto ChangeDeviceState(const DeviceStateTransition next) -> void { fDevice.ChangeState(fkDeviceStateTransitionMap.at(next)); }
auto ChangeDeviceState(const DeviceStateTransition next) -> void { fDevice->ChangeState(fkDeviceStateTransitionMap.at(next)); }
/// @brief Subscribe with a callback to device state changes
/// @param subscriber id
@ -112,14 +114,14 @@ class PluginServices
/// the state is running in.
auto SubscribeToDeviceStateChange(const std::string& subscriber, std::function<void(DeviceState /*newState*/)> callback) -> void
{
fDevice.SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){
fDevice->SubscribeToStateChange(subscriber, [&,callback](FairMQDevice::State newState){
callback(fkDeviceStateMap.at(newState));
});
}
/// @brief Unsubscribe from device state changes
/// @param subscriber id
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice.UnsubscribeFromStateChange(subscriber); }
auto UnsubscribeFromDeviceStateChange(const std::string& subscriber) -> void { fDevice->UnsubscribeFromStateChange(subscriber); }
// Config API
@ -137,7 +139,7 @@ class PluginServices
auto currentState = GetCurrentDeviceState();
if (currentState == DeviceState::InitializingDevice)
{
fConfig.SetValue(key, val);
fConfig->SetValue(key, val);
}
else
{
@ -153,14 +155,14 @@ class PluginServices
/// TODO Currently, if a non-existing key is requested and a default constructed object is returned.
/// This behaviour will be changed in the future to throw an exception in that case to provide a proper sentinel.
template<typename T>
auto GetProperty(const std::string& key) const -> T { return fConfig.GetValue<T>(key); }
auto GetProperty(const std::string& key) const -> T { return fConfig->GetValue<T>(key); }
/// @brief Read config property as string
/// @param key
/// @return config property value converted to string
///
/// If a type is not supported, the user can provide support by overloading the ostream operator for this type
auto GetPropertyAsString(const std::string& key) const -> std::string { return fConfig.GetStringValue(key); }
auto GetPropertyAsString(const std::string& key) const -> std::string { return fConfig->GetStringValue(key); }
/// @brief Subscribe to property updates of type T
/// @param subscriber
@ -175,31 +177,30 @@ class PluginServices
// std::function<void(const std::string& [>key*/, const T /*newValue<])> callback
// ) const -> void
// {
// fConfig.Subscribe(subscriber, callback);
// fConfig->Subscribe(subscriber, callback);
// }
//
// /// @brief Unsubscribe from property updates of type T
// /// @param subscriber
// template<typename T>
// auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig.Unsubscribe<T>(subscriber); }
// auto UnsubscribeFromPropertyChange(const std::string& subscriber) -> void { fConfig->Unsubscribe<T>(subscriber); }
//
// TODO Fix property subscription
// TODO Property iterator
static const std::unordered_map<std::string, DeviceState> fkDeviceStateStrMap;
static const std::unordered_map<DeviceState, std::string> fkStrDeviceStateMap;
static const std::unordered_map<DeviceState, std::string, tools::HashEnum<DeviceState>> fkStrDeviceStateMap;
static const std::unordered_map<std::string, DeviceStateTransition> fkDeviceStateTransitionStrMap;
static const std::unordered_map<DeviceStateTransition, std::string> fkStrDeviceStateTransitionMap;
static const std::unordered_map<FairMQDevice::State, DeviceState> fkDeviceStateMap;
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event> fkDeviceStateTransitionMap;
static const std::unordered_map<DeviceStateTransition, std::string, tools::HashEnum<DeviceStateTransition>> fkStrDeviceStateTransitionMap;
static const std::unordered_map<FairMQDevice::State, DeviceState, tools::HashEnum<FairMQDevice::State>> fkDeviceStateMap;
static const std::unordered_map<DeviceStateTransition, FairMQDevice::Event, tools::HashEnum<DeviceStateTransition>> fkDeviceStateTransitionMap;
private:
FairMQProgOptions& fConfig;
FairMQDevice& fDevice;
FairMQProgOptions* fConfig; // TODO make it a shared pointer, once old AliceO2 code is cleaned up
std::shared_ptr<FairMQDevice> fDevice;
}; /* class PluginServices */
} /* namespace mq */
} /* namespace fair */

View File

@ -13,6 +13,7 @@
#include <fairmq/tools/CppSTL.h>
#include <fairmq/tools/Network.h>
#include <fairmq/tools/Strings.h>
#include <fairmq/tools/Version.h>
// IWYU pragma: end_exports
#endif // FAIR_MQ_TOOLS_H

View File

@ -37,7 +37,7 @@ FairMQProgOptions::~FairMQProgOptions()
{
}
void FairMQProgOptions::ParseAll(const int argc, const char** argv, bool allowUnregistered)
void FairMQProgOptions::ParseAll(const int argc, char const* const* argv, bool allowUnregistered)
{
// init description
InitOptionDescription();

View File

@ -39,7 +39,7 @@ class FairMQProgOptions : public FairProgOptions , public FairMQEventManager
// parse command line and txt/INI configuration file.
// default parser for the mq-configuration file (JSON/XML) is called if command line key mq-config is called
virtual void ParseAll(const int argc, const char** argv, bool allowUnregistered = false);
virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false);
// external parser, store function
template <typename T, typename ...Args>

View File

@ -124,7 +124,7 @@ void FairProgOptions::UseConfigFile(const string& filename)
/// //////////////////////////////////////////////////////////////////////////////////////////////////////
/// Parser
int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered)
int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered)
{
// get options from cmd line and store in variable map
// here we use command_line_parser instead of parse_command_line, to allow unregistered and positional options
@ -151,7 +151,7 @@ int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::o
return 0;
}
int FairProgOptions::ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, bool allowUnregistered)
int FairProgOptions::ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, bool allowUnregistered)
{
return ParseCmdLine(argc, argv, desc, fVarMap, allowUnregistered);
}

View File

@ -151,8 +151,8 @@ class FairProgOptions
const po::variables_map& GetVarMap() const { return fVarMap; }
// boost prog options parsers
int ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCmdLine(const int argc, const char** argv, const po::options_description& desc, bool allowUnregistered = false);
int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCmdLine(const int argc, char const* const* argv, const po::options_description& desc, bool allowUnregistered = false);
int ParseCfgFile(const std::string& filename, const po::options_description& desc, po::variables_map& varmap, bool allowUnregistered = false);
int ParseCfgFile(const std::string& filename, const po::options_description& desc, bool allowUnregistered = false);
@ -161,7 +161,7 @@ class FairProgOptions
int ParseEnvironment(const std::function<std::string(std::string)>&);
virtual void ParseAll(const int argc, const char** argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable
virtual void ParseAll(const int argc, char const* const* argv, bool allowUnregistered = false) = 0;// TODO change return type to bool and propagate to executable
virtual int PrintOptions();
virtual int PrintOptionsRaw();

View File

@ -12,6 +12,7 @@
#include <tools/runSimpleMQStateMachine.h>
#include <fairmq/PluginManager.h>
#include <boost/program_options.hpp>
#include <memory>
template <typename R>
class GenericFairMQDevice : public FairMQDevice
@ -60,14 +61,14 @@ int main(int argc, const char** argv)
config.ParseAll(argc, argv, true);
std::unique_ptr<FairMQDevice> device(getDevice(config));
std::shared_ptr<FairMQDevice> device{getDevice(config)};
if (!device)
{
LOG(ERROR) << "getDevice(): no valid device provided. Exiting.";
return 1;
}
pluginManager->EmplacePluginServices(config, *device);
pluginManager->EmplacePluginServices(&config, device);
pluginManager->InstantiatePlugins();
int result = runStateMachine(*device, config);

View File

@ -31,7 +31,7 @@ class DummyPlugin : public fair::mq::Plugin
const Version version,
const std::string maintainer,
const std::string homepage,
PluginServices& pluginServices)
PluginServices* pluginServices)
: Plugin(name, version, maintainer, homepage, pluginServices)
{
SubscribeToDeviceStateChange(
@ -63,7 +63,6 @@ REGISTER_FAIRMQ_PLUGIN(
"Mr. Dummy <dummy@test.net>", // Maintainer
"https://git.test.net/dummy.git", // Homepage
fair::mq::test::DummyPluginProgramOptions // Free function which declares custom program options for the plugin
// signature: () -> boost::optional<boost::program_options::options_description>
)
} /* namespace test */

View File

@ -22,7 +22,7 @@ class Dummy2Plugin : public fair::mq::Plugin
{
public:
Dummy2Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices& pluginServices)
Dummy2Plugin(const std::string name, const Version version, const std::string maintainer, const std::string homepage, PluginServices* pluginServices)
: Plugin(name, version, maintainer, homepage, pluginServices)
{
}

View File

@ -9,8 +9,10 @@
#include <gtest/gtest.h>
#include <fairmq/Plugin.h>
#include <fairmq/PluginServices.h>
#include <fairmq/Tools.h>
#include <FairMQDevice.h>
#include <options/FairMQProgOptions.h>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
@ -21,27 +23,27 @@ namespace
using namespace std;
using namespace fair::mq;
auto control(FairMQDevice& device) -> void
auto control(shared_ptr<FairMQDevice> device) -> void
{
device.SetTransport("zeromq");
device->SetTransport("zeromq");
for (const auto event : {
FairMQDevice::INIT_DEVICE,
FairMQDevice::RESET_DEVICE,
FairMQDevice::END,
}) {
device.ChangeState(event);
if (event != FairMQDevice::END) device.WaitForEndOfState(event);
device->ChangeState(event);
if (event != FairMQDevice::END) device->WaitForEndOfState(event);
}
}
TEST(Plugin, Operators)
{
FairMQProgOptions config{};
FairMQDevice device{};
PluginServices services{config, device};
auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", services};
auto p2 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", services};
auto p3 = Plugin{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", services};
auto device = make_shared<FairMQDevice>();
PluginServices services{&config, device};
auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
auto p2 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
auto p3 = Plugin{"file", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/file.git", &services};
EXPECT_EQ(p1, p2);
EXPECT_NE(p1, p3);
control(device);
@ -50,9 +52,9 @@ TEST(Plugin, Operators)
TEST(Plugin, OstreamOperators)
{
FairMQProgOptions config{};
FairMQDevice device{};
PluginServices services{config, device};
auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", services};
auto device = make_shared<FairMQDevice>();
PluginServices services{&config, device};
auto p1 = Plugin{"dds", {1, 0, 0}, "Foo Bar <foo.bar@test.net>", "https://git.test.net/dds.git", &services};
stringstream ss;
ss << p1;
EXPECT_EQ(ss.str(), string{"'dds', version '1.0.0', maintainer 'Foo Bar <foo.bar@test.net>', homepage 'https://git.test.net/dds.git'"});
@ -61,9 +63,9 @@ TEST(Plugin, OstreamOperators)
TEST(PluginVersion, Operators)
{
struct Plugin::Version v1{1, 0, 0};
struct Plugin::Version v2{1, 0, 0};
struct Plugin::Version v3{1, 2, 0};
struct fair::mq::tools::Version v1{1, 0, 0};
struct fair::mq::tools::Version v2{1, 0, 0};
struct fair::mq::tools::Version v3{1, 2, 0};
EXPECT_EQ(v1, v2);
EXPECT_NE(v1, v3);
EXPECT_GT(v3, v2);

View File

@ -13,6 +13,7 @@
#include <options/FairMQProgOptions.h>
#include <FairMQLogger.h>
#include <fstream>
#include <memory>
#include <vector>
namespace
@ -23,25 +24,25 @@ using namespace boost::filesystem;
using namespace boost::program_options;
using namespace std;
auto control(FairMQDevice& device) -> void
auto control(shared_ptr<FairMQDevice> device) -> void
{
device.SetTransport("zeromq");
device->SetTransport("zeromq");
for (const auto event : {
FairMQDevice::INIT_DEVICE,
FairMQDevice::RESET_DEVICE,
FairMQDevice::END,
}) {
device.ChangeState(event);
if (event != FairMQDevice::END) device.WaitForEndOfState(event);
device->ChangeState(event);
if (event != FairMQDevice::END) device->WaitForEndOfState(event);
}
}
TEST(PluginManager, LoadPlugin)
{
FairMQProgOptions config{};
FairMQDevice device{};
auto device = make_shared<FairMQDevice>();
auto mgr = PluginManager{};
mgr.EmplacePluginServices(config, device);
mgr.EmplacePluginServices(&config, device);
mgr.PrependSearchPath("./lib");

View File

@ -9,7 +9,9 @@
#ifndef FAIR_MQ_TOOLS_CPPSTL_H
#define FAIR_MQ_TOOLS_CPPSTL_H
#include <functional>
#include <memory>
#include <type_traits>
namespace fair
{
@ -25,6 +27,18 @@ std::unique_ptr<T> make_unique(Args&& ...args)
return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}
// provide an enum hasher to compensate std::hash not supporting enums in C++11
template<typename Enum>
struct HashEnum
{
auto operator()(const Enum& e) const noexcept
-> typename std::enable_if<std::is_enum<Enum>::value, std::size_t>::type
{
using _type = typename std::underlying_type<Enum>::type;
return std::hash<_type>{}(static_cast<_type>(e));
}
};
} /* namespace tools */
} /* namespace mq */
} /* namespace fair */

View File

@ -6,6 +6,7 @@
#include <fairmq/tools/CppSTL.h>
#include <fairmq/tools/Network.h>
#include <fairmq/tools/Strings.h>
#include <fairmq/tools/Version.h>
namespace FairMQ
{
@ -13,6 +14,7 @@ namespace tools
{
using fair::mq::tools::make_unique;
using fair::mq::tools::HashEnum;
using fair::mq::tools::getHostIPs;
using fair::mq::tools::getInterfaceIP;
@ -20,6 +22,8 @@ using fair::mq::tools::getDefaultRouteNetworkInterface;
using fair::mq::tools::S;
using fair::mq::tools::Version;
} // namespace tools
} // namespace FairMQ

39
fairmq/tools/Version.h Normal file
View File

@ -0,0 +1,39 @@
/********************************************************************************
* 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" *
********************************************************************************/
#ifndef FAIR_MQ_TOOLS_VERSION_H
#define FAIR_MQ_TOOLS_VERSION_H
#include <ostream>
#include <tuple>
namespace fair
{
namespace mq
{
namespace tools
{
struct Version
{
const int fkMajor, fkMinor, fkPatch;
friend auto operator< (const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) < std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); }
friend auto operator> (const Version& lhs, const Version& rhs) -> bool { return rhs < lhs; }
friend auto operator<=(const Version& lhs, const Version& rhs) -> bool { return !(lhs > rhs); }
friend auto operator>=(const Version& lhs, const Version& rhs) -> bool { return !(lhs < rhs); }
friend auto operator==(const Version& lhs, const Version& rhs) -> bool { return std::tie(lhs.fkMajor, lhs.fkMinor, lhs.fkPatch) == std::tie(rhs.fkMajor, rhs.fkMinor, rhs.fkPatch); }
friend auto operator!=(const Version& lhs, const Version& rhs) -> bool { return !(lhs == rhs); }
friend auto operator<<(std::ostream& os, const Version& v) -> std::ostream& { return os << v.fkMajor << "." << v.fkMinor << "." << v.fkPatch; }
};
} /* namespace tools */
} /* namespace mq */
} /* namespace fair */
#endif /* FAIR_MQ_TOOLS_VERSION_H */