6a8422aa0f44c774a0cef4a6258e9dee5ca92e2e
[senf.git] / senf / Utils / Statistics.test.cc
1 // $Id$
2 //
3 // Copyright (C) 2008
4 // Fraunhofer Institute for Open Communication Systems (FOKUS)
5 // Competence Center NETwork research (NET), St. Augustin, GERMANY
6 //     Stefan Bund <g0dil@berlios.de>
7 //
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
12 //
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 // GNU General Public License for more details.
17 //
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the
20 // Free Software Foundation, Inc.,
21 // 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
22
23 /** \file
24     \brief Statistics unit tests */
25
26 //#include "Statistics.test.hh"
27 //#include "Statistics.test.ih"
28
29 // Custom includes
30 #include "Statistics.hh"
31 #include "StatisticsTargets.hh"
32 #include <boost/tokenizer.hpp>
33 #include <boost/iterator/transform_iterator.hpp>
34 #include <boost/iterator/filter_iterator.hpp>
35
36 #include "auto_unit_test.hh"
37 #include <boost/test/test_tools.hpp>
38 #include <boost/test/floating_point_comparison.hpp>
39
40 #define prefix_
41 ///////////////////////////////cc.p////////////////////////////////////////
42
43 namespace {
44
45     struct GetRank
46     {
47         typedef senf::Collector const & first_argument_type;
48         typedef unsigned result_type;
49         result_type operator()(first_argument_type arg) const
50             { return arg.rank(); }
51     };
52
53     struct splitFloats
54     {
55         typedef boost::char_separator<char> Separator;
56         typedef boost::tokenizer<Separator> Tokenizer;
57         struct Pred {
58             bool operator()(std::string const & s) const
59                 { try { boost::lexical_cast<double>(s); return true; }
60                     catch (std::bad_cast &) { return false; } }
61         };
62         typedef boost::filter_iterator<Pred,Tokenizer::iterator> FilterIterator;
63         struct Trafo {
64             typedef double result_type;
65             result_type operator()(std::string const & s) const
66                 { return boost::lexical_cast<double>(s); }
67         };
68         typedef boost::transform_iterator<Trafo,FilterIterator> TransformIterator;
69
70         typedef TransformIterator iterator;
71         typedef TransformIterator const_iterator;
72
73         splitFloats(std::string const & s) : s_ (s), sep_ (" \n"), tok_ (s_, sep_) {}
74         TransformIterator begin() const
75             { return TransformIterator(FilterIterator(tok_.begin(), tok_.end())); }
76         TransformIterator end() const
77             { return TransformIterator(FilterIterator(tok_.end(), tok_.end())); }
78
79         std::string s_;
80         Separator sep_;
81         Tokenizer tok_;
82     };
83
84     template <class R1, class R2>
85     void CHECK_CLOSE_RANGES(R1 const & r1, R2 const & r2, double delta)
86     {
87         typedef typename boost::range_const_iterator<R1>::type I1;
88         typedef typename boost::range_const_iterator<R2>::type I2;
89
90         I1 i1 (boost::begin(r1));
91         I1 i1_end (boost::end(r1));
92         I2 i2 (boost::begin(r2));
93         I2 i2_end (boost::end(r2));
94
95         for (; i1 != i1_end && i2 != i2_end; ++i1, ++i2) {
96             BOOST_CHECK_CLOSE(*i1, *i2, delta);
97         }
98
99         BOOST_CHECK( i1 == i1_end );
100         BOOST_CHECK( i2 == i2_end );
101     }
102 }
103
104 #define CHECK_STATS(a, b) CHECK_CLOSE_RANGES(splitFloats(a),splitFloats(b),0.001f)
105 #define CHECK_STATS_STR(a,b) BOOST_CHECK_EQUAL(a,b)
106
107 SENF_AUTO_UNIT_TEST(statistics)
108 {
109     senf::Statistics stats;
110     senf::log::StringTarget statslog;
111
112     statslog.tag("");
113     statslog.showTime(false);
114     statslog.showArea(false);
115     statslog.showLevel(false);
116     statslog.route<senf::StatisticsStream>();
117
118     stats
119             .output(2u).connect(
120                 senf::StatisticsLogger("level0"))
121         .collect(4u)
122             .output().connect(
123                 senf::StatisticsLogger("level1"))
124             .output(3u).connect(
125                 senf::StatisticsLogger("averaged1"))
126         .collect(3u)
127         .collect(2u)
128             .output().connect(
129                 senf::StatisticsLogger("level3"));
130
131     unsigned children1[] = { 4u };
132     BOOST_CHECK_EQUAL_COLLECTIONS(
133         boost::make_transform_iterator(stats.collectors().begin(), GetRank()),
134         boost::make_transform_iterator(stats.collectors().end(), GetRank()),
135         children1, children1 + sizeof(children1)/sizeof(children1[0]) );
136
137     unsigned children2[] = { 3u };
138     BOOST_CHECK_EQUAL_COLLECTIONS(
139         boost::make_transform_iterator(stats[4].collectors().begin(), GetRank()),
140         boost::make_transform_iterator(stats[4].collectors().end(), GetRank()),
141         children2, children2 + sizeof(children2)/sizeof(children2[0]) );
142
143     unsigned children3[] = { 2u };
144     BOOST_CHECK_EQUAL_COLLECTIONS(
145         boost::make_transform_iterator(stats[4][3].collectors().begin(), GetRank()),
146         boost::make_transform_iterator(stats[4][3].collectors().end(), GetRank()),
147         children3, children3 + sizeof(children3)/sizeof(children3[0]) );
148
149     float values[][3] = {
150         { -1.0f,  2.3f,  2.5f }, {  0.3f,  2.4f,  3.8f }, { -1.1f, -0.3f,  0.0f },
151         { -0.3f,  3.2f,  3.3f }, {  1.0f,  1.1f,  1.1f }, {  0.5f,  0.5f,  0.5f },
152         {  0.0f,  0.0f,  0.0f }, { -2.0f, -1.8f, -1.0f }, {  0.0f,  2.3f,  2.4f },
153         {  0.4f,  1.2f,  2.0f }, { -1.0f,  2.3f,  2.5f }, {  0.3f,  2.4f,  3.8f },
154         { -1.1f, -0.3f,  0.0f }, { -0.3f,  3.2f,  3.3f }, {  1.0f,  1.1f,  1.1f },
155         {  0.5f,  0.5f,  0.5f }, {  0.0f,  0.0f,  0.0f }, { -2.0f, -1.8f, -1.0f },
156         {  0.0f,  2.3f,  2.4f }, {  0.4f,  1.2f,  2.0f }, { -1.0f,  2.3f,  2.5f },
157         {  0.3f,  2.4f,  3.8f }, { -1.1f, -0.3f,  0.0f }, { -0.3f,  3.2f,  3.3f },
158         {  1.0f,  1.1f,  1.1f }, {  0.5f,  0.5f,  0.5f }, {  0.0f,  0.0f,  0.0f },
159         { -2.0f, -1.8f, -1.0f }, {  0.0f,  2.3f,  2.4f }, {  0.4f,  1.2f,  4.0f } };
160     // 30 entries
161     //   -> 30 calls of stats()
162     //         (rest 2)
163     //         -> 7 calls of stats[4]()
164     //              (rest 1)
165     //              -> 2 calls of stats[4][3]()
166     //                   (rest 0)
167     //                   -> 1 call of stats[4][3][2]
168
169     for (unsigned i (0); i < sizeof(values)/sizeof(values[0]); ++i)
170         stats(values[i][0], values[i][1], values[i][2]);
171
172     BOOST_CHECK_CLOSE( stats.min(), 0.4f, .001f );
173     BOOST_CHECK_CLOSE( stats.avg(), 1.2f, .001f );
174     BOOST_CHECK_CLOSE( stats.max(), 4.0f, .001f );
175     BOOST_CHECK_CLOSE( stats.dev(), 0.0f, .001f );
176
177     BOOST_CHECK_CLOSE( stats[4].min(), -2.0f, .001f );
178     BOOST_CHECK_CLOSE( stats[4].avg(), -0.05f, .001f );
179     BOOST_CHECK_CLOSE( stats[4].max(), 1.1f, .001f );
180     BOOST_CHECK_CLOSE( stats[4].dev(), 1.08282f, .001f );
181
182     BOOST_CHECK_CLOSE( stats[4][3].min(), -2.0f, .001f );
183     BOOST_CHECK_CLOSE( stats[4][3].avg(), 1.15f, .001f );
184     BOOST_CHECK_CLOSE( stats[4][3].max(),  3.8f, .001f );
185
186     CHECK_STATS( statslog.str(),
187                  "level0 -1 2.3 2.5 0\n"
188                  "level0 -0.35 2.35 3.15 0\n"
189                  "level0 -0.4 1.05 1.9 0\n"
190                  "level0 -0.7 1.45 1.65 0\n"
191                  "level1 -1.1 1.9 3.8 1.31719\n"
192                  "averaged1 -1.1 1.9 3.8 1.31719\n"
193                  "level0 0.35 2.15 2.2 0\n"
194                  "level0 0.75 0.8 0.8 0\n"
195                  "level0 0.25 0.25 0.25 0\n"
196                  "level0 -1 -0.9 -0.5 0\n"
197                  "level1 -2 -0.05 1.1 1.08282\n"
198                  "averaged1 -1.55 0.925 2.45 1.20001\n"
199                  "level0 -1 0.25 0.7 0\n"
200                  "level0 0.2 1.75 2.2 0\n"
201                  "level0 -0.3 1.75 2.25 0\n"
202                  "level0 -0.35 2.35 3.15 0\n"
203                  "level1 -1 2.05 3.8 0.492442\n"
204                  "averaged1 -1.36667 1.3 2.9 0.964152\n"
205                  "level0 -0.4 1.05 1.9 0\n"
206                  "level0 -0.7 1.45 1.65 0\n"
207                  "level0 0.35 2.15 2.2 0\n"
208                  "level0 0.75 0.8 0.8 0\n"
209                  "level1 -1.1 1.125 3.3 1.29687\n"
210                  "averaged1 -1.36667 1.04167 2.73333 0.957378\n"
211                  "level0 0.25 0.25 0.25 0\n"
212                  "level0 -1 -0.9 -0.5 0\n"
213                  "level0 -1 0.25 0.7 0\n"
214                  "level0 0.2 1.75 2.2 0\n"
215                  "level1 -2 0.425 2.4 1.52049\n"
216                  "averaged1 -1.36667 1.2 3.16667 1.10327\n"
217                  "level0 -0.3 1.75 2.25 0\n"
218                  "level0 -0.35 2.35 3.15 0\n"
219                  "level0 -0.4 1.05 1.9 0\n"
220                  "level0 -0.7 1.45 1.65 0\n"
221                  "level1 -1.1 1.9 3.8 1.31719\n"
222                  "averaged1 -1.4 1.15 3.16667 1.37818\n"
223                  "level3 -2 1.225 3.8 1.45752\n"
224                  "level0 0.35 2.15 2.2 0\n"
225                  "level0 0.75 0.8 0.8 0\n"
226                  "level0 0.25 0.25 0.25 0\n"
227                  "level0 -1 -0.9 -0.5 0\n"
228                  "level1 -2 -0.05 1.1 1.08282\n"
229                  "averaged1 -1.7 0.758333 2.43333 1.30683\n"
230                  "level0 -1 0.25 0.7 0\n"
231                  "level0 0.2 1.75 3.2 0\n" );
232
233     statslog.clear();
234     stats(20, 10.f, 10.f, 10.f, 0.f);
235     stats(4, 0.f, 0.f, 0.f, 0.f);
236
237     CHECK_STATS( statslog.str(),
238                  "level0 5.2 5.6 7 0\n"
239                  "level0 10 10 10 0\n"
240                  "level0 10 10 10 0\n"
241                  "level0 10 10 10 0\n"
242                  "level0 10 10 10 0\n"
243                  "level0 10 10 10 0\n"
244                  "level0 10 10 10 0\n"
245                  "level0 10 10 10 0\n"
246                  "level0 10 10 10 0\n"
247                  "level0 10 10 10 0\n"
248                  "level0 10 10 10 0\n"
249                  "level0 10 10 10 0\n"
250                  "level0 10 10 10 0\n"
251                  "level0 10 10 10 0\n"
252                  "level0 10 10 10 0\n"
253                  "level0 10 10 10 0\n"
254                  "level0 10 10 10 0\n"
255                  "level0 10 10 10 0\n"
256                  "level0 10 10 10 0\n"
257                  "level0 10 10 10 0\n"
258                  "level1 0 5.875 10 8.19554\n"
259                  "averaged1 -1.03333 2.575 4.96667 3.53185\n"
260                  "level1 10 10 10 0\n"
261                  "averaged1 2.66667 5.275 7.03333 3.09279\n"
262                  "level1 10 10 10 0\n"
263                  "averaged1 6.66667 8.625 10 2.73185\n"
264                  "level1 10 10 10 0\n"
265                  "averaged1 10 10 10 0\n"
266                  "level1 10 10 10 0\n"
267                  "averaged1 10 10 10 0\n"
268                  "level3 -2 7.6375 10 5.04759\n"
269                  "level0 5 5 5 0\n"
270                  "level0 0 0 0 0\n"
271                  "level0 0 0 0 0\n"
272                  "level0 0 0 0 0\n"
273                  "level1 0 5 10 8.66025\n"
274                  "averaged1 6.66667 8.33333 10 2.88675\n" );
275
276 }
277
278 ///////////////////////////////cc.e////////////////////////////////////////
279 #undef prefix_
280
281 \f
282 // Local Variables:
283 // mode: c++
284 // fill-column: 100
285 // comment-column: 40
286 // c-file-style: "senf"
287 // indent-tabs-mode: nil
288 // ispell-local-dictionary: "american"
289 // compile-command: "scons -u test"
290 // End: