OSDN Git Service

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