Fix some bugs when testing opensds ansible
[stor4nfv.git] / src / ceph / src / test / common / test_perf_histogram.cc
1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 &smarttab
3 /*
4  * Ceph - scalable distributed file system
5  *
6  * Copyright (C) 2017 OVH
7  *
8  * This is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public
10  * License version 2, as published by the Free Software
11  * Foundation.  See file COPYING.
12  *
13  */
14
15 #include "common/perf_histogram.h"
16
17 #include "gtest/gtest.h"
18
19 template <int DIM>
20 class PerfHistogramAccessor : public PerfHistogram<DIM> {
21 public:
22   typedef PerfHistogram<DIM> Base;
23
24   using Base::PerfHistogram;
25
26   static int64_t get_bucket_for_axis(
27       int64_t value, const PerfHistogramCommon::axis_config_d& axis_config) {
28     return Base::get_bucket_for_axis(value, axis_config);
29   }
30
31   static std::vector<std::pair<int64_t, int64_t>> get_axis_bucket_ranges(
32       const PerfHistogramCommon::axis_config_d& axis_config) {
33     return Base::get_axis_bucket_ranges(axis_config);
34   }
35
36   const typename Base::axis_config_d& get_axis_config(int num) {
37     return Base::m_axes_config[num];
38   }
39
40   template <typename F1, typename F2, typename F3>
41   void visit_values(F1 f1, F2 f2, F3 f3) {
42     Base::visit_values(f1, f2, f3);
43   }
44 };
45
46 TEST(PerfHistogram, GetBucketForAxis) {
47   PerfHistogramCommon::axis_config_d linear{
48       "", PerfHistogramCommon::SCALE_LINEAR, 100, 3, 4};
49
50   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(-1, linear));
51   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(0, linear));
52   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(99, linear));
53   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(100, linear));
54   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(101, linear));
55   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(102, linear));
56   ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(103, linear));
57   ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(105, linear));
58   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(106, linear));
59   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(108, linear));
60   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(109, linear));
61
62   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(
63                    std::numeric_limits<int64_t>::min(), linear));
64   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(
65                    std::numeric_limits<int64_t>::max(), linear));
66
67   PerfHistogramCommon::axis_config_d logarithmic{
68       "", PerfHistogramCommon::SCALE_LOG2, 100, 3, 5};
69
70   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(-1, logarithmic));
71   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(0, logarithmic));
72   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(99, logarithmic));
73   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(100, logarithmic));
74   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(101, logarithmic));
75   ASSERT_EQ(1, PerfHistogramAccessor<1>::get_bucket_for_axis(102, logarithmic));
76   ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(103, logarithmic));
77   ASSERT_EQ(2, PerfHistogramAccessor<1>::get_bucket_for_axis(105, logarithmic));
78   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(106, logarithmic));
79   ASSERT_EQ(3, PerfHistogramAccessor<1>::get_bucket_for_axis(111, logarithmic));
80   ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(112, logarithmic));
81   ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(124, logarithmic));
82
83   ASSERT_EQ(0, PerfHistogramAccessor<1>::get_bucket_for_axis(
84                    std::numeric_limits<int64_t>::min(), logarithmic));
85   ASSERT_EQ(4, PerfHistogramAccessor<1>::get_bucket_for_axis(
86                    std::numeric_limits<int64_t>::max(), logarithmic));
87 }
88
89 static const int XS = 5;
90 static const int YS = 7;
91
92 static const auto x_axis = PerfHistogramCommon::axis_config_d{
93     "x", PerfHistogramCommon::SCALE_LINEAR, 0, 1, XS};
94 static const auto y_axis = PerfHistogramCommon::axis_config_d{
95     "y", PerfHistogramCommon::SCALE_LOG2, 0, 1, YS};
96
97 TEST(PerfHistogram, ZeroedInitially) {
98   PerfHistogramAccessor<2> h{x_axis, y_axis};
99   for (int x = 0; x < XS; ++x) {
100     for (int y = 0; y < YS; ++y) {
101       ASSERT_EQ(0UL, h.read_bucket(x, y));
102     }
103   }
104 }
105
106 TEST(PerfHistogram, Copy) {
107   PerfHistogramAccessor<2> h1{x_axis, y_axis};
108   h1.inc_bucket(1, 1);
109   h1.inc_bucket(2, 3);
110   h1.inc_bucket(4, 5);
111
112   PerfHistogramAccessor<2> h2 = h1;
113
114   const int cx = 1;
115   const int cy = 2;
116
117   h1.inc_bucket(cx, cy);
118
119   // Axes configuration must be equal
120   for (int i = 0; i < 2; i++) {
121     const auto& ac1 = h1.get_axis_config(i);
122     const auto& ac2 = h2.get_axis_config(i);
123     ASSERT_EQ(ac1.m_name, ac2.m_name);
124     ASSERT_EQ(ac1.m_scale_type, ac2.m_scale_type);
125     ASSERT_EQ(ac1.m_min, ac2.m_min);
126     ASSERT_EQ(ac1.m_quant_size, ac2.m_quant_size);
127     ASSERT_EQ(ac1.m_buckets, ac2.m_buckets);
128   }
129
130   // second histogram must have histogram values equal to the first
131   // one at the time of copy
132   for (int x = 0; x < XS; x++) {
133     for (int y = 0; y < YS; y++) {
134       if (x == cx && y == cy) {
135         ASSERT_NE(h1.read_bucket(x, y), h2.read_bucket(x, y));
136       } else {
137         ASSERT_EQ(h1.read_bucket(x, y), h2.read_bucket(x, y));
138       }
139     }
140   }
141 }
142
143 TEST(PerfHistogram, SimpleValues) {
144   PerfHistogramAccessor<2> h{x_axis, y_axis};
145   ASSERT_EQ(0UL, h.read_bucket(1, 1));
146   h.inc(0, 0);
147   ASSERT_EQ(1UL, h.read_bucket(1, 1));
148
149   ASSERT_EQ(0UL, h.read_bucket(2, 2));
150   h.inc(1, 1);
151   ASSERT_EQ(1UL, h.read_bucket(2, 2));
152
153   ASSERT_EQ(0UL, h.read_bucket(3, 3));
154   h.inc(2, 2);
155   ASSERT_EQ(1UL, h.read_bucket(3, 3));
156
157   ASSERT_EQ(0UL, h.read_bucket(4, 3));
158   h.inc(3, 3);
159   ASSERT_EQ(1UL, h.read_bucket(4, 3));
160 }
161
162 TEST(PerfHistogram, OneBucketRange) {
163   auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(
164       PerfHistogramCommon::axis_config_d{"", PerfHistogramCommon::SCALE_LINEAR,
165                                          0, 1, 1});
166
167   ASSERT_EQ(1UL, ranges.size());
168   ASSERT_EQ(std::numeric_limits<int64_t>::min(), ranges[0].first);
169   ASSERT_EQ(std::numeric_limits<int64_t>::max(), ranges[0].second);
170 }
171
172 TEST(PerfHistogram, TwoBucketRange) {
173   auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(
174       PerfHistogramCommon::axis_config_d{"", PerfHistogramCommon::SCALE_LINEAR,
175                                          0, 1, 2});
176
177   ASSERT_EQ(2UL, ranges.size());
178   ASSERT_EQ(std::numeric_limits<int64_t>::min(), ranges[0].first);
179   ASSERT_EQ(-1, ranges[0].second);
180   ASSERT_EQ(0, ranges[1].first);
181   ASSERT_EQ(std::numeric_limits<int64_t>::max(), ranges[1].second);
182 }
183
184 TEST(PerfHistogram, LinearBucketRange) {
185   PerfHistogramCommon::axis_config_d ac{"", PerfHistogramCommon::SCALE_LINEAR,
186                                         100, 10, 15};
187   auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(ac);
188
189   for (size_t i = 0; i < ranges.size(); ++i) {
190     ASSERT_EQ(
191       static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].first, ac));
192     ASSERT_EQ(
193       static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].second, ac));
194   }
195
196   for (size_t i = 1; i < ranges.size(); ++i) {
197     ASSERT_EQ(ranges[i].first, ranges[i - 1].second + 1);
198   }
199 }
200
201 TEST(PerfHistogram, LogarithmicBucketRange) {
202   PerfHistogramCommon::axis_config_d ac{"", PerfHistogramCommon::SCALE_LOG2,
203                                         100, 10, 15};
204   auto ranges = PerfHistogramAccessor<1>::get_axis_bucket_ranges(ac);
205
206   for (size_t i = 0; i < ranges.size(); ++i) {
207     ASSERT_EQ(
208       static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].first, ac));
209     ASSERT_EQ(
210       static_cast<long>(i), PerfHistogramAccessor<1>::get_bucket_for_axis(ranges[i].second, ac));
211   }
212
213   for (size_t i = 1; i < ranges.size(); ++i) {
214     ASSERT_EQ(ranges[i].first, ranges[i - 1].second + 1);
215   }
216 }
217
218 TEST(PerfHistogram, AxisAddressing) {
219   PerfHistogramCommon::axis_config_d ac1{"", PerfHistogramCommon::SCALE_LINEAR,
220                                          0, 1, 7};
221   PerfHistogramCommon::axis_config_d ac2{"", PerfHistogramCommon::SCALE_LINEAR,
222                                          0, 1, 9};
223   PerfHistogramCommon::axis_config_d ac3{"", PerfHistogramCommon::SCALE_LINEAR,
224                                          0, 1, 11};
225
226   PerfHistogramAccessor<3> h{ac1, ac2, ac3};
227
228   h.inc(1, 2, 3);  // Should end up in buckets 2, 3, 4
229   h.inc_bucket(4, 5, 6);
230
231   std::vector<int64_t> rawValues;
232   h.visit_values([](int) {},
233                  [&rawValues](int64_t value) { rawValues.push_back(value); },
234                  [](int) {});
235
236   for (size_t i = 0; i < rawValues.size(); ++i) {
237     switch (i) {
238       case 4 + 11 * (3 + 9 * 2):
239       case 6 + 11 * (5 + 9 * 4):
240         ASSERT_EQ(1, rawValues[i]);
241         break;
242       default:
243         ASSERT_EQ(0, rawValues[i]);
244         break;
245     }
246   }
247 }