1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtTest module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include <QtTest/qbenchmark.h>
43 #include <QtTest/private/qbenchmark_p.h>
44 #include <QtTest/private/qbenchmarkmetric_p.h>
46 #include <QtCore/qprocess.h>
47 #include <QtCore/qdir.h>
48 #include <QtCore/qset.h>
49 #include <QtCore/qdebug.h>
53 QBenchmarkGlobalData *QBenchmarkGlobalData::current;
55 QBenchmarkGlobalData::QBenchmarkGlobalData()
59 , medianIterationCount(-1)
61 , verboseOutput(false)
67 QBenchmarkGlobalData::~QBenchmarkGlobalData()
70 QBenchmarkGlobalData::current = 0;
73 void QBenchmarkGlobalData::setMode(Mode mode)
79 measurer = createMeasurer();
82 QBenchmarkMeasurerBase * QBenchmarkGlobalData::createMeasurer()
84 QBenchmarkMeasurerBase *measurer = 0;
86 #ifdef QTESTLIB_USE_VALGRIND
87 } else if (mode_ == CallgrindChildProcess || mode_ == CallgrindParentProcess) {
88 measurer = new QBenchmarkCallgrindMeasurer;
90 #ifdef HAVE_TICK_COUNTER
91 } else if (mode_ == TickCounter) {
92 measurer = new QBenchmarkTickMeasurer;
94 } else if (mode_ == EventCounter) {
95 measurer = new QBenchmarkEvent;
97 measurer = new QBenchmarkTimeMeasurer;
103 int QBenchmarkGlobalData::adjustMedianIterationCount()
105 if (medianIterationCount != -1) {
106 return medianIterationCount;
108 return measurer->adjustMedianCount(1);
113 QBenchmarkTestMethodData *QBenchmarkTestMethodData::current;
115 QBenchmarkTestMethodData::QBenchmarkTestMethodData()
116 :resultAccepted(false), runOnce(false), iterationCount(-1)
120 QBenchmarkTestMethodData::~QBenchmarkTestMethodData()
122 QBenchmarkTestMethodData::current = 0;
125 void QBenchmarkTestMethodData::beginDataRun()
127 iterationCount = adjustIterationCount(1);
130 void QBenchmarkTestMethodData::endDataRun()
134 int QBenchmarkTestMethodData::adjustIterationCount(int suggestion)
136 // Let the -iterations option override the measurer.
137 if (QBenchmarkGlobalData::current->iterationCount != -1) {
138 iterationCount = QBenchmarkGlobalData::current->iterationCount;
140 iterationCount = QBenchmarkGlobalData::current->measurer->adjustIterationCount(suggestion);
143 return iterationCount;
146 void QBenchmarkTestMethodData::setResult(
147 qreal value, QTest::QBenchmarkMetric metric, bool setByMacro)
149 bool accepted = false;
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)
156 else if (QBenchmarkTestMethodData::current->runOnce || !setByMacro) {
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);
166 accepted = QBenchmarkGlobalData::current->measurer->isMeasurementAccepted(value);
168 // Accept the result or double the number of iterations.
170 resultAccepted = true;
174 this->result = QBenchmarkResult(
175 QBenchmarkGlobalData::current->context, value, iterationCount, metric, setByMacro);
179 \class QTest::QBenchmarkIterationController
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.
189 QTest::QBenchmarkIterationController::QBenchmarkIterationController(RunMode runMode)
192 if (runMode == RunOnce)
193 QBenchmarkTestMethodData::current->runOnce = true;
194 QTest::beginBenchmarkMeasurement();
197 QTest::QBenchmarkIterationController::QBenchmarkIterationController()
200 QTest::beginBenchmarkMeasurement();
205 QTest::QBenchmarkIterationController::~QBenchmarkIterationController()
207 const qreal result = QTest::endBenchmarkMeasurement();
208 QBenchmarkTestMethodData::current->setResult(result, QBenchmarkGlobalData::current->measurer->metricType());
213 bool QTest::QBenchmarkIterationController::isDone()
215 if (QBenchmarkTestMethodData::current->runOnce)
217 return i >= QTest::iterationCount();
222 void QTest::QBenchmarkIterationController::next()
229 int QTest::iterationCount()
231 return QBenchmarkTestMethodData::current->iterationCount;
236 void QTest::setIterationCountHint(int count)
238 QBenchmarkTestMethodData::current->adjustIterationCount(count);
243 void QTest::setIterationCount(int count)
245 QBenchmarkTestMethodData::current->iterationCount = count;
246 QBenchmarkTestMethodData::current->resultAccepted = true;
251 void QTest::beginBenchmarkMeasurement()
253 QBenchmarkGlobalData::current->measurer->start();
254 // the clock is ticking after the line above, don't add code here.
259 quint64 QTest::endBenchmarkMeasurement()
261 // the clock is ticking before the line below, don't add code here.
262 return QBenchmarkGlobalData::current->measurer->stop();
266 Sets the benchmark result for this test function to \a result.
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.
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.
277 Note that the -iterations command line argument has no effect
278 on test functions without the QBENCHMARK macro.
282 void QTest::setBenchmarkResult(qreal result, QTest::QBenchmarkMetric metric)
284 QBenchmarkTestMethodData::current->setResult(result, metric, false);
287 template <typename T>
288 typename T::value_type qAverage(const T &container)
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();