forked from qt-creator/qt-creator
Merge remote-tracking branch 'origin/4.2'
Conflicts: qbs/modules/qtc/qtc.qbs qtcreator.pri src/plugins/projectexplorer/kitinformation.cpp Change-Id: I94299b069418586db97d1d596a252794e4037556
This commit is contained in:
370
src/plugins/valgrind/unit_testdata/memcheck-output-sample1.xml
Normal file
370
src/plugins/valgrind/unit_testdata/memcheck-output-sample1.xml
Normal file
@@ -0,0 +1,370 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<valgrindoutput>
|
||||
|
||||
<protocolversion>4</protocolversion>
|
||||
<protocoltool>memcheck</protocoltool>
|
||||
|
||||
<preamble>
|
||||
<line>Memcheck, a memory error detector</line>
|
||||
<line>Copyright (C) 2002-2009, and GNU GPL'd, by Julian Seward et al.</line>
|
||||
<line>Using Valgrind-3.6.0.SVN-Debian and LibVEX; rerun with -h for copyright info</line>
|
||||
<line>Command: kate</line>
|
||||
</preamble>
|
||||
|
||||
<pid>22733</pid>
|
||||
<ppid>17584</ppid>
|
||||
<tool>memcheck</tool>
|
||||
|
||||
<args>
|
||||
<vargv>
|
||||
<exe>/usr/bin/valgrind.bin</exe>
|
||||
<arg>--suppressions=/usr/lib/valgrind/debian-libc6-dbg.supp</arg>
|
||||
<arg>--xml=yes</arg>
|
||||
<arg>--xml-file=test.xml</arg>
|
||||
<arg>--track-origins=yes</arg>
|
||||
</vargv>
|
||||
<argv>
|
||||
<exe>kate</exe>
|
||||
</argv>
|
||||
</args>
|
||||
|
||||
<status>
|
||||
<state>RUNNING</state>
|
||||
<time>00:00:00:00.241 </time>
|
||||
</status>
|
||||
|
||||
<error>
|
||||
<unique>0x9</unique>
|
||||
<tid>1</tid>
|
||||
<kind>InvalidRead</kind>
|
||||
<what>Invalid read of size 4</what>
|
||||
<stack>
|
||||
<frame>
|
||||
<ip>0x6E47964</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QFrame::frameStyle() const</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/widgets</dir>
|
||||
<file>qframe.cpp</file>
|
||||
<line>252</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x118F2AF7</ip>
|
||||
<obj>/usr/lib/kde4/plugins/styles/oxygen.so</obj>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A81671</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QWidget::event(QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qwidget.cpp</file>
|
||||
<line>8273</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A2B6EB</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplicationPrivate::notify_helper(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication.cpp</file>
|
||||
<line>4396</line>
|
||||
</frame>
|
||||
<!--
|
||||
<frame>
|
||||
<ip>0x6A311DC</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplication::notify(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication.cpp</file>
|
||||
<line>4277</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6443535</ip>
|
||||
<obj>/usr/lib/libkdeui.so.5.5.0</obj>
|
||||
<fn>KApplication::notify(QObject*, QEvent*)</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x83690AB</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QCoreApplication::notifyInternal(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/kernel</dir>
|
||||
<file>qcoreapplication.cpp</file>
|
||||
<line>732</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A77600</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QWidget::ensurePolished() const</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/../../include/QtCore/../../src/corelib/kernel</dir>
|
||||
<file>qcoreapplication.h</file>
|
||||
<line>215</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A869B2</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QWidget::setVisible(bool)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qwidget.cpp</file>
|
||||
<line>7539</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x18B1ED35</ip>
|
||||
<obj>/home/milian/projects/compiled/kde4/lib/libkatepartinterfaces.so.4.5.0</obj>
|
||||
<fn>QWidget::show()</fn>
|
||||
<dir>/usr/include/qt4/QtGui</dir>
|
||||
<file>qwidget.h</file>
|
||||
<line>487</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x18C23615</ip>
|
||||
<obj>/home/milian/projects/compiled/kde4/lib/libkatepartinterfaces.so.4.5.0</obj>
|
||||
<fn>KateViewInternal::KateViewInternal(KateView*)</fn>
|
||||
<dir>/home/milian/projects/kde4/kate/part/view</dir>
|
||||
<file>kateviewinternal.cpp</file>
|
||||
<line>144</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x18C0DA68</ip>
|
||||
<obj>/home/milian/projects/compiled/kde4/lib/libkatepartinterfaces.so.4.5.0</obj>
|
||||
<fn>KateView::KateView(KateDocument*, QWidget*)</fn>
|
||||
<dir>/home/milian/projects/kde4/kate/part/view</dir>
|
||||
<file>kateview.cpp</file>
|
||||
<line>136</line>
|
||||
</frame>
|
||||
-->
|
||||
</stack>
|
||||
<auxwhat>Address 0x11527cb8 is not stack'd, malloc'd or (recently) free'd</auxwhat>
|
||||
</error>
|
||||
|
||||
|
||||
<status>
|
||||
<state>FINISHED</state>
|
||||
<time>00:00:01:49.732 </time>
|
||||
</status>
|
||||
|
||||
<error>
|
||||
<unique>0x13</unique>
|
||||
<tid>1</tid>
|
||||
<kind>Leak_PossiblyLost</kind>
|
||||
<xwhat>
|
||||
<text>2 bytes in 1 blocks are possibly lost in loss record 2 of 2,003</text>
|
||||
<leakedbytes>2</leakedbytes>
|
||||
<leakedblocks>1</leakedblocks>
|
||||
</xwhat>
|
||||
<stack>
|
||||
<frame>
|
||||
<ip>0x4C284A8</ip>
|
||||
<obj>/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so</obj>
|
||||
<fn>malloc</fn>
|
||||
<dir>/build/buildd/valgrind-3.6.0~svn20100212/coregrind/m_replacemalloc</dir>
|
||||
<file>vg_replace_malloc.c</file>
|
||||
<line>236</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0xD4D7754</ip>
|
||||
<obj>/lib/libglib-2.0.so.0.2400.1</obj>
|
||||
<fn>g_malloc</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0xD4EF11D</ip>
|
||||
<obj>/lib/libglib-2.0.so.0.2400.1</obj>
|
||||
<fn>g_strdup</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0xD503DC4</ip>
|
||||
<obj>/lib/libglib-2.0.so.0.2400.1</obj>
|
||||
<fn>g_get_language_names</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0xD4F89A9</ip>
|
||||
<obj>/lib/libglib-2.0.so.0.2400.1</obj>
|
||||
<fn>g_thread_init_glib</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x8396569</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QEventDispatcherGlibPrivate::QEventDispatcherGlibPrivate(_GMainContext*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/kernel</dir>
|
||||
<file>qeventdispatcher_glib.cpp</file>
|
||||
<line>299</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6ADDBEE</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QGuiEventDispatcherGlibPrivate::QGuiEventDispatcherGlibPrivate()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qguieventdispatcher_glib.cpp</file>
|
||||
<line>171</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6ADDCDD</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QGuiEventDispatcherGlib::QGuiEventDispatcherGlib(QObject*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qguieventdispatcher_glib.cpp</file>
|
||||
<line>186</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6AA5152</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplicationPrivate::createEventDispatcher()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication_x11.cpp</file>
|
||||
<line>605</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x836D069</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QCoreApplication::init()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/kernel</dir>
|
||||
<file>qcoreapplication.cpp</file>
|
||||
<line>552</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x836D134</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QCoreApplication::QCoreApplication(QCoreApplicationPrivate&)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/kernel</dir>
|
||||
<file>qcoreapplication.cpp</file>
|
||||
<line>477</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A3815A</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplication::QApplication(int&, char**, bool, int)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication.cpp</file>
|
||||
<line>745</line>
|
||||
</frame>
|
||||
</stack>
|
||||
</error>
|
||||
|
||||
<error>
|
||||
<unique>0x7e4</unique>
|
||||
<tid>1</tid>
|
||||
<kind>Leak_DefinitelyLost</kind>
|
||||
<xwhat>
|
||||
<text>544,542 (56 direct, 544,486 indirect) bytes in 1 blocks are definitely lost in loss record 2,003 of 2,003</text>
|
||||
<leakedbytes>544542</leakedbytes>
|
||||
<leakedblocks>1</leakedblocks>
|
||||
</xwhat>
|
||||
<stack>
|
||||
<frame>
|
||||
<ip>0x4C284A8</ip>
|
||||
<obj>/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so</obj>
|
||||
<fn>malloc</fn>
|
||||
<dir>/build/buildd/valgrind-3.6.0~svn20100212/coregrind/m_replacemalloc</dir>
|
||||
<file>vg_replace_malloc.c</file>
|
||||
<line>236</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x82A1A6C</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QMapData::node_create(QMapData::Node**, int, int)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/tools</dir>
|
||||
<file>qmap.cpp</file>
|
||||
<line>140</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x8336F68</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QMap<QSettingsKey, QVariant>::detach_helper()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/../../include/QtCore/../../src/corelib/tools</dir>
|
||||
<file>qmap.h</file>
|
||||
<line>449</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x832C564</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QConfFile::mergedKeyMap() const</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/../../include/QtCore/../../src/corelib/tools</dir>
|
||||
<file>qmap.h</file>
|
||||
<line>202</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x833305A</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QConfFileSettingsPrivate::syncConfFile(int)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/io</dir>
|
||||
<file>qsettings.cpp</file>
|
||||
<line>1569</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x8333D5B</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QConfFileSettingsPrivate::sync()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/io</dir>
|
||||
<file>qsettings.cpp</file>
|
||||
<line>1386</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x83260D9</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QSettingsPrivate::update()</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/io</dir>
|
||||
<file>qsettings.cpp</file>
|
||||
<line>415</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x83267C7</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QSettings::event(QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/io</dir>
|
||||
<file>qsettings.cpp</file>
|
||||
<line>3326</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A2B6EB</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplicationPrivate::notify_helper(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication.cpp</file>
|
||||
<line>4396</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6A311DC</ip>
|
||||
<obj>/usr/lib/libQtGui.so.4.7.0</obj>
|
||||
<fn>QApplication::notify(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/gui/kernel</dir>
|
||||
<file>qapplication.cpp</file>
|
||||
<line>4277</line>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x6443535</ip>
|
||||
<obj>/usr/lib/libkdeui.so.5.5.0</obj>
|
||||
<fn>KApplication::notify(QObject*, QEvent*)</fn>
|
||||
</frame>
|
||||
<frame>
|
||||
<ip>0x83690AB</ip>
|
||||
<obj>/usr/lib/libQtCore.so.4.7.0</obj>
|
||||
<fn>QCoreApplication::notifyInternal(QObject*, QEvent*)</fn>
|
||||
<dir>/build/buildd/qt4-x11-4.7.0/src/corelib/kernel</dir>
|
||||
<file>qcoreapplication.cpp</file>
|
||||
<line>732</line>
|
||||
</frame>
|
||||
</stack>
|
||||
</error>
|
||||
|
||||
<errorcounts>
|
||||
<pair>
|
||||
<count>2</count>
|
||||
<unique>0x9</unique>
|
||||
</pair>
|
||||
</errorcounts>
|
||||
|
||||
<suppcounts>
|
||||
<pair>
|
||||
<count>12</count>
|
||||
<name>X on SUSE11 writev uninit padding</name>
|
||||
</pair>
|
||||
<pair>
|
||||
<count>2</count>
|
||||
<name>dl-hack3-cond-1</name>
|
||||
</pair>
|
||||
<pair>
|
||||
<count>2</count>
|
||||
<name>glibc-2.5.x-on-SUSE-10.2-(PPC)-2a</name>
|
||||
</pair>
|
||||
</suppcounts>
|
||||
|
||||
</valgrindoutput>
|
||||
|
||||
@@ -55,3 +55,16 @@ FORMS += \
|
||||
|
||||
RESOURCES += \
|
||||
valgrind.qrc
|
||||
|
||||
equals(TEST, 1) {
|
||||
DEFINES += "PARSERTESTS_DATA_DIR=\\\"$$_PRO_FILE_PWD_/unit_testdata\\\""
|
||||
DEFINES += "VALGRIND_FAKE_PATH=\\\"$$IDE_BUILD_TREE/src/tools/valgrindfake\\\""
|
||||
DEFINES += "TESTRUNNER_SRC_DIR=\\\"$$_PRO_FILE_PWD_/../../../tests/auto/valgrind/memcheck/testapps\\\""
|
||||
DEFINES += "TESTRUNNER_APP_DIR=\\\"$(PWD)/../../../tests/auto/valgrind/memcheck/testapps\\\""
|
||||
|
||||
HEADERS += valgrindmemcheckparsertest.h \
|
||||
valgrindtestrunnertest.h
|
||||
|
||||
SOURCES += valgrindmemcheckparsertest.cpp \
|
||||
valgrindtestrunnertest.cpp
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import qbs 1.0
|
||||
import qbs
|
||||
import qbs.FileInfo
|
||||
|
||||
QtcPlugin {
|
||||
name: "Valgrind"
|
||||
@@ -88,4 +89,21 @@ QtcPlugin {
|
||||
"threadedparser.cpp", "threadedparser.h",
|
||||
]
|
||||
}
|
||||
|
||||
Group {
|
||||
name: "Test sources"
|
||||
condition: qtc.testsEnabled
|
||||
files: [
|
||||
"valgrindmemcheckparsertest.cpp",
|
||||
"valgrindmemcheckparsertest.h",
|
||||
"valgrindtestrunnertest.cpp",
|
||||
"valgrindtestrunnertest.h",
|
||||
]
|
||||
cpp.defines: outer.concat([
|
||||
'PARSERTESTS_DATA_DIR="' + FileInfo.joinPaths(path, "unit_testdata") + '"',
|
||||
'VALGRIND_FAKE_PATH="' + FileInfo.joinPaths(project.buildDirectory, qtc.ide_bin_path) + '"',
|
||||
'TESTRUNNER_SRC_DIR="' + FileInfo.joinPaths(path, "../../../tests/auto/valgrind/memcheck/testapps") + '"',
|
||||
'TESTRUNNER_APP_DIR="' + FileInfo.joinPaths(project.buildDirectory, qtc.ide_bin_path, "testapps") + '"'
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
547
src/plugins/valgrind/valgrindmemcheckparsertest.cpp
Normal file
547
src/plugins/valgrind/valgrindmemcheckparsertest.cpp
Normal file
@@ -0,0 +1,547 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "valgrindmemcheckparsertest.h"
|
||||
|
||||
#include "xmlprotocol/frame.h"
|
||||
#include "xmlprotocol/parser.h"
|
||||
#include "xmlprotocol/stack.h"
|
||||
#include "xmlprotocol/suppression.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/runnables.h>
|
||||
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QString>
|
||||
#include <QTest>
|
||||
#include <QTcpServer>
|
||||
#include <QTcpSocket>
|
||||
#include <QSignalSpy>
|
||||
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace QTest {
|
||||
|
||||
template<>
|
||||
inline bool qCompare(int const &t1, MemcheckErrorKind const &t2,
|
||||
char const *actual, char const *expected, char const *file, int line)
|
||||
{
|
||||
return qCompare(t1, int(t2), actual, expected, file, line);
|
||||
}
|
||||
|
||||
} // namespace QTest
|
||||
QT_END_NAMESPACE
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Test {
|
||||
|
||||
static void dumpFrame(const Frame &f)
|
||||
{
|
||||
qDebug() << f.instructionPointer() << f.directory() << f.fileName() << f.functionName()
|
||||
<< f.line() << f.object();
|
||||
}
|
||||
|
||||
void dumpError(const Error &e)
|
||||
{
|
||||
qDebug() << e.kind() << e.leakedBlocks() << e.leakedBytes() << e.what() << e.tid() << e.unique();
|
||||
qDebug() << "stacks:" << e.stacks().size();
|
||||
for (const Stack &s : e.stacks()) {
|
||||
qDebug() << s.auxWhat() << s.directory() << s.file() << s.line() << s.helgrindThreadId();
|
||||
qDebug() << "frames:";
|
||||
for (const Frame &f : s.frames()) {
|
||||
dumpFrame(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static QString fakeValgrindExecutable()
|
||||
{
|
||||
QString valgrindFakePath(VALGRIND_FAKE_PATH);
|
||||
if (Utils::HostOsInfo::isWindowsHost()) {
|
||||
QFileInfo fi(QString(valgrindFakePath + "/debug"), "valgrind-fake.exe");
|
||||
if (fi.exists())
|
||||
return fi.canonicalFilePath();
|
||||
fi = QFileInfo(QString(valgrindFakePath + "/release"), "valgrind-fake.exe");
|
||||
if (fi.exists())
|
||||
return fi.canonicalFilePath();
|
||||
// Qbs uses the install-root/bin
|
||||
fi = QFileInfo(valgrindFakePath, "valgrind-fake.exe");
|
||||
if (fi.exists())
|
||||
return fi.canonicalFilePath();
|
||||
qFatal("Neither debug nor release build valgrind-fake found.");
|
||||
}
|
||||
return valgrindFakePath + "/valgrind-fake";
|
||||
}
|
||||
|
||||
static QString dataFile(const QLatin1String &file)
|
||||
{
|
||||
return QLatin1String(PARSERTESTS_DATA_DIR) + QLatin1String("/") + file;
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::initTestCase()
|
||||
{
|
||||
m_server = new QTcpServer(this);
|
||||
QVERIFY(m_server->listen());
|
||||
|
||||
m_socket = 0;
|
||||
m_process = 0;
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::initTest(const QLatin1String &testfile, const QStringList &otherArgs)
|
||||
{
|
||||
QVERIFY(!m_server->hasPendingConnections());
|
||||
|
||||
m_process = new QProcess(m_server);
|
||||
m_process->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
const QString fakeValgrind = fakeValgrindExecutable();
|
||||
QFileInfo fileInfo(fakeValgrind);
|
||||
QVERIFY2(fileInfo.isExecutable(), qPrintable(fakeValgrind));
|
||||
QVERIFY2(!fileInfo.isDir(), qPrintable(fakeValgrind));
|
||||
|
||||
m_process->start(
|
||||
fakeValgrind,
|
||||
QStringList()
|
||||
<< QString::fromLatin1("--xml-socket=127.0.0.1:%1").arg(m_server->serverPort())
|
||||
<< QLatin1String("-i")
|
||||
<< dataFile(testfile)
|
||||
<< otherArgs
|
||||
);
|
||||
|
||||
QVERIFY(m_process->waitForStarted(5000));
|
||||
QCOMPARE(m_process->state(), QProcess::Running);
|
||||
QVERIFY2(m_process->error() == QProcess::UnknownError, qPrintable(m_process->errorString()));
|
||||
QVERIFY(m_server->waitForNewConnection(5000));
|
||||
m_socket = m_server->nextPendingConnection();
|
||||
QVERIFY(m_socket);
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::cleanup()
|
||||
{
|
||||
if (m_socket) {
|
||||
delete m_socket;
|
||||
m_socket = 0;
|
||||
}
|
||||
if (m_process) {
|
||||
delete m_process;
|
||||
m_process = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testHelgrindSample1()
|
||||
{
|
||||
QSKIP("testfile does not exist");
|
||||
|
||||
initTest(QLatin1String("helgrind-output-sample1.xml"));
|
||||
|
||||
QList<Error> expectedErrors;
|
||||
{
|
||||
Error error1;
|
||||
error1.setUnique(0x0);
|
||||
error1.setTid(1);
|
||||
error1.setKind(LockOrder);
|
||||
error1.setWhat(QLatin1String("Thread #1: lock order \"0xA39C270 before 0xA3AC010\" violated"));
|
||||
error1.setHelgrindThreadId(1);
|
||||
Stack stack1;
|
||||
Frame frame11;
|
||||
frame11.setInstructionPointer(0x4C2B806);
|
||||
frame11.setObject(QLatin1String("/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so"));
|
||||
frame11.setFunctionName(QLatin1String("QMutex::lock()"));
|
||||
frame11.setDirectory(QLatin1String("/build/buildd/valgrind-3.6.0~svn20100212/helgrind"));
|
||||
frame11.setFileName(QLatin1String("hg_intercepts.c"));
|
||||
frame11.setLine(1988);
|
||||
Frame frame12;
|
||||
frame12.setInstructionPointer(0x72E57EE);
|
||||
frame12.setObject(QLatin1String("/home/frank/local/qt4-4.6.3-shared-debug/lib/libQtCore.so.4.6.3"));
|
||||
frame12.setFunctionName(QLatin1String("QMutexLocker::relock()"));
|
||||
frame12.setDirectory(QLatin1String("/home/frank/source/tarballs/qt-4.6.3-build/src/corelib/../../include/QtCore/../../src/corelib/thread"));
|
||||
frame12.setFileName(QLatin1String("qmutex.h"));
|
||||
frame12.setLine(120);
|
||||
stack1.setFrames(QVector<Frame>() << frame11 << frame12);
|
||||
|
||||
Stack stack2;
|
||||
stack2.setAuxWhat(QLatin1String("Required order was established by acquisition of lock at 0xA39C270"));
|
||||
Frame frame21;
|
||||
frame21.setInstructionPointer(0x4C2B806);
|
||||
frame21.setObject(QLatin1String("/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so"));
|
||||
frame21.setFunctionName(QLatin1String("QMutex::lock()"));
|
||||
frame21.setDirectory(QLatin1String("/build/buildd/valgrind-3.6.0~svn20100212/helgrind"));
|
||||
frame21.setFileName(QLatin1String("hg_intercepts.c"));
|
||||
frame21.setLine(1989);
|
||||
Frame frame22;
|
||||
frame22.setInstructionPointer(0x72E57EE);
|
||||
frame22.setObject(QLatin1String("/home/frank/local/qt4-4.6.3-shared-debug/lib/libQtCore.so.4.6.3"));
|
||||
frame22.setFunctionName(QLatin1String("QMutexLocker::relock()"));
|
||||
frame22.setDirectory(QLatin1String("/home/frank/source/tarballs/qt-4.6.3-build/src/corelib/../../include/QtCore/../../src/corelib/thread"));
|
||||
frame22.setFileName(QLatin1String("qmutex.h"));
|
||||
frame22.setLine(121);
|
||||
stack2.setFrames(QVector<Frame>() << frame21 << frame22);
|
||||
|
||||
Stack stack3;
|
||||
stack3.setAuxWhat(QLatin1String("followed by a later acquisition of lock at 0xA3AC010"));
|
||||
Frame frame31;
|
||||
frame31.setInstructionPointer(0x4C2B806);
|
||||
frame31.setObject(QLatin1String("/usr/lib/valgrind/vgpreload_helgrind-amd64-linux.so"));
|
||||
frame31.setFunctionName(QLatin1String("QMutex::lock()"));
|
||||
frame31.setDirectory(QLatin1String("/build/buildd/valgrind-3.6.0~svn20100212/helgrind"));
|
||||
frame31.setFileName(QLatin1String("hg_intercepts.c"));
|
||||
frame31.setLine(1990);
|
||||
Frame frame32;
|
||||
frame32.setInstructionPointer(0x72E57EE);
|
||||
frame32.setObject(QLatin1String("/home/frank/local/qt4-4.6.3-shared-debug/lib/libQtCore.so.4.6.3"));
|
||||
frame32.setFunctionName(QLatin1String("QMutexLocker::relock()"));
|
||||
frame32.setDirectory(QLatin1String("/home/frank/source/tarballs/qt-4.6.3-build/src/corelib/../../include/QtCore/../../src/corelib/thread"));
|
||||
frame32.setFileName(QLatin1String("qmutex.h"));
|
||||
frame32.setLine(122);
|
||||
|
||||
stack3.setFrames(QVector<Frame>() << frame31 << frame32);
|
||||
error1.setStacks(QVector<Stack>() << stack1 << stack2 << stack3);
|
||||
expectedErrors.append(error1);
|
||||
}
|
||||
|
||||
Parser parser;
|
||||
Recorder rec(&parser);
|
||||
|
||||
parser.parse(m_socket);
|
||||
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
|
||||
QVERIFY2(parser.errorString().isEmpty(), qPrintable(parser.errorString()));
|
||||
const QList<Error> actualErrors = rec.errors;
|
||||
|
||||
if (actualErrors.first() != expectedErrors.first()) {
|
||||
dumpError(actualErrors.first());
|
||||
dumpError(expectedErrors.first());
|
||||
}
|
||||
|
||||
QCOMPARE(actualErrors.first(), expectedErrors.first());
|
||||
|
||||
QCOMPARE(actualErrors.size(), 1);
|
||||
|
||||
// QCOMPARE(rec.errorcounts, expectedErrorCounts);
|
||||
// QCOMPARE(rec.suppcounts, expectedSuppCounts);
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testMemcheckSample1()
|
||||
{
|
||||
initTest(QLatin1String("memcheck-output-sample1.xml"));
|
||||
|
||||
QList<Error> expectedErrors;
|
||||
{
|
||||
Error error;
|
||||
error.setKind(InvalidRead);
|
||||
error.setWhat(QLatin1String("Invalid read of size 4"));
|
||||
error.setUnique(0x9);
|
||||
error.setTid(1);
|
||||
Frame f1;
|
||||
f1.setInstructionPointer(0x6E47964);
|
||||
f1.setObject(QLatin1String("/usr/lib/libQtGui.so.4.7.0"));
|
||||
f1.setFunctionName(QLatin1String("QFrame::frameStyle() const"));
|
||||
f1.setDirectory(QLatin1String("/build/buildd/qt4-x11-4.7.0/src/gui/widgets"));
|
||||
f1.setFileName(QLatin1String("qframe.cpp"));
|
||||
f1.setLine(252);
|
||||
Frame f2;
|
||||
f2.setInstructionPointer(0x118F2AF7);
|
||||
f2.setObject(QLatin1String("/usr/lib/kde4/plugins/styles/oxygen.so"));
|
||||
Frame f3;
|
||||
f3.setInstructionPointer(0x6A81671);
|
||||
f3.setObject(QLatin1String("/usr/lib/libQtGui.so.4.7.0"));
|
||||
f3.setFunctionName(QLatin1String("QWidget::event(QEvent*)"));
|
||||
f3.setDirectory(QLatin1String("/build/buildd/qt4-x11-4.7.0/src/gui/kernel"));
|
||||
f3.setFileName(QLatin1String("qwidget.cpp"));
|
||||
f3.setLine(8273);
|
||||
Frame f4;
|
||||
f4.setInstructionPointer(0x6A2B6EB);
|
||||
f4.setObject(QLatin1String("/usr/lib/libQtGui.so.4.7.0"));
|
||||
f4.setDirectory(QLatin1String("/build/buildd/qt4-x11-4.7.0/src/gui/kernel"));
|
||||
f4.setFileName(QLatin1String("qapplication.cpp"));
|
||||
f4.setFunctionName(QLatin1String("QApplicationPrivate::notify_helper(QObject*, QEvent*)"));
|
||||
f4.setLine(4396);
|
||||
Stack s1;
|
||||
s1.setAuxWhat(QLatin1String("Address 0x11527cb8 is not stack'd, malloc'd or (recently) free'd"));
|
||||
s1.setFrames(QVector<Frame>() << f1 << f2 << f3 << f4);
|
||||
error.setStacks( QVector<Stack>() << s1 );
|
||||
|
||||
expectedErrors << error;
|
||||
}
|
||||
|
||||
QVector<QPair<qint64,qint64> > expectedErrorCounts;
|
||||
expectedErrorCounts.push_back(QPair<qint64,qint64>(9, 2));
|
||||
|
||||
QVector<QPair<QString,qint64> > expectedSuppCounts;
|
||||
expectedSuppCounts.push_back(qMakePair(QString::fromLatin1("X on SUSE11 writev uninit padding"), static_cast<qint64>(12)));
|
||||
expectedSuppCounts.push_back(qMakePair(QString::fromLatin1("dl-hack3-cond-1"), static_cast<qint64>(2)));
|
||||
expectedSuppCounts.push_back(qMakePair(QString::fromLatin1("glibc-2.5.x-on-SUSE-10.2-(PPC)-2a"), static_cast<qint64>(2)));
|
||||
|
||||
Parser parser;
|
||||
Recorder rec(&parser);
|
||||
|
||||
parser.parse(m_socket);
|
||||
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
|
||||
QVERIFY2(parser.errorString().isEmpty(), qPrintable(parser.errorString()));
|
||||
const QList<Error> actualErrors = rec.errors;
|
||||
|
||||
if (actualErrors.first() != expectedErrors.first()) {
|
||||
dumpError(actualErrors.first());
|
||||
dumpError(expectedErrors.first());
|
||||
}
|
||||
|
||||
QCOMPARE(actualErrors.first(), expectedErrors.first());
|
||||
|
||||
QCOMPARE(actualErrors.size(), 3);
|
||||
|
||||
QCOMPARE(rec.errorcounts, expectedErrorCounts);
|
||||
QCOMPARE(rec.suppcounts, expectedSuppCounts);
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testMemcheckSample2()
|
||||
{
|
||||
QSKIP("testfile does not exist");
|
||||
|
||||
initTest(QLatin1String("memcheck-output-sample2.xml"));
|
||||
|
||||
Parser parser;
|
||||
Recorder rec(&parser);
|
||||
|
||||
parser.parse(m_socket);
|
||||
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
QVERIFY2(parser.errorString().isEmpty(), qPrintable(parser.errorString()));
|
||||
|
||||
//tests: multiple stacks with auxwhat == stack count - 1.
|
||||
//the first auxwhat should be assigned to the _second_ stack.
|
||||
const QList<Error> errors = rec.errors;
|
||||
QCOMPARE(errors.size(), 1);
|
||||
const QVector<Stack> stacks = errors.first().stacks();
|
||||
QCOMPARE(stacks.size(), 2);
|
||||
QCOMPARE(stacks.first().auxWhat(), QString());
|
||||
QCOMPARE(stacks.last().auxWhat(), QLatin1String("Address 0x11b66c50 is 0 bytes inside a block of size 16 free'd"));
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testMemcheckSample3()
|
||||
{
|
||||
QSKIP("testfile does not exist");
|
||||
|
||||
initTest(QLatin1String("memcheck-output-sample3.xml"));
|
||||
|
||||
Parser parser;
|
||||
Recorder rec(&parser);
|
||||
|
||||
parser.parse(m_socket);
|
||||
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
QVERIFY2(parser.errorString().isEmpty(), qPrintable(parser.errorString()));
|
||||
|
||||
const QList<Error> errors = rec.errors;
|
||||
QCOMPARE(errors.size(), 6);
|
||||
|
||||
{
|
||||
const Error error = errors.at(0);
|
||||
const QVector<Stack> stacks = error.stacks();
|
||||
|
||||
QCOMPARE(error.unique(), 0x1ll);
|
||||
QCOMPARE(error.what(), QLatin1String("Conditional jump or move depends on uninitialised value(s)"));
|
||||
QCOMPARE(error.kind(), UninitCondition);
|
||||
QCOMPARE(stacks.size(), 1);
|
||||
QCOMPARE(stacks.first().frames().size(), 12);
|
||||
QVERIFY(!error.suppression().isNull());
|
||||
QCOMPARE(error.suppression().frames().count(), stacks.first().frames().size());
|
||||
QCOMPARE(error.suppression().kind(), QLatin1String("Memcheck:Cond"));
|
||||
QVERIFY(!error.suppression().rawText().trimmed().isEmpty());
|
||||
|
||||
// rawtext contains <...> while <name></name> does not
|
||||
QCOMPARE(error.suppression().name(), QLatin1String("insert_a_suppression_name_here"));
|
||||
Suppression sup = error.suppression();
|
||||
sup.setName(QLatin1String("<insert_a_suppression_name_here>"));
|
||||
QCOMPARE(sup.toString().trimmed(), sup.rawText().trimmed());
|
||||
|
||||
QCOMPARE(error.suppression().frames().first().object(),
|
||||
QLatin1String("/usr/lib/kde4/plugins/styles/qtcurve.so"));
|
||||
QVERIFY(error.suppression().frames().first().function().isEmpty());
|
||||
QCOMPARE(error.suppression().frames().last().function(), QLatin1String("main"));
|
||||
QVERIFY(error.suppression().frames().last().object().isEmpty());
|
||||
}
|
||||
|
||||
QCOMPARE(rec.suppcounts.count(), 3);
|
||||
QCOMPARE(rec.suppcounts.at(0).second, qint64(1));
|
||||
QCOMPARE(rec.suppcounts.at(1).second, qint64(2));
|
||||
QCOMPARE(rec.suppcounts.at(2).second, qint64(3));
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testMemcheckCharm()
|
||||
{
|
||||
QSKIP("testfile does not exist");
|
||||
|
||||
// a somewhat larger file, to make sure buffering and partial I/O works ok
|
||||
initTest(QLatin1String("memcheck-output-untitled.xml"));
|
||||
|
||||
Parser parser;
|
||||
Recorder rec(&parser);
|
||||
|
||||
parser.parse(m_socket);
|
||||
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
|
||||
const QList<Error> errors = rec.errors;
|
||||
QCOMPARE(errors.size(), 102);
|
||||
QVERIFY2(parser.errorString().isEmpty(), qPrintable(parser.errorString()));
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testValgrindCrash()
|
||||
{
|
||||
initTest(QLatin1String("memcheck-output-sample1.xml"), QStringList() << "--crash");
|
||||
|
||||
Parser parser;
|
||||
parser.parse(m_socket);
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::CrashExit);
|
||||
|
||||
QVERIFY(!parser.errorString().isEmpty());
|
||||
QCOMPARE(m_socket->error(), QAbstractSocket::RemoteHostClosedError);
|
||||
QCOMPARE(parser.errorString(), m_socket->errorString());
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testValgrindGarbage()
|
||||
{
|
||||
initTest(QLatin1String("memcheck-output-sample1.xml"), QStringList() << "--garbage");
|
||||
|
||||
Parser parser;
|
||||
parser.parse(m_socket);
|
||||
m_process->waitForFinished();
|
||||
QCOMPARE(m_process->state(), QProcess::NotRunning);
|
||||
QCOMPARE(m_process->exitStatus(), QProcess::NormalExit);
|
||||
|
||||
QVERIFY(!parser.errorString().isEmpty());
|
||||
qDebug() << parser.errorString();
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testParserStop()
|
||||
{
|
||||
ThreadedParser parser;
|
||||
Memcheck::MemcheckRunner runner;
|
||||
runner.setValgrindExecutable(fakeValgrindExecutable());
|
||||
runner.setParser(&parser);
|
||||
runner.setValgrindArguments(QStringList() << QLatin1String("-i")
|
||||
<< dataFile(QLatin1String("memcheck-output-sample1.xml"))
|
||||
<< "--wait" << "5");
|
||||
runner.setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
runner.start();
|
||||
QTest::qWait(500);
|
||||
runner.stop();
|
||||
}
|
||||
|
||||
|
||||
void ValgrindMemcheckParserTest::testRealValgrind()
|
||||
{
|
||||
const Utils::Environment &sysEnv = Utils::Environment::systemEnvironment();
|
||||
auto fileName = sysEnv.searchInPath("valgrind");
|
||||
if (fileName.isEmpty())
|
||||
QSKIP("This test needs valgrind in PATH");
|
||||
QString executable = QProcessEnvironment::systemEnvironment().value("VALGRIND_TEST_BIN", fakeValgrindExecutable());
|
||||
qDebug() << "running exe:" << executable << " HINT: set VALGRIND_TEST_BIN to change this";
|
||||
ThreadedParser parser;
|
||||
|
||||
ProjectExplorer::StandardRunnable debuggee;
|
||||
debuggee.executable = executable;
|
||||
debuggee.environment = sysEnv;
|
||||
Memcheck::MemcheckRunner runner;
|
||||
runner.setValgrindExecutable(QLatin1String("valgrind"));
|
||||
runner.setDebuggee(debuggee);
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
runner.setParser(&parser);
|
||||
RunnerDumper dumper(&runner, &parser);
|
||||
runner.start();
|
||||
runner.waitForFinished();
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testValgrindStartError_data()
|
||||
{
|
||||
QTest::addColumn<QString>("valgrindExe");
|
||||
QTest::addColumn<QStringList>("valgrindArgs");
|
||||
QTest::addColumn<QString>("debuggee");
|
||||
QTest::addColumn<QString>("debuggeeArgs");
|
||||
|
||||
QTest::newRow("invalid_client") << QString::fromLatin1("valgrind") << QStringList()
|
||||
<< QString::fromLatin1("please-dont-let-this-app-exist") << QString();
|
||||
|
||||
QTest::newRow("invalid_valgrind") << QString::fromLatin1("valgrind-that-does-not-exist") << QStringList()
|
||||
<< fakeValgrindExecutable() << QString();
|
||||
|
||||
QTest::newRow("invalid_valgrind_args") << QString::fromLatin1("valgrind")
|
||||
<< (QStringList() << QString::fromLatin1("--foobar-fail"))
|
||||
<< fakeValgrindExecutable() << QString();
|
||||
}
|
||||
|
||||
void ValgrindMemcheckParserTest::testValgrindStartError()
|
||||
{
|
||||
QFETCH(QString, valgrindExe);
|
||||
QFETCH(QStringList, valgrindArgs);
|
||||
QFETCH(QString, debuggee);
|
||||
QFETCH(QString, debuggeeArgs);
|
||||
|
||||
ThreadedParser parser;
|
||||
|
||||
ProjectExplorer::StandardRunnable debuggeeExecutable;
|
||||
debuggeeExecutable.executable = debuggee;
|
||||
debuggeeExecutable.environment = Utils::Environment::systemEnvironment();
|
||||
debuggeeExecutable.commandLineArguments = debuggeeArgs;
|
||||
|
||||
Memcheck::MemcheckRunner runner;
|
||||
runner.setParser(&parser);
|
||||
runner.setValgrindExecutable(valgrindExe);
|
||||
runner.setValgrindArguments(valgrindArgs);
|
||||
runner.setDebuggee(debuggeeExecutable);
|
||||
runner.setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
RunnerDumper dumper(&runner, &parser);
|
||||
runner.start();
|
||||
runner.waitForFinished();
|
||||
QVERIFY(dumper.m_errorReceived);
|
||||
// just finish without deadlock and we are fine
|
||||
}
|
||||
|
||||
} // namespace Test
|
||||
} // namespace Valgrind
|
||||
172
src/plugins/valgrind/valgrindmemcheckparsertest.h
Normal file
172
src/plugins/valgrind/valgrindmemcheckparsertest.h
Normal file
@@ -0,0 +1,172 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Frank Osterfeld, KDAB (frank.osterfeld@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QPair>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
#include <QDebug>
|
||||
|
||||
#include "xmlprotocol/error.h"
|
||||
#include "xmlprotocol/status.h"
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
#include "xmlprotocol/parser.h"
|
||||
#include "memcheck/memcheckrunner.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QTcpServer;
|
||||
class QTcpSocket;
|
||||
class QProcess;
|
||||
QT_END_NAMESPACE
|
||||
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Test {
|
||||
|
||||
void dumpError(const Valgrind::XmlProtocol::Error &e);
|
||||
|
||||
class Recorder : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Recorder(Valgrind::XmlProtocol::Parser *parser, QObject *parent = 0)
|
||||
: QObject(parent)
|
||||
{
|
||||
connect(parser, &Valgrind::XmlProtocol::Parser::error,
|
||||
this, &Recorder::error);
|
||||
connect(parser, &Valgrind::XmlProtocol::Parser::errorCount,
|
||||
this, &Recorder::errorCount);
|
||||
connect(parser, &Valgrind::XmlProtocol::Parser::suppressionCount,
|
||||
this, &Recorder::suppressionCount);
|
||||
}
|
||||
|
||||
QList<Valgrind::XmlProtocol::Error> errors;
|
||||
QVector<QPair<qint64,qint64> > errorcounts;
|
||||
QVector<QPair<QString,qint64> > suppcounts;
|
||||
|
||||
public Q_SLOTS:
|
||||
void error(const Valgrind::XmlProtocol::Error &err)
|
||||
{
|
||||
errors.append(err);
|
||||
}
|
||||
|
||||
void errorCount(qint64 unique, qint64 count)
|
||||
{
|
||||
errorcounts.push_back(qMakePair(unique, count));
|
||||
}
|
||||
|
||||
void suppressionCount(const QString &name, qint64 count)
|
||||
{
|
||||
suppcounts.push_back(qMakePair(name, count));
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class RunnerDumper : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit RunnerDumper(Valgrind::Memcheck::MemcheckRunner *runner, Valgrind::XmlProtocol::ThreadedParser *parser)
|
||||
: QObject()
|
||||
, m_errorReceived(false)
|
||||
{
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::error,
|
||||
this, &RunnerDumper::error);
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::internalError,
|
||||
this, &RunnerDumper::internalError);
|
||||
connect(parser, &Valgrind::XmlProtocol::ThreadedParser::status,
|
||||
this, &RunnerDumper::status);
|
||||
connect(runner, &Valgrind::Memcheck::MemcheckRunner::logMessageReceived,
|
||||
this, &RunnerDumper::logMessageReceived);
|
||||
connect(runner, &Valgrind::ValgrindRunner::processErrorReceived,
|
||||
this, &RunnerDumper::processErrorReceived);
|
||||
}
|
||||
|
||||
public slots:
|
||||
void error(const Valgrind::XmlProtocol::Error &e)
|
||||
{
|
||||
qDebug() << "error received";
|
||||
dumpError(e);
|
||||
}
|
||||
void internalError(const QString& error)
|
||||
{
|
||||
qDebug() << "internal error received:" << error;
|
||||
}
|
||||
void status(const Valgrind::XmlProtocol::Status &status)
|
||||
{
|
||||
qDebug() << "status received:" << status.state() << status.time();
|
||||
}
|
||||
void logMessageReceived(const QByteArray &log)
|
||||
{
|
||||
qDebug() << "log message received:" << log;
|
||||
}
|
||||
void processErrorReceived(const QString &s)
|
||||
{
|
||||
Q_UNUSED(s);
|
||||
// qDebug() << "error received:" << s; // this can be a lot of text
|
||||
m_errorReceived = true;
|
||||
}
|
||||
|
||||
public:
|
||||
bool m_errorReceived;
|
||||
|
||||
};
|
||||
|
||||
class ValgrindMemcheckParserTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
private Q_SLOTS:
|
||||
void initTestCase();
|
||||
void cleanup();
|
||||
|
||||
void testMemcheckSample1();
|
||||
void testMemcheckSample2();
|
||||
void testMemcheckSample3();
|
||||
void testMemcheckCharm();
|
||||
void testHelgrindSample1();
|
||||
|
||||
void testValgrindCrash();
|
||||
void testValgrindGarbage();
|
||||
|
||||
void testParserStop();
|
||||
void testRealValgrind();
|
||||
void testValgrindStartError_data();
|
||||
void testValgrindStartError();
|
||||
|
||||
private:
|
||||
void initTest(const QLatin1String &testfile, const QStringList &otherArgs = QStringList());
|
||||
|
||||
QTcpServer *m_server = 0;
|
||||
QProcess *m_process = 0;
|
||||
QTcpSocket *m_socket = 0;
|
||||
};
|
||||
|
||||
} // namespace Test
|
||||
} // namespace Valgrind
|
||||
@@ -32,6 +32,11 @@
|
||||
#include "valgrindsettings.h"
|
||||
#include "valgrindconfigwidget.h"
|
||||
|
||||
#ifdef WITH_TESTS
|
||||
# include "valgrindmemcheckparsertest.h"
|
||||
# include "valgrindtestrunnertest.h"
|
||||
#endif
|
||||
|
||||
#include <coreplugin/dialogs/ioptionspage.h>
|
||||
#include <coreplugin/icontext.h>
|
||||
#include <coreplugin/icore.h>
|
||||
@@ -117,5 +122,14 @@ ValgrindGlobalSettings *ValgrindPlugin::globalSettings()
|
||||
return theGlobalSettings;
|
||||
}
|
||||
|
||||
QList<QObject *> ValgrindPlugin::createTestObjects() const
|
||||
{
|
||||
QList<QObject *> tests;
|
||||
#ifdef WITH_TESTS
|
||||
tests << new Test::ValgrindMemcheckParserTest << new Test::ValgrindTestRunnerTest;
|
||||
#endif
|
||||
return tests;
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
} // namespace Valgrind
|
||||
|
||||
@@ -48,6 +48,8 @@ public:
|
||||
ShutdownFlag aboutToShutdown() override;
|
||||
|
||||
static ValgrindGlobalSettings *globalSettings();
|
||||
private:
|
||||
QList<QObject *> createTestObjects() const override;
|
||||
};
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
775
src/plugins/valgrind/valgrindtestrunnertest.cpp
Normal file
775
src/plugins/valgrind/valgrindtestrunnertest.cpp
Normal file
@@ -0,0 +1,775 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "valgrindtestrunnertest.h"
|
||||
|
||||
#include "xmlprotocol/frame.h"
|
||||
#include "xmlprotocol/stack.h"
|
||||
#include "xmlprotocol/suppression.h"
|
||||
#include "xmlprotocol/threadedparser.h"
|
||||
#include "xmlprotocol/parser.h"
|
||||
#include "memcheck/memcheckrunner.h"
|
||||
|
||||
#include <projectexplorer/devicesupport/devicemanager.h>
|
||||
#include <projectexplorer/projectexplorer.h>
|
||||
#include <projectexplorer/runnables.h>
|
||||
|
||||
#include <QDebug>
|
||||
#include <QTest>
|
||||
#include <QDir>
|
||||
#include <QSignalSpy>
|
||||
|
||||
#define HEADER_LENGTH 25
|
||||
|
||||
using namespace Valgrind::XmlProtocol;
|
||||
using namespace Valgrind::Memcheck;
|
||||
|
||||
namespace Valgrind {
|
||||
namespace Test {
|
||||
|
||||
//BEGIN Test Helpers and boilerplate code
|
||||
|
||||
static const QString appSrcDir(TESTRUNNER_SRC_DIR);
|
||||
static const QString appBinDir(TESTRUNNER_APP_DIR);
|
||||
|
||||
static bool on64bit()
|
||||
{
|
||||
return sizeof(char*) == 8;
|
||||
}
|
||||
|
||||
static QString srcDirForApp(const QString &app)
|
||||
{
|
||||
return QDir::cleanPath(appSrcDir + QLatin1Char('/') + app);
|
||||
}
|
||||
|
||||
ValgrindTestRunnerTest::ValgrindTestRunnerTest(QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
qRegisterMetaType<Error>();
|
||||
}
|
||||
|
||||
QString ValgrindTestRunnerTest::runTestBinary(const QString &binary, const QStringList &vArgs)
|
||||
{
|
||||
const QFileInfo binPathFileInfo(appBinDir, binary);
|
||||
if (!binPathFileInfo.isExecutable())
|
||||
return QString();
|
||||
ProjectExplorer::StandardRunnable debuggee;
|
||||
const QString &binPath = binPathFileInfo.canonicalFilePath();
|
||||
debuggee.executable = binPath;
|
||||
debuggee.environment = Utils::Environment::systemEnvironment();
|
||||
m_runner->setValgrindArguments(QStringList() << "--num-callers=50" << "--track-origins=yes" << vArgs);
|
||||
m_runner->setDebuggee(debuggee);
|
||||
m_runner->setDevice(ProjectExplorer::DeviceManager::instance()->defaultDevice(
|
||||
Core::Id(ProjectExplorer::Constants::DESKTOP_DEVICE_TYPE)));
|
||||
m_runner->start();
|
||||
m_runner->waitForFinished();
|
||||
return binPath;
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::logMessageReceived(const QByteArray &message)
|
||||
{
|
||||
qDebug() << "log message received:" << message;
|
||||
m_logMessages << message;
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::internalError(const QString &error)
|
||||
{
|
||||
if (!m_expectCrash)
|
||||
QFAIL(qPrintable(error));
|
||||
else
|
||||
qDebug() << "expected crash:" << error;
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::error(const Error &error)
|
||||
{
|
||||
m_errors << error;
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::cleanup()
|
||||
{
|
||||
Q_ASSERT(m_runner);
|
||||
delete m_runner;
|
||||
m_runner = 0;
|
||||
Q_ASSERT(m_parser);
|
||||
delete m_parser;
|
||||
m_parser = 0;
|
||||
|
||||
m_logMessages.clear();
|
||||
m_errors.clear();
|
||||
m_expectCrash = false;
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::init()
|
||||
{
|
||||
const Utils::Environment &sysEnv = Utils::Environment::systemEnvironment();
|
||||
auto fileName = sysEnv.searchInPath("valgrind");
|
||||
if (fileName.isEmpty())
|
||||
QSKIP("This test needs valgrind in PATH");
|
||||
Q_ASSERT(m_logMessages.isEmpty());
|
||||
|
||||
Q_ASSERT(!m_runner);
|
||||
m_runner = new MemcheckRunner;
|
||||
m_runner->setValgrindExecutable(QLatin1String("valgrind"));
|
||||
m_runner->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
connect(m_runner, &MemcheckRunner::logMessageReceived,
|
||||
this, &ValgrindTestRunnerTest::logMessageReceived);
|
||||
connect(m_runner, &ValgrindRunner::processErrorReceived,
|
||||
this, &ValgrindTestRunnerTest::internalError);
|
||||
Q_ASSERT(!m_parser);
|
||||
m_parser = new ThreadedParser;
|
||||
connect(m_parser, &ThreadedParser::internalError,
|
||||
this, &ValgrindTestRunnerTest::internalError);
|
||||
connect(m_parser, &ThreadedParser::error,
|
||||
this, &ValgrindTestRunnerTest::error);
|
||||
|
||||
m_runner->setParser(m_parser);
|
||||
}
|
||||
|
||||
//BEGIN: Actual test cases
|
||||
|
||||
void ValgrindTestRunnerTest::testLeak1()
|
||||
{
|
||||
const QString binary = runTestBinary(QLatin1String("leak1/leak1"));
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(Leak_DefinitelyLost));
|
||||
QCOMPARE(error.leakedBlocks(), qint64(1));
|
||||
QCOMPARE(error.leakedBytes(), quint64(8));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
if (on64bit())
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned long)"));
|
||||
else
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned int)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 5 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak1"));
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testLeak2()
|
||||
{
|
||||
const QString binary = runTestBinary(QLatin1String("leak2/leak2"));
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(Leak_PossiblyLost));
|
||||
QCOMPARE(error.leakedBlocks(), qint64(1));
|
||||
QCOMPARE(error.leakedBytes(), quint64(5));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 3);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("malloc"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("strdup"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(2);
|
||||
if (on64bit()) {
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 7 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak2"));
|
||||
} else {
|
||||
QCOMPARE(frame.functionName(), QLatin1String("(below main)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testLeak3()
|
||||
{
|
||||
const QString binary = runTestBinary(QLatin1String("leak3/leak3"), QStringList() << "--show-reachable=yes");
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(Leak_StillReachable));
|
||||
QCOMPARE(error.leakedBlocks(), qint64(1));
|
||||
QCOMPARE(error.leakedBytes(), quint64(5));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 3);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("malloc"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("strdup"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(2);
|
||||
if (on64bit()) {
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 7 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak3"));
|
||||
} else {
|
||||
QCOMPARE(frame.functionName(), QLatin1String("(below main)"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testLeak4()
|
||||
{
|
||||
const QString app("leak4");
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app,
|
||||
QStringList() << "--show-reachable=yes");
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp("leak4");
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 3);
|
||||
//BEGIN first error
|
||||
{
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(Leak_IndirectlyLost));
|
||||
QCOMPARE(error.leakedBlocks(), qint64(1));
|
||||
QCOMPARE(error.leakedBytes(), quint64(8));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 3);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
if (on64bit())
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned long)"));
|
||||
else
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned int)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("Foo::Foo()"));
|
||||
QCOMPARE(frame.line(), 6 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(2);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 14 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
//BEGIN second error
|
||||
{
|
||||
const Error error = m_errors.at(1);
|
||||
QCOMPARE(error.kind(), int(Leak_DefinitelyLost));
|
||||
QCOMPARE(error.leakedBlocks(), qint64(1));
|
||||
if (on64bit())
|
||||
QCOMPARE(error.leakedBytes(), quint64(16));
|
||||
else
|
||||
QCOMPARE(error.leakedBytes(), quint64(12));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
if (on64bit())
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned long)"));
|
||||
else
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned int)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 14 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
// TODO add third error check
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testUninit1()
|
||||
{
|
||||
const QString app("uninit1");
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(UninitCondition));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 4 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 2 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testUninit2()
|
||||
{
|
||||
const QString app("uninit2");
|
||||
m_expectCrash = true;
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 2);
|
||||
//BEGIN first error
|
||||
{
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(UninitValue));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 4 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 2 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
//BEGIN second error
|
||||
{
|
||||
const Error error = m_errors.last();
|
||||
QCOMPARE(error.kind(), int(InvalidWrite));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 4 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testUninit3()
|
||||
{
|
||||
const QString app("uninit3");
|
||||
m_expectCrash = true;
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 2);
|
||||
//BEGIN first error
|
||||
{
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(UninitValue));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 4 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 2 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
//BEGIN second error
|
||||
{
|
||||
const Error error = m_errors.last();
|
||||
QCOMPARE(error.kind(), int(InvalidRead));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 4 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testSyscall()
|
||||
{
|
||||
const QString app("syscall");
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(SyscallParam));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
if (on64bit()) {
|
||||
QCOMPARE(stack.frames().count(), 4);
|
||||
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("_Exit"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("__run_exit_handlers"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(2);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("exit"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(3);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("(below main)"));
|
||||
}
|
||||
} else {
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("_Exit"));
|
||||
}
|
||||
}
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 1);
|
||||
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 2 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testFree1()
|
||||
{
|
||||
const QString app("free1");
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(InvalidFree));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
|
||||
{
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator delete(void*)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().last();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 7 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
|
||||
{
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator delete(void*)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().last();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 6 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testFree2()
|
||||
{
|
||||
const QString app("free2");
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(MismatchedFree));
|
||||
QCOMPARE(error.stacks().count(), 2);
|
||||
//BEGIN first stack
|
||||
{
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
|
||||
{
|
||||
const Frame frame = stack.frames().first();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("free"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().last();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 6 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
//BEGIN second stack
|
||||
{
|
||||
const Stack stack = error.stacks().last();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
|
||||
|
||||
{
|
||||
const Frame frame = stack.frames().first();
|
||||
if (on64bit())
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned long)"));
|
||||
else
|
||||
QCOMPARE(frame.functionName(), QLatin1String("operator new(unsigned int)"));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().last();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 5 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ValgrindTestRunnerTest::testInvalidjump()
|
||||
{
|
||||
const QString app("invalidjump");
|
||||
m_expectCrash = true;
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(InvalidJump));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
QVERIFY(!stack.auxWhat().isEmpty());
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QCOMPARE(frame.instructionPointer(), quint64(0));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().at(1);
|
||||
QCOMPARE(frame.functionName(), QLatin1String("(below main)"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ValgrindTestRunnerTest::testOverlap()
|
||||
{
|
||||
const QString app("overlap");
|
||||
m_expectCrash = true;
|
||||
const QString binary = runTestBinary(app + QLatin1Char('/') + app);
|
||||
if (binary.isEmpty())
|
||||
QSKIP("You need to pass BUILD_TESTS when building Qt Creator or build valgrind testapps "
|
||||
"manually before executing this test.");
|
||||
const QString srcDir = srcDirForApp(app);
|
||||
|
||||
QVERIFY(m_logMessages.isEmpty());
|
||||
|
||||
QCOMPARE(m_errors.count(), 1);
|
||||
const Error error = m_errors.first();
|
||||
QCOMPARE(error.kind(), int(Overlap));
|
||||
QCOMPARE(error.stacks().count(), 1);
|
||||
const Stack stack = error.stacks().first();
|
||||
QCOMPARE(stack.line(), qint64(-1));
|
||||
QCOMPARE(stack.frames().count(), 2);
|
||||
{
|
||||
const Frame frame = stack.frames().at(0);
|
||||
QVERIFY(frame.functionName().startsWith(QLatin1String("memcpy")));
|
||||
}
|
||||
{
|
||||
const Frame frame = stack.frames().last();
|
||||
QCOMPARE(frame.functionName(), QLatin1String("main"));
|
||||
QCOMPARE(frame.line(), 6 + HEADER_LENGTH);
|
||||
|
||||
QCOMPARE(frame.object(), binary);
|
||||
QCOMPARE(frame.fileName(), QLatin1String("main.cpp"));
|
||||
QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Test
|
||||
} // namespace Valgrind
|
||||
88
src/plugins/valgrind/valgrindtestrunnertest.h
Normal file
88
src/plugins/valgrind/valgrindtestrunnertest.h
Normal file
@@ -0,0 +1,88 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2016 The Qt Company Ltd.
|
||||
** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** This file is part of Qt Creator.
|
||||
**
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and The Qt Company. For licensing terms
|
||||
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||
** information use the contact form at https://www.qt.io/contact-us.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||
** included in the packaging of this file. Please review the following
|
||||
** information to ensure the GNU General Public License requirements will
|
||||
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
|
||||
#include "xmlprotocol/error.h"
|
||||
|
||||
namespace Valgrind {
|
||||
|
||||
namespace XmlProtocol {
|
||||
class ThreadedParser;
|
||||
}
|
||||
|
||||
namespace Memcheck {
|
||||
class MemcheckRunner;
|
||||
}
|
||||
|
||||
namespace Test {
|
||||
|
||||
class ValgrindTestRunnerTest : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ValgrindTestRunnerTest(QObject *parent = 0);
|
||||
|
||||
private slots:
|
||||
void init();
|
||||
void cleanup();
|
||||
|
||||
void testLeak1();
|
||||
void testLeak2();
|
||||
void testLeak3();
|
||||
void testLeak4();
|
||||
|
||||
void testUninit1();
|
||||
void testUninit2();
|
||||
void testUninit3();
|
||||
|
||||
void testFree1();
|
||||
void testFree2();
|
||||
|
||||
void testInvalidjump();
|
||||
void testSyscall();
|
||||
void testOverlap();
|
||||
|
||||
void logMessageReceived(const QByteArray &message);
|
||||
void internalError(const QString &error);
|
||||
void error(const Valgrind::XmlProtocol::Error &error);
|
||||
|
||||
private:
|
||||
QString runTestBinary(const QString &binary, const QStringList &vArgs = QStringList());
|
||||
|
||||
XmlProtocol::ThreadedParser *m_parser = 0;
|
||||
Memcheck::MemcheckRunner *m_runner = 0;
|
||||
QList<QByteArray> m_logMessages;
|
||||
QList<XmlProtocol::Error> m_errors;
|
||||
bool m_expectCrash = false;
|
||||
};
|
||||
|
||||
} // namespace Test
|
||||
} // namespace Valgrind
|
||||
Reference in New Issue
Block a user