1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtTest module of the Qt Toolkit.
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.
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.
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.
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.
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();