observation_unittest.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. // Copyright (C) 2015 Internet Systems Consortium, Inc. ("ISC")
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
  8. // REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  9. // AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
  10. // INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  11. // LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  12. // OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  13. // PERFORMANCE OF THIS SOFTWARE.
  14. #include <config.h>
  15. #include <stats/observation.h>
  16. #include <exceptions/exceptions.h>
  17. #include <util/boost_time_utils.h>
  18. #include <boost/shared_ptr.hpp>
  19. #include <boost/date_time/posix_time/posix_time_types.hpp>
  20. #include <gtest/gtest.h>
  21. #include <iostream>
  22. #include <sstream>
  23. #include <unistd.h>
  24. using namespace isc;
  25. using namespace isc::stats;
  26. using namespace boost::posix_time;
  27. namespace {
  28. /// @brief Test class for Observation
  29. ///
  30. /// This simple fixture class initializes four observations:
  31. /// a (integer), b (float), c(time duration) and d (string).
  32. class ObservationTest : public ::testing::Test {
  33. public:
  34. /// @brief Constructor
  35. /// Initializes four observations.
  36. ObservationTest()
  37. :a("alpha", static_cast<uint64_t>(1234)), // integer
  38. b("beta", 12.34), // float
  39. c("gamma", millisec::time_duration(1,2,3,4)), // duration
  40. d("delta", "1234") { // string
  41. }
  42. Observation a;
  43. Observation b;
  44. Observation c;
  45. Observation d;
  46. };
  47. // Basic tests for the Obseration constructors. This test checks whether
  48. // parameters passed to the constructor initialize the object properly.
  49. TEST_F(ObservationTest, constructor) {
  50. EXPECT_EQ(Observation::STAT_INTEGER, a.getType());
  51. EXPECT_EQ(Observation::STAT_FLOAT, b.getType());
  52. EXPECT_EQ(Observation::STAT_DURATION, c.getType());
  53. EXPECT_EQ(Observation::STAT_STRING, d.getType());
  54. EXPECT_EQ(1234, a.getInteger().first);
  55. EXPECT_EQ(12.34, b.getFloat().first);
  56. EXPECT_EQ(millisec::time_duration(1,2,3,4),
  57. c.getDuration().first);
  58. EXPECT_EQ("1234", d.getString().first);
  59. // Let's check that attempting to get a different type
  60. // than used will cause an exception.
  61. EXPECT_THROW(a.getFloat(), InvalidStatType);
  62. EXPECT_THROW(a.getDuration(), InvalidStatType);
  63. EXPECT_THROW(a.getString(), InvalidStatType);
  64. EXPECT_THROW(b.getInteger(), InvalidStatType);
  65. EXPECT_THROW(b.getDuration(), InvalidStatType);
  66. EXPECT_THROW(b.getString(), InvalidStatType);
  67. EXPECT_THROW(c.getInteger(), InvalidStatType);
  68. EXPECT_THROW(c.getFloat(), InvalidStatType);
  69. EXPECT_THROW(c.getString(), InvalidStatType);
  70. EXPECT_THROW(d.getInteger(), InvalidStatType);
  71. EXPECT_THROW(d.getFloat(), InvalidStatType);
  72. EXPECT_THROW(d.getDuration(), InvalidStatType);
  73. }
  74. // This test checks whether it is possible to set to an absolute value for all
  75. // given types.
  76. TEST_F(ObservationTest, setValue) {
  77. EXPECT_NO_THROW(a.setValue(static_cast<uint64_t>(5678)));
  78. EXPECT_NO_THROW(b.setValue(56e+78));
  79. EXPECT_NO_THROW(c.setValue(millisec::time_duration(5,6,7,8)));
  80. EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
  81. EXPECT_EQ(5678, a.getInteger().first);
  82. EXPECT_EQ(56e+78, b.getFloat().first);
  83. EXPECT_EQ(millisec::time_duration(5,6,7,8),
  84. c.getDuration().first);
  85. EXPECT_EQ("fiveSixSevenEight", d.getString().first);
  86. // Now check whether setting value to a different type does
  87. // throw an exception
  88. EXPECT_THROW(a.setValue(56e+78), InvalidStatType);
  89. EXPECT_THROW(a.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  90. EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType);
  91. EXPECT_THROW(b.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  92. EXPECT_THROW(b.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  93. EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType);
  94. EXPECT_THROW(c.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  95. EXPECT_THROW(c.setValue(56e+78), InvalidStatType);
  96. EXPECT_THROW(c.setValue("fiveSixSevenEight"), InvalidStatType);
  97. EXPECT_THROW(d.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  98. EXPECT_THROW(d.setValue(56e+78), InvalidStatType);
  99. EXPECT_THROW(d.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  100. }
  101. // This test checks whether it is possible to add value to existing
  102. // counter.
  103. TEST_F(ObservationTest, addValue) {
  104. // Note: all Observations were set to 1234,12.34 or similar in
  105. // ObservationTest constructor.
  106. EXPECT_NO_THROW(a.addValue(static_cast<uint64_t>(5678)));
  107. EXPECT_NO_THROW(b.addValue(56.78));
  108. EXPECT_NO_THROW(c.addValue(millisec::time_duration(5,6,7,8)));
  109. EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
  110. EXPECT_EQ(6912, a.getInteger().first);
  111. EXPECT_EQ(69.12, b.getFloat().first);
  112. EXPECT_EQ(millisec::time_duration(6,8,10,12), c.getDuration().first);
  113. EXPECT_EQ("1234fiveSixSevenEight", d.getString().first);
  114. }
  115. // Test checks whether timing is reported properly.
  116. TEST_F(ObservationTest, timers) {
  117. ptime before = microsec_clock::local_time();
  118. b.setValue(123.0); // Set it to a random value and record the time.
  119. // Allow a bit of inprecision. This test allows 50ms. That should be ok,
  120. // when running on virtual machines.
  121. ptime after = before + millisec::time_duration(0,0,0,50);
  122. // Now wait some time. We want to confirm that the timestamp recorded is the
  123. // time the observation took place, not current time.
  124. sleep(1);
  125. FloatSample sample = b.getFloat();
  126. // Let's check that the timestamp is within (before,after) range:
  127. // before < sample-time < after
  128. EXPECT_TRUE(before <= sample.second);
  129. EXPECT_TRUE(sample.second <= after);
  130. }
  131. // Checks whether an integer statistic can generate proper JSON structures.
  132. // See http://kea.isc.org/wiki/StatsDesign for details.
  133. TEST_F(ObservationTest, integerToJSON) {
  134. a.setValue(static_cast<uint64_t>(1234));
  135. std::string exp = "[ [ 1234, \""
  136. + isc::util::ptimeToText(a.getInteger().second) + "\" ] ]";
  137. std::cout << a.getJSON()->str() << std::endl;
  138. EXPECT_EQ(exp, a.getJSON()->str());
  139. }
  140. // Checks whether a floating point statistic can generate proper JSON
  141. // structures. See http://kea.isc.org/wiki/StatsDesign for details.
  142. TEST_F(ObservationTest, floatToJSON) {
  143. // Let's use a value that converts easily to floating point.
  144. // No need to deal with infinite fractions in binary systems.
  145. b.setValue(1234.5);
  146. std::string exp = "[ [ 1234.5, \""
  147. + isc::util::ptimeToText(b.getFloat().second) + "\" ] ]";
  148. std::cout << b.getJSON()->str() << std::endl;
  149. EXPECT_EQ(exp, b.getJSON()->str());
  150. }
  151. // Checks whether a time duration statistic can generate proper JSON structures.
  152. // See http://kea.isc.org/wiki/StatsDesign for details.
  153. TEST_F(ObservationTest, durationToJSON) {
  154. // 1 hour 2 minutes 3 seconds and 4 milliseconds
  155. c.setValue(time_duration(1,2,3,4));
  156. std::string exp = "[ [ \"01:02:03.000004\", \""
  157. + isc::util::ptimeToText(c.getDuration().second) + "\" ] ]";
  158. std::cout << c.getJSON()->str() << std::endl;
  159. EXPECT_EQ(exp, c.getJSON()->str());
  160. }
  161. // Checks whether a string statistic can generate proper JSON structures.
  162. // See http://kea.isc.org/wiki/StatsDesign for details.
  163. TEST_F(ObservationTest, stringToJSON) {
  164. //
  165. d.setValue("Lorem ipsum dolor sit amet");
  166. std::string exp = "[ [ \"Lorem ipsum dolor sit amet\", \""
  167. + isc::util::ptimeToText(d.getString().second) + "\" ] ]";
  168. std::cout << d.getJSON()->str() << std::endl;
  169. EXPECT_EQ(exp, d.getJSON()->str());
  170. }
  171. // Checks whether reset() resets the statistics properly.
  172. TEST_F(ObservationTest, reset) {
  173. a.reset(); // integer
  174. b.reset(); // float
  175. c.reset(); // duration
  176. d.reset(); // string
  177. EXPECT_EQ(0, a.getInteger().first);
  178. EXPECT_EQ(0.0, b.getFloat().first);
  179. EXPECT_EQ(time_duration(0,0,0,0), c.getDuration().first);
  180. EXPECT_EQ("", d.getString().first);
  181. }
  182. // Checks whether an observation can keep its name.
  183. TEST_F(ObservationTest, names) {
  184. EXPECT_EQ("alpha", a.getName());
  185. EXPECT_EQ("beta", b.getName());
  186. EXPECT_EQ("gamma", c.getName());
  187. EXPECT_EQ("delta", d.getName());
  188. }
  189. };