From 7fccf854dbd5fee11de26b99bbcaaf16090ed6a0 Mon Sep 17 00:00:00 2001 From: Simon Sobisch Date: Thu, 2 Nov 2023 23:51:54 +0000 Subject: [PATCH] peek into file before open * check file open, providing nice and early error * explicit check for perfparser (magic number QPERFSTREAM) opening directly without the need to fall back to file name * explicit check for V1 perf data which isn't supported by perfparser * explicit check for unknown file type Fixes: https://github.com/KDAB/hotspot/issues/477 --- src/parsers/perf/perfparser.cpp | 36 +++-- .../file_content/perf.data.true.v1 | Bin 0 -> 9832 bytes .../file_content/perf.data.true.v2 | Bin 0 -> 22500 bytes .../file_content/perf.data.true.v2.gz | Bin 0 -> 4303 bytes .../file_content/true.perfparser | Bin 0 -> 3364 bytes tests/integrationtests/tst_perfparser.cpp | 125 ++++++++++++++++-- 6 files changed, 141 insertions(+), 20 deletions(-) create mode 100644 tests/integrationtests/file_content/perf.data.true.v1 create mode 100644 tests/integrationtests/file_content/perf.data.true.v2 create mode 100644 tests/integrationtests/file_content/perf.data.true.v2.gz create mode 100644 tests/integrationtests/file_content/true.perfparser diff --git a/src/parsers/perf/perfparser.cpp b/src/parsers/perf/perfparser.cpp index f5efdd569..6dd83417a 100644 --- a/src/parsers/perf/perfparser.cpp +++ b/src/parsers/perf/perfparser.cpp @@ -1475,6 +1475,7 @@ PerfParser::~PerfParser() = default; bool PerfParser::initParserArgs(const QString& path) { + // check for common file issues const auto info = QFileInfo(path); if (!info.exists()) { emit parsingFailed(tr("File '%1' does not exist.").arg(path)); @@ -1489,6 +1490,22 @@ bool PerfParser::initParserArgs(const QString& path) return false; } + // peek into file header + const auto filename = decompressIfNeeded(path); + QFile file(filename); + file.open(QIODevice::ReadOnly); + if (file.peek(8) != "PERFILE2" && file.peek(11) != "QPERFSTREAM") { + if (file.peek(8) == "PERFFILE") { + emit parsingFailed(tr("Failed to parse file %1: %2").arg(path, tr("Unsupported V1 perf data"))); + } else { + emit parsingFailed(tr("Failed to parse file %1: %2").arg(path, tr("File format unknown"))); + } + file.close(); + return false; + } + file.close(); + + // check perfparser and set initial values auto parserBinary = Util::perfParserBinaryPath(); if (parserBinary.isEmpty()) { emit parsingFailed(tr("Failed to find hotspot-perfparser binary.")); @@ -1497,7 +1514,7 @@ bool PerfParser::initParserArgs(const QString& path) auto parserArgs = [this](const QString& filename) { const auto settings = Settings::instance(); - QStringList parserArgs = {QStringLiteral("--input"), decompressIfNeeded(filename), + QStringList parserArgs = {QStringLiteral("--input"), filename, QStringLiteral("--max-frames"), QStringLiteral("1024")}; const auto sysroot = settings->sysroot(); if (!sysroot.isEmpty()) { @@ -1530,7 +1547,7 @@ bool PerfParser::initParserArgs(const QString& path) return parserArgs; }; - m_parserArgs = parserArgs(path); + m_parserArgs = parserArgs(filename); m_parserBinary = parserBinary; return true; } @@ -1583,22 +1600,23 @@ void PerfParser::startParseFile(const QString& path) emit parsingFinished(); }; - if (path.endsWith(QLatin1String(".perfparser"))) { - QFile file(path); - if (!file.open(QIODevice::ReadOnly)) { - emit parsingFailed(tr("Failed to open file %1: %2").arg(path, file.errorString())); - return; - } + // note: file is always readable and in supported format here, + // already validated in initParserArgs() + QFile file(path); + file.open(QIODevice::ReadOnly); + if (file.peek(11) == "QPERFSTREAM") { d.setInput(&file); while (!file.atEnd() && !d.stopRequested) { if (!d.tryParse()) { - emit parsingFailed(tr("Failed to parse file")); + // TODO: provide reason + emit parsingFailed(tr("Failed to parse file %1: %2").arg(path, QStringLiteral("Unknown reason"))); return; } } finalize(); return; } + file.close(); QProcess process; process.setProcessEnvironment(perfparserEnvironment(debuginfodUrls)); diff --git a/tests/integrationtests/file_content/perf.data.true.v1 b/tests/integrationtests/file_content/perf.data.true.v1 new file mode 100644 index 0000000000000000000000000000000000000000..1c673fc480186d42b74f374882256c4a90211f93 GIT binary patch literal 9832 zcmcIqO^@3|7$}`Y$tZtUm82< z?x{gsKtgIRaNU*o0W0xwKuB}}A#v;e1A64v6(?@X%)H}xCboAsi8oSgk3D{#=lz&> zCU)i<3seNSW@kmjXr{NeA$%~f{pbF#m)WFXhD%S)fkiP?t0k6m7t&#h;x0%807TLC%vg7F;tX{5`Yvps*QngwsSIg67!>*N=FVvLU zj0~)@j;yYM0@=}J-6`SQ%1d67o197VPXYf!vHv9ew%6W;|I66^e*XN(Xj`6JGS$G` zMF$s$;z97kYJPrjEQCBnB$#CpH6;!kjQ^3?bG$gHp(^9A;#=18PW)UPdWXP%B~Sjg z;Tp)&GNX{9- z!=qrgmxtfMZauPFOexv|zjJo`$AJIzl+b&$I?xK_driGcH^gcuBkwuh{8n zIWT?A^wV;UkR-?1OF8PWs+x?yCCx)L0%o*q8`uZ@ydPc${#@pN!r$x!0ba8Z8D#pQ z@fgq#4iY;0Ovg~Bju#Kd3N%u8Rb(hlydv{FHzObk9nuN#$3){#MVcw&C0evTb1V&c zny0g2G4MiskjRVTE1=_P+=m>E=MShubXCT5h^SFsa(PiW1^hSIf}Gtj9=~gZvN2t$ zRA8GC3qp~I$KtCj9^^{=8Bd3=BHu%y%=V+`=)DFy9>*HUQ7$?ZKXZwc$cy>cLB~XO zI;vZmsUq3;b)!pM5n>&pbt&=K%#+`8{Z1&;(b}QMnGs3);WYSRT~s_?JV<_q9a(RqW8i+oLn zU8d#0-;lk z&G8m%z`GtjDH|vM!SBT3gfp9$i}&Wc%w91vqvb#5#p&j?f|+Qa#!VO!cCWn${1eTC zB>!z&BVR&{b%@ra@D?ut??ib{crR3{auCvbo5{=hyT^F{o+Q5rZxdO1+hDsacc-kw zF0(unJv3Up2|up0GcrDCS$1e3+*CrfiJx+&OM$p^b+7P#PX15mpfVJYl`dwGhnyaN zpY=GZ+qUWN2GQ}X1^(gY<;}eG#35P^mD#z*>_<0mT_=8_dWOX$bW~>dEl$cp<62|( zGomG9oy7U0&vYE0+0DkDEoNXQK5piAz$?AUHcnO62Pn(=*ZUyL3ISN>{Yn64tZp zxY_s+;^c`vbEvaW-lLnpM0_WP`Q5j=BKwB3zt7=?2<41IA(fQMdhRW zh0TBQFfy9)1e8%vc)wiD$uC(tl#B?0-HE*IGd=5*`UQ`p8du~jzs60>OCowozSOUQ zUmpD=tc*sFPg2KTCT4g_^|tgKR!Y9Ufm*|wNt^g@3cqoV`bkoqoR*~C(C^1ifaIp- z$`r^*{rxe8-wSg%-(R9Y$$199r?vGGesfzb2SdY}-a$5?Ymvk20bcRMpbt5ai7xzF z17l)k_IY{s#zKRfAgye8hR^HW0DS+Hh!5C!s|^$re4!I=fLd&DWBi4(;f&CbF7!&Y#opr#g4A~#&6V~Y(_d_DHQa+D$rU^~r z_5gQr2p6M~ytkUj2t2zx(7I>bjXmf!>{h8#p2lMFz}lnUjbCA$o)lar#>-y`P0uBN zyTHzvE?0!Ev;lq)@_%FJcxhIws=;OhU*qR;$JxL6 z?LEPM)@Jq(?E1vy@8|WfdS1Ags)w)Vq(h|Vo39JhPw?-m%HVu-{i`=$px2}JZ)c&M S)&F)`?EfEYn{NrSr2hdx9tUs$ literal 0 HcmV?d00001 diff --git a/tests/integrationtests/file_content/perf.data.true.v2 b/tests/integrationtests/file_content/perf.data.true.v2 new file mode 100644 index 0000000000000000000000000000000000000000..12fa8ac8733cfb0ece89afaf2301b41ebae6d7b9 GIT binary patch literal 22500 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 EKU!qXF8}}l literal 0 HcmV?d00001 diff --git a/tests/integrationtests/file_content/perf.data.true.v2.gz b/tests/integrationtests/file_content/perf.data.true.v2.gz new file mode 100644 index 0000000000000000000000000000000000000000..5f953ee5a9050fad709d1af03c8b4360c4b2990d GIT binary patch literal 4303 zcmV;=5HRl_iwFn`4Mb%C18`+>W-er5bYU)Za&=`cb}|6%Tx*OQ*L9wiWLJtEds8b; z)7BPaCyrc;9Fn`*UCAb}Tyn&v#g{o;c~w~*afid@Xvvw;%y6}v1ok#X3kOkCq3EAJ z0tk&8^no@qV5s?#wrkf-ou*FIA8FkdO61r91S191G%XAyj(Q*Gk~8G+vEpnIpnDg? zZ|-BxIrrRi&p9(gZb2v>OJ{^=jiY4)u(N&x(8zF}<=y8#;N1ab3}5T0U%Hnf|Dt=` z?&*K-ONW(P_uir>0q_1=M}3SO1@0Cq(DbWte!y8jwW64sQV*?^>ve0rVV#z2WzF`U z&lu8x#usgd*WkI2egegr-6hA*DVYTAP`YrY3pHm9LoU zs$yDvqrz7jL3CMYMfaW`<^Oz}|K%~t-*Ar`g}jHVg%`Gc(Lz}55V`*D11BPl%c9? z-jnar|M<^>f8OPz{*h}~uC4*}@sAEU!uz*lKR5z*KRKN7$`3i5>tWypDa!`&PAdcT zaCN^Ae!6VRH6ArN6f%Lrg{s*&rR;4N4n53%kjin@4?U20VO1o^B#|5g`H$aE`EUBc zU#^&XgMRkq@9+m#@AttD@L+UM^?PQGUGoln$nQ99nNsfzzH8nWf&chDBk-?U{2Dzl zTg-nT-%B6!!T%zjOR83F*iu8aywcSR_@kv#!+lq;* zl3iXxS9{;ocG>AB$Z>I$e9>Vi6fkolhc|zRpD2XDE=J)`_eq6(VAgVv{o%~lqdvwX z1Fe2dw~cypnYU_&Tr+xYjqdzp!pHnXHkwsaImb5)#U$yf;mzNfpG^3vhq7ttrp-_? zJbiXs4riR2g#9qezC?C_pD0x5=TQ0j_>_ zymsh;osq0Tvdyw)vF$Q&U1pE^kl!JHS+(S{TvHg5WkK?I^LO~`*~fi&{z>CDK32(t zwwf|<9d17EgFSfWO~Y(Yk38-P|MIvFf8j{v2Iu>me#x<9s+DEMA&Igygl4+!BL?wg zl;^^2`@n3m00Y;9i$gxUU3&1o>*>yC{F0+ym+?WKbM%_OgKuEYr~NS#j`Egm^yTY( z?g@N1N4?(!y;B%|ABL0L<`<-*@T8C^4fou0!!J47BCOextZN#I4?V-CN8C>O;18Vd zMeHUCmmtSLJro4U8%DKZGO>>JbH%l)#Bo=kB6@kqQ~vvQb9dvq zv=BMiqL0=dt!=#$jD{l9Axn4g`TV|bJLciwbMe8CQ$E1p=GaJl9(?%QJ=Pici~}E5 z?@@TZtm#^tE;sF<%Q@&?l)!%ALRRllPOVlf{dAk|L$f{P-RO{aV{7t$;lOvi*Y)Bi zUDxp^T-P&w|9l^Pt4nfAAw#;%grnO?XXpV|JWBRg#YZ*LtfXTyz!EI zea3nZ^(^~3>eud@r6-{OS=eY(_x!}AkHDAR`e|JUW#dn2|8>ykO+XfZXI`Ml}z-Iyf3Ggkz{{h_l4;1eQJOr2qJONk(d=~I?fR_Nj3it!SU0^e!x!xKK>1gPXe9-JPY_qz~2Y_4?yml6vqKy`=)!Je1x4q ze#p|gTR-}<0~lF+Vjb*P9~D3rU74R@?tKRE4nXFoeumKlKeD%DU$b${AKeA@uL0iO zQGY)mdoglPNBu(`^gj%!UZHw80QGl3FYq%JZvBdP+-#L!JN>N_Q~A5U@+<3qVtwR4 z|0_msAp2afQ+CQu*(p0^r|guSvQu`-|NBCo`j>=aHfF0vRpE+4HeV7JM4=cn&uUPe z&x@s)tXi_ZYG~2PBiwvGE5!Jk-cWcvsx@4k7c!X`eVrg%HLegZ&Bxf2Rb@?)dHkA& z{F?J<>vDcsYoewly&jwlh4IBlLr3{0j|8$z8P}&K-SwlCq%N21UEP*!s)lVjhs-JF zic(kBlXIb|P?QqT4V!OR*13An*7ds8rs_Uv$w-^sGIX)@m{AmF{xM?O|<63{yX=$hO7TnialBvm)1>+?2AlZs}E0^G|5>#EjV<4y>%yMYDBlnpB9;tRW*xiF_ts6k}ZC zgeVoo`Iv=F`FK)50*l0&xu;4}A+wN5=OmYfpWs=8VcULuLgX)s2mCM9)shFZk ziFjzCbSyZ-WssWk1tAyv)Tdf+7FQ68842$?th5NNX7Y(R`b^JB z#eBZho-W>F^}}>bc23F{O0i%NF}BO~y0lcblz{ipEE$^4iKTcZBhAG{!IS1;#Idu3 zOp*>ks!0{&h52+s6iXUPv;Wd?YyeV^=3su{e)*% zKdNwv{9Ha0Lz|5&#fvGSB<00eLdcc!;xzJJ$@w^%eG*Ql1HoiES6ax4LP^M-K(%}^ zp2!H1D3?j+78VgLLJ1)elsE}hHub75H!Ys*Xf7$75Q|t^*#2BPo5HntF@f6obT*z6 zL_Uh9g%p`$Iz-xER=7ejFBXJENsP5Nu4Ukzi+i4QcaR;;B^HXfD~5J9S4tPebV-PH zZ+hHCtRr5Edvx=avR&qm3%RFDMXw<%ibjWER@9=m;%>-gZL4r~<0Zm!yEKLxsL488 zl3CGVR+WYYjmW9Q%I8+>Lr1c>CB4`+FjUuh(u2#ock8=VGp)g#2Ny?U5Q~SKMh;7bB74RJ%&UP{-g_BZt&2Cg!E2n2R;mZN;*= zW601^tFsB&R&p-wY(bira(O8(W@DO8YKV%EjXTF=MbMN-G{*BIc}XrD4l^MZP$WU& z%vKt#1v~m|)3Qq@`iQVr5slMLWSMk-ON7v>9YK_!#gV~yggG`Ukx3(0(t8{+Zy4Lj z(;+LgbjXTzNHQlFh3g$d@=0XA?Fi!z=uJ&s!vl!6@JZWAx(6a5Ju`w90Wu51XD9Lc zX->Sb-z=mug+gpH0u>Zvilw3uPsUDinIz5zit*w}sncjWR-$bYIGj4AW(`cm9`!y# zdeU`UUz-=)j@uCAyxmC)@w>81Z{1_r3FG|L=9N7eu%Dy{=!r z^Sk}OZ^h`3_1fMogJme-Xi_1{zUMtzT?;9?(yg6Xgx{B@8#xmRO}>( zf1#s(wWGd2@2)RGoxKk`)6xGzNBu^}_?u8)gcsuTPf^^2{=G$tZ$th2P=5yM^CHEM z!u9nM#WnZWXIf=*(@8K|FUmr8kO^9vwCPIawK~DaTkke0(86p!JQ5X3V>C(HWvl~de!>%c z*W;9-bO$a+t=bbK4Dcu%8|0{F@t&N~25;(-?Jb{|l`zq!{E^0012Fr-uLl literal 0 HcmV?d00001 diff --git a/tests/integrationtests/file_content/true.perfparser b/tests/integrationtests/file_content/true.perfparser new file mode 100644 index 0000000000000000000000000000000000000000..ae951816d53b41e97abab0f7155ec9cb727d0cdd GIT binary patch literal 3364 zcmeHKU2GIp6u#T-4=uJ33lfqF^8iG&JG26mV)=>Iw1tNH6WiI@X}j#~Oqrdv zYGT+2dGJA{X<|Z5bVCSHAB>V{6ER_f8fwv4YHM2rT!KauG4+XPg6MZP2O?Zg=KxuY|< zU`;LsuL_|mRWoce-3oVOL=K1KP$1kCk)v`%*7R2Sg|=vav>D`Pmuv|)%T4$bq#V~` znIT9jxws67Y|B2w*7W;&wo84QY0$WGyVN8%hxY7!3A*|{nvqEunj>$F zHbz2?EeJE#cyt|ldcN9VCT#^{2_rb7S%U~vTAFHFad>wH0;;0xfgwv783wM2k1Ez+ zV_W#aCZKZL%4is=(bN0!fEcJeUx+$FVvmBi+kg>yV*$M@E{99z#|9GzTa`8kZLCA7 zDOZhcDXKPNCJY;hDz1rHnvyIn0U-`0N z<}c4>IkT|y$pQz9-Vb>3Sesxjr5=OIt?km!b9oMa_-Z`I!R3dnEC*M%UY7)T+s<=v zb?trvwJ>@O>18da?@TE`Z>#gAD86b}CnocV6v2<(3+)2@)hR%svntP-!keE+0{lJ& z-%W7skp~2`)EmxmW+{6nE5N%qBmrihhwmm>`t|hz0dAejaqtH`w2d%4g7H()oLH&z z-ANw5QJubW;#rq1I|FAGj5gpj+r>SWg4E!6wHuV44ei(2|tZo3K;S;U`O4olzRvsa<^40yHe|hMhNk@qvR-?xQO>($ZPMi0*VY(UBMw^3z3AhYR z+7cW#Q(7>cNSQ{^y=(^cMC^_U+aaXvXh+Jn{e7_OA2ja|d=VEF4HzhMC9J+buJ>CS z?!1bv^_#Innrd%DoNA&*8cJNk6I~Q#Y~3uniqf*a;q6<1uZo{wtOjwC<|KaSg9^NBE+{> z7nX~?buK+FQ;GMhiaM;pHItcVB`PysuB1Vmtz(?SW737c=n}7P)dUyzUW?m0GOzeLUkB$=Y EFHtmATL1t6 literal 0 HcmV?d00001 diff --git a/tests/integrationtests/tst_perfparser.cpp b/tests/integrationtests/tst_perfparser.cpp index 184bff7ed..01357bc65 100644 --- a/tests/integrationtests/tst_perfparser.cpp +++ b/tests/integrationtests/tst_perfparser.cpp @@ -172,6 +172,109 @@ private slots: m_capabilities = host.perfCapabilities(); } + void testFileErrorHandling() + { + PerfParser parser(this); + QSignalSpy parsingFailedSpy(&parser, &PerfParser::parsingFailed); + QString message; + + const auto notThereFile = QStringLiteral("not_here"); + parser.initParserArgs(notThereFile); + + QCOMPARE(parsingFailedSpy.count(), 1); + message = qvariant_cast(parsingFailedSpy.takeFirst().at(0)); + QVERIFY(message.contains(notThereFile)); + QVERIFY(message.contains(QLatin1String("does not exist"))); + + const auto parentDirs = QStringLiteral("../.."); + parser.initParserArgs(parentDirs); + // note: initializing parser args reset the attached spy counter + QCOMPARE(parsingFailedSpy.count(), 1); + message = qvariant_cast(parsingFailedSpy.takeFirst().at(0)); + QVERIFY(message.contains(parentDirs)); + QVERIFY(message.contains(QLatin1String("is not a file"))); + + const auto noRead = QStringLiteral("no_r_possible"); + const auto shell = QStandardPaths::findExecutable(QStringLiteral("bash")); + if (!shell.isEmpty()) { + QProcess::execute( + shell, {QLatin1String("-c"), QStringLiteral("rm -rf %1 && touch %1 && chmod a-r %1").arg(noRead)}); + parser.initParserArgs(noRead); + + QCOMPARE(parsingFailedSpy.count(), 1); + message = qvariant_cast(parsingFailedSpy.takeFirst().at(0)); + QVERIFY(message.contains(noRead)); + QVERIFY(message.contains(QLatin1String("not readable"))); + } + } + + void testFileContent() + { + Settings::instance()->setAppPath(QStringLiteral("/usr/bin")); // should be the output of `which true` + Settings::instance()->setExtraLibPaths(QFINDTESTDATA("file_content")); + PerfParser parser(this); + QSignalSpy parsingFailedSpy(&parser, &PerfParser::parsingFailed); + QSignalSpy parsingFinishedSpy(&parser, &PerfParser::parsingFinished); + QString message; + + // check pre-exported perfparser + const auto perfData = QFINDTESTDATA("file_content/true.perfparser"); + QVERIFY(!perfData.isEmpty() && QFile::exists(perfData)); + parser.startParseFile(perfData); + QVERIFY(parsingFinishedSpy.wait(2000)); + QCOMPARE(parsingFailedSpy.count(), 0); + QCOMPARE(parsingFinishedSpy.count(), 1); + + // check pre-exported perfparser with "bad extension" + const auto shell = QStandardPaths::findExecutable(QStringLiteral("bash")); + if (!shell.isEmpty()) { + const auto perfDataSomeName = QStringLiteral("fruitper"); + QProcess::execute(shell, + {QStringLiteral("-c"), QLatin1String("cp -f %1 %2").arg(perfData, perfDataSomeName)}); + + parser.startParseFile(perfDataSomeName); + QVERIFY(parsingFinishedSpy.wait(3000)); + QCOMPARE(parsingFailedSpy.count(), 0); + QCOMPARE(parsingFinishedSpy.count(), 2); + } + + // check for invalid data -> expected error + const auto noPerf = QFINDTESTDATA("tst_perfparser.cpp"); + QVERIFY(!noPerf.isEmpty() && QFile::exists(noPerf)); + parser.startParseFile(noPerf); + QCOMPARE(parsingFailedSpy.count(), 1); + message = qvariant_cast(parsingFailedSpy.takeFirst().at(0)); + QVERIFY(message.contains(noPerf)); + QVERIFY(message.contains(QLatin1String("File format unknown"))); + + // check for PERFv1 -> expected error + const auto perf1 = QFINDTESTDATA("file_content/perf.data.true.v1"); + QVERIFY(!perf1.isEmpty() && QFile::exists(perf1)); + parser.startParseFile(perf1); + QCOMPARE(parsingFailedSpy.count(), 1); + message = qvariant_cast(parsingFailedSpy.takeFirst().at(0)); + QVERIFY(message.contains(perf1)); + QVERIFY(message.contains(QLatin1String("V1 perf data"))); + + // check for PERFv2 + const auto perf2 = QFINDTESTDATA("file_content/perf.data.true.v2"); + QVERIFY(!perf2.isEmpty() && QFile::exists(perf2)); + parser.startParseFile(perf2); + QVERIFY(parsingFinishedSpy.wait(2000)); + QCOMPARE(parsingFailedSpy.count(), 0); + QCOMPARE(parsingFinishedSpy.count(), 3); + +#if KFArchive_FOUND + // check for PERFv2, gzipped + const auto perf2gz = QFINDTESTDATA("file_content/perf.data.true.v2.gz"); + QVERIFY(!perf2gz.isEmpty() && QFile::exists(perf2gz)); + parser.startParseFile(perf2gz); + QVERIFY(parsingFinishedSpy.wait(2000)); + QCOMPARE(parsingFailedSpy.count(), 0); + QCOMPARE(parsingFinishedSpy.count(), 4); +#endif + } + void init() { m_bottomUpData = {}; @@ -743,8 +846,8 @@ private slots: VERIFY_OR_THROW(recordingFinishedSpy.wait(10000)); - COMPARE_OR_THROW(recordingFailedSpy.count(), 0); - COMPARE_OR_THROW(recordingFinishedSpy.count(), 1); + QCOMPARE(recordingFailedSpy.count(), 0); + QCOMPARE(recordingFinishedSpy.count(), 1); COMPARE_OR_THROW(QFileInfo::exists(fileName), true); m_perfCommand = perf.perfCommand(); @@ -790,25 +893,25 @@ private slots: parser.startParseFile(fileName); - VERIFY_OR_THROW(parsingFinishedSpy.wait(6000)); + QVERIFY(parsingFinishedSpy.wait(6000)); // Verify that the test passed - COMPARE_OR_THROW(parsingFailedSpy.count(), 0); - COMPARE_OR_THROW(parsingFinishedSpy.count(), 1); + QCOMPARE(parsingFailedSpy.count(), 0); + QCOMPARE(parsingFinishedSpy.count(), 1); // Verify the summary data isn't empty - COMPARE_OR_THROW(summaryDataSpy.count(), 1); + QCOMPARE(summaryDataSpy.count(), 1); QList summaryDataArgs = summaryDataSpy.takeFirst(); m_summaryData = qvariant_cast(summaryDataArgs.at(0)); - COMPARE_OR_THROW(m_perfCommand, m_summaryData.command); + QCOMPARE(m_perfCommand, m_summaryData.command); VERIFY_OR_THROW(m_summaryData.sampleCount > 0); VERIFY_OR_THROW(m_summaryData.applicationTime.delta() > 0); VERIFY_OR_THROW(m_summaryData.cpusAvailable > 0); - COMPARE_OR_THROW(m_summaryData.processCount, quint32(1)); // for now we always have a single process + QCOMPARE(m_summaryData.processCount, quint32(1)); // for now we always have a single process VERIFY_OR_THROW(m_summaryData.threadCount > 0); // and at least one thread - COMPARE_OR_THROW(m_summaryData.cpuArchitecture, m_cpuArchitecture); - COMPARE_OR_THROW(m_summaryData.linuxKernelVersion, m_linuxKernelVersion); - COMPARE_OR_THROW(m_summaryData.hostName, m_machineHostName); + QCOMPARE(m_summaryData.cpuArchitecture, m_cpuArchitecture); + QCOMPARE(m_summaryData.linuxKernelVersion, m_linuxKernelVersion); + QCOMPARE(m_summaryData.hostName, m_machineHostName); if (checkFrequency) { // Verify the sample frequency is acceptable, greater than 500Hz