diff --git a/CMakeLists.txt b/CMakeLists.txt index 92487d179924f0ed309c739343e66eee7bd10f0b..92636cffa98b47805a7661f14574f7e05d9e840e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,7 @@ SET(PKG_CONFIG_EXTRA "plugindir=${PLUGINDIR}") PKG_CONFIG_APPEND_LIBS(${PROJECT_NAME}) # Search for Boost. +SET(BOOST_COMPONENTS serialization system unit_test_framework thread) SEARCH_FOR_BOOST() SEARCH_FOR_PTHREAD() diff --git a/doc/additionalDoc/debug-logger.h b/doc/additionalDoc/debug-logger.h index 53514b582eb914310ff21e385c4f867239fba328..dce8cde54c49ba4171fc25a0e6c6e93498d38790 100644 --- a/doc/additionalDoc/debug-logger.h +++ b/doc/additionalDoc/debug-logger.h @@ -35,11 +35,11 @@ Inside the constructor of the entity: \endcode The first line sets the frequency at which the logger will be updated.<br> -The second line specifies at which frequency the message should be +The second line specifies at which frequency the STREAM messages should be printed.<br> The third line specifies the level of message to accept.<br> The fourth line returns the level of verbosity. -In this case, all messages are accepted. <br> +In this case, all messages are accepted and the STREAM message are displayed on the output streams once on five. <br> The full list of options are: <ul> @@ -54,15 +54,19 @@ The full list of options are: Here is some example on how to display or record some information. \code - sendMsg("This is a message of level MSG_TYPE_DEBUG",MSG_TYPE_DEBUG); - sendMsg("This is a message of level MSG_TYPE_INFO",MSG_TYPE_INFO); - sendMsg("This is a message of level MSG_TYPE_WARNING",MSG_TYPE_WARNING); - sendMsg("This is a message of level MSG_TYPE_ERROR",MSG_TYPE_ERROR); - sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM",MSG_TYPE_DEBUG_STREAM); - sendMsg("This is a message of level MSG_TYPE_INFO_STREAM",MSG_TYPE_INFO_STREAM); - sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM",MSG_TYPE_WARNING_STREAM); - sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM",MSG_TYPE_ERROR_STREAM); + sendMsg("This is a message of level MSG_TYPE_DEBUG",MSG_TYPE_DEBUG, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_INFO",MSG_TYPE_INFO, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_WARNING",MSG_TYPE_WARNING, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_ERROR",MSG_TYPE_ERROR, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_DEBUG_STREAM",MSG_TYPE_DEBUG_STREAM, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_INFO_STREAM",MSG_TYPE_INFO_STREAM, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_WARNING_STREAM",MSG_TYPE_WARNING_STREAM, __FILE__,__LINE__); + sendMsg("This is a message of level MSG_TYPE_ERROR_STREAM",MSG_TYPE_ERROR_STREAM, __FILE__,__LINE__); logger_.countdown(); \endcode + +Specifying the file with __FILE__ and the line inside the file by __LINE__ are necessary for the +STREAM messages. Indeed they are indexed using the two values. As the default value are "" and 0 +the counting will be confused. */ diff --git a/include/dynamic-graph/entity.h b/include/dynamic-graph/entity.h index 5c57b5f37cf7a8e8f7530ca960acdc6e687d48fa..1db47a3796efa14964594e79dab6bf968d5bc206 100644 --- a/include/dynamic-graph/entity.h +++ b/include/dynamic-graph/entity.h @@ -112,7 +112,24 @@ namespace dynamicgraph /// \brief Get the logger's verbosity level. LoggerVerbosity getLoggerVerbosityLevel() - { return logger_.getVerbosity(); }; + { return logger_.getVerbosity(); } + + /// \brief Set the time sample. + bool setTimeSample(double t) + { return logger_.setTimeSample(t); } + + /// \brief Get the time sample. + double getTimeSample() + { return logger_.getTimeSample();} + + /// \brief Set the period of the stream period + bool setStreamPrintPeriod(double t) + { return logger_.setStreamPrintPeriod(t); } + + /// \brief Get the period of the stream period + double getStreamPrintPeriod() + { return logger_.getStreamPrintPeriod();} + protected: void addCommand(const std::string& name,command::Command* command); diff --git a/include/dynamic-graph/logger.h b/include/dynamic-graph/logger.h index 39e2b31533fc481502c2fe36d1e3ece6a9e5a6e7..ba102ed12159773b6c9e757b5dddcdc1e21c6ef5 100644 --- a/include/dynamic-graph/logger.h +++ b/include/dynamic-graph/logger.h @@ -178,9 +178,16 @@ namespace dynamicgraph { * is going to be called. */ bool setTimeSample(double t); + /** Get the sampling time at which the method countdown() + * is going to be called. */ + double getTimeSample(); + /** Set the time period for printing of streaming messages. */ bool setStreamPrintPeriod(double s); + /** Get the time period for printing of streaming messages. */ + double getStreamPrintPeriod(); + /** Set the verbosity level of the logger. */ void setVerbosity(LoggerVerbosity lv); diff --git a/include/dynamic-graph/process-list.hh b/include/dynamic-graph/process-list.hh new file mode 100644 index 0000000000000000000000000000000000000000..7782b82eb0a9d756d46c09374b22e5dc9b52ebfb --- /dev/null +++ b/include/dynamic-graph/process-list.hh @@ -0,0 +1,182 @@ +/* Copyright LAAS, CNRS + * Author: O. Stasse, 2019 + * See LICENSE file in the root directory of this repository. + */ + +#ifndef DYNAMIC_GRAPH_PROCESS_LIST_H_ +# define DYNAMIC_GRAPH_PROCESS_LIST_H + +#include <boost/archive/text_oarchive.hpp> +#include <boost/archive/text_iarchive.hpp> +#include <boost/serialization/vector.hpp> + +# include <dynamic-graph/fwd.hh> +# include <dynamic-graph/dynamic-graph-api.h> + +namespace dynamicgraph +{ + namespace CPU + { + class DYNAMIC_GRAPH_DLLAPI ProcessData + { + }; + + class DYNAMIC_GRAPH_DLLAPI ProcessList + { + public: + ProcessList(); + + }; + + /// \class This class gather information on a specific CPU. + /// + class DYNAMIC_GRAPH_DLLAPI CPUData + { + public: + + CPUData(); + int cpu_id_; + + inline unsigned long long int + computePeriod(unsigned long long int &a, + unsigned long long int &b) + { + return (a>b) ? a-b :0; + } + + /// \brief Various classes of time spend by the CPU + /// @{ + /// Total time + unsigned long long int total_time_; + /// Time spend in user mode + unsigned long long int user_mode_time_; + /// Time spend in user mode with low priority (nice mode) + unsigned long long int nice_time_; + /// Time spend in system mode + unsigned long long int system_time_; + /// Time spend in system mode + unsigned long long int system_all_time_; + /// Time spend in doing nothing. + unsigned long long int idle_time_; + /// Time spend in doing nothing. + unsigned long long int idle_all_time_; + /// Time spend in waiting an input/output to complete. + unsigned long long int iowait_time_; + /// Time spend in servicing hardware interrupts. + unsigned long long int irq_time_; + /// Time spend in servicing software interrupts. + unsigned long long int softirq_time_; + /// Time spend in other operating systems in a virtualized environments + /// Never doing this for control ! + unsigned long long int steal_time_; + /// Time spend running a virtual CPU for guest operating systems + /// under the control of the Linux kernel + unsigned long long int guest_time_; + /// Time spent running a niced guest + /// (virtual CPU for guest operating systems under the + /// control of the Linux kernel) + unsigned long long int guest_nice_time_; + /// @} + + /// \brief Various classes of time spend by the CPU by period + /// @{ + /// Total time + unsigned long long int total_period_; + /// Time spend in user mode + unsigned long long int user_mode_period_; + /// Time spend in user mode with low priority (nice mode) + unsigned long long int nice_period_; + /// Time spend in system mode + unsigned long long int system_period_; + /// Time spend in all system mode + unsigned long long int system_all_period_; + /// Time spend in doing nothing. + unsigned long long int idle_period_; + /// Time spend in doing nothing. + unsigned long long int idle_all_period_; + /// Time spend in waiting an input/output to complete. + unsigned long long int iowait_period_; + /// Time spend in servicing hardware interrupts. + unsigned long long int irq_period_; + /// Time spend in servicing software interrupts. + unsigned long long int softirq_period_; + /// Time spend in other operating systems in a virtualized environments + /// Never doing this for control ! + unsigned long long int steal_period_; + /// Time spend running a virtual CPU for guest operating systems + /// under the control of the Linux kernel + unsigned long long int guest_period_; + /// @} + + double percent_; + void ProcessLine(std::istringstream &aCPULine); + + friend class boost::serialization::access; + + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & version; + ar & total_time_; + ar & user_mode_time_; + ar & nice_time_; + ar & system_time_; + ar & system_all_time_; + ar & idle_time_; + ar & idle_all_time_; + ar & iowait_time_; + ar & irq_time_; + ar & softirq_time_; + ar & steal_time_; + ar & guest_time_; + ar & guest_nice_time_; + ar & percent_; + } + + }; + + /// \class This class gathers information on a computer. + /// This includes a list of CPU + class DYNAMIC_GRAPH_DLLAPI System + { + private: + bool init_; + + public: + System(); + + /// Read /proc/state file to extract CPU count. + void init(); + + /// Update CPU data information from /proc/stat + void readProcStat(); + + /// Friend class for serialization. + friend class boost::serialization::access; + + /// Number of CPU. + unsigned int cpuNb_; + + void ProcessCPULine(unsigned int cpunb, + std::istringstream &aCPULine); + + /// \brief Vector of CPU informations. + std::vector<CPUData> vCPUData_; + + /// \brief Global CPU information. + CPUData gCPUData_; + + template<class Archive> + void serialize(Archive & ar, const unsigned int version) + { + ar & version; + ar & cpuNb_; + ar & gCPUData_; + ar & vCPUData_; + } + + }; + } +} + +#endif /* DYNAMIC_GRAPH_PROCESS_LIST_H_ */ diff --git a/include/dynamic-graph/signal-ptr.h b/include/dynamic-graph/signal-ptr.h index b54c07cfe0ce00a196322e16f995e67eb287cd29..d66729e74d027620a9b17d86560c1d981cc3c3d5 100644 --- a/include/dynamic-graph/signal-ptr.h +++ b/include/dynamic-graph/signal-ptr.h @@ -132,8 +132,9 @@ namespace dynamicgraph std::string next2="" ) const; protected: // Interdiction of the rest of the heritage - + using Signal<T,Time>::addDependency; virtual void addDependency () {} + using Signal<T,Time>::removeDependency; virtual void removeDependency () {} virtual void clearDependencies () {} diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 00054c99e6935415523dec8fed476bd23fdd785a..31bf3adfe65fab037a7427f761eb396e467efdf6 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -30,6 +30,8 @@ ADD_LIBRARY(${LIBRARY_NAME} exception/exception-signal.cpp exception/exception-traces.cpp + mt/process-list.cpp + signal/signal-array.cpp signal/signal-caster.cpp signal/signal-cast-helper.cpp diff --git a/src/debug/logger.cpp b/src/debug/logger.cpp index 83b54ecdd8554515dbe11fb67a2506d5f2836c2b..6ebcaafd46687c37768038ad33bfe6c86edca22e 100644 --- a/src/debug/logger.cpp +++ b/src/debug/logger.cpp @@ -63,7 +63,7 @@ namespace dynamicgraph //TODO Modif ici // if print is allowed by current verbosity level - if(isStreamMsg(type)) + if( isStreamMsg(type)) { int l = line; // check whether counter already exists @@ -80,7 +80,10 @@ namespace dynamicgraph if(it->second>0.0) { it->second -= m_timeSample; - return; + if (it->second<=0.0) + it->second = m_streamPrintPeriod; + else + return; } else // otherwise reset counter and print it->second = m_streamPrintPeriod; @@ -103,4 +106,14 @@ namespace dynamicgraph m_streamPrintPeriod = s; return true; } + + double Logger::getTimeSample() + { + return m_timeSample; + } + + double Logger::getStreamPrintPeriod() + { + return m_streamPrintPeriod; + } } // namespace dynamicgraph diff --git a/src/debug/real-time-logger.cpp b/src/debug/real-time-logger.cpp index 340738054f903b13fb8104b6569ed8b6c406d35c..c3278435c163713a863f58d39289c63292e21467 100644 --- a/src/debug/real-time-logger.cpp +++ b/src/debug/real-time-logger.cpp @@ -74,35 +74,67 @@ namespace dynamicgraph struct RealTimeLogger::thread { bool requestShutdown_; + int threadPolicy_; + int threadPriority_; + bool changedThreadParams; boost::thread t_; - + thread (RealTimeLogger* logger) : requestShutdown_ (false) + , threadPolicy_(SCHED_OTHER) + , threadPriority_(0) + , changedThreadParams(true) , t_ (&thread::spin, this, logger) {} - void spin (RealTimeLogger* logger) + void setThreadPolicy(int policy) + { + threadPolicy_ = policy; + changedThreadParams = true; + + } + + void setPriority(int priority) + { + threadPriority_ = priority; + changedThreadParams = true; + } + + int getThreadPolicy() { return threadPolicy_; } + int getThreadPriority() { return threadPriority_; } + + void changeThreadParams() { - // Change the thread's scheduler from real-time to normal and reduce its priority int threadPolicy; struct sched_param threadParam; - if (pthread_getschedparam (pthread_self(), &threadPolicy, &threadParam) == 0) - { - threadPolicy = SCHED_OTHER; - threadParam.sched_priority -= 5; - if (threadParam.sched_priority < sched_get_priority_min (threadPolicy)) - threadParam.sched_priority = sched_get_priority_min (threadPolicy); + if (pthread_getschedparam (pthread_self(), &threadPolicy, &threadParam) + == 0) + { + threadPolicy = threadPolicy_; + threadParam.sched_priority = threadPriority_; + if (threadParam.sched_priority < + sched_get_priority_min (threadPolicy)) + threadParam.sched_priority = sched_get_priority_min (threadPolicy); - pthread_setschedparam (pthread_self(), threadPolicy, &threadParam); - } + pthread_setschedparam (pthread_self(), threadPolicy, &threadParam); + changedThreadParams = false; + } + } + + void spin (RealTimeLogger* logger) + { + // Change the thread's scheduler from real-time to normal + // and reduce its priority while (!requestShutdown_ || !logger->empty()) - { - // If the logger did not write anything, it means the buffer is empty. - // Do a pause - if (!logger->spinOnce()) - boost::this_thread::sleep(boost::posix_time::milliseconds(100)); - } + { + // If the logger did not write anything, it means the buffer is empty. + // Do a pause + if (!logger->spinOnce()) + boost::this_thread::sleep(boost::posix_time::milliseconds(1000)); + if (changedThreadParams) + changeThreadParams(); + } } }; diff --git a/src/mt/process-list.cpp b/src/mt/process-list.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b0d37b4ecabd38c982d62ca89a32bb8dba183a79 --- /dev/null +++ b/src/mt/process-list.cpp @@ -0,0 +1,175 @@ +/* Copyright LAAS, CNRS + * Author: O. Stasse, 2019 + * See LICENSE file in the root directory of this repository. + */ +#include <fstream> +#include <sstream> +#include <string> + +#include <dynamic-graph/process-list.hh> + +using namespace dynamicgraph::CPU; +CPUData::CPUData(): + user_mode_time_(0), + nice_time_(0), + system_time_(0), + idle_time_(0), + iowait_time_(0), + irq_time_(0), + softirq_time_(0), + steal_time_(0), + guest_time_(0), + guest_nice_time_(0), + percent_(0.0) +{ +} + +void CPUData::ProcessLine(std::istringstream &aCPULine) +{ + unsigned long long int luser_mode_time=0, + lnice_time=0, lsystem_time=0, lidle_time=0, + liowait_time=0, lirq_time=0, lsoftirq_time=0, + lsteal_time=0,lguest_time=0, lguest_nice_time; + + aCPULine >> luser_mode_time; + aCPULine >> lnice_time; + aCPULine >> lsystem_time; + aCPULine >> lidle_time; + aCPULine >> liowait_time; + aCPULine >> lirq_time; + aCPULine >> lsoftirq_time; + aCPULine >> lsteal_time; + aCPULine >> lguest_time; + aCPULine >> lguest_nice_time; + + // Remove guest time already in user_time: + luser_mode_time -= lguest_time; + lnice_time -= lguest_nice_time; + + // Compute cumulative time + unsigned long long int lidle_all_time=0, + lsystem_all_time=0, lguest_all_time=0, ltotal_time=0; + + lidle_all_time = lidle_time + liowait_time; + lsystem_all_time = lsystem_time + lirq_time + lsoftirq_time; + lguest_all_time = lguest_time + lguest_nice_time; + ltotal_time = luser_mode_time + lnice_time + lsystem_all_time + + lidle_all_time + lsteal_time + lguest_all_time; + + + // Update periodic computation. + user_mode_period_ = computePeriod(luser_mode_time, user_mode_time_); + nice_period_ = computePeriod(lnice_time, nice_time_); + system_period_ = computePeriod(lsystem_time, system_time_); + system_all_period_ = computePeriod(lsystem_all_time,system_all_time_); + idle_period_ = computePeriod(lidle_time, idle_time_); + idle_all_period_ = computePeriod(lidle_all_time, idle_all_time_); + iowait_period_ = computePeriod(liowait_time, idle_time_); + irq_period_ = computePeriod(lirq_time, irq_time_); + softirq_period_ = computePeriod(lsoftirq_time, softirq_time_); + steal_period_ = computePeriod(lsteal_time, steal_time_); + guest_period_ = computePeriod(lguest_all_time, guest_time_); + total_period_ = computePeriod(ltotal_time, total_time_); + + /// Update time. + user_mode_time_ = luser_mode_time; + nice_time_ = lnice_time; + system_time_ = lsystem_time; + system_all_time_ = lsystem_all_time; + idle_time_ = lidle_time; + idle_all_time_ = lidle_all_time; + iowait_time_ = liowait_time; + irq_time_ = lirq_time; + softirq_time_ = lsoftirq_time; + steal_time_ = lsteal_time; + guest_time_ = lguest_all_time; + total_time_ = ltotal_time; + + if (total_period_!=0.0) + { + percent_ = (double)(user_mode_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( nice_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( system_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( irq_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( softirq_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( steal_period_)/(double)(total_period_) * 100.0; + percent_ += (double)( iowait_period_)/(double)(total_period_) * 100.0; + } + std::cout << cpu_id_ << " " << percent_ << std::endl; +} + +System::System() +{ + vCPUData_.clear(); + init(); +} + +void System::init() +{ + init_ = false; + readProcStat(); + init_ = true; +} + +void System::ProcessCPULine(unsigned int cpunb, + std::istringstream &aCPULine) +{ + vCPUData_[cpunb].ProcessLine(aCPULine); +} + +void System::readProcStat() +{ + std::ifstream aif; + cpuNb_ = 1; + + aif.open("/proc/stat",std::ifstream::in); + std::string aline; + aline.clear(); + while (std::getline(aif,aline)) + { + // Read on line of the file + std::istringstream anISSLine(aline); + std::string line_hdr; + anISSLine >> line_hdr; + + // Check if the line start with cpu + std::size_t pos = line_hdr.find("cpu"); + std::string str_cpunbr = line_hdr.substr(pos+3); + + // Check if this is the first line + if (pos==0 and str_cpunbr.empty()) + { + gCPUData_.ProcessLine(anISSLine); + gCPUData_.cpu_id_=-1; + } + else + { + // If not then check if there is a CPU number + if (pos==0) + { + std::istringstream iss(str_cpunbr); + unsigned int lcpunb; + iss >> lcpunb; + // If we did not initialize + if (!init_) + { + // Count the number of CPU. + if (lcpunb>cpuNb_) + cpuNb_ = lcpunb; + } + else + // Otherwise process the line. + ProcessCPULine(lcpunb,anISSLine); + } + } + } + + if (!init_) + { + /// The number of CPU has been detected by going through /proc/stat. + vCPUData_.resize(cpuNb_+1); + for(int i=0;i<(int)cpuNb_;i++) + vCPUData_[i].cpu_id_ = i; + } + aif.close(); +} diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 1246147ab43f94a1a08aa2e23c52115b55b26060..39626ac5eac142ab20efa520e764036773ee8530 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -62,3 +62,6 @@ TARGET_LINK_LIBRARIES(debug-tracer tracer) DYNAMIC_GRAPH_TEST(debug-logger) DYNAMIC_GRAPH_TEST(debug-logger-winit) DYNAMIC_GRAPH_TEST(signal-all) +DYNAMIC_GRAPH_TEST(command-test) +DYNAMIC_GRAPH_TEST(test-mt) +TARGET_LINK_LIBRARIES(test-mt tracer) \ No newline at end of file diff --git a/tests/command-test.cpp b/tests/command-test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..3c04780cad31b09ecd8dce2966b1fe9c6c59015b --- /dev/null +++ b/tests/command-test.cpp @@ -0,0 +1,166 @@ +/* Copyright 2019, LAAS-CNRS + * + * Olivier Stasse + * + * See LICENSE file + * + */ +#include <sstream> +#include <iostream> +#include <dynamic-graph/entity.h> +#include <dynamic-graph/exception-factory.h> +#include "dynamic-graph/factory.h" +#include "dynamic-graph/pool.h" +#include "dynamic-graph/command-bind.h" + +#define ENABLE_RT_LOG +#include <dynamic-graph/real-time-logger.h> +#include <dynamic-graph/logger.h> + +#define BOOST_TEST_MODULE debug-logger + +#include <boost/test/unit_test.hpp> +#include <boost/test/output_test_stream.hpp> + +using boost::test_tools::output_test_stream; + +using namespace dynamicgraph::command; + +namespace dynamicgraph +{ + class CustomEntity : public Entity + { + public: + static const std::string CLASS_NAME; + bool test_zero_arg_; + bool test_one_arg_; + bool test_two_args_; + bool test_three_args_; + bool test_four_args_; + + virtual const std::string& getClassName () const + { + return CLASS_NAME; + } + CustomEntity (const std::string n) + : Entity (n) + { + test_zero_arg_ = false; + test_one_arg_ = false; + test_two_args_ = false; + test_three_args_ = false; + test_four_args_ = false; + + addCommand("0_arg", + makeCommandVoid0(*this, &CustomEntity::zero_arg, + docCommandVoid0("zero arg"))); + + addCommand("1_arg", + makeCommandVoid1(*this, &CustomEntity::one_arg, + docCommandVoid1("one arg", + "int"))); + + addCommand("2_args", + makeCommandVoid2(*this, &CustomEntity::two_args, + docCommandVoid2("two args", + "int", + "int"))); + + addCommand("3_args", + makeCommandVoid3(*this, &CustomEntity::three_args, + docCommandVoid3("three args", + "int","int","int"))); + + addCommand("4_args", + makeCommandVoid4(*this, &CustomEntity::four_args, + docCommandVoid4("four args", + "int", + "int", + "int", + "int"))); + + } + + ~CustomEntity() + { + } + + void zero_arg() + { + test_zero_arg_ = true; + } + + void one_arg(const int & ) + { + test_one_arg_ = true; + } + + void two_args(const int & , + const int & ) + { + test_two_args_ = true; + } + + void three_args(const int & , + const int & , + const int & ) + { + test_three_args_ = true; + } + + void four_args(const int & , + const int & , + const int & , + const int & ) + { + test_four_args_ = true; + } + + }; + DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN (CustomEntity,"CustomEntity"); +} + + +BOOST_AUTO_TEST_CASE(command_test) +{ + dynamicgraph::CustomEntity& entity = + *(dynamic_cast<dynamicgraph::CustomEntity *> + (dynamicgraph::FactoryStorage::getInstance()->newEntity("CustomEntity", + "my-entity"))); + + std::map<const std::string,Command *> aCommandMap = + entity.getNewStyleCommandMap(); + + std::map<const std::string,Command *>::iterator it_map; + + it_map = aCommandMap.find("0_arg"); + if (it_map==aCommandMap.end()) + BOOST_CHECK(false); + it_map->second->execute(); + BOOST_CHECK(entity.test_zero_arg_); + + int first_arg=1; + Value aValue(first_arg); + std::vector<std::string> vec_fname(4); + vec_fname[0]="1_arg"; + vec_fname[1]="2_args"; + vec_fname[2]="3_args"; + vec_fname[3]="4_args"; + std::vector<Value> values; + + for (unsigned int i=0;i<4;i++) + { + it_map = aCommandMap.find(vec_fname[i]); + if (it_map==aCommandMap.end()) + BOOST_CHECK(false); + values.push_back(aValue); + it_map->second->setParameterValues(values); + it_map->second->execute(); + } + + BOOST_CHECK(entity.test_one_arg_); + BOOST_CHECK(entity.test_two_args_); + BOOST_CHECK(entity.test_three_args_); + BOOST_CHECK(entity.test_four_args_); + +} diff --git a/tests/debug-logger-winit.cpp b/tests/debug-logger-winit.cpp index da951130b554dc4414123c233e9b1740a04562d2..d043b5396972fe10821726194280d30130d21913 100644 --- a/tests/debug-logger-winit.cpp +++ b/tests/debug-logger-winit.cpp @@ -7,20 +7,25 @@ */ #include <sstream> #include <iostream> + +#define ENABLE_RT_LOG #include <dynamic-graph/entity.h> #include <dynamic-graph/exception-factory.h> #include "dynamic-graph/factory.h" #include "dynamic-graph/pool.h" -#define ENABLE_RT_LOG #include <dynamic-graph/real-time-logger.h> #include <dynamic-graph/logger.h> + #define BOOST_TEST_MODULE debug-logger #include <boost/test/unit_test.hpp> #include <boost/test/output_test_stream.hpp> +#include <boost/thread/thread.hpp> +#include <boost/date_time/posix_time/posix_time.hpp> + using boost::test_tools::output_test_stream; @@ -78,7 +83,7 @@ BOOST_AUTO_TEST_CASE(debug_logger_wrong_initialization) dynamicgraph::FactoryStorage::getInstance()->newEntity("CustomEntity", "my-entity-2"))); - for(unsigned int i=0;i<10000;i++) + for(unsigned int i=0;i<1000;i++) { entity.testDebugTrace(); } diff --git a/tests/debug-logger.cpp b/tests/debug-logger.cpp index e36483f42d4002eaa6a5e863018614d57773740a..7499e0b100922d97b517b691f294cab3a16857c7 100644 --- a/tests/debug-logger.cpp +++ b/tests/debug-logger.cpp @@ -78,6 +78,11 @@ BOOST_AUTO_TEST_CASE(debug_logger) dynamicgraph::FactoryStorage::getInstance()->newEntity("CustomEntity", "my-entity"))); + entity.setTimeSample(0.002); + BOOST_CHECK_EQUAL(entity.getTimeSample(),0.002); + entity.setStreamPrintPeriod(0.004); + BOOST_CHECK_EQUAL(entity.getStreamPrintPeriod(),0.004); + for(unsigned int i=0;i<10000;i++) { entity.testDebugTrace(); diff --git a/tests/real-time-logger.cpp b/tests/real-time-logger.cpp index eb5b7e1c7bfafa35b06efb3a18f504fe3bf5956b..ac9b38cc1f664abb6217176517e9e918dc6fb23a 100644 --- a/tests/real-time-logger.cpp +++ b/tests/real-time-logger.cpp @@ -43,6 +43,20 @@ BOOST_AUTO_TEST_CASE (monothread) BOOST_AUTO_TEST_CASE (multithread) { + // The part of the code changing priority will only be effective + // if this test is run as root. Otherwise it behaves like a classical thread. + // Test confirms that in this case, it runs with a priority -51 + // and that the thread for logging is running on SCHED_OTHER + // with a nice priority (20). + int threadPolicy; + struct sched_param threadParam; + if (pthread_getschedparam (pthread_self(), &threadPolicy, &threadParam)==0) + { + threadPolicy = SCHED_RR; + threadParam.sched_priority = 50; + pthread_setschedparam (pthread_self(), threadPolicy, &threadParam); + } + RealTimeLogger& rtl = RealTimeLogger::instance(); dgADD_OSTREAM_TO_RTLOG (std::cout); diff --git a/tests/test-mt.cpp b/tests/test-mt.cpp new file mode 100644 index 0000000000000000000000000000000000000000..059ea2a456d6bcacb2465116a9568208a68b6635 --- /dev/null +++ b/tests/test-mt.cpp @@ -0,0 +1,35 @@ +/* Copyright 2019, LAAS-CNRS + * + * Olivier Stasse + * + */ +#include <sstream> +#include <fstream> +#include <iostream> +#include <unistd.h> +#include <dynamic-graph/process-list.hh> + +#define BOOST_TEST_MODULE debug-trace + +#include <boost/test/unit_test.hpp> +#include <boost/test/output_test_stream.hpp> + +using boost::test_tools::output_test_stream; + + +BOOST_AUTO_TEST_CASE(testMt) +{ + dynamicgraph::CPU::System aSystem; + + // create and open a character archive for output + std::ofstream ofs("cpu_state.dat"); + boost::archive::text_oarchive oa(ofs); + oa << aSystem; + + for(unsigned int i=0;i<10;i++) + { + usleep(100000); + aSystem.readProcStat(); + } +} +