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