OSDN Git Service

Update license.
[qt-creator-jp/qt-creator-jp.git] / tests / valgrind / memcheck / testrunner.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Author: Milian Wolff, KDAB (milian.wolff@kdab.com)
8 **
9 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 **
11 **
12 ** GNU Lesser General Public License Usage
13 **
14 ** This file may be used under the terms of the GNU Lesser General Public
15 ** License version 2.1 as published by the Free Software Foundation and
16 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
17 ** Please review the following information to ensure the GNU Lesser General
18 ** Public License version 2.1 requirements will be met:
19 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
20 **
21 ** In addition, as a special exception, Nokia gives you certain additional
22 ** rights. These rights are described in the Nokia Qt LGPL Exception
23 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
24 **
25 ** Other Usage
26 **
27 ** Alternatively, this file may be used in accordance with the terms and
28 ** conditions contained in a signed written agreement between you and Nokia.
29 **
30 ** If you have questions regarding the use of this file, please contact
31 ** Nokia at qt-info@nokia.com.
32 **
33 **************************************************************************/
34
35 #include "testrunner.h"
36
37 #include <valgrind/xmlprotocol/frame.h>
38 #include <valgrind/xmlprotocol/stack.h>
39 #include <valgrind/xmlprotocol/suppression.h>
40 #include <valgrind/xmlprotocol/threadedparser.h>
41 #include <valgrind/xmlprotocol/parser.h>
42 #include <valgrind/memcheck/memcheckrunner.h>
43
44 #include <QDebug>
45 #include <QTest>
46 #include <QDir>
47 #include <QSignalSpy>
48
49 const QString appSrcDir(TESTRUNNER_SRC_DIR);
50 const QString appBinDir(TESTRUNNER_APP_DIR);
51
52 QString srcDirForApp(const QString &app)
53 {
54     return appSrcDir + QDir::separator() + app;
55 }
56
57 QTEST_MAIN(Valgrind::TestRunner)
58
59 using namespace Valgrind;
60 using namespace Valgrind::XmlProtocol;
61 using namespace Valgrind::Memcheck;
62
63 //BEGIN Test Helpers and boilterplate code
64
65 TestRunner::TestRunner(QObject *parent)
66     : QObject(parent),
67       m_parser(0),
68       m_runner(0)
69 {
70     qRegisterMetaType<Error>();
71 }
72
73 QString TestRunner::runTestBinary(const QString &binary, const QStringList &vArgs)
74 {
75     const QString binPath = appBinDir + QDir::separator() + binary;
76     Q_ASSERT(QFileInfo(binPath).isExecutable());
77     m_runner->setValgrindArguments(QStringList() << "--num-callers=50" << "--track-origins=yes" << vArgs);
78     m_runner->setDebuggeeExecutable(binPath);
79     m_runner->start();
80     m_runner->waitForFinished();
81     return binPath;
82 }
83
84 void TestRunner::logMessageReceived(const QByteArray &message)
85 {
86     qDebug() << "log message received:" << message;
87     m_logMessages << message;
88 }
89
90 void TestRunner::internalError(const QString &error)
91 {
92     if (!m_expectCrash)
93         QFAIL(qPrintable(error));
94     else
95         qDebug() << "expected crash:" << error;
96 }
97
98 void TestRunner::error(const Error &error)
99 {
100     m_errors << error;
101 }
102
103 void TestRunner::cleanup()
104 {
105     Q_ASSERT(m_runner);
106     delete m_runner;
107     m_runner = 0;
108     Q_ASSERT(m_parser);
109     delete m_parser;
110     m_parser = 0;
111
112     m_logMessages.clear();
113     m_errors.clear();
114     m_expectCrash = false;
115 }
116
117 void TestRunner::init()
118 {
119     Q_ASSERT(m_logMessages.isEmpty());
120
121     Q_ASSERT(!m_runner);
122     m_runner = new MemcheckRunner;
123     m_runner->setValgrindExecutable(QLatin1String("valgrind"));
124     m_runner->setProcessChannelMode(QProcess::ForwardedChannels);
125     connect(m_runner, SIGNAL(logMessageReceived(QByteArray)),
126             this, SLOT(logMessageReceived(QByteArray)));
127     connect(m_runner, SIGNAL(processErrorReceived(QString, QProcess::ProcessError)),
128             this, SLOT(internalError(QString)));
129     Q_ASSERT(!m_parser);
130     m_parser = new ThreadedParser;
131     connect(m_parser, SIGNAL(internalError(QString)),
132             this, SLOT(internalError(QString)));
133     connect(m_parser, SIGNAL(error(Valgrind::XmlProtocol::Error)),
134             this, SLOT(error(Valgrind::XmlProtocol::Error)));
135
136     m_runner->setParser(m_parser);
137 }
138
139 //BEGIN: Actual test cases
140
141 void TestRunner::testLeak1()
142 {
143     const QString binary = runTestBinary(QLatin1String("leak1/leak1"));
144
145     QVERIFY(m_logMessages.isEmpty());
146
147     QCOMPARE(m_errors.count(), 1);
148     const Error error = m_errors.first();
149     QCOMPARE(error.kind(), int(Leak_DefinitelyLost));
150     QCOMPARE(error.leakedBlocks(), qint64(1));
151     QCOMPARE(error.leakedBytes(), quint64(8));
152     QCOMPARE(error.stacks().count(), 1);
153     const Stack stack = error.stacks().first();
154     QCOMPARE(stack.line(), qint64(-1));
155     QCOMPARE(stack.frames().count(), 2);
156     {
157         const Frame frame = stack.frames().at(0);
158         QCOMPARE(frame.functionName(), QString("operator new(unsigned long)"));
159     }
160     {
161         const Frame frame = stack.frames().at(1);
162         QCOMPARE(frame.functionName(), QString("main"));
163         QCOMPARE(frame.line(), 5);
164
165         QCOMPARE(frame.object(), binary);
166         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
167         QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak1"));
168     }
169 }
170
171 void TestRunner::testLeak2()
172 {
173     const QString binary = runTestBinary(QLatin1String("leak2/leak2"));
174
175     QVERIFY(m_logMessages.isEmpty());
176
177     QCOMPARE(m_errors.count(), 1);
178     const Error error = m_errors.first();
179     QCOMPARE(error.kind(), int(Leak_PossiblyLost));
180     QCOMPARE(error.leakedBlocks(), qint64(1));
181     QCOMPARE(error.leakedBytes(), quint64(5));
182     QCOMPARE(error.stacks().count(), 1);
183     const Stack stack = error.stacks().first();
184     QCOMPARE(stack.line(), qint64(-1));
185     QCOMPARE(stack.frames().count(), 3);
186     {
187         const Frame frame = stack.frames().at(0);
188         QCOMPARE(frame.functionName(), QString("malloc"));
189     }
190     {
191         const Frame frame = stack.frames().at(1);
192         QCOMPARE(frame.functionName(), QString("strdup"));
193     }
194     {
195         const Frame frame = stack.frames().at(2);
196         QCOMPARE(frame.functionName(), QString("main"));
197         QCOMPARE(frame.line(), 7);
198
199         QCOMPARE(frame.object(), binary);
200         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
201         QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak2"));
202     }
203 }
204
205 void TestRunner::testLeak3()
206 {
207     const QString binary = runTestBinary(QLatin1String("leak3/leak3"), QStringList() << "--show-reachable=yes");
208
209     QVERIFY(m_logMessages.isEmpty());
210
211     QCOMPARE(m_errors.count(), 1);
212     const Error error = m_errors.first();
213     QCOMPARE(error.kind(), int(Leak_StillReachable));
214     QCOMPARE(error.leakedBlocks(), qint64(1));
215     QCOMPARE(error.leakedBytes(), quint64(5));
216     QCOMPARE(error.stacks().count(), 1);
217     const Stack stack = error.stacks().first();
218     QCOMPARE(stack.line(), qint64(-1));
219     QCOMPARE(stack.frames().count(), 3);
220     {
221         const Frame frame = stack.frames().at(0);
222         QCOMPARE(frame.functionName(), QString("malloc"));
223     }
224     {
225         const Frame frame = stack.frames().at(1);
226         QCOMPARE(frame.functionName(), QString("strdup"));
227     }
228     {
229         const Frame frame = stack.frames().at(2);
230         QCOMPARE(frame.functionName(), QString("main"));
231         QCOMPARE(frame.line(), 7);
232
233         QCOMPARE(frame.object(), binary);
234         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
235         QCOMPARE(QDir::cleanPath(frame.directory()), srcDirForApp("leak3"));
236     }
237 }
238
239 void TestRunner::testLeak4()
240 {
241     const QString app("leak4");
242     const QString binary = runTestBinary(app + QDir::separator() + app,
243                                          QStringList() << "--show-reachable=yes");
244     const QString srcDir = srcDirForApp("leak4");
245
246     QVERIFY(m_logMessages.isEmpty());
247
248     QCOMPARE(m_errors.count(), 2);
249     //BEGIN first error
250     {
251     const Error error = m_errors.first();
252     QCOMPARE(error.kind(), int(Leak_IndirectlyLost));
253     QCOMPARE(error.leakedBlocks(), qint64(1));
254     QCOMPARE(error.leakedBytes(), quint64(8));
255     QCOMPARE(error.stacks().count(), 1);
256     const Stack stack = error.stacks().first();
257     QCOMPARE(stack.line(), qint64(-1));
258     QCOMPARE(stack.frames().count(), 3);
259     {
260         const Frame frame = stack.frames().at(0);
261         QCOMPARE(frame.functionName(), QString("operator new(unsigned long)"));
262     }
263     {
264         const Frame frame = stack.frames().at(2);
265         QCOMPARE(frame.functionName(), QString("main"));
266         QCOMPARE(frame.line(), 13);
267
268         QCOMPARE(frame.object(), binary);
269         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
270         QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
271     }
272     {
273         const Frame frame = stack.frames().at(1);
274         QCOMPARE(frame.functionName(), QString("foo::foo()"));
275         QCOMPARE(frame.line(), 5);
276
277         QCOMPARE(frame.object(), binary);
278         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
279         QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
280     }
281     {
282         const Frame frame = stack.frames().at(2);
283         QCOMPARE(frame.functionName(), QString("main"));
284         QCOMPARE(frame.line(), 13);
285
286         QCOMPARE(frame.object(), binary);
287         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
288         QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
289     }
290     }
291     //BEGIN second error
292     {
293     const Error error = m_errors.last();
294     QCOMPARE(error.kind(), int(Leak_DefinitelyLost));
295     QCOMPARE(error.leakedBlocks(), qint64(1));
296     QCOMPARE(error.leakedBytes(), quint64(16));
297     QCOMPARE(error.stacks().count(), 1);
298     const Stack stack = error.stacks().first();
299     QCOMPARE(stack.line(), qint64(-1));
300     QCOMPARE(stack.frames().count(), 2);
301     {
302         const Frame frame = stack.frames().at(0);
303         QCOMPARE(frame.functionName(), QString("operator new(unsigned long)"));
304     }
305     {
306         const Frame frame = stack.frames().at(1);
307         QCOMPARE(frame.functionName(), QString("main"));
308         QCOMPARE(frame.line(), 13);
309
310         QCOMPARE(frame.object(), binary);
311         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
312         QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
313     }
314     }
315 }
316
317 void TestRunner::uninit1()
318 {
319     const QString app("uninit1");
320     const QString binary = runTestBinary(app + QDir::separator() + app);
321     const QString srcDir = srcDirForApp(app);
322
323     QVERIFY(m_logMessages.isEmpty());
324
325     QCOMPARE(m_errors.count(), 1);
326     const Error error = m_errors.first();
327     QCOMPARE(error.kind(), int(UninitCondition));
328     QCOMPARE(error.stacks().count(), 2);
329     //BEGIN first stack
330     {
331     const Stack stack = error.stacks().first();
332     QCOMPARE(stack.line(), qint64(-1));
333     QCOMPARE(stack.frames().count(), 1);
334
335     const Frame frame = stack.frames().first();
336     QCOMPARE(frame.functionName(), QString("main"));
337     QCOMPARE(frame.line(), 4);
338
339     QCOMPARE(frame.object(), binary);
340     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
341     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
342     }
343     //BEGIN second stack
344     {
345     const Stack stack = error.stacks().last();
346     QCOMPARE(stack.line(), qint64(-1));
347     QCOMPARE(stack.frames().count(), 1);
348
349     const Frame frame = stack.frames().first();
350     QCOMPARE(frame.functionName(), QString("main"));
351     QCOMPARE(frame.line(), 2);
352
353     QCOMPARE(frame.object(), binary);
354     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
355     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
356     }
357 }
358
359 void TestRunner::uninit2()
360 {
361     const QString app("uninit2");
362     m_expectCrash = true;
363     const QString binary = runTestBinary(app + QDir::separator() + app);
364     const QString srcDir = srcDirForApp(app);
365
366     QVERIFY(m_logMessages.isEmpty());
367
368     QCOMPARE(m_errors.count(), 2);
369     //BEGIN first error
370     {
371     const Error error = m_errors.first();
372     QCOMPARE(error.kind(), int(UninitValue));
373     QCOMPARE(error.stacks().count(), 2);
374     //BEGIN first stack
375     {
376     const Stack stack = error.stacks().first();
377     QCOMPARE(stack.line(), qint64(-1));
378     QCOMPARE(stack.frames().count(), 1);
379
380     const Frame frame = stack.frames().first();
381     QCOMPARE(frame.functionName(), QString("main"));
382     QCOMPARE(frame.line(), 4);
383
384     QCOMPARE(frame.object(), binary);
385     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
386     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
387     }
388     //BEGIN second stack
389     {
390     const Stack stack = error.stacks().last();
391     QCOMPARE(stack.line(), qint64(-1));
392     QCOMPARE(stack.frames().count(), 1);
393
394     const Frame frame = stack.frames().first();
395     QCOMPARE(frame.functionName(), QString("main"));
396     QCOMPARE(frame.line(), 2);
397
398     QCOMPARE(frame.object(), binary);
399     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
400     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
401     }
402     }
403     //BEGIN second error
404     {
405     const Error error = m_errors.last();
406     QCOMPARE(error.kind(), int(InvalidWrite));
407     QCOMPARE(error.stacks().count(), 1);
408
409     const Stack stack = error.stacks().first();
410     QCOMPARE(stack.line(), qint64(-1));
411     QCOMPARE(stack.frames().count(), 1);
412
413     const Frame frame = stack.frames().first();
414     QCOMPARE(frame.functionName(), QString("main"));
415     QCOMPARE(frame.line(), 4);
416
417     QCOMPARE(frame.object(), binary);
418     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
419     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
420     }
421 }
422
423 void TestRunner::uninit3()
424 {
425     const QString app("uninit3");
426     m_expectCrash = true;
427     const QString binary = runTestBinary(app + QDir::separator() + app);
428     const QString srcDir = srcDirForApp(app);
429
430     QVERIFY(m_logMessages.isEmpty());
431
432     QCOMPARE(m_errors.count(), 2);
433     //BEGIN first error
434     {
435     const Error error = m_errors.first();
436     QCOMPARE(error.kind(), int(UninitValue));
437     QCOMPARE(error.stacks().count(), 2);
438     //BEGIN first stack
439     {
440     const Stack stack = error.stacks().first();
441     QCOMPARE(stack.line(), qint64(-1));
442     QCOMPARE(stack.frames().count(), 1);
443
444     const Frame frame = stack.frames().first();
445     QCOMPARE(frame.functionName(), QString("main"));
446     QCOMPARE(frame.line(), 3);
447
448     QCOMPARE(frame.object(), binary);
449     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
450     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
451     }
452     //BEGIN second stack
453     {
454     const Stack stack = error.stacks().last();
455     QCOMPARE(stack.line(), qint64(-1));
456     QCOMPARE(stack.frames().count(), 1);
457
458     const Frame frame = stack.frames().first();
459     QCOMPARE(frame.functionName(), QString("main"));
460     QCOMPARE(frame.line(), 1);
461
462     QCOMPARE(frame.object(), binary);
463     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
464     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
465     }
466     }
467     //BEGIN second error
468     {
469     const Error error = m_errors.last();
470     QCOMPARE(error.kind(), int(InvalidRead));
471     QCOMPARE(error.stacks().count(), 1);
472
473     const Stack stack = error.stacks().first();
474     QCOMPARE(stack.line(), qint64(-1));
475     QCOMPARE(stack.frames().count(), 1);
476
477     const Frame frame = stack.frames().first();
478     QCOMPARE(frame.functionName(), QString("main"));
479     QCOMPARE(frame.line(), 3);
480
481     QCOMPARE(frame.object(), binary);
482     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
483     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
484     }
485 }
486
487 void TestRunner::syscall()
488 {
489     const QString app("syscall");
490     const QString binary = runTestBinary(app + QDir::separator() + app);
491     const QString srcDir = srcDirForApp(app);
492
493     QVERIFY(m_logMessages.isEmpty());
494
495     QCOMPARE(m_errors.count(), 1);
496     const Error error = m_errors.first();
497     QCOMPARE(error.kind(), int(SyscallParam));
498     QCOMPARE(error.stacks().count(), 2);
499     //BEGIN first stack
500     {
501     const Stack stack = error.stacks().first();
502     QCOMPARE(stack.line(), qint64(-1));
503     QCOMPARE(stack.frames().count(), 3);
504
505     {
506     ///TODO: is this platform specific?
507     const Frame frame = stack.frames().at(0);
508     QCOMPARE(frame.functionName(), QString("_Exit"));
509     }
510     {
511     const Frame frame = stack.frames().at(1);
512     QCOMPARE(frame.functionName(), QString("exit"));
513     }
514     {
515     const Frame frame = stack.frames().at(2);
516     QCOMPARE(frame.functionName(), QString("(below main)"));
517     }
518     }
519     //BEGIN second stack
520     {
521     const Stack stack = error.stacks().last();
522     QCOMPARE(stack.line(), qint64(-1));
523     QCOMPARE(stack.frames().count(), 1);
524
525     const Frame frame = stack.frames().first();
526     QCOMPARE(frame.functionName(), QString("main"));
527     QCOMPARE(frame.line(), 2);
528
529     QCOMPARE(frame.object(), binary);
530     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
531     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
532     }
533 }
534
535 void TestRunner::free1()
536 {
537     const QString app("free1");
538     const QString binary = runTestBinary(app + QDir::separator() + app);
539     const QString srcDir = srcDirForApp(app);
540
541     QVERIFY(m_logMessages.isEmpty());
542
543     QCOMPARE(m_errors.count(), 1);
544     const Error error = m_errors.first();
545     QCOMPARE(error.kind(), int(InvalidFree));
546     QCOMPARE(error.stacks().count(), 2);
547     //BEGIN first stack
548     {
549     const Stack stack = error.stacks().first();
550     QCOMPARE(stack.line(), qint64(-1));
551     QCOMPARE(stack.frames().count(), 2);
552
553     {
554     const Frame frame = stack.frames().first();
555     QCOMPARE(frame.functionName(), QString("operator delete(void*)"));
556     }
557     {
558     const Frame frame = stack.frames().last();
559     QCOMPARE(frame.functionName(), QString("main"));
560     QCOMPARE(frame.line(), 7);
561
562     QCOMPARE(frame.object(), binary);
563     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
564     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
565     }
566     }
567     //BEGIN second stack
568     {
569     const Stack stack = error.stacks().last();
570     QCOMPARE(stack.line(), qint64(-1));
571     QCOMPARE(stack.frames().count(), 2);
572
573
574     {
575     const Frame frame = stack.frames().first();
576     QCOMPARE(frame.functionName(), QString("operator delete(void*)"));
577     }
578     {
579     const Frame frame = stack.frames().last();
580     QCOMPARE(frame.functionName(), QString("main"));
581     QCOMPARE(frame.line(), 6);
582
583     QCOMPARE(frame.object(), binary);
584     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
585     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
586     }
587     }
588 }
589
590 void TestRunner::free2()
591 {
592     const QString app("free2");
593     const QString binary = runTestBinary(app + QDir::separator() + app);
594     const QString srcDir = srcDirForApp(app);
595
596     QVERIFY(m_logMessages.isEmpty());
597
598     QCOMPARE(m_errors.count(), 1);
599     const Error error = m_errors.first();
600     QCOMPARE(error.kind(), int(MismatchedFree));
601     QCOMPARE(error.stacks().count(), 2);
602     //BEGIN first stack
603     {
604     const Stack stack = error.stacks().first();
605     QCOMPARE(stack.line(), qint64(-1));
606     QCOMPARE(stack.frames().count(), 2);
607
608     {
609     const Frame frame = stack.frames().first();
610     QCOMPARE(frame.functionName(), QString("free"));
611     }
612     {
613     const Frame frame = stack.frames().last();
614     QCOMPARE(frame.functionName(), QString("main"));
615     QCOMPARE(frame.line(), 6);
616
617     QCOMPARE(frame.object(), binary);
618     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
619     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
620     }
621     }
622     //BEGIN second stack
623     {
624     const Stack stack = error.stacks().last();
625     QCOMPARE(stack.line(), qint64(-1));
626     QCOMPARE(stack.frames().count(), 2);
627
628
629     {
630     const Frame frame = stack.frames().first();
631     QCOMPARE(frame.functionName(), QString("operator new(unsigned long)"));
632     }
633     {
634     const Frame frame = stack.frames().last();
635     QCOMPARE(frame.functionName(), QString("main"));
636     QCOMPARE(frame.line(), 5);
637
638     QCOMPARE(frame.object(), binary);
639     QCOMPARE(frame.file(), QLatin1String("main.cpp"));
640     QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
641     }
642     }
643 }
644
645 void TestRunner::invalidjump()
646 {
647     const QString app("invalidjump");
648     m_expectCrash = true;
649     const QString binary = runTestBinary(app + QDir::separator() + app);
650     const QString srcDir = srcDirForApp(app);
651
652     QVERIFY(m_logMessages.isEmpty());
653
654     QCOMPARE(m_errors.count(), 1);
655     const Error error = m_errors.first();
656     QCOMPARE(error.kind(), int(InvalidJump));
657     QCOMPARE(error.stacks().count(), 1);
658     const Stack stack = error.stacks().first();
659     QCOMPARE(stack.line(), qint64(-1));
660     QCOMPARE(stack.frames().count(), 2);
661     QVERIFY(!stack.auxWhat().isEmpty());
662     {
663         const Frame frame = stack.frames().at(0);
664         QCOMPARE(frame.instructionPointer(), quint64(0));
665     }
666     {
667         const Frame frame = stack.frames().at(1);
668         QCOMPARE(frame.functionName(), QString("(below main)"));
669     }
670 }
671
672
673 void TestRunner::overlap()
674 {
675     const QString app("overlap");
676     m_expectCrash = true;
677     const QString binary = runTestBinary(app + QDir::separator() + app);
678     const QString srcDir = srcDirForApp(app);
679
680     QVERIFY(m_logMessages.isEmpty());
681
682     QCOMPARE(m_errors.count(), 1);
683     const Error error = m_errors.first();
684     QCOMPARE(error.kind(), int(Overlap));
685     QCOMPARE(error.stacks().count(), 1);
686     const Stack stack = error.stacks().first();
687     QCOMPARE(stack.line(), qint64(-1));
688     QCOMPARE(stack.frames().count(), 2);
689     {
690         const Frame frame = stack.frames().at(0);
691         QCOMPARE(frame.functionName(), QString("memcpy"));
692     }
693     {
694         const Frame frame = stack.frames().last();
695         QCOMPARE(frame.functionName(), QString("main"));
696         QCOMPARE(frame.line(), 6);
697
698         QCOMPARE(frame.object(), binary);
699         QCOMPARE(frame.file(), QLatin1String("main.cpp"));
700         QCOMPARE(QDir::cleanPath(frame.directory()), srcDir);
701     }
702 }