Commit e234bbd8 authored by hjk's avatar hjk Committed by hjk

Debugger: Add dumper for Nim's string and sequence types

... and make the auto test infrastructure able to handle
a test. To pass the test, some Nim compiler must be
accessible.

Change-Id: I707aa72c0f3a2ea35c7131cba490cafb41617f6c
Reviewed-by: Christian Stenger's avatarChristian Stenger <christian.stenger@qt.io>
parent 21ba1f7b
......@@ -1015,7 +1015,8 @@ class DumperBase:
if arrayByteSize == 0:
# This should not happen. But it does, see QTCREATORBUG-14755.
# GDB/GCC produce sizeof == 0 for QProcess arr[3]
s = str(value.type)
# And in the Nim string dumper.
s = value.type.name
itemCount = s[s.find('[')+1:s.find(']')]
if not itemCount:
itemCount = '100'
......
......@@ -161,6 +161,25 @@ def qdump__Eigen__Matrix(d, value):
s = s + 1
#######################################################################
#
# Nim
#
#######################################################################
def qdump__NimStringDesc(d, value):
size, reserved = value.split('pp')
data = value.address() + 2 * d.ptrSize()
d.putCharArrayHelper(data, size, d.createType('char'), 'utf8')
def qdump__NimGenericSequence__(d, value, regex = "^TY[\d]+$"):
size, reserved = d.split('pp', value)
data = value.address() + 2 * d.ptrSize()
typeobj = value["data"].type.dereference()
d.putItemCount(size)
d.putArrayData(data, size, typeobj)
d.putBetterType("%s (%s[%s])" % (value.type.name, typeobj.name, size))
#######################################################################
#
# D
......
......@@ -646,33 +646,11 @@ struct NetworkProfile {};
struct QmlProfile {};
struct QmlPrivateProfile {};
struct BigArrayProfile {};
struct NimProfile {};
struct DataBase
{
DataBase()
: useQt(false), useQHash(false),
forceC(false), engines(AllEngines),
glibcxxDebug(false), useDebugImage(false),
bigArray(false)
{}
mutable bool useQt;
mutable bool useQHash;
mutable bool forceC;
mutable int engines;
mutable bool glibcxxDebug;
mutable bool useDebugImage;
mutable bool bigArray;
mutable GdbVersion neededGdbVersion; // DEC. 70600
mutable LldbVersion neededLldbVersion;
mutable QtVersion neededQtVersion; // HEX! 0x50300
mutable GccVersion neededGccVersion; // DEC. 40702 for 4.7.2
mutable ClangVersion neededClangVersion; // DEC.
mutable BoostVersion neededBoostVersion; // DEC. 105400 for 1.54.0
};
struct BigArrayProfile {};
class Data : public DataBase
class Data
{
public:
Data() {}
......@@ -854,14 +832,37 @@ public:
const Data &operator+(const ForceC &) const
{
forceC = true;
mainFile = "main.c";
return *this;
}
public:
mutable bool useQt = false;
mutable bool useQHash = false;
mutable int engines = AllEngines;
mutable int skipLevels = 0; // Levels to go 'up' before dumping variables.
mutable bool glibcxxDebug = false;
mutable bool useDebugImage = false;
mutable bool bigArray = false;
mutable GdbVersion neededGdbVersion; // DEC. 70600
mutable LldbVersion neededLldbVersion;
mutable QtVersion neededQtVersion; // HEX! 0x50300
mutable GccVersion neededGccVersion; // DEC. 40702 for 4.7.2
mutable ClangVersion neededClangVersion; // DEC.
mutable BoostVersion neededBoostVersion; // DEC. 105400 for 1.54.0
mutable QString configTest;
mutable QString allProfile; // Overrides anything below if not empty.
mutable QString allCode; // Overrides anything below if not empty.
mutable QString mainFile = "main.cpp";
mutable QString projectFile = "doit.pro";
mutable QString profileExtra;
mutable QString includes;
mutable QString code;
mutable QList<Check> checks;
};
......@@ -1150,28 +1151,42 @@ void tst_Dumpers::dumper()
+ QByteArray::number(data.neededGccVersion.max));
}
const char *mainFile = data.forceC ? "main.c" : "main.cpp";
if (!data.configTest.isEmpty()) {
QProcess configTest;
configTest.start(data.configTest);
QVERIFY(configTest.waitForFinished());
output = configTest.readAllStandardOutput();
error = configTest.readAllStandardError();
if (configTest.exitCode()) {
MSKIP_SINGLE("Configure test failed: '"
+ data.configTest.toUtf8() + "' " + output + ' ' + error);
}
}
QFile proFile(t->buildPath + QLatin1String("/doit.pro"));
QFile proFile(t->buildPath + '/' + data.projectFile);
QVERIFY(proFile.open(QIODevice::ReadWrite));
proFile.write("SOURCES = ");
proFile.write(mainFile);
proFile.write("\nTARGET = doit\n");
proFile.write("\nCONFIG -= app_bundle\n");
proFile.write("\nCONFIG -= release\n");
proFile.write("\nCONFIG += debug\n");
if (data.useQt)
proFile.write("QT -= widgets gui\n");
else
proFile.write("CONFIG -= QT\n");
if (m_useGLibCxxDebug)
proFile.write("DEFINES += _GLIBCXX_DEBUG\n");
if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500)
proFile.write("QMAKE_CXXFLAGS += -gdwarf-3\n");
proFile.write(data.profileExtra.toUtf8());
if (data.allProfile.isEmpty()) {
proFile.write("SOURCES = ");
proFile.write(data.mainFile.toUtf8());
proFile.write("\nTARGET = doit\n");
proFile.write("\nCONFIG -= app_bundle\n");
proFile.write("\nCONFIG -= release\n");
proFile.write("\nCONFIG += debug\n");
if (data.useQt)
proFile.write("QT -= widgets gui\n");
else
proFile.write("CONFIG -= QT\n");
if (m_useGLibCxxDebug)
proFile.write("DEFINES += _GLIBCXX_DEBUG\n");
if (m_debuggerEngine == GdbEngine && m_debuggerVersion < 70500)
proFile.write("QMAKE_CXXFLAGS += -gdwarf-3\n");
proFile.write(data.profileExtra.toUtf8());
} else {
proFile.write(data.allProfile.toUtf8());
}
proFile.close();
QFile source(t->buildPath + QLatin1Char('/') + QLatin1String(mainFile));
QFile source(t->buildPath + QLatin1Char('/') + data.mainFile);
QVERIFY(source.open(QIODevice::ReadWrite));
QString fullCode = QString() +
"\n\n#if defined(_MSC_VER)" + (data.useQt ?
......@@ -1234,6 +1249,8 @@ void tst_Dumpers::dumper()
"\n BREAK;"
"\n return 0;"
"\n}\n";
if (!data.allCode.isEmpty())
fullCode = data.allCode;
source.write(fullCode.toUtf8());
source.close();
......@@ -1251,7 +1268,12 @@ void tst_Dumpers::dumper()
output = qmake.readAllStandardOutput();
error = qmake.readAllStandardError();
//qDebug() << "stdout: " << output;
if (!error.isEmpty()) { qDebug() << error; QVERIFY(false); }
if (data.allProfile.isEmpty()) { // Nim...
if (!error.isEmpty()) {
qDebug() << error; QVERIFY(false);
}
}
QProcess make;
make.setWorkingDirectory(t->buildPath);
......@@ -1267,7 +1289,7 @@ void tst_Dumpers::dumper()
qDebug() << "\n------------------ CODE --------------------";
qDebug() << fullCode;
qDebug() << "\n------------------ CODE --------------------";
qDebug() << ".pro: " << qPrintable(proFile.fileName());
qDebug() << "Project file: " << qPrintable(proFile.fileName());
}
QByteArray dumperDir = DUMPERDIR;
......@@ -1321,6 +1343,7 @@ void tst_Dumpers::dumper()
"python from gdbbridge import *\n"
"python theDumper.setupDumpers()\n"
"run " + nograb + "\n"
"up " + QString::number(data.skipLevels) + "\n"
"python theDumper.fetchVariables({"
"'token':2,'fancy':1,'forcens':1,"
"'autoderef':1,'dyntype':1,'passexceptions':1,"
......@@ -6207,6 +6230,54 @@ void tst_Dumpers::dumper_data()
+ Check("v14.2", "[2]", "116", "@QChar")
+ Check("v15", "\"utf16\"", "@QJSValue (QString)")
+ Check("v15.1", "[1]", "116", "@QChar");
#ifdef Q_OS_LINUX
// Hint: To open a failing test in Creator, do:
// touch qt_tst_dumpers_Nim_.../dummy.nimproject
// qtcreator qt_tst_dumpers_Nim_*/dummy.nimproject
Data nimData;
nimData.configTest = "which nim";
nimData.allProfile =
"CONFIG -= qt\n"
"# Prevents linking\n"
"TARGET=\n"
"# Overwrites qmake-generated 'all' target.\n"
"all.commands = nim c --debugInfo --lineDir:on --out:doit main.nim\n"
"all.depends = main.nim\n"
"all.CONFIG = phony\n\n"
"QMAKE_EXTRA_TARGETS += all\n";
nimData.allCode =
"type Mirror = ref object\n"
" tag:int\n"
" other:array[0..1, Mirror]\n\n"
"proc mainProc =\n"
" var name: string = \"Hello World\"\n"
" var i: int = 43\n"
" var x: seq[int]\n"
" x = @[1, 2, 3, 4, 5, 6]\n\n"
" # Crash it.\n"
" var m1 = Mirror(tag:1)\n"
" var m2 = Mirror(tag:2)\n"
" var m3 = Mirror(tag:3)\n\n"
" m1.other[0] = m2; m1.other[1] = m3\n"
" m2.other[0] = m1; m2.other[1] = m3\n"
" m3.other[0] = m1; m3.other[1] = m2\n\n"
" for i in 1..30000:\n"
//" echo i\n"
" var mx : Mirror; mx.deepCopy(m1)\n"
" m1 = mx\n\n"
"if isMainModule:\n"
" mainProc()\n";
nimData.mainFile = "main.nim";
nimData.skipLevels = 15;
QTest::newRow("Nim")
<< nimData
+ GdbEngine
+ Check("name", "\"Hello World\"", "NimStringDesc")
+ Check("x", "<6 items>", Pattern("TY.*NI.6..")) // Something like "TY95019 (NI[6])"
+ Check("x.2", "[2]", "3", "NI");
#endif
}
int main(int argc, char *argv[])
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment