Fix binary incompatibility between openssl versions
[profile/ivi/qtbase.git] / src / testlib / qbenchmark.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
5 **
6 ** This file is part of the QtTest module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia.  For licensing terms and
14 ** conditions see http://qt.digia.com/licensing.  For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights.  These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file.  Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include <QtTest/qbenchmark.h>
43 #include <QtTest/private/qbenchmark_p.h>
44 #include <QtTest/private/qbenchmarkmetric_p.h>
45
46 #include <QtCore/qprocess.h>
47 #include <QtCore/qdir.h>
48 #include <QtCore/qset.h>
49 #include <QtCore/qdebug.h>
50
51 QT_BEGIN_NAMESPACE
52
53 QBenchmarkGlobalData *QBenchmarkGlobalData::current;
54
55 QBenchmarkGlobalData::QBenchmarkGlobalData()
56     : measurer(0)
57     , walltimeMinimum(-1)
58     , iterationCount(-1)
59     , medianIterationCount(-1)
60     , createChart(false)
61     , verboseOutput(false)
62     , mode_(WallTime)
63 {
64     setMode(mode_);
65 }
66
67 QBenchmarkGlobalData::~QBenchmarkGlobalData()
68 {
69     delete measurer;
70     QBenchmarkGlobalData::current = 0;
71 }
72
73 void QBenchmarkGlobalData::setMode(Mode mode)
74 {
75     mode_ = mode;
76
77     if (measurer)
78         delete measurer;
79     measurer = createMeasurer();
80 }
81
82 QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
83 {
84     QBenchmarkMeasurerBase *measurer = 0;
85     if (0) {
86 #ifdef QTESTLIB_USE_VALGRIND
87     } else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
88         measurer = new QBenchmarkCallgrindMeasurer;
89 #endif
90 #ifdef HAVE_TICK_COUNTER
91     } else if (mode_ == TickCounter) {
92         measurer = new QBenchmarkTickMeasurer;
93 #endif
94     } else if (mode_ == EventCounter) {
95         measurer = new QBenchmarkEvent;
96     } else {
97         measurer =  new QBenchmarkTimeMeasurer;
98     }
99     measurer->init();
100     return measurer;
101 }
102
103 int QBenchmarkGlobalData::adjustMedianIterationCount()
104 {
105     if (medianIterationCount != -1) {
106         return medianIterationCount;
107     } else {
108         return measurer->adjustMedianCount(1);
109     }
110 }
111
112
113 QBenchmarkTestMethodData *QBenchmarkTestMethodData::current;
114
115 QBenchmarkTestMethodData::QBenchmarkTestMethodData()
116 :resultAccepted(false), runOnce(false), iterationCount(-1)
117 {
118 }
119
120 QBenchmarkTestMethodData::~QBenchmarkTestMethodData()
121 {
122     QBenchmarkTestMethodData::current = 0;
123 }
124
125 void QBenchmarkTestMethodData::beginDataRun()
126 {
127     iterationCount = adjustIterationCount(1);
128 }
129
130 void QBenchmarkTestMethodData::endDataRun()
131 {
132 }
133
134 int QBenchmarkTestMethodData::adjustIterationCount(int suggestion)
135 {
136     // Let the -iterations option override the measurer.
137     if (QBenchmarkGlobalData::current->iterationCount != -1) {
138         iterationCount = QBenchmarkGlobalData::current->iterationCount;
139     } else {
140         iterationCount = QBenchmarkGlobalData::current->measurer->adjustIterationCount(suggestion);
141     }
142
143     return iterationCount;
144 }
145
146 void QBenchmarkTestMethodData::setResult(
147     qreal value, QTest::QBenchmarkMetric metric, bool setByMacro)
148 {
149     bool accepted = false;
150
151     // Always accept the result if the iteration count has been
152     // specified on the command line with -iterations.
153     if (QBenchmarkGlobalData::current->iterationCount != -1)
154         accepted = true;
155
156     else if (QBenchmarkTestMethodData::current->runOnce || !setByMacro) {
157         iterationCount = 1;
158         accepted = true;
159     }
160
161     // Test the result directly without calling the measurer if the minimum time
162     // has been specified on the command line with -minimumvalue.
163     else if (QBenchmarkGlobalData::current->walltimeMinimum != -1)
164         accepted = (value > QBenchmarkGlobalData::current->walltimeMinimum);
165     else
166         accepted = QBenchmarkGlobalData::current->measurer->isMeasurementAccepted(value);
167
168     // Accept the result or double the number of iterations.
169     if (accepted)
170         resultAccepted = true;
171     else
172         iterationCount *= 2;
173
174     this->result = QBenchmarkResult(
175         QBenchmarkGlobalData::current->context, value, iterationCount, metric, setByMacro);
176 }
177
178 /*!
179     \class QTest::QBenchmarkIterationController
180     \internal
181
182     The QBenchmarkIterationController class is used by the QBENCHMARK macro to
183     drive the benchmarking loop. It is repsonsible for starting and stopping
184     the timing measurements as well as calling the result reporting functions.
185 */
186
187 /*! \internal
188 */
189 QTest::QBenchmarkIterationController::QBenchmarkIterationController(RunMode runMode)
190 {
191     i = 0;
192     if (runMode == RunOnce)
193         QBenchmarkTestMethodData::current->runOnce = true;
194     QTest::beginBenchmarkMeasurement();
195 }
196
197 QTest::QBenchmarkIterationController::QBenchmarkIterationController()
198 {
199     i = 0;
200     QTest::beginBenchmarkMeasurement();
201 }
202
203 /*! \internal
204 */
205 QTest::QBenchmarkIterationController::~QBenchmarkIterationController()
206 {
207     const qreal result = QTest::endBenchmarkMeasurement();
208     QBenchmarkTestMethodData::current->setResult(result, QBenchmarkGlobalData::current->measurer->metricType());
209 }
210
211 /*! \internal
212 */
213 bool QTest::QBenchmarkIterationController::isDone()
214 {
215     if (QBenchmarkTestMethodData::current->runOnce)
216         return i > 0;
217     return i >= QTest::iterationCount();
218 }
219
220 /*! \internal
221 */
222 void QTest::QBenchmarkIterationController::next()
223 {
224     ++i;
225 }
226
227 /*! \internal
228 */
229 int QTest::iterationCount()
230 {
231     return QBenchmarkTestMethodData::current->iterationCount;
232 }
233
234 /*! \internal
235 */
236 void QTest::setIterationCountHint(int count)
237 {
238     QBenchmarkTestMethodData::current->adjustIterationCount(count);
239 }
240
241 /*! \internal
242 */
243 void QTest::setIterationCount(int count)
244 {
245     QBenchmarkTestMethodData::current->iterationCount = count;
246     QBenchmarkTestMethodData::current->resultAccepted = true;
247 }
248
249 /*! \internal
250 */
251 void QTest::beginBenchmarkMeasurement()
252 {
253     QBenchmarkGlobalData::current->measurer->start();
254     // the clock is ticking after the line above, don't add code here.
255 }
256
257 /*! \internal
258 */
259 quint64 QTest::endBenchmarkMeasurement()
260 {
261     // the clock is ticking before the line below, don't add code here.
262     return QBenchmarkGlobalData::current->measurer->stop();
263 }
264
265 /*!
266     Sets the benchmark result for this test function to \a result.
267
268     Use this function if you want to report benchmark results without
269     using the QBENCHMARK macro. Use \a metric to specify how QTestLib
270     should interpret the results.
271
272     The context for the result will be the test function name and any
273     data tag from the _data function. This function can only be called
274     once in each test function, subsequent calls will replace the
275     earlier reported results.
276
277     Note that the -iterations command line argument has no effect
278     on test functions without the QBENCHMARK macro.
279
280     \since 4.7
281 */
282 void QTest::setBenchmarkResult(qreal result, QTest::QBenchmarkMetric metric)
283 {
284     QBenchmarkTestMethodData::current->setResult(result, metric, false);
285 }
286
287 template <typename T>
288 typename T::value_type qAverage(const T &container)
289 {
290     typename T::const_iterator it = container.constBegin();
291     typename T::const_iterator end = container.constEnd();
292     typename T::value_type acc = typename T::value_type();
293     int count = 0;
294     while (it != end) {
295         acc += *it;
296         ++it;
297         ++count;
298     }
299     return acc / count;
300 }
301
302 QT_END_NAMESPACE