From b0a36bccee5c3a59386e9e232a9850e78bb9cd5b Mon Sep 17 00:00:00 2001 From: Tomek Mrugalski Date: Thu, 14 May 2015 19:43:05 +0200 Subject: [PATCH] [3793] Changes after review: - {ptime,duration}ToText moved to lib/util - missing comments added - EXPECT_EQ -> ASSERT_EQ - several consts added - protected methods are now private in Observation - tabs converted to spaces --- configure.ac | 4 +- src/lib/cc/data.h | 1 - src/lib/stats/Makefile.am | 9 +-- src/lib/stats/observation.cc | 66 +++++++++++---------- src/lib/stats/observation.h | 43 +++++--------- src/lib/stats/stats_mgr.cc | 20 +++---- src/lib/stats/stats_mgr.h | 60 ++++++++++--------- src/lib/stats/tests/Makefile.am | 2 +- src/lib/stats/tests/observation_unittest.cc | 38 +++++++----- src/lib/stats/tests/stats_mgr_unittest.cc | 45 ++++++++------ src/lib/util/Makefile.am | 3 +- src/lib/util/boost_time_utils.cc | 37 ++++++++++++ src/lib/util/boost_time_utils.h | 34 +++++++++++ 13 files changed, 220 insertions(+), 142 deletions(-) create mode 100644 src/lib/util/boost_time_utils.cc create mode 100644 src/lib/util/boost_time_utils.h diff --git a/configure.ac b/configure.ac index b23a5a26c2..ce1a717ee0 100644 --- a/configure.ac +++ b/configure.ac @@ -1494,8 +1494,8 @@ AC_CONFIG_FILES([compatcheck/Makefile src/lib/testutils/Makefile src/lib/testutils/dhcp_test_lib.sh src/lib/testutils/testdata/Makefile - src/lib/stats/Makefile - src/lib/stats/tests/Makefile + src/lib/stats/Makefile + src/lib/stats/tests/Makefile src/lib/util/Makefile src/lib/util/io/Makefile src/lib/util/python/Makefile diff --git a/src/lib/cc/data.h b/src/lib/cc/data.h index ee2c15c6de..66b2d184ee 100644 --- a/src/lib/cc/data.h +++ b/src/lib/cc/data.h @@ -677,7 +677,6 @@ public: /// @brief Returns number of stored elements /// - /// @note: this is costly operation for a map! /// @return number of elements. size_t size() const { return (m.size()); diff --git a/src/lib/stats/Makefile.am b/src/lib/stats/Makefile.am index f7b41cd18d..4ff2abbf44 100644 --- a/src/lib/stats/Makefile.am +++ b/src/lib/stats/Makefile.am @@ -1,6 +1,7 @@ SUBDIRS = . tests AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib +AM_CPPFLAGS += $(BOOST_INCLUDES) AM_CXXFLAGS=$(KEA_CXXFLAGS) lib_LTLIBRARIES = libkea-stats.la @@ -8,13 +9,9 @@ libkea_stats_la_SOURCES = observation.h observation.cc libkea_stats_la_SOURCES += context.h context.cc libkea_stats_la_SOURCES += stats_mgr.h stats_mgr.cc +libkea_stats_la_CPPFLAGS = $(AM_CPPFLAGS) libkea_stats_la_LIBADD = $(top_builddir)/src/lib/cc/libkea-cc.la - -# This library seem to be required when certain methods are called from -# boost::posix_time. In particular, to_simple_string(ptime) and -# to_simple_string(time_duration) require it on Ubuntu. It doesn't seem -# to be required on Mac OS, though. -libkea_stats_la_LIBADD += -lboost_date_time +libkea_stats_la_LIBADD += $(top_builddir)/src/lib/util/libkea-util.la libkea_stats_includedir = $(includedir)/$(PACKAGE_NAME)/stats libkea_stats_include_HEADERS = stats_mgr.h diff --git a/src/lib/stats/observation.cc b/src/lib/stats/observation.cc index 35d9624a96..bfd88b320f 100644 --- a/src/lib/stats/observation.cc +++ b/src/lib/stats/observation.cc @@ -1,6 +1,22 @@ -#include +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + #include +#include #include +#include +#include #include using namespace std; @@ -10,17 +26,17 @@ using namespace boost::posix_time; namespace isc { namespace stats { -Observation::Observation(const std::string& name, uint64_t value) +Observation::Observation(const std::string& name, const uint64_t value) :name_(name), type_(STAT_INTEGER) { setValue(value); } -Observation::Observation(const std::string& name, double value) +Observation::Observation(const std::string& name, const double value) :name_(name), type_(STAT_FLOAT) { setValue(value); } -Observation::Observation(const std::string& name, StatsDuration value) +Observation::Observation(const std::string& name, const StatsDuration value) :name_(name), type_(STAT_DURATION) { setValue(value); } @@ -30,17 +46,17 @@ Observation::Observation(const std::string& name, const std::string& value) setValue(value); } -void Observation::addValue(uint64_t value) { +void Observation::addValue(const uint64_t value) { IntegerSample current = getInteger(); setValue(current.first + value); } -void Observation::addValue(double value) { +void Observation::addValue(const double value) { FloatSample current = getFloat(); setValue(current.first + value); } -void Observation::addValue(StatsDuration value) { +void Observation::addValue(const StatsDuration& value) { DurationSample current = getDuration(); setValue(current.first + value); } @@ -50,15 +66,15 @@ void Observation::addValue(const std::string& value) { setValue(current.first + value); } -void Observation::setValue(uint64_t value) { +void Observation::setValue(const uint64_t value) { setValueInternal(value, integer_samples_, STAT_INTEGER); } -void Observation::setValue(double value) { +void Observation::setValue(const double value) { setValueInternal(value, float_samples_, STAT_FLOAT); } -void Observation::setValue(StatsDuration value) { +void Observation::setValue(const StatsDuration& value) { setValueInternal(value, duration_samples_, STAT_DURATION); } @@ -140,20 +156,6 @@ std::string Observation::typeToText(Type type) { return (tmp.str()); } -std::string -Observation::ptimeToText(ptime t) { - - // The alternative would be to call to_simple_string(ptime), but unfortunately - // that requires linking with boost libraries. - - return (to_simple_string(t)); -} - -std::string -Observation::durationToText(StatsDuration dur) { - return (to_simple_string(dur)); -} - isc::data::ConstElementPtr Observation::getJSON() const { @@ -168,29 +170,30 @@ Observation::getJSON() const { case STAT_INTEGER: { IntegerSample s = getInteger(); value = isc::data::Element::create(static_cast(s.first)); - timestamp = isc::data::Element::create(ptimeToText(s.second)); + timestamp = isc::data::Element::create(isc::util::ptimeToText(s.second)); break; } case STAT_FLOAT: { FloatSample s = getFloat(); value = isc::data::Element::create(s.first); - timestamp = isc::data::Element::create(ptimeToText(s.second)); + timestamp = isc::data::Element::create(isc::util::ptimeToText(s.second)); break; } case STAT_DURATION: { DurationSample s = getDuration(); - value = isc::data::Element::create(durationToText(s.first)); - timestamp = isc::data::Element::create(ptimeToText(s.second)); + value = isc::data::Element::create(isc::util::durationToText(s.first)); + timestamp = isc::data::Element::create(isc::util::ptimeToText(s.second)); break; } case STAT_STRING: { StringSample s = getString(); value = isc::data::Element::create(s.first); - timestamp = isc::data::Element::create(ptimeToText(s.second)); + timestamp = isc::data::Element::create(isc::util::ptimeToText(s.second)); break; } default: - isc_throw(InvalidStatType, "Unknown stat type: " << typeToText(type_)); + isc_throw(InvalidStatType, "Unknown statistic type: " + << typeToText(type_)); }; entry->add(value); @@ -221,7 +224,8 @@ void Observation::reset() { return; } default: - isc_throw(InvalidStatType, "Unknown stat type: " << typeToText(type_)); + isc_throw(InvalidStatType, "Unknown statistic type: " + << typeToText(type_)); }; } diff --git a/src/lib/stats/observation.h b/src/lib/stats/observation.h index 5c3e440c30..9dc7e09d45 100644 --- a/src/lib/stats/observation.h +++ b/src/lib/stats/observation.h @@ -15,12 +15,13 @@ #ifndef OBSERVATION_H #define OBSERVATION_H -#include -#include #include +#include +#include #include #include #include +#include namespace isc { namespace stats { @@ -37,11 +38,7 @@ public: /// @brief Defines duration resolution /// -/// Boost offers a base boost::posix_time::time_duration class, that has specific -/// implementations: boost::posix_time::{hours,minutes,seconds,millisec,microsec, -/// nanosec}. For statistics purposes, the most appropriate choice seems to be -/// microseconds precision, so we'll stick with that. -typedef boost::posix_time::microsec::time_duration StatsDuration; +typedef boost::posix_time::time_duration StatsDuration; /// @defgroup stat_samples Specifies supported observation types. /// @@ -101,19 +98,19 @@ class Observation { /// /// @param name observation name /// @param value integer value observed. - Observation(const std::string& name, uint64_t value); + Observation(const std::string& name, const uint64_t value); /// @brief Constructor for floating point observations /// /// @param name observation name /// @param value floating point value observed. - Observation(const std::string& name, double value); + Observation(const std::string& name, const double value); /// @brief Constructor for duration observations /// /// @param name observation name /// @param value duration observed. - Observation(const std::string& name, StatsDuration value); + Observation(const std::string& name, const StatsDuration value); /// @brief Constructor for string observations /// @@ -125,43 +122,43 @@ class Observation { /// /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void setValue(uint64_t value); + void setValue(const uint64_t value); /// @brief Records absolute floating point observation /// /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void setValue(double value); + void setValue(const double value); /// @brief Records absolute duration observation /// /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void setValue(StatsDuration duration); + void setValue(const StatsDuration& duration); /// @brief Records absolute string observation /// /// @param value string value observed /// @throw InvalidStatType if statistic is not a string - void setValue(const std::string& value = ""); + void setValue(const std::string& value); /// @brief Records incremental integer observation /// /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void addValue(uint64_t value = 1); + void addValue(const uint64_t value = 1); /// @brief Records incremental floating point observation /// /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void addValue(double value = 1.0f); + void addValue(const double value = 1.0f); /// @brief Records incremental duration observation /// /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void addValue(StatsDuration value = StatsDuration(0,0,0,0)); + void addValue(const StatsDuration& value = StatsDuration(0,0,1,0)); /// @brief Records incremental string observation. /// @@ -208,20 +205,12 @@ class Observation { /// @return textual name of statistic type static std::string typeToText(Type type); - /// @brief Converts ptime structure to text - /// @return a string representing time - static std::string ptimeToText(boost::posix_time::ptime time); - - /// @brief Converts StatsDuration to text - /// @return a string representing time - static std::string durationToText(StatsDuration dur); - /// @brief Returns observation name std::string getName() const { return (name_); } - protected: +private: /// @brief Records absolute sample (internal version) /// /// This method records an absolute value of an observation. @@ -238,7 +227,7 @@ class Observation { void setValueInternal(SampleType value, StorageType& storage, Type exp_type); - /// @brief Returns a sample + /// @brief Returns a sample (internal version) /// /// @tparam SampleType type of sample (e.g. IntegerSample) /// @tparam StorageType type of storage (e.g. list) diff --git a/src/lib/stats/stats_mgr.cc b/src/lib/stats/stats_mgr.cc index e9730b2c97..2a592b63f1 100644 --- a/src/lib/stats/stats_mgr.cc +++ b/src/lib/stats/stats_mgr.cc @@ -30,30 +30,30 @@ StatsMgr::StatsMgr() } -void StatsMgr::setValue(const std::string& name, uint64_t value) { +void StatsMgr::setValue(const std::string& name, const uint64_t value) { setValueInternal(name, value); } -void StatsMgr::setValue(const std::string& name, double value) { +void StatsMgr::setValue(const std::string& name, const double value) { setValueInternal(name, value); } -void StatsMgr::setValue(const std::string& name, StatsDuration value) { +void StatsMgr::setValue(const std::string& name, const StatsDuration& value) { setValueInternal(name, value); } void StatsMgr::setValue(const std::string& name, const std::string& value) { setValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, uint64_t value) { +void StatsMgr::addValue(const std::string& name, const uint64_t value) { addValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, double value) { +void StatsMgr::addValue(const std::string& name, const double value) { addValueInternal(name, value); } -void StatsMgr::addValue(const std::string& name, StatsDuration value) { +void StatsMgr::addValue(const std::string& name, const StatsDuration& value) { addValueInternal(name, value); } @@ -63,24 +63,24 @@ void StatsMgr::addValue(const std::string& name, const std::string& value) { ObservationPtr StatsMgr::getObservation(const std::string& name) const { /// @todo: Implement contexts. - // Currently we keep everyting is a global context. + // Currently we keep everyting in a global context. return (global_->get(name)); } void StatsMgr::addObservation(const ObservationPtr& stat) { /// @todo: Implement contexts. - // Currently we keep everyting is a global context. + // Currently we keep everyting in a global context. return (global_->add(stat)); } bool StatsMgr::deleteObservation(const std::string& name) { /// @todo: Implement contexts. - // Currently we keep everyting is a global context. + // Currently we keep everyting in a global context. return (global_->del(name)); } void StatsMgr::setMaxSampleAge(const std::string& , - boost::posix_time::time_duration) { + const StatsDuration&) { isc_throw(NotImplemented, "setMaxSampleAge not implemented"); } diff --git a/src/lib/stats/stats_mgr.h b/src/lib/stats/stats_mgr.h index f38a4c7bee..dbbea8bcbb 100644 --- a/src/lib/stats/stats_mgr.h +++ b/src/lib/stats/stats_mgr.h @@ -60,54 +60,54 @@ class StatsMgr : public boost::noncopyable { /// /// @{ - /// @brief Records absolute integer observation + /// @brief Records absolute integer observation. /// /// @param name name of the observation /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void setValue(const std::string& name, uint64_t value); + void setValue(const std::string& name, const uint64_t value); - /// @brief Records absolute floating point observation + /// @brief Records absolute floating point observation. /// /// @param name name of the observation /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void setValue(const std::string& name, double value); + void setValue(const std::string& name, const double value); - /// @brief Records absolute duration observation + /// @brief Records absolute duration observation. /// /// @param name name of the observation /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void setValue(const std::string& name, StatsDuration value); + void setValue(const std::string& name, const StatsDuration& value); - /// @brief Records absolute string observation + /// @brief Records absolute string observation. /// /// @param name name of the observation /// @param value string value observed /// @throw InvalidStatType if statistic is not a string void setValue(const std::string& name, const std::string& value); - /// @brief Records incremental integer observation + /// @brief Records incremental integer observation. /// /// @param name name of the observation /// @param value integer value observed /// @throw InvalidStatType if statistic is not integer - void addValue(const std::string& name, uint64_t value); + void addValue(const std::string& name, const uint64_t value); - /// @brief Records incremental floating point observation + /// @brief Records incremental floating point observation. /// /// @param name name of the observation /// @param value floating point value observed /// @throw InvalidStatType if statistic is not fp - void addValue(const std::string& name, double value); + void addValue(const std::string& name, const double value); - /// @brief Records incremental duration observation + /// @brief Records incremental duration observation. /// /// @param name name of the observation /// @param value duration value observed /// @throw InvalidStatType if statistic is not time duration - void addValue(const std::string& name, StatsDuration time); + void addValue(const std::string& name, const StatsDuration& time); /// @brief Records incremental string observation. /// @@ -116,8 +116,7 @@ class StatsMgr : public boost::noncopyable { /// @throw InvalidStatType if statistic is not a string void addValue(const std::string& name, const std::string& value); - /// @brief determines whether a given statistic is kept as a single value - /// or as a number of values + /// @brief Determines maximum age of samples. /// /// Specifies that statistic name should be stored not as a single value, /// but rather as a set of values. duration determines the timespan. @@ -131,10 +130,9 @@ class StatsMgr : public boost::noncopyable { /// call setMaxSampleAge("incoming-packets", time_duration(0,5,0,0)); /// to revert statistic to a single value, call: /// setMaxSampleAge("incoming-packets" time_duration(0,0,0,0)) - void setMaxSampleAge(const std::string& name, - boost::posix_time::time_duration duration); + void setMaxSampleAge(const std::string& name, const StatsDuration& duration); - /// @brief determines how many samples of a given statistic should be kept. + /// @brief Determines how many samples of a given statistic should be kept. /// /// Specifies that statistic name should be stored not as single value, but /// rather as a set of values. In this form, at most max_samples will be kept. @@ -164,6 +162,7 @@ class StatsMgr : public boost::noncopyable { bool reset(const std::string& name); /// @brief Removes specified statistic. + /// /// @param name name of the statistic to be removed. /// @return true if successful, false if there's no such statistic bool del(const std::string& name); @@ -175,20 +174,23 @@ class StatsMgr : public boost::noncopyable { void removeAll(); /// @brief Returns number of available statistics. + /// /// @return number of recorded statistics. size_t count() const; - /// @brief Returns a single statistic as a JSON structure + /// @brief Returns a single statistic as a JSON structure. + /// /// @return JSON structures representing a single statistic isc::data::ConstElementPtr get(const std::string& name) const; - /// @brief Returns all statistics as a JSON structure + /// @brief Returns all statistics as a JSON structure. + /// /// @return JSON structures representing all statistics isc::data::ConstElementPtr getAll() const; /// @} - /// @brief Returns an observation + /// @brief Returns an observation. /// /// Used in testing only. Production code should use @ref get() method. /// @param name name of the statistic @@ -197,13 +199,13 @@ class StatsMgr : public boost::noncopyable { private: - /// @brief Sets a given statistic to specified value (internal version) + /// @brief Sets a given statistic to specified value (internal version). /// /// This template method sets statistic identified by name to a value /// specified by value. This internal method is used by public @ref setValue /// methods. /// - /// @tparam DataType one of uint64_t, double DurationStat or string + /// @tparam DataType one of uint64_t, double, StatsDuration or string /// @param name name of the statistic /// @param value specified statistic will be set to this value /// @throw InvalidStatType is statistic exists and has a different type. @@ -218,13 +220,13 @@ class StatsMgr : public boost::noncopyable { } } - /// @brief Adds specified value to a given statistic (internal version) + /// @brief Adds specified value to a given statistic (internal version). /// /// This template method adds specified value to a given statistic (identified /// by name to a value). This internal method is used by public @ref setValue /// methods. /// - /// @tparam DataType one of uint64_t, double DurationStat or string + /// @tparam DataType one of uint64_t, double, StatsDuration or string /// @param name name of the statistic /// @param value specified statistic will be set to this value /// @throw InvalidStatType is statistic exists and has a different type. @@ -244,25 +246,25 @@ class StatsMgr : public boost::noncopyable { } } - /// @brief Private constructor + /// @brief Private constructor. /// StatsMgr is a singleton. It should be accessed using @ref instance /// method. StatsMgr(); - /// @brief Adds a new observation + /// @brief Adds a new observation. /// /// That's an utility method used by public @ref setValue() and /// @ref addValue() methods. /// @param obs observation void addObservation(const ObservationPtr& o); - /// @brief Tries to delete an observation + /// @brief Tries to delete an observation. /// /// @param name of the statistic to be deleted /// @return true if deleted, false if not found bool deleteObservation(const std::string& name); - // This is a global context. All stats will initially be stored here. + // This is a global context. All statistics will initially be stored here. StatContextPtr global_; }; diff --git a/src/lib/stats/tests/Makefile.am b/src/lib/stats/tests/Makefile.am index 03bd5497b9..e42f4c1716 100644 --- a/src/lib/stats/tests/Makefile.am +++ b/src/lib/stats/tests/Makefile.am @@ -25,8 +25,8 @@ libstats_unittests_CXXFLAGS = $(AM_CXXFLAGS) libstats_unittests_LDADD = $(top_builddir)/src/lib/stats/libkea-stats.la libstats_unittests_LDADD += $(top_builddir)/src/lib/cc/libkea-cc.la libstats_unittests_LDADD += $(top_builddir)/src/lib/log/libkea-log.la +libstats_unittests_LDADD += $(top_builddir)/src/lib/util/libkea-util.la libstats_unittests_LDADD += $(top_builddir)/src/lib/exceptions/libkea-exceptions.la -libstats_unittests_LDADD += -lboost_date_time libstats_unittests_LDADD += $(GTEST_LDADD) endif diff --git a/src/lib/stats/tests/observation_unittest.cc b/src/lib/stats/tests/observation_unittest.cc index c6d192a181..9c1dd82b43 100644 --- a/src/lib/stats/tests/observation_unittest.cc +++ b/src/lib/stats/tests/observation_unittest.cc @@ -16,7 +16,7 @@ #include #include - +#include #include #include #include @@ -32,8 +32,15 @@ using namespace boost::posix_time; namespace { +/// @brief Test class for Observation +/// +/// This simple fixture class initializes four observations: +/// a (integer), b (float), c(time duration) and d (string). class ObservationTest : public ::testing::Test { public: + + /// @brief Constructor + /// Initializes four observations. ObservationTest() :a("alpha", static_cast(1234)), // integer b("beta", 12.34), // float @@ -47,8 +54,8 @@ public: Observation d; }; -// Basic tests for V4 functionality. This test checks whether parameters -// passed to constructor initialize the object properly. +// Basic tests for the Obseration constructors. This test checks whether +// parameters passed to the constructor initialize the object properly. TEST_F(ObservationTest, constructor) { EXPECT_EQ(Observation::STAT_INTEGER, a.getType()); @@ -137,12 +144,12 @@ TEST_F(ObservationTest, addValue) { // Test checks whether timing is reported properly. TEST_F(ObservationTest, timers) { - ptime min = microsec_clock::local_time(); - b.setValue(123.0); // set it to a random value + ptime before = microsec_clock::local_time(); + b.setValue(123.0); // Set it to a random value and record the time. - // Allow a bit of inprecision. This test allows 5ms. That's ok, when running - // on virtual machines. - ptime max = min + millisec::time_duration(0,0,0,5); + // Allow a bit of inprecision. This test allows 50ms. That should be ok, + // when running on virtual machines. + ptime after = before + millisec::time_duration(0,0,0,50); // Now wait some time. We want to confirm that the timestamp recorded is the // time the observation took place, not current time. @@ -150,9 +157,10 @@ TEST_F(ObservationTest, timers) { FloatSample sample = b.getFloat(); - // Let's check that the timestamp is within (min,max) range. - EXPECT_TRUE(min <= sample.second); - EXPECT_TRUE(sample.second <= max); + // Let's check that the timestamp is within (before,after) range: + // before < sample-time < after + EXPECT_TRUE(before <= sample.second); + EXPECT_TRUE(sample.second <= after); } // Checks whether an integer statistic can generate proper JSON structures. @@ -162,7 +170,7 @@ TEST_F(ObservationTest, integerToJSON) { a.setValue(static_cast(1234)); std::string exp = "[ [ 1234, \"" - + Observation::ptimeToText(a.getInteger().second) + "\" ] ]"; + + isc::util::ptimeToText(a.getInteger().second) + "\" ] ]"; std::cout << a.getJSON()->str() << std::endl; EXPECT_EQ(exp, a.getJSON()->str()); @@ -177,7 +185,7 @@ TEST_F(ObservationTest, floatToJSON) { b.setValue(1234.5); std::string exp = "[ [ 1234.5, \"" - + Observation::ptimeToText(b.getFloat().second) + "\" ] ]"; + + isc::util::ptimeToText(b.getFloat().second) + "\" ] ]"; std::cout << b.getJSON()->str() << std::endl; EXPECT_EQ(exp, b.getJSON()->str()); @@ -191,7 +199,7 @@ TEST_F(ObservationTest, durationToJSON) { c.setValue(time_duration(1,2,3,4)); std::string exp = "[ [ \"01:02:03.000004\", \"" - + Observation::ptimeToText(c.getDuration().second) + "\" ] ]"; + + isc::util::ptimeToText(c.getDuration().second) + "\" ] ]"; std::cout << c.getJSON()->str() << std::endl; EXPECT_EQ(exp, c.getJSON()->str()); @@ -205,7 +213,7 @@ TEST_F(ObservationTest, stringToJSON) { d.setValue("Lorem ipsum dolor sit amet"); std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \"" - + Observation::ptimeToText(d.getString().second) + "\" ] ]"; + + isc::util::ptimeToText(d.getString().second) + "\" ] ]"; std::cout << d.getJSON()->str() << std::endl; EXPECT_EQ(exp, d.getJSON()->str()); diff --git a/src/lib/stats/tests/stats_mgr_unittest.cc b/src/lib/stats/tests/stats_mgr_unittest.cc index 4c1cb5f884..6ff79b106d 100644 --- a/src/lib/stats/tests/stats_mgr_unittest.cc +++ b/src/lib/stats/tests/stats_mgr_unittest.cc @@ -16,9 +16,10 @@ #include #include +#include +#include #include #include -#include #include #include @@ -31,12 +32,20 @@ using namespace boost::posix_time; namespace { +/// @brief Fixture class for StatsMgr testing +/// +/// Very simple class that makes sure that StatsMgr is indeed instantiated +/// before the test and any statistics are wiped out after it. class StatsMgrTest : public ::testing::Test { public: + /// @brief Constructor + /// Makes sure that the Statistics Manager is instantiated. StatsMgrTest() { StatsMgr::instance(); } + /// @brief Destructor + /// Removes all statistics. ~StatsMgrTest() { StatsMgr::instance().removeAll(); } @@ -60,10 +69,10 @@ TEST_F(StatsMgrTest, integerStat) { ObservationPtr alpha; EXPECT_NO_THROW(alpha = StatsMgr::instance().getObservation("alpha")); - EXPECT_TRUE(alpha); + ASSERT_TRUE(alpha); std::string exp = "{ \"alpha\": [ [ 1234, \"" - + Observation::ptimeToText(alpha->getInteger().second) + "\" ] ] }"; + + isc::util::ptimeToText(alpha->getInteger().second) + "\" ] ] }"; EXPECT_EQ(exp, StatsMgr::instance().get("alpha")->str()); } @@ -75,10 +84,10 @@ TEST_F(StatsMgrTest, floatStat) { ObservationPtr beta; EXPECT_NO_THROW(beta = StatsMgr::instance().getObservation("beta")); - EXPECT_TRUE(beta); + ASSERT_TRUE(beta); std::string exp = "{ \"beta\": [ [ 12.34, \"" - + Observation::ptimeToText(beta->getFloat().second) + "\" ] ] }"; + + isc::util::ptimeToText(beta->getFloat().second) + "\" ] ] }"; EXPECT_EQ(exp, StatsMgr::instance().get("beta")->str()); } @@ -91,10 +100,10 @@ TEST_F(StatsMgrTest, durationStat) { ObservationPtr gamma; EXPECT_NO_THROW(gamma = StatsMgr::instance().getObservation("gamma")); - EXPECT_TRUE(gamma); + ASSERT_TRUE(gamma); std::string exp = "{ \"gamma\": [ [ \"01:02:03.000004\", \"" - + Observation::ptimeToText(gamma->getDuration().second) + "\" ] ] }"; + + isc::util::ptimeToText(gamma->getDuration().second) + "\" ] ] }"; EXPECT_EQ(exp, StatsMgr::instance().get("gamma")->str()); } @@ -107,10 +116,10 @@ TEST_F(StatsMgrTest, stringStat) { ObservationPtr delta; EXPECT_NO_THROW(delta = StatsMgr::instance().getObservation("delta")); - EXPECT_TRUE(delta); + ASSERT_TRUE(delta); std::string exp = "{ \"delta\": [ [ \"Lorem ipsum\", \"" - + Observation::ptimeToText(delta->getString().second) + "\" ] ] }"; + + isc::util::ptimeToText(delta->getString().second) + "\" ] ] }"; EXPECT_EQ(exp, StatsMgr::instance().get("delta")->str()); } @@ -157,16 +166,16 @@ TEST_F(StatsMgrTest, getGetAll) { ASSERT_TRUE(rep_delta); std::string exp_str_alpha = "[ [ 6912, \"" - + Observation::ptimeToText(StatsMgr::instance().getObservation("alpha") + + isc::util::ptimeToText(StatsMgr::instance().getObservation("alpha") ->getInteger().second) + "\" ] ]"; std::string exp_str_beta = "[ [ 69.12, \"" - + Observation::ptimeToText(StatsMgr::instance().getObservation("beta") + + isc::util::ptimeToText(StatsMgr::instance().getObservation("beta") ->getFloat().second) + "\" ] ]"; std::string exp_str_gamma = "[ [ \"06:08:10.000012\", \"" - + Observation::ptimeToText(StatsMgr::instance().getObservation("gamma") + + isc::util::ptimeToText(StatsMgr::instance().getObservation("gamma") ->getDuration().second) + "\" ] ]"; std::string exp_str_delta = "[ [ \"Lorem ipsum\", \"" - + Observation::ptimeToText(StatsMgr::instance().getObservation("delta") + + isc::util::ptimeToText(StatsMgr::instance().getObservation("delta") ->getString().second) + "\" ] ]"; // Check that individual stats are reported properly @@ -182,8 +191,6 @@ TEST_F(StatsMgrTest, getGetAll) { ConstElementPtr rep_all = StatsMgr::instance().getAll(); ASSERT_TRUE(rep_all); - std::cout << rep_all->str() << std::endl; - // Verifying this is a bit more involved, as we don't know whether the // order would be preserved or not. EXPECT_EQ(4, rep_all->size()); @@ -305,7 +312,7 @@ TEST_F(StatsMgrTest, DISABLED_performanceSingleAdd) { time_duration dur = after - before; std::cout << "Incrementing a single statistic " << cycles << " times took: " - << Observation::durationToText(dur) << std::endl; + << isc::util::durationToText(dur) << std::endl; } // This is a performance benchmark that checks how long does it take @@ -327,7 +334,7 @@ TEST_F(StatsMgrTest, DISABLED_performanceSingleSet) { time_duration dur = after - before; std::cout << "Setting a single statistic " << cycles << " times took: " - << Observation::durationToText(dur) << std::endl; + << isc::util::durationToText(dur) << std::endl; } // This is a performance benchmark that checks how long does it take to @@ -357,7 +364,7 @@ TEST_F(StatsMgrTest, DISABLED_performanceMultipleAdd) { time_duration dur = after - before; std::cout << "Incrementing one of " << stats << " statistics " << cycles - << " times took: " << Observation::durationToText(dur) << std::endl; + << " times took: " << isc::util::durationToText(dur) << std::endl; } // This is a performance benchmark that checks how long does it take to @@ -387,7 +394,7 @@ TEST_F(StatsMgrTest, DISABLED_performanceMultipleSet) { time_duration dur = after - before; std::cout << "Setting one of " << stats << " statistics " << cycles - << " times took: " << Observation::durationToText(dur) << std::endl; + << " times took: " << isc::util::durationToText(dur) << std::endl; } }; diff --git a/src/lib/util/Makefile.am b/src/lib/util/Makefile.am index 9e722f0478..e1e6484a4b 100644 --- a/src/lib/util/Makefile.am +++ b/src/lib/util/Makefile.am @@ -9,7 +9,8 @@ AM_CPPFLAGS += $(BOOST_INCLUDES) AM_CXXFLAGS = $(KEA_CXXFLAGS) lib_LTLIBRARIES = libkea-util.la -libkea_util_la_SOURCES = csv_file.h csv_file.cc +libkea_util_la_SOURCES = boost_time_utils.h boost_time_utils.cc +libkea_util_la_SOURCES += csv_file.h csv_file.cc libkea_util_la_SOURCES += filename.h filename.cc libkea_util_la_SOURCES += locks.h lru_list.h libkea_util_la_SOURCES += strutil.h strutil.cc diff --git a/src/lib/util/boost_time_utils.cc b/src/lib/util/boost_time_utils.cc new file mode 100644 index 0000000000..feefc5c458 --- /dev/null +++ b/src/lib/util/boost_time_utils.cc @@ -0,0 +1,37 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#include + +std::string +isc::util::ptimeToText(boost::posix_time::ptime t) { + boost::gregorian::date d = t.date(); + std::stringstream s; + s << d.year() << "-" << d.month() << "-" << d.day(); + s << " " << durationToText(t.time_of_day()); + return (s.str()); +} + +std::string +isc::util::durationToText(boost::posix_time::time_duration dur) { + std::stringstream s; + s << std::setw(2) << std::setfill('0') << dur.hours() + << ":" << std::setw(2) << std::setfill('0') << dur.minutes() + << ":" << std::setw(2) << std::setfill('0') << dur.seconds() + << "." << std::setw(boost::posix_time::time_duration::num_fractional_digits()) + << std::setfill('0') + << dur.fractional_seconds(); + + return (s.str()); +} diff --git a/src/lib/util/boost_time_utils.h b/src/lib/util/boost_time_utils.h new file mode 100644 index 0000000000..f8e7315585 --- /dev/null +++ b/src/lib/util/boost_time_utils.h @@ -0,0 +1,34 @@ +// Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC") +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH +// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, +// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM +// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE +// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR +// PERFORMANCE OF THIS SOFTWARE. + +#ifndef KEA_BOOST_TIME_UTILS_H +#define KEA_BOOST_TIME_UTILS_H + +#include + +namespace isc { +namespace util { + +/// @brief Converts ptime structure to text +/// @return a string representing time +std::string ptimeToText(boost::posix_time::ptime t); + +/// @brief Converts StatsDuration to text +/// @return a string representing time +std::string durationToText(boost::posix_time::time_duration dur); + +}; // end of isc::util namespace +}; // end of isc namespace + +#endif -- 2.47.2