2009-07-14 16:39:35 +02:00
|
|
|
#include <ctype.h>
|
2009-04-06 14:07:30 +02:00
|
|
|
|
|
|
|
#include <QtCore/QObject>
|
2009-04-06 16:30:11 +02:00
|
|
|
#include <QtCore/QProcess>
|
|
|
|
#include <QtCore/QFileInfo>
|
2009-07-27 15:19:02 +02:00
|
|
|
#include <QtCore/QMap>
|
2009-07-22 11:00:56 +02:00
|
|
|
#include <QtCore/QMetaMethod>
|
2009-07-20 16:10:37 +02:00
|
|
|
#include <QtCore/QModelIndex>
|
2009-07-16 14:35:49 +02:00
|
|
|
#if QT_VERSION >= 0x040500
|
|
|
|
#include <QtCore/QSharedPointer>
|
|
|
|
#endif
|
2009-07-14 09:57:34 +02:00
|
|
|
#include <QtCore/QStringList>
|
2009-07-15 09:46:55 +02:00
|
|
|
#include <QtCore/QTextCodec>
|
2009-07-20 16:10:37 +02:00
|
|
|
#include <QtGui/QApplication>
|
2009-07-17 10:57:26 +02:00
|
|
|
#include <QtGui/QDialog>
|
2009-07-16 14:35:49 +02:00
|
|
|
#include <QtGui/QImage>
|
2009-07-20 16:10:37 +02:00
|
|
|
#include <QtGui/QPixmap>
|
2009-07-14 09:57:34 +02:00
|
|
|
#include <QtGui/QStandardItemModel>
|
|
|
|
#include <QtGui/QStringListModel>
|
2009-04-06 14:07:30 +02:00
|
|
|
#include <QtTest/QtTest>
|
2009-06-25 15:00:57 +02:00
|
|
|
|
|
|
|
#include <QtCore/private/qobject_p.h>
|
|
|
|
|
2009-04-06 16:30:11 +02:00
|
|
|
//#include <QtTest/qtest_gui.h>
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
#include "gdb/gdbmi.h"
|
|
|
|
#include "tcf/json.h"
|
|
|
|
#include "gdbmacros.h"
|
|
|
|
|
|
|
|
|
|
|
|
#undef NS
|
|
|
|
#ifdef QT_NAMESPACE
|
|
|
|
# define STRINGIFY0(s) #s
|
|
|
|
# define STRINGIFY1(s) STRINGIFY0(s)
|
|
|
|
# define NS STRINGIFY1(QT_NAMESPACE) "::"
|
|
|
|
#else
|
|
|
|
# define NS ""
|
|
|
|
#endif
|
|
|
|
|
2009-04-06 14:07:30 +02:00
|
|
|
using namespace Debugger;
|
|
|
|
using namespace Debugger::Internal;
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi1[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[frame={level=\"0\",addr=\"0x00000000004061ca\","
|
2009-04-06 14:07:30 +02:00
|
|
|
"func=\"main\",file=\"test1.cpp\","
|
|
|
|
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]";
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi2[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[frame={level=\"0\",addr=\"0x00002ac058675840\","
|
2009-04-06 14:07:30 +02:00
|
|
|
"func=\"QApplication\",file=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\","
|
|
|
|
"fullname=\"/home/apoenitz/dev/qt/src/gui/kernel/qapplication.cpp\",line=\"592\"},"
|
|
|
|
"frame={level=\"1\",addr=\"0x00000000004061e0\",func=\"main\",file=\"test1.cpp\","
|
2009-04-06 14:33:45 +02:00
|
|
|
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi3[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[stack={frame={level=\"0\",addr=\"0x00000000004061ca\","
|
2009-04-06 14:07:30 +02:00
|
|
|
"func=\"main\",file=\"test1.cpp\","
|
2009-04-06 14:33:45 +02:00
|
|
|
"fullname=\"/home/apoenitz/work/test1/test1.cpp\",line=\"209\"}}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi4[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"&\"source /home/apoenitz/dev/ide/main/bin/gdb/qt4macros\\n\""
|
2009-04-06 14:07:30 +02:00
|
|
|
"4^done\n";
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi5[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[reason=\"breakpoint-hit\",bkptno=\"1\",thread-id=\"1\","
|
2009-04-06 14:07:30 +02:00
|
|
|
"frame={addr=\"0x0000000000405738\",func=\"main\","
|
|
|
|
"args=[{name=\"argc\",value=\"1\"},{name=\"argv\",value=\"0x7fff1ac78f28\"}],"
|
|
|
|
"file=\"test1.cpp\",fullname=\"/home/apoenitz/work/test1/test1.cpp\","
|
2009-04-06 14:33:45 +02:00
|
|
|
"line=\"209\"}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi8[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[data={locals={{name=\"a\"},{name=\"w\"}}}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi9[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[data={locals=[name=\"baz\",name=\"urgs\",name=\"purgs\"]}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi10[] =
|
2009-04-06 14:33:45 +02:00
|
|
|
"[name=\"urgs\",numchild=\"1\",type=\"Urgs\"]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi11[] =
|
2009-04-06 14:07:30 +02:00
|
|
|
"[{name=\"size\",value=\"1\",type=\"size_t\",readonly=\"true\"},"
|
|
|
|
"{name=\"0\",value=\"one\",type=\"QByteArray\"}]";
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
static const char gdbmi12[] =
|
2009-05-04 20:49:40 +02:00
|
|
|
"[{iname=\"local.hallo\",value=\"\\\"\\\\\\00382\\t\\377\",type=\"QByteArray\","
|
2009-04-06 14:33:45 +02:00
|
|
|
"numchild=\"0\"}]";
|
2009-04-06 14:07:30 +02:00
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
|
|
|
|
static const char jsont1[] =
|
|
|
|
"{\"Size\":100564,\"UID\":0,\"GID\":0,\"Permissions\":33261,"
|
|
|
|
"\"ATime\":1242370878000,\"MTime\":1239154689000}";
|
|
|
|
|
2009-07-08 17:27:45 +02:00
|
|
|
struct Int3 {
|
|
|
|
Int3() { i1 = 42; i2 = 43; i3 = 44; }
|
|
|
|
int i1, i2, i3;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct QString3 {
|
|
|
|
QString3() { s1 = "a"; s2 = "b"; s3 = "c"; }
|
|
|
|
QString s1, s2, s3;
|
|
|
|
};
|
|
|
|
|
2009-04-06 14:07:30 +02:00
|
|
|
class tst_Debugger : public QObject
|
|
|
|
{
|
|
|
|
Q_OBJECT
|
|
|
|
|
|
|
|
public:
|
|
|
|
tst_Debugger() {}
|
|
|
|
|
|
|
|
void testMi(const char* input)
|
|
|
|
{
|
|
|
|
QCOMPARE('\n' + QString::fromLatin1(GdbMi(input).toString(false)),
|
|
|
|
'\n' + QString(input));
|
|
|
|
}
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
void testJson(const char* input)
|
|
|
|
{
|
|
|
|
QCOMPARE('\n' + QString::fromLatin1(JsonValue(input).toString(false)),
|
|
|
|
'\n' + QString(input));
|
|
|
|
}
|
|
|
|
|
2009-04-06 14:07:30 +02:00
|
|
|
private slots:
|
2009-05-18 14:15:25 +02:00
|
|
|
void mi1() { testMi(gdbmi1); }
|
|
|
|
void mi2() { testMi(gdbmi2); }
|
|
|
|
void mi3() { testMi(gdbmi3); }
|
|
|
|
//void mi4() { testMi(gdbmi4); }
|
|
|
|
void mi5() { testMi(gdbmi5); }
|
|
|
|
void mi8() { testMi(gdbmi8); }
|
|
|
|
void mi9() { testMi(gdbmi9); }
|
|
|
|
void mi10() { testMi(gdbmi10); }
|
|
|
|
void mi11() { testMi(gdbmi11); }
|
|
|
|
//void mi12() { testMi(gdbmi12); }
|
|
|
|
|
|
|
|
void json1() { testJson(jsont1); }
|
2009-04-16 12:52:29 +02:00
|
|
|
|
|
|
|
void infoBreak();
|
2009-06-23 10:24:25 +02:00
|
|
|
void niceType();
|
|
|
|
void niceType_data();
|
2009-04-16 12:52:29 +02:00
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
void dumperCompatibility();
|
2009-07-14 16:39:35 +02:00
|
|
|
void dumpQAbstractItemModel();
|
|
|
|
void dumpQByteArray();
|
2009-07-10 14:57:50 +02:00
|
|
|
void dumpQChar();
|
2009-07-10 17:43:47 +02:00
|
|
|
void dumpQDateTime();
|
2009-07-14 09:57:34 +02:00
|
|
|
void dumpQDir();
|
2009-07-10 14:57:50 +02:00
|
|
|
void dumpQFile();
|
2009-07-14 09:57:34 +02:00
|
|
|
void dumpQFileInfo();
|
2009-06-25 15:00:57 +02:00
|
|
|
void dumpQHash();
|
2009-07-16 14:35:49 +02:00
|
|
|
void dumpQImage();
|
|
|
|
void dumpQImageData();
|
2009-07-09 09:55:19 +02:00
|
|
|
void dumpQList_int();
|
|
|
|
void dumpQList_char();
|
|
|
|
void dumpQList_QString();
|
|
|
|
void dumpQList_QString3();
|
|
|
|
void dumpQList_Int3();
|
2009-07-27 15:19:02 +02:00
|
|
|
void dumpQMapNode();
|
2009-06-25 15:00:57 +02:00
|
|
|
void dumpQObject();
|
2009-07-27 15:19:02 +02:00
|
|
|
void dumpQObjectChildList();
|
2009-07-17 10:57:26 +02:00
|
|
|
void dumpQObjectMethodList();
|
|
|
|
void dumpQObjectPropertyList();
|
2009-07-20 16:10:37 +02:00
|
|
|
void dumpQObjectSignal();
|
2009-07-22 11:00:56 +02:00
|
|
|
void dumpQObjectSignalList();
|
2009-07-24 11:53:32 +02:00
|
|
|
void dumpQObjectSlot();
|
|
|
|
void dumpQObjectSlotList();
|
2009-07-20 16:10:37 +02:00
|
|
|
void dumpQPixmap();
|
2009-07-16 14:35:49 +02:00
|
|
|
#if QT_VERSION >= 0x040500
|
|
|
|
void dumpQSharedPointer();
|
|
|
|
#endif
|
2009-06-25 15:00:57 +02:00
|
|
|
void dumpQString();
|
2009-07-15 09:46:55 +02:00
|
|
|
void dumpQTextCodec();
|
2009-07-09 10:26:54 +02:00
|
|
|
void dumpQVariant_invalid();
|
|
|
|
void dumpQVariant_QString();
|
|
|
|
void dumpQVariant_QStringList();
|
2009-06-25 15:00:57 +02:00
|
|
|
void dumpStdVector();
|
|
|
|
|
2009-05-18 14:15:25 +02:00
|
|
|
public slots:
|
2009-04-06 16:30:11 +02:00
|
|
|
void runQtc();
|
2009-04-07 09:40:56 +02:00
|
|
|
|
|
|
|
public slots:
|
|
|
|
void readStandardOutput();
|
|
|
|
void readStandardError();
|
|
|
|
|
|
|
|
private:
|
2009-04-07 09:51:21 +02:00
|
|
|
QProcess m_proc; // the Qt Creator process
|
2009-07-10 14:57:50 +02:00
|
|
|
|
2009-07-14 16:39:35 +02:00
|
|
|
void dumpQAbstractItemModelHelper(QAbstractItemModel &m);
|
|
|
|
void dumpQByteArrayHelper(QByteArray &ba);
|
2009-07-10 14:57:50 +02:00
|
|
|
void dumpQCharHelper(QChar &c);
|
2009-07-10 17:43:47 +02:00
|
|
|
void dumpQDateTimeHelper(QDateTime &d);
|
2009-07-14 09:57:34 +02:00
|
|
|
void dumpQDirHelper(QDir &d);
|
2009-07-10 17:43:47 +02:00
|
|
|
void dumpQFileHelper(const QString &name, bool exists);
|
2009-07-16 14:35:49 +02:00
|
|
|
void dumpQImageHelper(QImage &img);
|
|
|
|
void dumpQImageDataHelper(QImage &img);
|
2009-07-27 15:19:02 +02:00
|
|
|
template <typename K, typename V> void dumpQMapNodeHelper(QMap<K, V> &m);
|
|
|
|
void dumpQObjectChildListHelper(QObject &o);
|
2009-07-17 10:57:26 +02:00
|
|
|
void dumpQObjectMethodListHelper(QObject &obj);
|
|
|
|
void dumpQObjectPropertyListHelper(QObject &obj);
|
2009-07-20 16:10:37 +02:00
|
|
|
void dumpQObjectSignalHelper(QObject &o, int sigNum);
|
2009-07-22 11:00:56 +02:00
|
|
|
void dumpQObjectSignalListHelper(QObject &o);
|
2009-07-24 11:53:32 +02:00
|
|
|
void dumpQObjectSlotHelper(QObject &o, int slot);
|
|
|
|
void dumpQObjectSlotListHelper(QObject &o);
|
2009-07-20 16:10:37 +02:00
|
|
|
void dumpQPixmapHelper(QPixmap &p);
|
2009-07-16 14:35:49 +02:00
|
|
|
#if QT_VERSION >= 0x040500
|
|
|
|
template <typename T>
|
|
|
|
void dumpQSharedPointerHelper(QSharedPointer<T> &ptr, bool isSimple);
|
|
|
|
#endif
|
2009-07-15 09:46:55 +02:00
|
|
|
void dumpQTextCodecHelper(QTextCodec *codec);
|
2009-04-06 14:07:30 +02:00
|
|
|
};
|
|
|
|
|
2009-04-07 09:51:21 +02:00
|
|
|
static QByteArray stripped(QByteArray ba)
|
|
|
|
{
|
|
|
|
for (int i = ba.size(); --i >= 0; ) {
|
|
|
|
if (ba.at(i) == '\n' || ba.at(i) == ' ')
|
|
|
|
ba.chop(1);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return ba;
|
|
|
|
}
|
|
|
|
|
2009-04-16 12:52:29 +02:00
|
|
|
void tst_Debugger::infoBreak()
|
|
|
|
{
|
2009-07-10 14:57:50 +02:00
|
|
|
// This tests the regular expression used in GdbEngine::extractDataFromInfoBreak
|
2009-04-16 12:52:29 +02:00
|
|
|
// to discover breakpoints in constructors.
|
|
|
|
|
|
|
|
// Copied from gdbengine.cpp:
|
|
|
|
|
|
|
|
QRegExp re("MULTIPLE.*(0x[0-9a-f]+) in (.*)\\s+at (.*):([\\d]+)([^\\d]|$)");
|
|
|
|
re.setMinimal(true);
|
|
|
|
|
|
|
|
QCOMPARE(re.indexIn(
|
|
|
|
"2 breakpoint keep y <MULTIPLE> 0x0040168e\n"
|
|
|
|
"2.1 y 0x0040168e "
|
|
|
|
"in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7\n"
|
|
|
|
"2.2 y 0x00401792 "
|
|
|
|
"in MainWindow::MainWindow(QWidget*) at mainwindow.cpp:7\n"), 33);
|
|
|
|
QCOMPARE(re.cap(1), QString("0x0040168e"));
|
|
|
|
QCOMPARE(re.cap(2).trimmed(), QString("MainWindow::MainWindow(QWidget*)"));
|
|
|
|
QCOMPARE(re.cap(3), QString("mainwindow.cpp"));
|
|
|
|
QCOMPARE(re.cap(4), QString("7"));
|
|
|
|
|
|
|
|
|
|
|
|
QCOMPARE(re.indexIn(
|
|
|
|
"Num Type Disp Enb Address What"
|
|
|
|
"4 breakpoint keep y <MULTIPLE> 0x00000000004066ad"
|
|
|
|
"4.1 y 0x00000000004066ad in CTorTester"
|
|
|
|
" at /main/tests/manual/gdbdebugger/simple/app.cpp:124"), 88);
|
|
|
|
|
|
|
|
QCOMPARE(re.cap(1), QString("0x00000000004066ad"));
|
|
|
|
QCOMPARE(re.cap(2).trimmed(), QString("CTorTester"));
|
|
|
|
QCOMPARE(re.cap(3), QString("/main/tests/manual/gdbdebugger/simple/app.cpp"));
|
|
|
|
QCOMPARE(re.cap(4), QString("124"));
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
//
|
|
|
|
// type simplification
|
|
|
|
//
|
|
|
|
|
2009-06-23 10:24:25 +02:00
|
|
|
static QString chopConst(QString type)
|
|
|
|
{
|
|
|
|
while (1) {
|
|
|
|
if (type.startsWith("const"))
|
|
|
|
type = type.mid(5);
|
|
|
|
else if (type.startsWith(' '))
|
|
|
|
type = type.mid(1);
|
|
|
|
else if (type.endsWith("const"))
|
|
|
|
type.chop(5);
|
|
|
|
else if (type.endsWith(' '))
|
|
|
|
type.chop(1);
|
|
|
|
else
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString niceType(QString type)
|
|
|
|
{
|
|
|
|
type.replace('*', '@');
|
|
|
|
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
|
|
|
int start = type.indexOf("std::allocator<");
|
|
|
|
if (start == -1)
|
2009-07-10 14:57:50 +02:00
|
|
|
break;
|
2009-06-23 10:24:25 +02:00
|
|
|
// search for matching '>'
|
|
|
|
int pos;
|
|
|
|
int level = 0;
|
|
|
|
for (pos = start + 12; pos < type.size(); ++pos) {
|
|
|
|
int c = type.at(pos).unicode();
|
|
|
|
if (c == '<') {
|
|
|
|
++level;
|
|
|
|
} else if (c == '>') {
|
|
|
|
--level;
|
|
|
|
if (level == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
QString alloc = type.mid(start, pos + 1 - start).trimmed();
|
|
|
|
QString inner = alloc.mid(15, alloc.size() - 16).trimmed();
|
|
|
|
//qDebug() << "MATCH: " << pos << alloc << inner;
|
|
|
|
|
|
|
|
if (inner == QLatin1String("char"))
|
|
|
|
// std::string
|
|
|
|
type.replace(QLatin1String("basic_string<char, std::char_traits<char>, "
|
|
|
|
"std::allocator<char> >"), QLatin1String("string"));
|
|
|
|
else if (inner == QLatin1String("wchar_t"))
|
|
|
|
// std::wstring
|
|
|
|
type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, "
|
|
|
|
"std::allocator<wchar_t> >"), QLatin1String("wstring"));
|
|
|
|
|
|
|
|
// std::vector, std::deque, std::list
|
|
|
|
QRegExp re1(QString("(vector|list|deque)<%1, %2\\s*>").arg(inner, alloc));
|
|
|
|
if (re1.indexIn(type) != -1)
|
|
|
|
type.replace(re1.cap(0), QString("%1<%2>").arg(re1.cap(1), inner));
|
|
|
|
|
|
|
|
|
|
|
|
// std::stack
|
|
|
|
QRegExp re6(QString("stack<%1, std::deque<%2> >").arg(inner, inner));
|
|
|
|
re6.setMinimal(true);
|
|
|
|
if (re6.indexIn(type) != -1)
|
|
|
|
type.replace(re6.cap(0), QString("stack<%1>").arg(inner));
|
|
|
|
|
|
|
|
// std::set
|
|
|
|
QRegExp re4(QString("set<%1, std::less<%2>, %3\\s*>").arg(inner, inner, alloc));
|
|
|
|
re4.setMinimal(true);
|
|
|
|
if (re4.indexIn(type) != -1)
|
|
|
|
type.replace(re4.cap(0), QString("set<%1>").arg(inner));
|
|
|
|
|
|
|
|
|
|
|
|
// std::map
|
|
|
|
if (inner.startsWith("std::pair<")) {
|
|
|
|
// search for outermost ','
|
|
|
|
int pos;
|
|
|
|
int level = 0;
|
|
|
|
for (pos = 10; pos < inner.size(); ++pos) {
|
|
|
|
int c = inner.at(pos).unicode();
|
|
|
|
if (c == '<')
|
|
|
|
++level;
|
|
|
|
else if (c == '>')
|
|
|
|
--level;
|
|
|
|
else if (c == ',' && level == 0)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
QString ckey = inner.mid(10, pos - 10);
|
|
|
|
QString key = chopConst(ckey);
|
|
|
|
QString value = inner.mid(pos + 2, inner.size() - 3 - pos);
|
|
|
|
|
|
|
|
QRegExp re5(QString("map<%1, %2, std::less<%3>, %4\\s*>")
|
|
|
|
.arg(key, value, key, alloc));
|
|
|
|
re5.setMinimal(true);
|
|
|
|
if (re5.indexIn(type) != -1)
|
|
|
|
type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value));
|
|
|
|
else {
|
|
|
|
QRegExp re7(QString("map<const %1, %2, std::less<const %3>, %4\\s*>")
|
|
|
|
.arg(key, value, key, alloc));
|
|
|
|
re7.setMinimal(true);
|
|
|
|
if (re7.indexIn(type) != -1)
|
|
|
|
type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
type.replace('@', '*');
|
|
|
|
type.replace(QLatin1String(" >"), QString(QLatin1Char('>')));
|
|
|
|
return type;
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::niceType()
|
|
|
|
{
|
|
|
|
// cf. watchutils.cpp
|
|
|
|
QFETCH(QString, input);
|
|
|
|
QFETCH(QString, simplified);
|
|
|
|
QCOMPARE(::niceType(input), simplified);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::niceType_data()
|
|
|
|
{
|
|
|
|
QTest::addColumn<QString>("input");
|
|
|
|
QTest::addColumn<QString>("simplified");
|
|
|
|
|
|
|
|
QTest::newRow("list")
|
|
|
|
<< "std::list<int, std::allocator<int> >"
|
|
|
|
<< "std::list<int>";
|
|
|
|
|
|
|
|
QTest::newRow("combined")
|
|
|
|
<< "std::vector<std::list<int, std::allocator<int> >*, "
|
|
|
|
"std::allocator<std::list<int, std::allocator<int> >*> >"
|
|
|
|
<< "std::vector<std::list<int>*>";
|
|
|
|
|
|
|
|
QTest::newRow("stack")
|
|
|
|
<< "std::stack<int, std::deque<int, std::allocator<int> > >"
|
|
|
|
<< "std::stack<int>";
|
2009-07-10 14:57:50 +02:00
|
|
|
|
2009-06-23 10:24:25 +02:00
|
|
|
QTest::newRow("map")
|
|
|
|
<< "std::map<myns::QString, Foo, std::less<myns::QString>, "
|
|
|
|
"std::allocator<std::pair<const myns::QString, Foo> > >"
|
|
|
|
<< "std::map<myns::QString, Foo>";
|
|
|
|
|
|
|
|
QTest::newRow("map2")
|
|
|
|
<< "std::map<const char*, Foo, std::less<const char*>, "
|
|
|
|
"std::allocator<std::pair<const char* const, Foo> > >"
|
|
|
|
<< "std::map<const char*, Foo>";
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
//
|
|
|
|
// Dumpers
|
|
|
|
//
|
|
|
|
|
|
|
|
static void testDumper(QByteArray expected0, void *data, QByteArray outertype,
|
|
|
|
bool dumpChildren, QByteArray innertype = "", QByteArray exp = "",
|
|
|
|
int extraInt0 = 0, int extraInt1 = 0, int extraInt2 = 0, int extraInt3 = 0)
|
2009-07-10 14:57:50 +02:00
|
|
|
{
|
|
|
|
sprintf(xDumpInBuffer, "%s%c%s%c%s%c%s%c%s%c",
|
2009-06-25 15:00:57 +02:00
|
|
|
outertype.data(), 0, "iname", 0, exp.data(), 0,
|
|
|
|
innertype.data(), 0, "iname", 0);
|
|
|
|
void *res = qDumpObjectData440(2, 42, data, dumpChildren,
|
|
|
|
extraInt0, extraInt1, extraInt2, extraInt3);
|
|
|
|
QString expected(expected0);
|
|
|
|
char buf[100];
|
|
|
|
sprintf(buf, "%p", data);
|
|
|
|
if (!expected.startsWith('t') && !expected.startsWith('f'))
|
|
|
|
expected = "tiname='$I',addr='$A'," + expected;
|
|
|
|
expected.replace("$I", "iname");
|
|
|
|
expected.replace("$T", QByteArray(outertype));
|
|
|
|
expected.replace("$A", QByteArray(buf));
|
|
|
|
expected.replace('\'', '"');
|
|
|
|
QString actual____ = QString::fromLatin1(xDumpOutBuffer);
|
|
|
|
actual____.replace('\'', '"');
|
|
|
|
QCOMPARE(res, xDumpOutBuffer);
|
|
|
|
if (actual____ != expected) {
|
|
|
|
QStringList l1 = actual____.split(",");
|
|
|
|
QStringList l2 = expected.split(",");
|
|
|
|
for (int i = 0; i < l1.size() && i < l2.size(); ++i) {
|
|
|
|
if (l1.at(i) == l2.at(i))
|
|
|
|
qDebug() << "== " << l1.at(i);
|
|
|
|
else
|
|
|
|
qDebug() << "!= " << l1.at(i) << l2.at(i);
|
|
|
|
}
|
|
|
|
if (l1.size() != l2.size())
|
|
|
|
qDebug() << "!= size: " << l1.size() << l2.size();
|
|
|
|
}
|
|
|
|
QCOMPARE(actual____, expected);
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray str(const void *p)
|
|
|
|
{
|
|
|
|
char buf[100];
|
|
|
|
sprintf(buf, "%p", p);
|
|
|
|
return buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const void *deref(const void *p)
|
|
|
|
{
|
|
|
|
return *reinterpret_cast<const char* const*>(p);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumperCompatibility()
|
|
|
|
{
|
2009-07-16 12:57:07 +02:00
|
|
|
// Ensure that no arbitrary padding is introduced by QVectorTypedData.
|
|
|
|
const size_t qVectorDataSize = 16;
|
|
|
|
QCOMPARE(sizeof(QVectorData), qVectorDataSize);
|
|
|
|
QCOMPARE( ((size_t)&(((QVectorTypedData<int> *)(0))->array)), qVectorDataSize);
|
2009-06-25 15:00:57 +02:00
|
|
|
}
|
|
|
|
|
2009-07-14 09:57:34 +02:00
|
|
|
static const QByteArray utfToBase64(const QString &string)
|
|
|
|
{
|
|
|
|
return QByteArray(reinterpret_cast<const char *>(string.utf16()), 2 * string.size()).toBase64();
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *boolToVal(bool b)
|
|
|
|
{
|
|
|
|
return b ? "'true'" : "'false'";
|
|
|
|
}
|
|
|
|
|
|
|
|
static const QByteArray ptrToBa(const void *p)
|
|
|
|
{
|
|
|
|
return QByteArray().append(p == 0 ?
|
|
|
|
"<null>" :
|
|
|
|
QString("0x") + QString::number((quintptr) p, 16));
|
|
|
|
}
|
|
|
|
|
|
|
|
static const QByteArray generateQStringSpec(const QString& str)
|
|
|
|
{
|
|
|
|
return QByteArray("value='").append(utfToBase64(str)).
|
|
|
|
append("',type='"NS"QString',numchild='0',valueencoded='2'");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const QByteArray generateBoolSpec(bool b)
|
|
|
|
{
|
|
|
|
return QByteArray("value=").append(boolToVal(b)).append(",type='bool',numchild='0'");
|
|
|
|
}
|
|
|
|
|
2009-07-15 09:46:55 +02:00
|
|
|
template <typename T>
|
|
|
|
static const QByteArray generateIntegerSpec(T n, QString type)
|
|
|
|
{
|
|
|
|
return QByteArray("value='").append(QString::number(n)).append("',type='").
|
|
|
|
append(type).append("',numchild='0'");
|
|
|
|
}
|
|
|
|
|
2009-07-14 09:57:34 +02:00
|
|
|
static const QByteArray generateLongSpec(long n)
|
|
|
|
{
|
2009-07-15 09:46:55 +02:00
|
|
|
return generateIntegerSpec(n, "long");
|
|
|
|
}
|
|
|
|
|
|
|
|
static const QByteArray generateIntSpec(int n)
|
|
|
|
{
|
|
|
|
return generateIntegerSpec(n, "int");
|
2009-07-14 09:57:34 +02:00
|
|
|
}
|
|
|
|
|
2009-07-14 16:39:35 +02:00
|
|
|
void tst_Debugger::dumpQAbstractItemModelHelper(QAbstractItemModel &m)
|
2009-07-14 09:57:34 +02:00
|
|
|
{
|
|
|
|
QByteArray expected("tiname='iname',addr='");
|
|
|
|
QString address = ptrToBa(&m);
|
|
|
|
expected.append(address).append("',type='"NS"QAbstractItemModel',value='(").
|
|
|
|
append(QString::number(m.rowCount())).append(",").
|
|
|
|
append(QString::number(m.columnCount())).append(")',numchild='1',").
|
|
|
|
append("children=[{numchild='1',name='"NS"QObject',addr='").append(address).
|
|
|
|
append("',value='").append(utfToBase64(m.objectName())).
|
|
|
|
append("',valueencoded='2',type='"NS"QObject',displayedtype='").
|
|
|
|
append(m.metaObject()->className()).append("'}");
|
|
|
|
for (int row = 0; row < m.rowCount(); ++row) {
|
|
|
|
for (int column = 0; column < m.columnCount(); ++column) {
|
|
|
|
QModelIndex mi = m.index(row, column);
|
|
|
|
expected.append(",{name='[").append(QString::number(row)).append(",").
|
|
|
|
append(QString::number(column)).append("]',value='").
|
|
|
|
append(utfToBase64(m.data(mi).toString())).
|
|
|
|
append("',valueencoded='2',numchild='1',addr='$").
|
|
|
|
append(QString::number(mi.row())).append(",").append(QString::number(mi.column())).
|
|
|
|
append(",").append(ptrToBa(mi.internalPointer())).append(",").
|
|
|
|
append(ptrToBa(mi.model())).append("',type='"NS"QAbstractItem'}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &m, NS"QAbstractItemModel", true);
|
|
|
|
}
|
|
|
|
|
2009-07-14 16:39:35 +02:00
|
|
|
void tst_Debugger::dumpQAbstractItemModel()
|
2009-07-14 09:57:34 +02:00
|
|
|
{
|
|
|
|
// Case 1: No rows, one column.
|
|
|
|
QStringList strList;
|
|
|
|
QStringListModel model(strList);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model);
|
2009-07-14 09:57:34 +02:00
|
|
|
|
|
|
|
// Case 2: One row, one column.
|
|
|
|
strList << "String 1";
|
|
|
|
model.setStringList(strList);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model);
|
2009-07-14 09:57:34 +02:00
|
|
|
|
|
|
|
// Case 3: Two rows, one column.
|
|
|
|
strList << "String 2";
|
|
|
|
model.setStringList(strList);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model);
|
2009-07-14 09:57:34 +02:00
|
|
|
|
|
|
|
// Case 4: No rows, two columns.
|
|
|
|
QStandardItemModel model2(0, 2);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model2);
|
2009-07-14 09:57:34 +02:00
|
|
|
|
|
|
|
// Case 5: One row, two columns.
|
|
|
|
QStandardItem item1("Item (0,0)");
|
|
|
|
QStandardItem item2("(Item (0,1)");
|
|
|
|
model2.appendRow(QList<QStandardItem *>() << &item1 << &item2);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model2);
|
2009-07-14 09:57:34 +02:00
|
|
|
|
|
|
|
// Case 6: Two rows, two columns
|
|
|
|
QStandardItem item3("Item (1,0");
|
|
|
|
QStandardItem item4("Item (1,1)");
|
|
|
|
model2.appendRow(QList<QStandardItem *>() << &item3 << &item4);
|
2009-07-14 16:39:35 +02:00
|
|
|
dumpQAbstractItemModelHelper(model);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQByteArrayHelper(QByteArray &ba)
|
|
|
|
{
|
|
|
|
QString size = QString::number(ba.size());
|
|
|
|
QByteArray value;
|
|
|
|
if (ba.size() <= 100)
|
|
|
|
value = ba;
|
|
|
|
else
|
|
|
|
value.append(ba.left(100).toBase64()).append(" <size: ").append(size).
|
|
|
|
append(", cut...>");
|
|
|
|
QByteArray expected("value='");
|
|
|
|
expected.append(value.toBase64()).append("',valueencoded='1',type='"NS"QByteArray',numchild='").
|
|
|
|
append(size).append("',childtype='char',childnumchild='0',children=[");
|
|
|
|
for (int i = 0; i < ba.size(); ++i) {
|
|
|
|
char c = ba.at(i);
|
|
|
|
char printedVal = isprint(c) && c != '\'' && c != '"' ? c : '?';
|
|
|
|
QString hexNumber = QString::number(c, 16);
|
|
|
|
if (hexNumber.size() < 2)
|
|
|
|
hexNumber.prepend("0");
|
|
|
|
expected.append("{value='").append(hexNumber).append(" (").
|
|
|
|
append(QString::number(c)).append(" '").append(printedVal).append("')'}");
|
|
|
|
if (i != ba.size() - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &ba, NS"QByteArray", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQByteArray()
|
|
|
|
{
|
|
|
|
// Case 1: Empty object.
|
|
|
|
QByteArray ba;
|
|
|
|
dumpQByteArrayHelper(ba);
|
|
|
|
|
|
|
|
// Case 2: One element.
|
|
|
|
ba.append('a');
|
|
|
|
dumpQByteArrayHelper(ba);
|
|
|
|
|
|
|
|
// Case 3: Two elements.
|
|
|
|
ba.append('b');
|
|
|
|
dumpQByteArrayHelper(ba);
|
|
|
|
|
|
|
|
// Case 4: > 100 elements.
|
|
|
|
ba = QByteArray(101, 'a');
|
|
|
|
|
|
|
|
// Case 5: Regular and special characters and the replacement character.
|
|
|
|
ba = QByteArray("abc\a\n\r\e\'\"?");
|
|
|
|
dumpQByteArrayHelper(ba);
|
2009-07-14 09:57:34 +02:00
|
|
|
}
|
|
|
|
|
2009-07-10 14:57:50 +02:00
|
|
|
void tst_Debugger::dumpQCharHelper(QChar &c)
|
|
|
|
{
|
|
|
|
char ch = c.isPrint() && c.unicode() < 127 ? c.toAscii() : '?';
|
|
|
|
testDumper(QByteArray("value=''") + QByteArray(1, ch) + QByteArray("', ucs=")
|
|
|
|
+ QByteArray(QString::number(c.unicode()).toAscii())
|
|
|
|
+ QByteArray("',numchild='0'"), &c, NS"QChar", false);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQChar()
|
|
|
|
{
|
|
|
|
// Case 1: Printable ASCII character.
|
|
|
|
QChar c('X');
|
|
|
|
dumpQCharHelper(c);
|
|
|
|
|
|
|
|
// Case 2: Printable non-ASCII character.
|
|
|
|
c = QChar(0x600);
|
|
|
|
dumpQCharHelper(c);
|
|
|
|
|
|
|
|
// Case 3: Non-printable ASCII character.
|
|
|
|
c = QChar::fromAscii('\a');
|
|
|
|
dumpQCharHelper(c);
|
|
|
|
|
|
|
|
// Case 4: Non-printable non-ASCII character.
|
|
|
|
c = QChar(0x9f);
|
|
|
|
dumpQCharHelper(c);
|
|
|
|
|
|
|
|
// Case 5: Printable ASCII Character that looks like the replacement character.
|
|
|
|
c = QChar::fromAscii('?');
|
|
|
|
dumpQCharHelper(c);
|
|
|
|
}
|
|
|
|
|
2009-07-10 17:43:47 +02:00
|
|
|
void tst_Debugger::dumpQDateTimeHelper(QDateTime &d)
|
|
|
|
{
|
|
|
|
QByteArray expected("value='");
|
|
|
|
if (d.isNull())
|
|
|
|
expected.append("(null)',");
|
|
|
|
else
|
|
|
|
expected.append(utfToBase64(d.toString())).append("',valueencoded='2',");
|
|
|
|
expected.append("type='$T',numchild='3',children=[");
|
2009-07-14 09:57:34 +02:00
|
|
|
expected.append("{name='isNull',").append(generateBoolSpec(d.isNull())).append("},");
|
2009-07-15 09:46:55 +02:00
|
|
|
expected.append("{name='toTime_t',").append(generateLongSpec((d.toTime_t()))).append("},");
|
2009-07-10 17:43:47 +02:00
|
|
|
expected.append("{name='toString',").append(generateQStringSpec(d.toString())).append("},");
|
|
|
|
expected.append("{name='toString_(ISO)',").append(generateQStringSpec(d.toString(Qt::ISODate))).append("},");
|
|
|
|
expected.append("{name='toString_(SystemLocale)',").
|
|
|
|
append(generateQStringSpec(d.toString(Qt::SystemLocaleDate))).append("},");
|
|
|
|
expected.append("{name='toString_(Locale)',").
|
|
|
|
append(generateQStringSpec(d.toString(Qt::LocaleDate))).append("}]");
|
|
|
|
testDumper(expected, &d, NS"QDateTime", true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQDateTime()
|
|
|
|
{
|
|
|
|
// Case 1: Null object.
|
|
|
|
QDateTime d;
|
|
|
|
dumpQDateTimeHelper(d);
|
|
|
|
|
|
|
|
// Case 2: Non-null object.
|
|
|
|
d = QDateTime::currentDateTime();
|
|
|
|
dumpQDateTimeHelper(d);
|
|
|
|
}
|
|
|
|
|
2009-07-14 09:57:34 +02:00
|
|
|
void tst_Debugger::dumpQDirHelper(QDir &d)
|
|
|
|
{
|
|
|
|
testDumper(QByteArray("value='") + utfToBase64(d.absolutePath())
|
|
|
|
+ QByteArray("',valueencoded='2',type='"NS"QDir',numchild='3',children=[{name='absolutePath',")
|
|
|
|
+ generateQStringSpec(d.absolutePath()) + QByteArray("},{name='canonicalPath',")
|
|
|
|
+ generateQStringSpec(d.canonicalPath()) + QByteArray("}]"), &d, NS"QDir", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQDir()
|
|
|
|
{
|
|
|
|
// Case 1: Current working directory.
|
|
|
|
QDir dir = QDir::current();
|
|
|
|
dumpQDirHelper(dir);
|
|
|
|
|
|
|
|
// Case 2: Root directory.
|
|
|
|
dir = QDir::root();
|
|
|
|
dumpQDirHelper(dir);
|
|
|
|
}
|
|
|
|
|
2009-07-10 14:57:50 +02:00
|
|
|
void tst_Debugger::dumpQFileHelper(const QString &name, bool exists)
|
|
|
|
{
|
|
|
|
QFile file(name);
|
2009-07-10 17:43:47 +02:00
|
|
|
QByteArray filenameAsBase64 = utfToBase64(name);
|
2009-07-10 14:57:50 +02:00
|
|
|
testDumper(
|
|
|
|
QByteArray("value='") + filenameAsBase64 +
|
|
|
|
QByteArray("',valueencoded='2',type='$T',numchild='2',children=[{name='fileName',value='") +
|
|
|
|
filenameAsBase64 +
|
|
|
|
QByteArray("',type='"NS"QString',numchild='0',valueencoded='2'},{name='exists',value=") +
|
2009-07-10 17:43:47 +02:00
|
|
|
QByteArray(boolToVal(exists)) + QByteArray(",type='bool',numchild='0'}]"),
|
2009-07-10 14:57:50 +02:00
|
|
|
&file, NS"QFile", true);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQFile()
|
|
|
|
{
|
|
|
|
// Case 1: Empty file name => Does not exist.
|
|
|
|
dumpQFileHelper("", false);
|
|
|
|
|
|
|
|
// Case 2: File that is known to exist.
|
|
|
|
QTemporaryFile file;
|
|
|
|
file.open();
|
|
|
|
dumpQFileHelper(file.fileName(), true);
|
|
|
|
|
|
|
|
// Case 3: File with a name that most likely does not exist.
|
|
|
|
dumpQFileHelper("jfjfdskjdflsdfjfdls", false);
|
|
|
|
}
|
|
|
|
|
2009-07-14 09:57:34 +02:00
|
|
|
void tst_Debugger::dumpQFileInfo()
|
|
|
|
{
|
|
|
|
QFileInfo fi(".");
|
|
|
|
QByteArray expected("value='");
|
|
|
|
expected.append(utfToBase64(fi.filePath())).
|
|
|
|
append("',valueencoded='2',type='"NS"QFileInfo',numchild='3',").
|
|
|
|
append("children=[").
|
|
|
|
append("{name='absolutePath',").append(generateQStringSpec(fi.absolutePath())).append("},").
|
|
|
|
append("{name='absoluteFilePath',").append(generateQStringSpec(fi.absoluteFilePath())).append("},").
|
|
|
|
append("{name='canonicalPath',").append(generateQStringSpec(fi.canonicalPath())).append("},").
|
|
|
|
append("{name='canonicalFilePath',").append(generateQStringSpec(fi.canonicalFilePath())).append("},").
|
|
|
|
append("{name='completeBaseName',").append(generateQStringSpec(fi.completeBaseName())).append("},").
|
|
|
|
append("{name='completeSuffix',").append(generateQStringSpec(fi.completeSuffix())).append("},").
|
|
|
|
append("{name='baseName',").append(generateQStringSpec(fi.baseName())).append("},").
|
|
|
|
#ifdef Q_OS_MACX
|
|
|
|
append("{name='isBundle',").append(generateBoolSpec(fi.isBundle()).append("},").
|
|
|
|
append("{name='bundleName',").append(generateQStringSpec(fi.bundleName())).append("'},").
|
|
|
|
#endif
|
|
|
|
append("{name='completeSuffix',").append(generateQStringSpec(fi.completeSuffix())).append("},").
|
|
|
|
append("{name='fileName',").append(generateQStringSpec(fi.fileName())).append("},").
|
|
|
|
append("{name='filePath',").append(generateQStringSpec(fi.filePath())).append("},").
|
|
|
|
append("{name='group',").append(generateQStringSpec(fi.group())).append("},").
|
|
|
|
append("{name='owner',").append(generateQStringSpec(fi.owner())).append("},").
|
|
|
|
append("{name='path',").append(generateQStringSpec(fi.path())).append("},").
|
|
|
|
append("{name='groupid',").append(generateLongSpec(fi.groupId())).append("},").
|
|
|
|
append("{name='ownerid',").append(generateLongSpec(fi.ownerId())).append("},").
|
|
|
|
append("{name='permissions',").append(generateLongSpec(fi.permissions())).append("},").
|
|
|
|
append("{name='caching',").append(generateBoolSpec(fi.caching())).append("},").
|
|
|
|
append("{name='exists',").append(generateBoolSpec(fi.exists())).append("},").
|
|
|
|
append("{name='isAbsolute',").append(generateBoolSpec(fi.isAbsolute())).append("},").
|
|
|
|
append("{name='isDir',").append(generateBoolSpec(fi.isDir())).append("},").
|
|
|
|
append("{name='isExecutable',").append(generateBoolSpec(fi.isExecutable())).append("},").
|
|
|
|
append("{name='isFile',").append(generateBoolSpec(fi.isFile())).append("},").
|
|
|
|
append("{name='isHidden',").append(generateBoolSpec(fi.isHidden())).append("},").
|
|
|
|
append("{name='isReadable',").append(generateBoolSpec(fi.isReadable())).append("},").
|
|
|
|
append("{name='isRelative',").append(generateBoolSpec(fi.isRelative())).append("},").
|
|
|
|
append("{name='isRoot',").append(generateBoolSpec(fi.isRoot())).append("},").
|
|
|
|
append("{name='isSymLink',").append(generateBoolSpec(fi.isSymLink())).append("},").
|
|
|
|
append("{name='isWritable',").append(generateBoolSpec(fi.isWritable())).append("},").
|
|
|
|
append("{name='created',value='").append(utfToBase64(fi.created().toString())).
|
|
|
|
append("',valueencoded='2',type='"NS"QDateTime',numchild='1'},").
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
???
|
|
|
|
d.beginHash();
|
|
|
|
d.putItem("name", "created");
|
|
|
|
d.putItem("value", info.created().toString());
|
|
|
|
d.putItem("valueencoded", "2");
|
|
|
|
d.beginItem("exp");
|
|
|
|
d.put("(("NSX"QFileInfo"NSY"*)").put(d.data).put(")->created()");
|
|
|
|
d.endItem();
|
|
|
|
d.putItem("type", NS"QDateTime");
|
|
|
|
d.putItem("numchild", "1");
|
|
|
|
d.endHash();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
append("]");
|
|
|
|
|
|
|
|
|
|
|
|
// testDumper(expected, &fi, NS"QFileInfo", true);
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
void tst_Debugger::dumpQHash()
|
|
|
|
{
|
|
|
|
QHash<QString, QList<int> > hash;
|
|
|
|
hash.insert("Hallo", QList<int>());
|
|
|
|
hash.insert("Welt", QList<int>() << 1);
|
|
|
|
hash.insert("!", QList<int>() << 1 << 2);
|
|
|
|
hash.insert("!", QList<int>() << 1 << 2);
|
|
|
|
}
|
|
|
|
|
2009-07-16 14:35:49 +02:00
|
|
|
void tst_Debugger::dumpQImageHelper(QImage &img)
|
|
|
|
{
|
|
|
|
QByteArray expected = QByteArray("value='(").
|
|
|
|
append(QString::number(img.width())).append("x").
|
|
|
|
append(QString::number(img.height())).append(")',type='"NS"QImage',").
|
|
|
|
append("numchild='1',children=[{name='data',type='"NS"QImageData',").
|
|
|
|
append("addr='").append(ptrToBa(&img)).append("'}]");
|
|
|
|
testDumper(expected, &img, NS"QImage", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQImage()
|
|
|
|
{
|
|
|
|
// Case 1: Null image.
|
|
|
|
QImage img;
|
|
|
|
dumpQImageHelper(img);
|
|
|
|
|
|
|
|
// Case 2: Normal image.
|
|
|
|
img = QImage(3, 700, QImage::Format_RGB555);
|
|
|
|
dumpQImageHelper(img);
|
|
|
|
|
|
|
|
// Case 3: Invalid image.
|
|
|
|
img = QImage(100, 0, QImage::Format_Invalid);
|
|
|
|
dumpQImageHelper(img);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQImageDataHelper(QImage &img)
|
|
|
|
{
|
|
|
|
const QByteArray ba(QByteArray::fromRawData((const char*) img.bits(), img.numBytes()));
|
|
|
|
QByteArray expected = QByteArray("tiname='$I',addr='$A',type='"NS"QImageData',").
|
|
|
|
append("numchild='0',value='<hover here>',valuetooltipencoded='1',").
|
|
|
|
append("valuetooltipsize='").append(QString::number(ba.size())).append("',").
|
|
|
|
append("valuetooltip='").append(ba.toBase64()).append("'");
|
|
|
|
testDumper(expected, &img, NS"QImageData", false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQImageData()
|
|
|
|
{
|
|
|
|
// Case 1: Null image.
|
|
|
|
QImage img;
|
|
|
|
dumpQImageDataHelper(img);
|
|
|
|
|
|
|
|
// Case 2: Normal image.
|
|
|
|
img = QImage(3, 700, QImage::Format_RGB555);
|
|
|
|
dumpQImageDataHelper(img);
|
|
|
|
|
|
|
|
// Case 3: Invalid image.
|
|
|
|
img = QImage(100, 0, QImage::Format_Invalid);
|
|
|
|
dumpQImageDataHelper(img);
|
|
|
|
}
|
|
|
|
|
2009-07-09 09:55:19 +02:00
|
|
|
void tst_Debugger::dumpQList_int()
|
2009-07-08 17:27:45 +02:00
|
|
|
{
|
|
|
|
QList<int> ilist;
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',children=[]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&ilist, NS"QList", true, "int");
|
|
|
|
ilist.append(1);
|
|
|
|
ilist.append(2);
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',childtype='int',childnumchild='0',children=["
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&ilist.at(0)) + "',value='1'},"
|
|
|
|
"{addr='" + str(&ilist.at(1)) + "',value='2'}]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&ilist, NS"QList", true, "int");
|
2009-07-09 09:55:19 +02:00
|
|
|
}
|
2009-07-08 17:27:45 +02:00
|
|
|
|
2009-07-09 09:55:19 +02:00
|
|
|
void tst_Debugger::dumpQList_char()
|
|
|
|
{
|
2009-07-08 17:27:45 +02:00
|
|
|
QList<char> clist;
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',children=[]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&clist, NS"QList", true, "char");
|
|
|
|
clist.append('a');
|
|
|
|
clist.append('b');
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',childtype='char',childnumchild='0',children=["
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&clist.at(0)) + "',value=''a', ascii=97'},"
|
|
|
|
"{addr='" + str(&clist.at(1)) + "',value=''b', ascii=98'}]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&clist, NS"QList", true, "char");
|
2009-07-09 09:55:19 +02:00
|
|
|
}
|
2009-07-08 17:27:45 +02:00
|
|
|
|
2009-07-09 09:55:19 +02:00
|
|
|
void tst_Debugger::dumpQList_QString()
|
|
|
|
{
|
2009-07-08 17:27:45 +02:00
|
|
|
QList<QString> slist;
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',children=[]",
|
|
|
|
&slist, NS"QList", true, NS"QString");
|
2009-07-08 17:27:45 +02:00
|
|
|
slist.append("a");
|
|
|
|
slist.append("b");
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='1',childtype='"NS"QString',childnumchild='0',children=["
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&slist.at(0)) + "',value='YQA=',valueencoded='2'},"
|
|
|
|
"{addr='" + str(&slist.at(1)) + "',value='YgA=',valueencoded='2'}]",
|
2009-07-10 11:08:26 +02:00
|
|
|
&slist, NS"QList", true, NS"QString");
|
2009-07-09 09:55:19 +02:00
|
|
|
}
|
2009-07-08 17:27:45 +02:00
|
|
|
|
2009-07-09 09:55:19 +02:00
|
|
|
void tst_Debugger::dumpQList_Int3()
|
|
|
|
{
|
2009-07-08 17:27:45 +02:00
|
|
|
QList<Int3> i3list;
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='0',children=[]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&i3list, NS"QList", true, "Int3");
|
|
|
|
i3list.append(Int3());
|
|
|
|
i3list.append(Int3());
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
|
|
|
"internal='0',childtype='Int3',children=["
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&i3list.at(0)) + "'},"
|
|
|
|
"{addr='" + str(&i3list.at(1)) + "'}]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&i3list, NS"QList", true, "Int3");
|
2009-07-09 09:55:19 +02:00
|
|
|
}
|
2009-07-08 17:27:45 +02:00
|
|
|
|
2009-07-09 09:55:19 +02:00
|
|
|
void tst_Debugger::dumpQList_QString3()
|
|
|
|
{
|
2009-07-08 17:27:45 +02:00
|
|
|
QList<QString3> s3list;
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"internal='0',children=[]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&s3list, NS"QList", true, "QString3");
|
|
|
|
s3list.append(QString3());
|
|
|
|
s3list.append(QString3());
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
|
|
|
"internal='0',childtype='QString3',children=["
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&s3list.at(0)) + "'},"
|
|
|
|
"{addr='" + str(&s3list.at(1)) + "'}]",
|
2009-07-08 17:27:45 +02:00
|
|
|
&s3list, NS"QList", true, "QString3");
|
|
|
|
}
|
|
|
|
|
2009-07-27 15:19:02 +02:00
|
|
|
// Helper functions for QMap* dumping.
|
|
|
|
template <typename T> static const char *typeToString(const T &)
|
|
|
|
{
|
|
|
|
return "<unknown type>";
|
|
|
|
}
|
|
|
|
template <typename T> const QByteArray valToString(const T &)
|
|
|
|
{
|
|
|
|
return "<unknown value>";
|
|
|
|
}
|
|
|
|
template <> const QByteArray valToString(const int &n)
|
|
|
|
{
|
|
|
|
return QByteArray().append(QString::number(n));
|
|
|
|
}
|
|
|
|
template <> const QByteArray valToString(const QString &s)
|
|
|
|
{
|
|
|
|
return QByteArray(utfToBase64(s)).append("',valueencoded='2");
|
|
|
|
}
|
|
|
|
template <> const char *typeToString(const int &)
|
|
|
|
{
|
|
|
|
return "int";
|
|
|
|
}
|
|
|
|
template <> const char *typeToString(const QString &)
|
|
|
|
{
|
|
|
|
return NS"QString";
|
|
|
|
}
|
|
|
|
template <typename T> static const char *typeToNumchild(const T &)
|
|
|
|
{
|
|
|
|
return "1";
|
|
|
|
}
|
|
|
|
template <> const char *typeToNumchild(const int &)
|
|
|
|
{
|
|
|
|
return "0";
|
|
|
|
}
|
|
|
|
template <> const char *typeToNumchild(const QString &)
|
|
|
|
{
|
|
|
|
return "0";
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename K, typename V>
|
|
|
|
void tst_Debugger::dumpQMapNodeHelper(QMap<K, V> &map)
|
|
|
|
{
|
|
|
|
for (typename QMap<K, V>::iterator it = map.begin(); it != map.end(); ++it) {
|
|
|
|
const K &key = it.key();
|
|
|
|
const V &val = it.value();
|
|
|
|
const char * const keyType = typeToString(key);
|
|
|
|
QByteArray expected = QByteArray("value='',numchild='2',childtype='").
|
|
|
|
append(keyType).append("',childnumchild='").append(typeToNumchild(key)).
|
|
|
|
append("',children=[{name='key',addr='").append(ptrToBa(&key)).
|
|
|
|
append("',value='").append(valToString(key)).append("'},{name='value',addr='").
|
|
|
|
append(ptrToBa(&val)).append("',value='").append(valToString(val)).
|
|
|
|
append("'}]");
|
|
|
|
QByteArray valType = QByteArray(typeToString(val));
|
|
|
|
QByteArray nodeType = keyType + QByteArray("@") + valType;
|
|
|
|
typedef QMapNode<K, V> node_t;
|
|
|
|
testDumper(expected, *reinterpret_cast<QMapData **>(&it), NS"QMapNode",
|
|
|
|
true, nodeType, "", 0, 0, sizeof(node_t), offsetof(node_t, value));
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQMapNode()
|
|
|
|
{
|
|
|
|
// Case 1: Empty Map.
|
|
|
|
QMap<int, QString> map;
|
|
|
|
dumpQMapNodeHelper(map);
|
|
|
|
|
|
|
|
// Case 2: One element.
|
|
|
|
map[3] = "String 1";
|
|
|
|
dumpQMapNodeHelper(map);
|
|
|
|
|
|
|
|
// Case 3: Two elements.
|
|
|
|
map[10] = "String 2";
|
|
|
|
dumpQMapNodeHelper(map);
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
void tst_Debugger::dumpQObject()
|
|
|
|
{
|
|
|
|
QObject parent;
|
|
|
|
testDumper("value='',valueencoded='2',type='$T',displayedtype='QObject',"
|
|
|
|
"numchild='4'",
|
|
|
|
&parent, NS"QObject", false);
|
|
|
|
testDumper("value='',valueencoded='2',type='$T',displayedtype='QObject',"
|
|
|
|
"numchild='4',children=["
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='properties',addr='$A',type='$TPropertyList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<1 items>',numchild='1'},"
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='signals',addr='$A',type='$TSignalList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<2 items>',numchild='2'},"
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='slots',addr='$A',type='$TSlotList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<2 items>',numchild='2'},"
|
2009-07-08 17:27:45 +02:00
|
|
|
"{name='parent',value='0x0',type='$T *',numchild='0'},"
|
2009-06-25 15:00:57 +02:00
|
|
|
"{name='className',value='QObject',type='',numchild='0'}]",
|
|
|
|
&parent, NS"QObject", true);
|
2009-07-09 09:55:19 +02:00
|
|
|
|
|
|
|
#if 0
|
|
|
|
testDumper("numchild='2',value='<2 items>',type='QObjectSlotList',"
|
|
|
|
"children=[{name='2',value='deleteLater()',"
|
2009-07-09 10:26:54 +02:00
|
|
|
"numchild='0',addr='$A',type='QObjectSlot'},"
|
2009-06-25 15:00:57 +02:00
|
|
|
"{name='3',value='_q_reregisterTimers(void*)',"
|
2009-07-09 10:26:54 +02:00
|
|
|
"numchild='0',addr='$A',type='QObjectSlot'}]",
|
2009-06-25 15:00:57 +02:00
|
|
|
&parent, NS"QObjectSlotList", true);
|
2009-07-09 09:55:19 +02:00
|
|
|
#endif
|
2009-06-25 15:00:57 +02:00
|
|
|
|
|
|
|
parent.setObjectName("A Parent");
|
|
|
|
testDumper("value='QQAgAFAAYQByAGUAbgB0AA==',valueencoded='2',type='$T',"
|
|
|
|
"displayedtype='QObject',numchild='4'",
|
|
|
|
&parent, NS"QObject", false);
|
|
|
|
QObject child(&parent);
|
|
|
|
testDumper("value='',valueencoded='2',type='$T',"
|
|
|
|
"displayedtype='QObject',numchild='4'",
|
|
|
|
&child, NS"QObject", false);
|
|
|
|
child.setObjectName("A Child");
|
|
|
|
QByteArray ba ="value='QQAgAEMAaABpAGwAZAA=',valueencoded='2',type='$T',"
|
|
|
|
"displayedtype='QObject',numchild='4',children=["
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='properties',addr='$A',type='$TPropertyList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<1 items>',numchild='1'},"
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='signals',addr='$A',type='$TSignalList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<2 items>',numchild='2'},"
|
2009-07-09 10:26:54 +02:00
|
|
|
"{name='slots',addr='$A',type='$TSlotList',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"value='<2 items>',numchild='2'},"
|
|
|
|
"{name='parent',addr='" + str(&parent) + "',"
|
|
|
|
"value='QQAgAFAAYQByAGUAbgB0AA==',valueencoded='2',type='$T',"
|
2009-07-08 17:27:45 +02:00
|
|
|
"displayedtype='QObject',numchild='1'},"
|
2009-06-25 15:00:57 +02:00
|
|
|
"{name='className',value='QObject',type='',numchild='0'}]";
|
|
|
|
testDumper(ba, &child, NS"QObject", true);
|
|
|
|
QObject::connect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
|
|
|
|
testDumper(ba, &child, NS"QObject", true);
|
|
|
|
QObject::disconnect(&child, SIGNAL(destroyed()), qApp, SLOT(quit()));
|
|
|
|
testDumper(ba, &child, NS"QObject", true);
|
|
|
|
child.setObjectName("A renamed Child");
|
|
|
|
testDumper("value='QQAgAHIAZQBuAGEAbQBlAGQAIABDAGgAaQBsAGQA',valueencoded='2',"
|
|
|
|
"type='$T',displayedtype='QObject',numchild='4'",
|
|
|
|
&child, NS"QObject", false);
|
|
|
|
}
|
|
|
|
|
2009-07-27 15:19:02 +02:00
|
|
|
void tst_Debugger::dumpQObjectChildListHelper(QObject &o)
|
|
|
|
{
|
|
|
|
const QObjectList children = o.children();
|
|
|
|
const int size = children.size();
|
|
|
|
const QString sizeStr = QString::number(size);
|
|
|
|
QByteArray expected = QByteArray("numchild='").append(sizeStr).append("',value='<").
|
|
|
|
append(sizeStr).append(" items>',type='"NS"QObjectChildList',children=[");
|
|
|
|
for (int i = 0; i < size; ++i) {
|
|
|
|
const QObject *child = children.at(i);
|
|
|
|
expected.append("{addr='").append(ptrToBa(child)).append("',value='").
|
|
|
|
append(utfToBase64(child->objectName())).
|
|
|
|
append("',valueencoded='2',type='"NS"QObject',displayedtype='").
|
|
|
|
append(child->metaObject()->className()).append("',numchild='1'}");
|
|
|
|
if (i < size - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &o, NS"QObjectChildList", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectChildList()
|
|
|
|
{
|
|
|
|
// Case 1: Object with no children.
|
|
|
|
QObject o;
|
|
|
|
dumpQObjectChildListHelper(o);
|
|
|
|
|
|
|
|
// Case 2: Object with one child.
|
|
|
|
QObject o2(&o);
|
|
|
|
dumpQObjectChildListHelper(o);
|
|
|
|
|
|
|
|
// Case 3: Object with two children.
|
|
|
|
QObject o3(&o);
|
|
|
|
dumpQObjectChildListHelper(o);
|
|
|
|
}
|
|
|
|
|
2009-07-17 10:57:26 +02:00
|
|
|
void tst_Debugger::dumpQObjectMethodListHelper(QObject &obj)
|
|
|
|
{
|
|
|
|
const QMetaObject *mo = obj.metaObject();
|
|
|
|
const int methodCount = mo->methodCount();
|
|
|
|
QByteArray expected = QByteArray("addr='<synthetic>',type='"NS"QObjectMethodList',").
|
|
|
|
append("numchild='").append(QString::number(methodCount)).
|
|
|
|
append("',childtype='QMetaMethod::Method',childnumchild='0',children=[");
|
|
|
|
for (int i = 0; i != methodCount; ++i) {
|
|
|
|
const QMetaMethod & method = mo->method(i);
|
|
|
|
int mt = method.methodType();
|
|
|
|
expected.append("{name='").append(QString::number(i)).append(" ").
|
|
|
|
append(QString::number(mo->indexOfMethod(method.signature()))).
|
|
|
|
append(" ").append(method.signature()).append("',value='").
|
|
|
|
append(mt == QMetaMethod::Signal ? "<Signal>" : "<Slot>").
|
|
|
|
append(" (").append(QString::number(mt)).append(")'}");
|
|
|
|
if (i != methodCount - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &obj, NS"QObjectMethodList", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectMethodList()
|
|
|
|
{
|
|
|
|
QStringListModel m;
|
|
|
|
dumpQObjectMethodListHelper(m);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectPropertyListHelper(QObject &obj)
|
|
|
|
{
|
|
|
|
const QMetaObject *mo = obj.metaObject();
|
|
|
|
const QString propertyCount = QString::number(mo->propertyCount());
|
|
|
|
QByteArray expected = QByteArray("addr='<synthetic>',type='"NS"QObjectPropertyList',").
|
|
|
|
append("numchild='").append(propertyCount).append("',value='<").
|
|
|
|
append(propertyCount).append(" items>',children=[");
|
|
|
|
for (int i = mo->propertyCount() - 1; i >= 0; --i) {
|
|
|
|
const QMetaProperty & prop = mo->property(i);
|
|
|
|
expected.append("{name='").append(prop.name()).append("',");
|
|
|
|
switch (prop.type()) {
|
|
|
|
case QVariant::String:
|
|
|
|
expected.append("type='").append(prop.typeName()).append("',value='").
|
|
|
|
append(utfToBase64(prop.read(&obj).toString())).
|
|
|
|
append("',valueencoded='2',numchild='0'");
|
|
|
|
break;
|
|
|
|
case QVariant::Bool:
|
|
|
|
expected.append("type='").append(prop.typeName()).append("',value=").
|
|
|
|
append(boolToVal(prop.read(&obj).toBool())).append("numchild='0'");
|
|
|
|
break;
|
|
|
|
case QVariant::Int: {
|
|
|
|
const int value = prop.read(&obj).toInt();
|
|
|
|
const QString valueString = QString::number(value);
|
|
|
|
if (prop.isEnumType() || prop.isFlagType()) {
|
|
|
|
const QMetaEnum &me = prop.enumerator();
|
|
|
|
QByteArray type = me.scope();
|
|
|
|
if (!type.isEmpty())
|
|
|
|
type += "::";
|
|
|
|
type += me.name();
|
|
|
|
expected.append("type='").append(type.constData()).append("',value='");
|
|
|
|
if (prop.isEnumType()) {
|
|
|
|
if (const char *enumValue = me.valueToKey(value))
|
|
|
|
expected.append(enumValue);
|
|
|
|
else
|
|
|
|
expected.append(valueString);
|
|
|
|
} else {
|
|
|
|
const QByteArray &flagsValue = me.valueToKeys(value);
|
|
|
|
expected.append(flagsValue.isEmpty() ? valueString : flagsValue.constData());
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
expected.append("value='").append(valueString);
|
|
|
|
}
|
|
|
|
expected.append("',numchild='0'");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
expected.append("addr='").append(ptrToBa(&obj)).
|
|
|
|
append("',type'"NS"QObjectPropertyList',numchild='1'");
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
expected.append("}");
|
|
|
|
if (i > 0)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &obj, NS"QObjectPropertyList", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectPropertyList()
|
|
|
|
{
|
|
|
|
// Case 1: Model without a parent.
|
|
|
|
QStringListModel m(QStringList() << "Test1" << "Test2");
|
|
|
|
dumpQObjectPropertyListHelper(m);
|
|
|
|
|
|
|
|
// Case 2: Model with a parent.
|
|
|
|
QStringListModel m2(&m);
|
|
|
|
dumpQObjectPropertyListHelper(m2);
|
|
|
|
}
|
|
|
|
|
2009-07-20 16:10:37 +02:00
|
|
|
static const char *connectionType(uint type)
|
|
|
|
{
|
|
|
|
Qt::ConnectionType connType = static_cast<Qt::ConnectionType>(type);
|
|
|
|
const char *output;
|
|
|
|
switch (connType) {
|
|
|
|
case Qt::AutoConnection: output = "auto"; break;
|
|
|
|
case Qt::DirectConnection: output = "direct"; break;
|
|
|
|
case Qt::QueuedConnection: output = "queued"; break;
|
|
|
|
case Qt::BlockingQueuedConnection: output = "blockingqueued"; break;
|
|
|
|
case 3: output = "autocompat"; break;
|
2009-07-20 16:21:43 +02:00
|
|
|
#if QT_VERSION >= 0x040600
|
2009-07-20 16:10:37 +02:00
|
|
|
case Qt::UniqueConnection: output = "unique"; break;
|
2009-07-20 16:21:43 +02:00
|
|
|
#endif
|
2009-07-20 16:10:37 +02:00
|
|
|
};
|
|
|
|
return output;
|
|
|
|
};
|
|
|
|
|
2009-07-22 11:00:56 +02:00
|
|
|
class Cheater : public QObject
|
2009-07-20 16:10:37 +02:00
|
|
|
{
|
2009-07-22 11:00:56 +02:00
|
|
|
public:
|
2009-07-24 11:53:32 +02:00
|
|
|
static const QObjectPrivate *getPrivate(const QObject &o)
|
2009-07-20 16:10:37 +02:00
|
|
|
{
|
2009-07-24 11:53:32 +02:00
|
|
|
return dynamic_cast<const QObjectPrivate *>(static_cast<const Cheater&>(o).d_ptr);
|
2009-07-22 11:00:56 +02:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
typedef QVector<QObjectPrivate::ConnectionList> ConnLists;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSignalHelper(QObject &o, int sigNum)
|
|
|
|
{
|
2009-07-20 16:10:37 +02:00
|
|
|
QByteArray expected("addr='<synthetic>',numchild='1',type='"NS"QObjectSignal'");
|
|
|
|
#if QT_VERSION >= 0x040400
|
|
|
|
expected.append(",children=[");
|
|
|
|
const QObjectPrivate *p = Cheater::getPrivate(o);
|
|
|
|
Q_ASSERT(p != 0);
|
|
|
|
const ConnLists *connLists = reinterpret_cast<const ConnLists *>(p->connectionLists);
|
|
|
|
QObjectPrivate::ConnectionList connList =
|
|
|
|
connLists != 0 && connLists->size() > sigNum ?
|
|
|
|
connLists->at(sigNum) : QObjectPrivate::ConnectionList();
|
|
|
|
for (int i = 0; i < connList.size(); ++i) {
|
|
|
|
const QObjectPrivate::Connection *conn = connList.at(i);
|
|
|
|
const QString iStr = QString::number(i);
|
|
|
|
expected.append("{name='").append(iStr).append(" receiver',");
|
|
|
|
if (conn->receiver == &o)
|
|
|
|
expected.append("value='").append(utfToBase64("<this>")).
|
|
|
|
append("',valueencoded='2',type='").append(o.metaObject()->className()).
|
|
|
|
append("',numchild='0',addr='").append(ptrToBa(&o)).append("'");
|
|
|
|
else if (conn->receiver == 0)
|
|
|
|
expected.append("value='0x0',type='"NS"QObject *',numchild='0'");
|
|
|
|
else
|
|
|
|
expected.append("addr='").append(ptrToBa(conn->receiver)).append("',value='").
|
|
|
|
append(utfToBase64(conn->receiver->objectName())).append("',valueencoded='2',").
|
|
|
|
append("type='"NS"QObject',displayedtype='").
|
|
|
|
append(conn->receiver->metaObject()->className()).append("',numchild='1'");
|
|
|
|
expected.append("},{name='").append(iStr).append(" slot',type='',value='");
|
|
|
|
if (conn->receiver != 0)
|
|
|
|
expected.append(conn->receiver->metaObject()->method(conn->method).signature());
|
|
|
|
else
|
|
|
|
expected.append("<invalid receiver>");
|
|
|
|
expected.append("',numchild='0'},{name='").append(iStr).append(" type',type='',value='<").
|
|
|
|
append(connectionType(conn->connectionType)).append(" connection>',").
|
|
|
|
append("numchild='0'}");
|
|
|
|
if (i < connList.size() - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("],numchild='").append(QString::number(connList.size())).append("'");
|
|
|
|
#endif
|
|
|
|
testDumper(expected, &o, NS"QObjectSignal", true, "", "", sigNum);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSignal()
|
|
|
|
{
|
|
|
|
// Case 1: Simple QObject.
|
|
|
|
QObject o;
|
|
|
|
o.setObjectName("Test");
|
|
|
|
dumpQObjectSignalHelper(o, 0);
|
|
|
|
|
|
|
|
// Case 2: QAbstractItemModel with no connections.
|
|
|
|
QStringListModel m(QStringList() << "Test1" << "Test2");
|
|
|
|
const QMetaObject *mo = m.metaObject();
|
|
|
|
QList<int> signalIndices;
|
|
|
|
for (int i = 0; i < mo->methodCount(); ++i) {
|
|
|
|
const QMetaMethod &mm = mo->method(i);
|
|
|
|
if (mm.methodType() == QMetaMethod::Signal) {
|
|
|
|
int signalIndex = mo->indexOfSignal(mm.signature());
|
|
|
|
Q_ASSERT(signalIndex != -1);
|
|
|
|
signalIndices.append(signalIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach(const int signalIndex, signalIndices)
|
|
|
|
dumpQObjectSignalHelper(m, signalIndex);
|
|
|
|
|
|
|
|
// Case 3: QAbstractItemModel with connections to itself and to another
|
|
|
|
// object, using different connection types.
|
|
|
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
|
|
|
|
&o, SLOT(deleteLater()), Qt::DirectConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(revert()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::BlockingQueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(deleteLater()), Qt::AutoConnection);
|
|
|
|
#if QT_VERSION >= 0x040600
|
|
|
|
connect(&m, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
|
|
|
|
&m, SLOT(revert()), Qt::UniqueConnection);
|
|
|
|
#endif
|
|
|
|
foreach(const int signalIndex, signalIndices)
|
|
|
|
dumpQObjectSignalHelper(m, signalIndex);
|
|
|
|
}
|
|
|
|
|
2009-07-22 11:00:56 +02:00
|
|
|
void tst_Debugger::dumpQObjectSignalListHelper(QObject &o)
|
|
|
|
{
|
|
|
|
const QMetaObject *mo = o.metaObject();
|
|
|
|
QList<QMetaMethod> methods;
|
|
|
|
for (int i = 0; i < mo->methodCount(); ++i) {
|
|
|
|
const QMetaMethod &method = mo->method(i);
|
|
|
|
if (method.methodType() == QMetaMethod::Signal)
|
|
|
|
methods.append(method);
|
|
|
|
}
|
|
|
|
QString sizeStr = QString::number(methods.size());
|
|
|
|
QByteArray addrString = ptrToBa(&o);
|
|
|
|
QByteArray expected = QByteArray("tiname='$I',addr='$A',type='QObjectSignalList',value='<").
|
|
|
|
append(sizeStr).append(" items>',addr='").append(addrString).append("',numchild='").
|
|
|
|
append(sizeStr).append("'");
|
|
|
|
#if QT_VERSION >= 0x040400
|
|
|
|
expected.append(",children=[");
|
|
|
|
const QObjectPrivate *p = Cheater::getPrivate(o);
|
|
|
|
Q_ASSERT(p != 0);
|
|
|
|
const ConnLists *connLists = reinterpret_cast<const ConnLists *>(p->connectionLists);
|
|
|
|
for (int i = 0; i < methods.size(); ++i) {
|
|
|
|
const char * const signature = methods.at(i).signature();
|
|
|
|
int sigNum = mo->indexOfSignal(signature);
|
|
|
|
QObjectPrivate::ConnectionList connList =
|
|
|
|
connLists != 0 && connLists->size() > sigNum ?
|
|
|
|
connLists->at(sigNum) : QObjectPrivate::ConnectionList();
|
|
|
|
expected.append("{name='").append(QString::number(sigNum)).append("',value='").
|
|
|
|
append(signature).append("',numchild='").append(QString::number(connList.size())).
|
|
|
|
append("',addr='").append(addrString).append("',type='"NS"QObjectSignal'}");
|
|
|
|
if (i < methods.size() - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
expected.append("]");
|
|
|
|
#endif
|
|
|
|
testDumper(expected, &o, NS"QObjectSignalList", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSignalList()
|
2009-07-20 16:10:37 +02:00
|
|
|
{
|
2009-07-22 11:00:56 +02:00
|
|
|
// Case 1: Simple QObject.
|
|
|
|
QObject o;
|
|
|
|
o.setObjectName("Test");
|
|
|
|
dumpQObjectSignalListHelper(o);
|
2009-07-20 16:10:37 +02:00
|
|
|
|
2009-07-22 11:00:56 +02:00
|
|
|
// Case 2: QAbstractItemModel with no connections.
|
|
|
|
QStringListModel m(QStringList() << "Test1" << "Test2");
|
|
|
|
dumpQObjectSignalListHelper(m);
|
|
|
|
|
|
|
|
// Case 3: QAbstractItemModel with connections to itself and to another
|
|
|
|
// object, using different connection types.
|
|
|
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
|
|
|
|
&o, SLOT(deleteLater()), Qt::DirectConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(revert()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::BlockingQueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(deleteLater()), Qt::AutoConnection);
|
|
|
|
dumpQObjectSignalListHelper(m);
|
|
|
|
}
|
|
|
|
|
2009-07-24 11:53:32 +02:00
|
|
|
void tst_Debugger::dumpQObjectSlotHelper(QObject &o, int slot)
|
|
|
|
{
|
|
|
|
// TODO: This test passes, but it's because both the dumper and
|
|
|
|
// the test are broken (no slots are ever listed).
|
|
|
|
QByteArray expected = QByteArray("addr='").append(ptrToBa(&o)).
|
|
|
|
append("',numchild='1',type='"NS"QObjectSlot'");
|
|
|
|
#if QT_VERSION >= 0x040400
|
|
|
|
expected.append(",children=[");
|
|
|
|
const QObjectPrivate *p = Cheater::getPrivate(o);
|
|
|
|
int numChild = 0;
|
|
|
|
#if QT_VERSION >= 0x040600
|
|
|
|
int senderNum = 0;
|
|
|
|
for (QObjectPrivate::Connection *senderConn = p->senders;
|
|
|
|
senderConn != 0; senderConn = senderConn->next, ++senderNum) {
|
|
|
|
#else
|
|
|
|
for (senderNum = 0; senderNum < p->senders.size(); ++senderNum) {
|
|
|
|
QObjectPrivate::Connection *senderConn = &p->senders.at(senderNum);
|
|
|
|
#endif
|
|
|
|
QString senderNumStr = QString::number(senderNum);
|
|
|
|
QObject *sender = senderConn->sender;
|
|
|
|
int signal = senderConn->method;
|
|
|
|
const ConnLists *connLists =
|
|
|
|
reinterpret_cast<const ConnLists *>(p->connectionLists);
|
|
|
|
const QObjectPrivate::ConnectionList &connList =
|
|
|
|
connLists != 0 && connLists->size() > signal ?
|
|
|
|
connLists->at(signal) : QObjectPrivate::ConnectionList();
|
|
|
|
for (int i = 0; i < connList.size(); ++i) {
|
|
|
|
const QObjectPrivate::Connection *conn = connList.at(i);
|
|
|
|
if (conn->receiver == &o && conn->method == slot) {
|
|
|
|
++numChild;
|
|
|
|
const QMetaMethod &method = sender->metaObject()->method(signal);
|
|
|
|
if (numChild > 0)
|
|
|
|
expected.append(",");
|
|
|
|
expected.append("{name='").append(senderNumStr).append(" sender',");
|
|
|
|
if (sender == &o) {
|
|
|
|
expected.append("value='").append(utfToBase64("<this>")).
|
|
|
|
append("',type='").append(o.metaObject()->className()).
|
|
|
|
append("',numchild='0',addr='").append(ptrToBa(&o)).append("'");
|
|
|
|
} else if (sender != 0) {
|
|
|
|
expected.append("addr='").append(ptrToBa(sender)).
|
|
|
|
append(",value='").append(utfToBase64(sender->objectName())).
|
|
|
|
append("',valueencoded='2',type='"NS"QObject',displayedtype='").
|
|
|
|
append(sender->metaObject()->className()).
|
|
|
|
append("',numchild='1'");
|
|
|
|
} else {
|
|
|
|
expected.append("value='0x0',type='"NS"QObject *',numchild='0'");
|
|
|
|
}
|
|
|
|
expected.append("},{name='").append(senderNumStr).
|
|
|
|
append(" signal',type='',value='").append(method.signature()).
|
|
|
|
append("',numchild='0'},{name='").append(senderNumStr).
|
|
|
|
append(" type',type='',value='<'").append(connectionType(conn->method)).
|
|
|
|
append(" connection>',numchild='0'}");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expected.append("],numchild='0'");
|
|
|
|
#endif
|
|
|
|
testDumper(expected, &o, NS"QObjectSlot", true, "", "", slot);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSlot()
|
|
|
|
{
|
|
|
|
// Case 1: Simple QObject.
|
|
|
|
QObject o;
|
|
|
|
o.setObjectName("Test");
|
|
|
|
dumpQObjectSlotHelper(o, o.metaObject()->indexOfSlot("deleteLater()"));
|
|
|
|
|
|
|
|
// Case 2: QAbstractItemModel with no connections.
|
|
|
|
QStringListModel m(QStringList() << "Test1" << "Test2");
|
|
|
|
const QMetaObject *mo = m.metaObject();
|
|
|
|
QList<int> slotIndices;
|
|
|
|
for (int i = 0; i < mo->methodCount(); ++i) {
|
|
|
|
const QMetaMethod &mm = mo->method(i);
|
|
|
|
if (mm.methodType() == QMetaMethod::Slot) {
|
|
|
|
int slotIndex = mo->indexOfSlot(mm.signature());
|
|
|
|
Q_ASSERT(slotIndex != -1);
|
|
|
|
slotIndices.append(slotIndex);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
foreach(const int slotIndex, slotIndices)
|
|
|
|
dumpQObjectSlotHelper(m, slotIndex);
|
|
|
|
|
|
|
|
// Case 3: QAbstractItemModel with connections to itself and to another
|
|
|
|
// object, using different connection types.
|
|
|
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
|
|
|
|
&o, SLOT(deleteLater()), Qt::DirectConnection);
|
|
|
|
connect(&o, SIGNAL(destroyed(QObject *)),
|
|
|
|
&m, SLOT(revert()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::BlockingQueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(deleteLater()), Qt::AutoConnection);
|
|
|
|
#if QT_VERSION >= 0x040600
|
|
|
|
connect(&m, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)),
|
|
|
|
&m, SLOT(revert()), Qt::UniqueConnection);
|
|
|
|
#endif
|
|
|
|
foreach(const int slotIndex, slotIndices)
|
|
|
|
dumpQObjectSlotHelper(m, slotIndex);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSlotListHelper(QObject &o)
|
|
|
|
{
|
|
|
|
const QMetaObject *mo = o.metaObject();
|
|
|
|
QList<QMetaMethod> slotList;;
|
|
|
|
for (int i = 0; i < mo->methodCount(); ++i) {
|
|
|
|
const QMetaMethod &method = mo->method(i);
|
|
|
|
if (method.methodType() == QMetaMethod::Slot)
|
|
|
|
slotList.append(method);
|
|
|
|
}
|
|
|
|
const QString numSlotsStr = QString::number(slotList.size());
|
|
|
|
QByteArray expected = QByteArray("numchild='").append(numSlotsStr).
|
|
|
|
append("',value='<").append(numSlotsStr).
|
|
|
|
append(" items>',type='"NS"QObjectSlotList',children=[");
|
|
|
|
#if QT_VERSION >= 0x040400
|
|
|
|
const QObjectPrivate *p = Cheater::getPrivate(o);
|
|
|
|
for (int i = 0; i < slotList.size(); ++i) {
|
|
|
|
const QMetaMethod &method = slotList.at(i);
|
|
|
|
int k = mo->indexOfSlot(method.signature());
|
|
|
|
Q_ASSERT(k != -1);
|
|
|
|
expected.append("{name='").append(QString::number(k)).
|
|
|
|
append("',value='").append(method.signature());
|
|
|
|
int numChild = 0;
|
|
|
|
#if QT_VERSION >= 0x040600
|
|
|
|
int s = 0;
|
|
|
|
for (QObjectPrivate::Connection *senderList = p->senders; senderList != 0;
|
|
|
|
senderList = senderList->next, ++s) {
|
|
|
|
#else
|
|
|
|
for (int s = 0; s != p->senders.size(); ++s) {
|
|
|
|
const Connection *senderList = &p->senders.at(s);
|
|
|
|
#endif // QT_VERSION >= 0x040600
|
|
|
|
const QObject *sender = senderList->sender;
|
|
|
|
int signal = senderList->method;
|
|
|
|
const ConnLists *connLists =
|
|
|
|
reinterpret_cast<const ConnLists *>(Cheater::getPrivate(*sender)->connectionLists);
|
|
|
|
const QObjectPrivate::ConnectionList &connList =
|
|
|
|
connLists != 0 && connLists->size() > signal ?
|
|
|
|
connLists->at(signal) : QObjectPrivate::ConnectionList();
|
|
|
|
for (int c = 0; c != connList.size(); ++c) {
|
|
|
|
const QObjectPrivate::Connection *conn = connList.at(c);
|
|
|
|
if (conn->receiver == &o && conn->method == k)
|
|
|
|
++numChild;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
expected.append("',numchild='").append(QString::number(numChild)).
|
|
|
|
append("',addr='").append(ptrToBa(&o)).append("',type='"NS"QObjectSlot'}");
|
|
|
|
if (i < slotList.size() - 1)
|
|
|
|
expected.append(",");
|
|
|
|
}
|
|
|
|
#endif // QT_VERSION >= 0x040400
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, &o, NS"QObjectSlotList", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQObjectSlotList()
|
|
|
|
{
|
|
|
|
// Case 1: Simple QObject.
|
|
|
|
QObject o;
|
|
|
|
o.setObjectName("Test");
|
|
|
|
dumpQObjectSlotListHelper(o);
|
|
|
|
|
|
|
|
// Case 2: QAbstractItemModel with no connections.
|
|
|
|
QStringListModel m(QStringList() << "Test1" << "Test2");
|
|
|
|
dumpQObjectSlotListHelper(m);
|
|
|
|
|
|
|
|
// Case 3: QAbstractItemModel with connections to itself and to another
|
|
|
|
// object, using different connection types.
|
|
|
|
qRegisterMetaType<QModelIndex>("QModelIndex");
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeInserted(const QModelIndex &, int, int)),
|
|
|
|
&o, SLOT(deleteLater()), Qt::DirectConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(revert()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsAboutToBeRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::QueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsInserted(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(submit()), Qt::BlockingQueuedConnection);
|
|
|
|
connect(&m, SIGNAL(columnsRemoved(const QModelIndex &, int, int)),
|
|
|
|
&m, SLOT(deleteLater()), Qt::AutoConnection);
|
|
|
|
connect(&o, SIGNAL(destroyed(QObject *)), &m, SLOT(submit()));
|
|
|
|
dumpQObjectSlotListHelper(m);
|
|
|
|
}
|
|
|
|
|
2009-07-22 11:00:56 +02:00
|
|
|
void tst_Debugger::dumpQPixmapHelper(QPixmap &p)
|
|
|
|
{
|
|
|
|
QByteArray expected = QByteArray("value='(").append(QString::number(p.width())).
|
|
|
|
append("x").append(QString::number(p.height())).
|
|
|
|
append("',type='"NS"QPixmap',numchild='0'");
|
|
|
|
testDumper(expected, &p, NS"QPixmap", true);
|
2009-07-20 16:10:37 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQPixmap()
|
|
|
|
{
|
|
|
|
#if 0 // Crashes.
|
|
|
|
// Case 1: Null Pixmap.
|
|
|
|
QPixmap p;
|
|
|
|
dumpQPixmapHelper(p);
|
|
|
|
|
|
|
|
// Case 2: Uninitialized non-null pixmap.
|
|
|
|
p = QPixmap(20, 100);
|
|
|
|
dumpQPixmapHelper(p);
|
|
|
|
|
|
|
|
// Case 3: Initialized non-null pixmap.
|
|
|
|
const char * const pixmap[] = {
|
|
|
|
"2 24 3 1", " c None", ". c #DBD3CB", "+ c #FCFBFA",
|
|
|
|
" ", " ", " ", ".+", ".+", ".+", ".+", ".+", ".+", ".+", ".+", ".+",
|
|
|
|
".+", ".+", ".+", ".+", ".+", ".+", ".+", ".+", ".+", " ", " ", " "
|
|
|
|
};
|
|
|
|
p = QPixmap(pixmap);
|
|
|
|
dumpQPixmapHelper(p);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2009-07-16 14:35:49 +02:00
|
|
|
#if QT_VERSION >= 0x040500
|
|
|
|
template<typename T>
|
|
|
|
void tst_Debugger::dumpQSharedPointerHelper(QSharedPointer<T> &ptr, bool isSimple)
|
|
|
|
{
|
|
|
|
// TODO: This works only for integer types at the moment.
|
|
|
|
QByteArray expected("value = '");
|
|
|
|
QString val;
|
|
|
|
if (isSimple) {
|
|
|
|
val = QString::number(*ptr.data());
|
|
|
|
expected.append(val);
|
|
|
|
}
|
|
|
|
QAtomicInt *weakAddr;
|
|
|
|
QAtomicInt *strongAddr;
|
|
|
|
int weakValue;
|
|
|
|
int strongValue;
|
|
|
|
if (!ptr.isNull()) {
|
|
|
|
weakAddr = &ptr.d->weakref;
|
|
|
|
strongAddr = &ptr.d->strongref;
|
|
|
|
weakValue = *weakAddr;
|
|
|
|
strongValue = *strongAddr;
|
|
|
|
} else {
|
|
|
|
weakAddr = strongAddr = 0;
|
|
|
|
weakValue = strongValue = 0;
|
|
|
|
}
|
|
|
|
expected.append("',valuedisabled='true',numchild='1',children=[").
|
|
|
|
append("{name='data',addr='").append(ptrToBa(ptr.data())).
|
|
|
|
append("',type='int',value='").append(val).append("'},").
|
|
|
|
append("{name='weakref',value='").append(QString::number(weakValue)).
|
|
|
|
append("',type='int',addr='").append(ptrToBa(weakAddr)).append("',numchild='0'},").
|
|
|
|
append("{name='data',value='").append(val).append("'},").
|
|
|
|
append("{name='strongref',value='").append(QString::number(strongValue)).
|
|
|
|
append("',type='int',addr='").append(ptrToBa(strongAddr)).append("',numchild='0'}]");
|
|
|
|
testDumper(expected, &ptr, NS"QSharedPointer", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQSharedPointer()
|
|
|
|
{
|
|
|
|
QSharedPointer<int> ptr(new int(99));
|
|
|
|
// dumpQSharedPointerHelper(ptr, 1, 0, true);
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
void tst_Debugger::dumpQString()
|
2009-07-10 14:57:50 +02:00
|
|
|
{
|
2009-06-25 15:00:57 +02:00
|
|
|
QString s;
|
|
|
|
testDumper("value='',valueencoded='2',type='$T',numchild='0'",
|
|
|
|
&s, NS"QString", false);
|
|
|
|
s = "abc";
|
|
|
|
testDumper("value='YQBiAGMA',valueencoded='2',type='$T',numchild='0'",
|
|
|
|
&s, NS"QString", false);
|
|
|
|
}
|
|
|
|
|
2009-07-09 10:26:54 +02:00
|
|
|
void tst_Debugger::dumpQVariant_invalid()
|
2009-07-10 14:57:50 +02:00
|
|
|
{
|
2009-07-01 14:46:17 +02:00
|
|
|
QVariant v;
|
|
|
|
testDumper("value='(invalid)',type='$T',numchild='0'",
|
|
|
|
&v, NS"QVariant", false);
|
2009-07-09 10:26:54 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQVariant_QString()
|
2009-07-10 14:57:50 +02:00
|
|
|
{
|
2009-07-09 10:26:54 +02:00
|
|
|
QVariant v = "abc";
|
|
|
|
testDumper("value='KFFTdHJpbmcpICJhYmMi',valueencoded='5',type='$T',"
|
|
|
|
"numchild='0'",
|
|
|
|
&v, NS"QVariant", true);
|
|
|
|
/*
|
|
|
|
FIXME: the QString version should have a child:
|
2009-07-01 14:46:17 +02:00
|
|
|
testDumper("value='KFFTdHJpbmcpICJhYmMi',valueencoded='5',type='$T',"
|
|
|
|
"numchild='1',children=[{name='value',value='IgBhAGIAYwAiAA==',"
|
|
|
|
"valueencoded='4',type='QString',numchild='0'}]",
|
|
|
|
&v, NS"QVariant", true);
|
2009-07-09 10:26:54 +02:00
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQVariant_QStringList()
|
|
|
|
{
|
|
|
|
QVariant v = QStringList() << "Hi";
|
2009-07-01 14:46:17 +02:00
|
|
|
return; // FIXME
|
|
|
|
testDumper("value='(QStringList) ',type='$T',"
|
|
|
|
"numchild='1',children=[{name='value',"
|
|
|
|
"exp='(*('myns::QStringList'*)3215364300)',"
|
|
|
|
"type='QStringList',numchild='1'}]",
|
|
|
|
&v, NS"QVariant", true);
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
void tst_Debugger::dumpStdVector()
|
|
|
|
{
|
|
|
|
std::vector<std::list<int> *> vector;
|
|
|
|
QByteArray inner = "std::list<int> *";
|
|
|
|
QByteArray innerp = "std::list<int>";
|
|
|
|
testDumper("value='<0 items>',valuedisabled='true',numchild='0'",
|
|
|
|
&vector, "std::vector", false, inner, "", sizeof(std::list<int> *));
|
|
|
|
std::list<int> list;
|
|
|
|
vector.push_back(new std::list<int>(list));
|
|
|
|
testDumper("value='<1 items>',valuedisabled='true',numchild='1',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"childtype='" + inner + "',childnumchild='1',"
|
2009-07-10 13:40:17 +02:00
|
|
|
"children=[{addr='" + str(deref(&vector[0])) + "',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"saddr='" + str(deref(&vector[0])) + "',type='" + innerp + "'}]",
|
|
|
|
&vector, "std::vector", true, inner, "", sizeof(std::list<int> *));
|
|
|
|
vector.push_back(0);
|
|
|
|
list.push_back(45);
|
|
|
|
testDumper("value='<2 items>',valuedisabled='true',numchild='2',"
|
2009-07-10 11:08:26 +02:00
|
|
|
"childtype='" + inner + "',childnumchild='1',"
|
2009-07-10 13:40:17 +02:00
|
|
|
"children=[{addr='" + str(deref(&vector[0])) + "',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"saddr='" + str(deref(&vector[0])) + "',type='" + innerp + "'},"
|
2009-07-10 13:40:17 +02:00
|
|
|
"{addr='" + str(&vector[1]) + "',"
|
2009-06-25 15:00:57 +02:00
|
|
|
"type='" + innerp + "',value='<null>',numchild='0'}]",
|
|
|
|
&vector, "std::vector", true, inner, "", sizeof(std::list<int> *));
|
|
|
|
vector.push_back(new std::list<int>(list));
|
|
|
|
vector.push_back(0);
|
|
|
|
}
|
|
|
|
|
2009-07-15 09:46:55 +02:00
|
|
|
void tst_Debugger::dumpQTextCodecHelper(QTextCodec *codec)
|
|
|
|
{
|
|
|
|
const QByteArray &name = codec->name().toBase64();
|
|
|
|
QByteArray expected = QByteArray("value='").append(name).
|
|
|
|
append("',valueencoded='1',type='"NS"QTextCodec',numchild='2',children=[").
|
|
|
|
append("{name='name',value='").append(name).append("',type='"NS"QByteArray'").
|
|
|
|
append(",numchild='0',valueencoded='1'},").append("{name='mibEnum',").
|
|
|
|
append(generateIntSpec(codec->mibEnum())).append("}");
|
|
|
|
expected.append("]");
|
|
|
|
testDumper(expected, codec, NS"QTextCodec", true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::dumpQTextCodec()
|
|
|
|
{
|
|
|
|
const QList<QByteArray> &codecNames = QTextCodec::availableCodecs();
|
|
|
|
foreach (const QByteArray &codecName, codecNames)
|
|
|
|
dumpQTextCodecHelper(QTextCodec::codecForName(codecName));
|
|
|
|
}
|
|
|
|
|
2009-06-25 15:00:57 +02:00
|
|
|
//
|
|
|
|
// Creator
|
|
|
|
//
|
|
|
|
|
2009-04-07 09:40:56 +02:00
|
|
|
void tst_Debugger::readStandardOutput()
|
|
|
|
{
|
2009-04-07 09:51:21 +02:00
|
|
|
qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput());
|
2009-04-07 09:40:56 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void tst_Debugger::readStandardError()
|
|
|
|
{
|
2009-04-07 09:51:21 +02:00
|
|
|
qDebug() << "qtcreator-err: " << stripped(m_proc.readAllStandardError());
|
2009-04-07 09:40:56 +02:00
|
|
|
}
|
|
|
|
|
2009-04-06 16:30:11 +02:00
|
|
|
void tst_Debugger::runQtc()
|
|
|
|
{
|
|
|
|
QString test = QFileInfo(qApp->arguments().at(0)).absoluteFilePath();
|
|
|
|
QString qtc = QFileInfo(test).absolutePath() + "/../../../bin/qtcreator.bin";
|
|
|
|
qtc = QFileInfo(qtc).absoluteFilePath();
|
|
|
|
QStringList env = QProcess::systemEnvironment();
|
|
|
|
env.append("QTC_DEBUGGER_TEST=" + test);
|
2009-04-07 09:40:56 +02:00
|
|
|
m_proc.setEnvironment(env);
|
|
|
|
connect(&m_proc, SIGNAL(readyReadStandardOutput()),
|
|
|
|
this, SLOT(readStandardOutput()));
|
|
|
|
connect(&m_proc, SIGNAL(readyReadStandardError()),
|
|
|
|
this, SLOT(readStandardError()));
|
|
|
|
m_proc.start(qtc);
|
|
|
|
m_proc.waitForStarted();
|
|
|
|
QCOMPARE(m_proc.state(), QProcess::Running);
|
|
|
|
m_proc.waitForFinished();
|
|
|
|
QCOMPARE(m_proc.state(), QProcess::NotRunning);
|
2009-04-06 16:30:11 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void runDebuggee()
|
|
|
|
{
|
|
|
|
qDebug() << "RUNNING DEBUGGEE";
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
|
|
|
QCoreApplication app(argc, argv);
|
|
|
|
QStringList args = app.arguments();
|
|
|
|
|
|
|
|
if (args.size() == 2 && args.at(1) == "--run-debuggee") {
|
|
|
|
runDebuggee();
|
2009-04-14 12:14:01 +02:00
|
|
|
app.exec();
|
2009-04-06 16:30:11 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
tst_Debugger test;
|
|
|
|
return QTest::qExec(&test, argc, argv);
|
|
|
|
}
|
2009-04-06 14:07:30 +02:00
|
|
|
|
|
|
|
#include "main.moc"
|
|
|
|
|