observation_unittest.cc 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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 <boost/shared_ptr.hpp>
  18. #include <boost/date_time/posix_time/posix_time_types.hpp>
  19. #include <gtest/gtest.h>
  20. #include <iostream>
  21. #include <sstream>
  22. #include <unistd.h>
  23. using namespace isc;
  24. using namespace isc::stats;
  25. using namespace boost::posix_time;
  26. namespace {
  27. class ObservationTest : public ::testing::Test {
  28. public:
  29. ObservationTest()
  30. :a(static_cast<uint64_t>(1234)), // integer
  31. b(12.34), // float
  32. c(millisec::time_duration(1,2,3,4)), // duration
  33. d("1234") { // string
  34. }
  35. Observation a;
  36. Observation b;
  37. Observation c;
  38. Observation d;
  39. };
  40. // Basic tests for V4 functionality. This test checks whether parameters
  41. // passed to constructor initialize the object properly.
  42. TEST_F(ObservationTest, constructor) {
  43. EXPECT_EQ(Observation::STAT_INTEGER, a.getType());
  44. EXPECT_EQ(Observation::STAT_FLOAT, b.getType());
  45. EXPECT_EQ(Observation::STAT_DURATION, c.getType());
  46. EXPECT_EQ(Observation::STAT_STRING, d.getType());
  47. EXPECT_EQ(1234, a.getInteger().first);
  48. EXPECT_EQ(12.34, b.getFloat().first);
  49. EXPECT_EQ(millisec::time_duration(1,2,3,4),
  50. c.getDuration().first);
  51. EXPECT_EQ("1234", d.getString().first);
  52. // Let's check that attempting to get a different type
  53. // than used will cause an exception.
  54. EXPECT_THROW(a.getFloat(), InvalidStatType);
  55. EXPECT_THROW(a.getDuration(), InvalidStatType);
  56. EXPECT_THROW(a.getString(), InvalidStatType);
  57. EXPECT_THROW(b.getInteger(), InvalidStatType);
  58. EXPECT_THROW(b.getDuration(), InvalidStatType);
  59. EXPECT_THROW(b.getString(), InvalidStatType);
  60. EXPECT_THROW(c.getInteger(), InvalidStatType);
  61. EXPECT_THROW(c.getFloat(), InvalidStatType);
  62. EXPECT_THROW(c.getString(), InvalidStatType);
  63. EXPECT_THROW(d.getInteger(), InvalidStatType);
  64. EXPECT_THROW(d.getFloat(), InvalidStatType);
  65. EXPECT_THROW(d.getDuration(), InvalidStatType);
  66. }
  67. // This test checks whether it is possible to set to an absolute value for all
  68. // given types.
  69. TEST_F(ObservationTest, setValue) {
  70. EXPECT_NO_THROW(a.setValue(static_cast<uint64_t>(5678)));
  71. EXPECT_NO_THROW(b.setValue(56e+78));
  72. EXPECT_NO_THROW(c.setValue(millisec::time_duration(5,6,7,8)));
  73. EXPECT_NO_THROW(d.setValue("fiveSixSevenEight"));
  74. EXPECT_EQ(5678, a.getInteger().first);
  75. EXPECT_EQ(56e+78, b.getFloat().first);
  76. EXPECT_EQ(millisec::time_duration(5,6,7,8),
  77. c.getDuration().first);
  78. EXPECT_EQ("fiveSixSevenEight", d.getString().first);
  79. // Now check whether setting value to a different type does
  80. // throw an exception
  81. EXPECT_THROW(a.setValue(56e+78), InvalidStatType);
  82. EXPECT_THROW(a.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  83. EXPECT_THROW(a.setValue("fiveSixSevenEight"), InvalidStatType);
  84. EXPECT_THROW(b.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  85. EXPECT_THROW(b.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  86. EXPECT_THROW(b.setValue("fiveSixSevenEight"), InvalidStatType);
  87. EXPECT_THROW(c.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  88. EXPECT_THROW(c.setValue(56e+78), InvalidStatType);
  89. EXPECT_THROW(c.setValue("fiveSixSevenEight"), InvalidStatType);
  90. EXPECT_THROW(d.setValue(static_cast<uint64_t>(5678)), InvalidStatType);
  91. EXPECT_THROW(d.setValue(56e+78), InvalidStatType);
  92. EXPECT_THROW(d.setValue(millisec::time_duration(5,6,7,8)), InvalidStatType);
  93. }
  94. // This test checks whether it is possible to add value to existing
  95. // counter.
  96. TEST_F(ObservationTest, addValue) {
  97. // Note: all Observations were set to 1234,12.34 or similar in
  98. // ObservationTest constructor.
  99. EXPECT_NO_THROW(a.addValue(static_cast<uint64_t>(5678)));
  100. EXPECT_NO_THROW(b.addValue(56.78));
  101. EXPECT_NO_THROW(c.addValue(millisec::time_duration(5,6,7,8)));
  102. EXPECT_NO_THROW(d.addValue("fiveSixSevenEight"));
  103. EXPECT_EQ(6912, a.getInteger().first);
  104. EXPECT_EQ(69.12, b.getFloat().first);
  105. EXPECT_EQ(millisec::time_duration(6,8,10,12), c.getDuration().first);
  106. EXPECT_EQ("1234fiveSixSevenEight", d.getString().first);
  107. }
  108. // Observation will be extended to cover multiple samples of the same
  109. // property. That is not implemented for now, so regardless of the
  110. // number of recorded observation, always the last one is kept.
  111. TEST_F(ObservationTest, getLists) {
  112. // Let's record some data!
  113. for (int i = 0; i <= 42; ++i) {
  114. a.setValue(static_cast<uint64_t>(i));
  115. b.setValue(0.25*i);
  116. c.setValue(millisec::time_duration(0,0,i,0));
  117. std::stringstream tmp;
  118. tmp << i;
  119. d.setValue(tmp.str());
  120. }
  121. // Get the lists.
  122. std::list<IntegerSample> int_list = a.getIntegerList();
  123. std::list<FloatSample> float_list = b.getFloatList();
  124. std::list<DurationSample> dur_list = c.getDurationList();
  125. std::list<StringSample> str_list = d.getStringList();
  126. // Check that they have only one observation.
  127. ASSERT_EQ(1, int_list.size());
  128. ASSERT_EQ(1, float_list.size());
  129. ASSERT_EQ(1, dur_list.size());
  130. ASSERT_EQ(1, str_list.size());
  131. // Now check that that the recorded value is correct.
  132. EXPECT_EQ(42, int_list.begin()->first);
  133. EXPECT_EQ(10.5, float_list.begin()->first);
  134. EXPECT_EQ(millisec::time_duration(0,0,42,0), dur_list.begin()->first);
  135. EXPECT_EQ("42", str_list.begin()->first);
  136. }
  137. // Test checks whether timing is reported properly.
  138. TEST_F(ObservationTest, timers) {
  139. ptime min = microsec_clock::local_time();
  140. b.setValue(123.0); // set it to a random value
  141. // Allow a bit of inprecision. This test allows 5ms. That's ok, when running
  142. // on virtual machines.
  143. ptime max = min + millisec::time_duration(0,0,0,5);
  144. // Now wait some time. We want to confirm that the timestamp recorded is the
  145. // time the observation took place, not current time.
  146. sleep(1);
  147. FloatSample sample = b.getFloat();
  148. // Let's check that the timestamp is within (min,max) range.
  149. EXPECT_TRUE(min <= sample.second);
  150. EXPECT_TRUE(sample.second <= max);
  151. }
  152. // Checks whether an integer statistic can generate proper JSON structures.
  153. // See http://kea.isc.org/wiki/StatsDesign for details.
  154. TEST_F(ObservationTest, integerToJSON) {
  155. a.setValue(static_cast<uint64_t>(1234));
  156. std::string exp = "[ 1234, \""
  157. + Observation::ptimeToText(a.getInteger().second) + "\" ]";
  158. std::cout << a.getJSON()->str() << std::endl;
  159. EXPECT_EQ(exp, a.getJSON()->str());
  160. }
  161. // Checks whether a floating point statistic can generate proper JSON
  162. // structures. See http://kea.isc.org/wiki/StatsDesign for details.
  163. TEST_F(ObservationTest, floatToJSON) {
  164. // Let's use a value that converts easily to floating point.
  165. // No need to deal with infinite fractions in binary systems.
  166. b.setValue(1234.5);
  167. std::string exp = "[ 1234.5, \""
  168. + Observation::ptimeToText(b.getFloat().second) + "\" ]";
  169. std::cout << b.getJSON()->str() << std::endl;
  170. EXPECT_EQ(exp, b.getJSON()->str());
  171. }
  172. // Checks whether a time duration statistic can generate proper JSON structures.
  173. // See http://kea.isc.org/wiki/StatsDesign for details.
  174. TEST_F(ObservationTest, durationToJSON) {
  175. // 1 hour 2 minutes 3 seconds and 4 milliseconds
  176. c.setValue(time_duration(1,2,3,4));
  177. std::string exp = "[ \"01:02:03.000004\", \""
  178. + Observation::ptimeToText(c.getDuration().second) + "\" ]";
  179. std::cout << c.getJSON()->str() << std::endl;
  180. EXPECT_EQ(exp, c.getJSON()->str());
  181. }
  182. // Checks whether a string statistic can generate proper JSON structures.
  183. // See http://kea.isc.org/wiki/StatsDesign for details.
  184. TEST_F(ObservationTest, stringToJSON) {
  185. //
  186. d.setValue("Lorem ipsum dolor sit amet");
  187. std::string exp = "[ \"Lorem ipsum dolor sit amet\", \""
  188. + Observation::ptimeToText(d.getString().second) + "\" ]";
  189. std::cout << d.getJSON()->str() << std::endl;
  190. EXPECT_EQ(exp, d.getJSON()->str());
  191. }
  192. // Checks whether reset() resets the statistics properly.
  193. TEST_F(ObservationTest, reset) {
  194. a.reset(); // integer
  195. b.reset(); // float
  196. c.reset(); // duration
  197. d.reset(); // string
  198. EXPECT_EQ(0, a.getInteger().first);
  199. EXPECT_EQ(0.0, b.getFloat().first);
  200. EXPECT_EQ(time_duration(0,0,0,0), c.getDuration().first);
  201. EXPECT_EQ("", d.getString().first);
  202. }
  203. };