File indexing completed on 2024-05-12 05:51:05
0001 /* 0002 SPDX-FileCopyrightText: 2022 Héctor Mesa Jiménez <wmj.py@gmx.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "test_gdbmi.h" 0008 0009 #include "../gdbmi/parser.h" 0010 #include "../gdbmi/tokens.h" 0011 0012 #include <QSignalSpy> 0013 #include <QString> 0014 #include <QTest> 0015 0016 QTEST_MAIN(TestGdbmi) 0017 0018 void TestGdbmi::tryToken() 0019 { 0020 QFETCH(QString, msg); 0021 QFETCH(int, start); 0022 QFETCH(bool, empty); 0023 QFETCH(bool, error); 0024 QFETCH(int, position); 0025 QFETCH(int, value); 0026 0027 const auto tok = gdbmi::tryToken(msg.toUtf8(), start); 0028 0029 QCOMPARE(tok.isEmpty(), empty); 0030 if (empty) { 0031 QCOMPARE(tok.hasError(), error); 0032 QCOMPARE(tok.position, start); 0033 } else { 0034 QVERIFY(tok.value.has_value()); 0035 QCOMPARE(tok.value.value(), value); 0036 QCOMPARE(tok.position, position); 0037 } 0038 } 0039 0040 void TestGdbmi::tryToken_data() 0041 { 0042 QTest::addColumn<QString>("msg"); 0043 QTest::addColumn<int>("start"); 0044 QTest::addColumn<bool>("empty"); 0045 QTest::addColumn<bool>("error"); 0046 QTest::addColumn<int>("position"); 0047 QTest::addColumn<int>("value"); 0048 0049 QTest::newRow("1234") << "1234" << 0 << false << false << 4 << 1234; 0050 QTest::newRow("1234a") << "1234a" << 0 << false << false << 4 << 1234; 0051 QTest::newRow("1234\\n") << "1234\n" << 0 << false << false << 4 << 1234; 0052 QTest::newRow("__1234") << "__1234" << 2 << false << false << 6 << 1234; 0053 QTest::newRow("asdf") << "asdf" << 0 << true << false << 0 << -1; 0054 } 0055 0056 void TestGdbmi::advanceBlanks() 0057 { 0058 QFETCH(QString, msg); 0059 QFETCH(int, start); 0060 QFETCH(int, position); 0061 0062 const int pos = gdbmi::advanceBlanks(msg.toUtf8(), start); 0063 QCOMPARE(pos, position); 0064 } 0065 0066 void TestGdbmi::advanceBlanks_data() 0067 { 0068 QTest::addColumn<QString>("msg"); 0069 QTest::addColumn<int>("start"); 0070 QTest::addColumn<int>("position"); 0071 0072 QTest::newRow(" \\t asdf") << " \t asdf" << 0 << 4; 0073 QTest::newRow(" \\t \\nasdf") << " \t \nasdf" << 0 << 4; 0074 QTest::newRow(" \\t \\nasdf[2]") << " \t \nasdf" << 2 << 4; 0075 QTest::newRow("asdf") << "asdf" << 2 << 2; 0076 } 0077 0078 void TestGdbmi::tryString() 0079 { 0080 QFETCH(QString, msg); 0081 QFETCH(int, start); 0082 QFETCH(bool, empty); 0083 QFETCH(bool, error); 0084 QFETCH(int, position); 0085 QFETCH(QString, value); 0086 0087 const auto tok = gdbmi::tryString(msg.toUtf8(), start); 0088 0089 QCOMPARE(tok.isEmpty(), empty); 0090 if (empty) { 0091 QCOMPARE(tok.hasError(), error); 0092 QCOMPARE(tok.position, start); 0093 } else { 0094 QVERIFY(tok.value.has_value()); 0095 QCOMPARE(tok.value.value(), value); 0096 QCOMPARE(tok.position, position); 0097 } 0098 } 0099 0100 void TestGdbmi::tryString_data() 0101 { 0102 QTest::addColumn<QString>("msg"); 0103 QTest::addColumn<int>("start"); 0104 QTest::addColumn<bool>("empty"); 0105 QTest::addColumn<bool>("error"); 0106 QTest::addColumn<int>("position"); 0107 QTest::addColumn<QString>("value"); 0108 0109 QTest::newRow("\"12\\n34\"") << R"-("12\n34")-" << 0 << false << false << 8 << "12\n34"; 0110 QTest::newRow("\"\"") << "\"\"" << 0 << false << false << 2 << ""; 0111 // base 0112 QTest::newRow("\"1234\"") << "\"1234\"" << 0 << false << false << 6 << "1234"; 0113 // escaped quote 0114 QTest::newRow("\"12\\\"34\"") << R"-("12\\\"34")-" << 0 << false << false << 10 << R"-(12\"34)-"; 0115 // incomplete (start) 0116 QTest::newRow("\"1234\"") << "\"1234\"" << 1 << true << true << 0 << ""; 0117 // incomplete (end) 0118 QTest::newRow("\"1234") << "\"1234" << 0 << true << true << 0 << ""; 0119 } 0120 0121 void TestGdbmi::tryClassName() 0122 { 0123 QFETCH(QString, msg); 0124 QFETCH(int, start); 0125 QFETCH(bool, empty); 0126 QFETCH(bool, error); 0127 QFETCH(int, position); 0128 QFETCH(QString, value); 0129 0130 const auto tok = gdbmi::tryClassName(msg.toUtf8(), start); 0131 0132 QCOMPARE(tok.isEmpty(), empty); 0133 if (empty) { 0134 QCOMPARE(tok.hasError(), error); 0135 QCOMPARE(tok.position, start); 0136 } else { 0137 QVERIFY(tok.value.has_value()); 0138 QCOMPARE(tok.value.value(), value); 0139 QCOMPARE(tok.position, position); 0140 } 0141 } 0142 0143 void TestGdbmi::tryClassName_data() 0144 { 0145 QTest::addColumn<QString>("msg"); 0146 QTest::addColumn<int>("start"); 0147 QTest::addColumn<bool>("empty"); 0148 QTest::addColumn<bool>("error"); 0149 QTest::addColumn<int>("position"); 0150 QTest::addColumn<QString>("value"); 0151 0152 QTest::newRow("^exit") << "^exit" << 1 << false << false << 5 << "exit"; 0153 QTest::newRow("^exit\\n") << "^exit\n" << 1 << false << false << 5 << "exit"; 0154 QTest::newRow("^exit\\r\\n") << "^exit\r\n" << 1 << false << false << 5 << "exit"; 0155 QTest::newRow("^__exit") << "^ exit" << 1 << false << false << 7 << "exit"; 0156 QTest::newRow("^stopped,reason") << "^stopped,reason" << 1 << false << false << 8 << "stopped"; 0157 QTest::newRow("_") << "" << 0 << true << true << -1 << ""; 0158 QTest::newRow("^running\\n*running,id=1") << "^running\n*running,id=1" << 1 << false << false << 8 << "running"; 0159 } 0160 0161 void TestGdbmi::tryVariable() 0162 { 0163 QFETCH(QString, msg); 0164 QFETCH(int, start); 0165 QFETCH(bool, empty); 0166 QFETCH(bool, error); 0167 QFETCH(int, position); 0168 QFETCH(QString, value); 0169 0170 const auto tok = gdbmi::tryVariable(msg.toUtf8(), start); 0171 0172 QCOMPARE(tok.isEmpty(), empty); 0173 if (empty) { 0174 QCOMPARE(tok.hasError(), error); 0175 QCOMPARE(tok.position, start); 0176 } else { 0177 QVERIFY(tok.value.has_value()); 0178 QCOMPARE(tok.value.value(), value); 0179 QCOMPARE(tok.position, position); 0180 } 0181 } 0182 0183 void TestGdbmi::tryVariable_data() 0184 { 0185 QTest::addColumn<QString>("msg"); 0186 QTest::addColumn<int>("start"); 0187 QTest::addColumn<bool>("empty"); 0188 QTest::addColumn<bool>("error"); 0189 QTest::addColumn<int>("position"); 0190 QTest::addColumn<QString>("value"); 0191 0192 QTest::newRow("reason=\"breakpoint-hit\"") << "reason=\"breakpoint-hit\"" << 0 << false << false << 7 << "reason"; 0193 QTest::newRow("reason =\"breakpoint-hit\"") << "reason =\"breakpoint-hit\"" << 0 << false << false << 8 << "reason"; 0194 QTest::newRow("__reason=\"breakpoint-hit\"") << " reason=\"breakpoint-hit\"" << 0 << false << false << 9 << "reason"; 0195 QTest::newRow("reason") << "reason" << 0 << true << true << 0 << ""; 0196 } 0197 0198 void TestGdbmi::tryStreamOutput() 0199 { 0200 QFETCH(QString, msg); 0201 QFETCH(int, start); 0202 QFETCH(bool, empty); 0203 QFETCH(bool, error); 0204 QFETCH(int, position); 0205 QFETCH(QString, value); 0206 QFETCH(char, prefix); 0207 0208 const auto tok = gdbmi::tryStreamOutput(prefix, msg.toUtf8(), start); 0209 0210 QCOMPARE(tok.isEmpty(), empty); 0211 if (empty) { 0212 QCOMPARE(tok.hasError(), error); 0213 QCOMPARE(tok.position, start); 0214 } else { 0215 QVERIFY(tok.value.has_value()); 0216 QCOMPARE(tok.value.value().message, value); 0217 QCOMPARE(tok.position, position); 0218 } 0219 } 0220 0221 void TestGdbmi::tryStreamOutput_data() 0222 { 0223 QTest::addColumn<QString>("msg"); 0224 QTest::addColumn<int>("start"); 0225 QTest::addColumn<bool>("empty"); 0226 QTest::addColumn<bool>("error"); 0227 QTest::addColumn<int>("position"); 0228 QTest::addColumn<QString>("value"); 0229 QTest::addColumn<char>("prefix"); 0230 0231 QTest::newRow("~\"algo\",^running") << "~\"algo\",^running" << 0 << false << false << 7 << "algo" << '~'; 0232 QTest::newRow("~\"algo\"") << "~\"algo\"" << 0 << false << false << 7 << "algo" << '~'; 0233 QTest::newRow("~\"algo\"\\n") << "~\"algo\"\n" << 0 << false << false << 8 << "algo" << '~'; 0234 QTest::newRow("~\"algo\"\\n") << "~\"algo\"\\n" << 0 << false << false << 7 << "algo" << '~'; 0235 QTest::newRow("~\"algo") << "~\"algo" << 0 << false << false << 6 << "\"algo" << '~'; 0236 QTest::newRow("~\"algo\\n") << "~\"algo\n" << 0 << false << false << 7 << "\"algo" << '~'; 0237 } 0238 0239 void TestGdbmi::tryResult() 0240 { 0241 QFETCH(QString, msg); 0242 QFETCH(int, start); 0243 QFETCH(bool, empty); 0244 QFETCH(bool, error); 0245 QFETCH(int, position); 0246 QFETCH(QJsonObject, value); 0247 0248 const auto tok = gdbmi::tryResult(msg.toUtf8(), start); 0249 0250 QCOMPARE(tok.isEmpty(), empty); 0251 if (empty) { 0252 QCOMPARE(tok.hasError(), error); 0253 QCOMPARE(tok.position, start); 0254 } else { 0255 QCOMPARE(tok.position, position); 0256 QVERIFY(tok.value.has_value()); 0257 const auto tokval = tok.value.value(); 0258 QVERIFY(value.contains(tokval.name)); 0259 compare(value[tokval.name], tokval.value); 0260 } 0261 } 0262 0263 void TestGdbmi::tryResult_data() 0264 { 0265 QTest::addColumn<QString>("msg"); 0266 QTest::addColumn<int>("start"); 0267 QTest::addColumn<bool>("empty"); 0268 QTest::addColumn<bool>("error"); 0269 QTest::addColumn<int>("position"); 0270 QTest::addColumn<QJsonObject>("value"); 0271 0272 QTest::newRow("reason=\"breakpoint-hit\"") << "reason=\"breakpoint-hit\"" << 0 << false << false << 23 0273 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}; 0274 QTest::newRow("reason=\"breakpoint-hit") << "reason=\"breakpoint-hit" << 0 << true << true << 0 << QJsonObject{}; 0275 QTest::newRow("^done,reason=\"breakpoint-hit\"") << "^done,reason=\"breakpoint-hit\"" << 6 << false << false << 29 0276 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}; 0277 QTest::newRow("thread-groups=[\"i1\"]") << "thread-groups=[\"i1\"]" << 0 << false << false << 20 0278 << QJsonObject{{QStringLiteral("thread-groups"), QJsonArray{QStringLiteral("i1")}}}; 0279 QTest::newRow("args=[]") << "args=[]" << 0 << false << false << 7 << QJsonObject{{QStringLiteral("args"), QJsonArray()}}; 0280 QTest::newRow("frame={}") << "frame={}" << 0 << false << false << 8 << QJsonObject{{QStringLiteral("frame"), QJsonObject()}}; 0281 } 0282 0283 void TestGdbmi::tryResults() 0284 { 0285 QFETCH(QString, msg); 0286 QFETCH(int, start); 0287 QFETCH(bool, empty); 0288 QFETCH(bool, error); 0289 QFETCH(int, position); 0290 QFETCH(QJsonObject, value); 0291 0292 const auto tok = gdbmi::tryResults(msg.toUtf8(), start); 0293 0294 QCOMPARE(tok.isEmpty(), empty); 0295 if (empty) { 0296 QCOMPARE(tok.hasError(), error); 0297 QCOMPARE(tok.position, start); 0298 } else { 0299 QCOMPARE(tok.position, position); 0300 QVERIFY(tok.value.has_value()); 0301 compare(value, tok.value.value()); 0302 } 0303 } 0304 0305 void TestGdbmi::tryResults_data() 0306 { 0307 QTest::addColumn<QString>("msg"); 0308 QTest::addColumn<int>("start"); 0309 QTest::addColumn<bool>("empty"); 0310 QTest::addColumn<bool>("error"); 0311 QTest::addColumn<int>("position"); 0312 QTest::addColumn<QJsonObject>("value"); 0313 0314 QTest::newRow("string1") << "reason=\"breakpoint-hit\"" << 0 << false << false << 23 0315 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}; 0316 QTest::newRow("breakpoint1") 0317 << "number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0x08048564\",func=\"main\",file=\"myprog.c\",fullname=\"/home/nickrob/" 0318 "myprog.c\",line=\"68\",thread-groups=[\"i1\"],times=\"0\"" 0319 << 0 << false << false << 173 0320 << QJsonObject{{QStringLiteral("number"), QStringLiteral("1")}, 0321 {QStringLiteral("type"), QStringLiteral("breakpoint")}, 0322 {QStringLiteral("disp"), QStringLiteral("keep")}, 0323 {QStringLiteral("enabled"), QStringLiteral("y")}, 0324 {QStringLiteral("addr"), QStringLiteral("0x08048564")}, 0325 {QStringLiteral("func"), QStringLiteral("main")}, 0326 {QStringLiteral("file"), QStringLiteral("myprog.c")}, 0327 {QStringLiteral("fullname"), QStringLiteral("/home/nickrob/myprog.c")}, 0328 {QStringLiteral("line"), QStringLiteral("68")}, 0329 {QStringLiteral("thread-groups"), QJsonArray{QStringLiteral("i1")}}, 0330 {QStringLiteral("times"), QStringLiteral("0")}}; 0331 QTest::newRow("breakpoint2") 0332 << "number=\"1\",type=\"breakpoint\",disp=\"del\",enabled=\"y\",addr=\"0x00005555555551f5\",func=\"main()\",file=\"/pruebas/cpp1/" 0333 "main.cpp\",fullname=\"/pruebas/cpp1/main.cpp\",line=\"7\",thread-groups=[\"i1\"],times=\"1\",original-location=\"main\"" 0334 << 0 << false << false << 220 0335 << QJsonObject{{QStringLiteral("number"), QStringLiteral("1")}, 0336 {QStringLiteral("type"), QStringLiteral("breakpoint")}, 0337 {QStringLiteral("disp"), QStringLiteral("del")}, 0338 {QStringLiteral("enabled"), QStringLiteral("y")}, 0339 {QStringLiteral("addr"), QStringLiteral("0x00005555555551f5")}, 0340 {QStringLiteral("func"), QStringLiteral("main()")}, 0341 {QStringLiteral("file"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0342 {QStringLiteral("fullname"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0343 {QStringLiteral("line"), QStringLiteral("7")}, 0344 {QStringLiteral("thread-groups"), QJsonArray{QStringLiteral("i1")}}, 0345 {QStringLiteral("times"), QStringLiteral("1")}, 0346 {QStringLiteral("original-location"), QStringLiteral("main")}}; 0347 0348 QTest::newRow("breakpoint-frame-noargs") << "addr=\"0x00005555555551f5\",func=\"main\",args=[],file=\"/pruebas/cpp1/main.cpp\"" << 0 << false << false << 75 0349 << QJsonObject{{QStringLiteral("addr"), QStringLiteral("0x00005555555551f5")}, 0350 {QStringLiteral("func"), QStringLiteral("main")}, 0351 {QStringLiteral("args"), QJsonArray()}, 0352 {QStringLiteral("file"), QStringLiteral("/pruebas/cpp1/main.cpp")}}; 0353 0354 QTest::newRow("breakpoint-frame-noargs-full") << "addr=\"0x00005555555551f5\",func=\"main\",args=[],file=\"/pruebas/cpp1/main.cpp\",fullname=\"/pruebas/" 0355 "cpp1/main.cpp\",line=\"7\",arch=\"i386:x86-64\"" 0356 << 0 << false << false << 137 0357 << QJsonObject{{QStringLiteral("addr"), QStringLiteral("0x00005555555551f5")}, 0358 {QStringLiteral("func"), QStringLiteral("main")}, 0359 {QStringLiteral("args"), QJsonArray()}, 0360 {QStringLiteral("file"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0361 {QStringLiteral("fullname"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0362 {QStringLiteral("line"), QStringLiteral("7")}, 0363 {QStringLiteral("arch"), QStringLiteral("i386:x86-64")}}; 0364 0365 QTest::newRow("breakpoint-full") 0366 << "reason=\"breakpoint-hit\",disp=\"del\",bkptno=\"1\",frame={addr=\"0x00005555555551f5\",func=\"main\",args=[],file=\"/pruebas/cpp1/" 0367 "main.cpp\",fullname=\"/pruebas/cpp1/main.cpp\",line=\"7\",arch=\"i386:x86-64\"},thread-id=\"1\",stopped-threads=\"all\",core=\"1\"\n" 0368 << 0 << false << false << 236 0369 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}, 0370 {QStringLiteral("disp"), QStringLiteral("del")}, 0371 {QStringLiteral("bkptno"), QStringLiteral("1")}, 0372 {QStringLiteral("frame"), 0373 QJsonObject{{QStringLiteral("addr"), QStringLiteral("0x00005555555551f5")}, 0374 {QStringLiteral("func"), QStringLiteral("main")}, 0375 {QStringLiteral("args"), QJsonArray()}, 0376 {QStringLiteral("file"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0377 {QStringLiteral("fullname"), QStringLiteral("/pruebas/cpp1/main.cpp")}, 0378 {QStringLiteral("line"), QStringLiteral("7")}, 0379 {QStringLiteral("arch"), QStringLiteral("i386:x86-64")}}}, 0380 {QStringLiteral("thread-id"), QStringLiteral("1")}, 0381 {QStringLiteral("stopped-threads"), QStringLiteral("all")}, 0382 {QStringLiteral("core"), QStringLiteral("1")}}; 0383 } 0384 0385 void TestGdbmi::tryTuple() 0386 { 0387 QFETCH(QString, msg); 0388 QFETCH(int, start); 0389 QFETCH(bool, empty); 0390 QFETCH(bool, error); 0391 QFETCH(int, position); 0392 QFETCH(QJsonObject, value); 0393 0394 const auto tok = gdbmi::tryTuple(msg.toUtf8(), start); 0395 0396 QCOMPARE(tok.isEmpty(), empty); 0397 if (empty) { 0398 QCOMPARE(tok.hasError(), error); 0399 QCOMPARE(tok.position, start); 0400 } else { 0401 QCOMPARE(tok.position, position); 0402 QVERIFY(tok.value.has_value()); 0403 compare(value, tok.value.value()); 0404 } 0405 } 0406 0407 void TestGdbmi::tryTuple_data() 0408 { 0409 QTest::addColumn<QString>("msg"); 0410 QTest::addColumn<int>("start"); 0411 QTest::addColumn<bool>("empty"); 0412 QTest::addColumn<bool>("error"); 0413 QTest::addColumn<int>("position"); 0414 QTest::addColumn<QJsonObject>("value"); 0415 0416 QTest::newRow("{}") << "{}" << 0 << false << false << 2 << QJsonObject(); 0417 QTest::newRow("{ }") << "{ }" << 0 << false << false << 3 << QJsonObject(); 0418 QTest::newRow("{reason=\"breakpoint-hit\"}") << "{reason=\"breakpoint-hit\"}" << 0 << false << false << 25 0419 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}; 0420 QTest::newRow( 0421 "{number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0x08048564\",func=\"main\",file=\"myprog.c\",fullname=\"/home/nickrob/" 0422 "myprog.c\",line=\"68\",thread-groups=[\"i1\"],times=\"0\"}") 0423 << "{number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0x08048564\",func=\"main\",file=\"myprog.c\",fullname=\"/home/nickrob/" 0424 "myprog.c\",line=\"68\",thread-groups=[\"i1\"],times=\"0\"}" 0425 << 0 << false << false << 175 0426 << QJsonObject{{QStringLiteral("number"), QStringLiteral("1")}, 0427 {QStringLiteral("type"), QStringLiteral("breakpoint")}, 0428 {QStringLiteral("disp"), QStringLiteral("keep")}, 0429 {QStringLiteral("enabled"), QStringLiteral("y")}, 0430 {QStringLiteral("addr"), QStringLiteral("0x08048564")}, 0431 {QStringLiteral("func"), QStringLiteral("main")}, 0432 {QStringLiteral("file"), QStringLiteral("myprog.c")}, 0433 {QStringLiteral("fullname"), QStringLiteral("/home/nickrob/myprog.c")}, 0434 {QStringLiteral("line"), QStringLiteral("68")}, 0435 {QStringLiteral("thread-groups"), QJsonArray{QStringLiteral("i1")}}, 0436 {QStringLiteral("times"), QStringLiteral("0")}}; 0437 } 0438 0439 void TestGdbmi::tryValue() 0440 { 0441 QFETCH(QString, msg); 0442 QFETCH(int, start); 0443 QFETCH(bool, empty); 0444 QFETCH(bool, error); 0445 QFETCH(int, position); 0446 QFETCH(QJsonValue, value); 0447 0448 const auto tok = gdbmi::tryValue(msg.toUtf8(), start); 0449 0450 QCOMPARE(tok.isEmpty(), empty); 0451 if (empty) { 0452 QCOMPARE(tok.hasError(), error); 0453 QCOMPARE(tok.position, start); 0454 } else { 0455 QCOMPARE(tok.position, position); 0456 QVERIFY(tok.value.has_value()); 0457 compare(value, tok.value.value()); 0458 } 0459 } 0460 0461 void TestGdbmi::tryValue_data() 0462 { 0463 QTest::addColumn<QString>("msg"); 0464 QTest::addColumn<int>("start"); 0465 QTest::addColumn<bool>("empty"); 0466 QTest::addColumn<bool>("error"); 0467 QTest::addColumn<int>("position"); 0468 QTest::addColumn<QJsonValue>("value"); 0469 0470 QTest::newRow("\"breakpoint-hit\"") << "\"breakpoint-hit\"" << 0 << false << false << 16 << QJsonValue(QStringLiteral("breakpoint-hit")); 0471 QTest::newRow("{reason=\"breakpoint-hit\"}") << "{reason=\"breakpoint-hit\"}" << 0 << false << false << 25 0472 << QJsonValue(QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}); 0473 QTest::newRow("[\"breakpoint-hit\", \"i1\"]") << "[\"breakpoint-hit\", \"i1\"]" << 0 << false << false << 24 0474 << QJsonValue(QJsonArray{QStringLiteral("breakpoint-hit"), QStringLiteral("i1")}); 0475 } 0476 0477 void TestGdbmi::tryList() 0478 { 0479 QFETCH(QString, msg); 0480 QFETCH(int, start); 0481 QFETCH(bool, empty); 0482 QFETCH(bool, error); 0483 QFETCH(int, position); 0484 QFETCH(QJsonValue, value); 0485 0486 const auto tok = gdbmi::tryList(msg.toUtf8(), start); 0487 0488 QCOMPARE(tok.isEmpty(), empty); 0489 if (empty) { 0490 QCOMPARE(tok.hasError(), error); 0491 QCOMPARE(tok.position, start); 0492 } else { 0493 QCOMPARE(tok.position, position); 0494 QVERIFY(tok.value.has_value()); 0495 compare(value, tok.value.value()); 0496 } 0497 } 0498 0499 void TestGdbmi::tryList_data() 0500 { 0501 QTest::addColumn<QString>("msg"); 0502 QTest::addColumn<int>("start"); 0503 QTest::addColumn<bool>("empty"); 0504 QTest::addColumn<bool>("error"); 0505 QTest::addColumn<int>("position"); 0506 QTest::addColumn<QJsonValue>("value"); 0507 0508 QTest::newRow("empty") << "[]" << 0 << false << false << 2 << QJsonValue(QJsonArray()); 0509 QTest::newRow("empty_with_blank") << "[ ]" << 0 << false << false << 3 << QJsonValue(QJsonArray()); 0510 QTest::newRow("single_str_item") << "[\"breakpoint-hit\"]" << 0 << false << false << 18 << QJsonValue(QJsonArray{QStringLiteral("breakpoint-hit")}); 0511 QTest::newRow("item_collection") << "[\"breakpoint-hit\", \"i1\"]" << 0 << false << false << 24 0512 << QJsonValue(QJsonArray{QStringLiteral("breakpoint-hit"), QStringLiteral("i1")}); 0513 QTest::newRow("single_tuple") << "[reason=\"breakpoint-hit\"]" << 0 << false << false << 25 0514 << QJsonValue(QJsonArray{QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}}}); 0515 QTest::newRow("single_object") << "[{key1=\"value1\", key2=\"value2\"}]" << 0 << false << false << 32 0516 << QJsonValue(QJsonArray{ 0517 QJsonObject{{QStringLiteral("key1"), QStringLiteral("value1")}, {QStringLiteral("key2"), QStringLiteral("value2")}}}); 0518 QTest::newRow("tuple_collection") << "[frame=\"frame1\", frame=\"frame2\"]" << 0 << false << false << 32 0519 << QJsonValue(QJsonArray{QJsonObject{{QStringLiteral("frame"), QStringLiteral("frame1")}}, 0520 QJsonObject{{QStringLiteral("frame"), QStringLiteral("frame2")}}}); 0521 } 0522 0523 void TestGdbmi::quoted() 0524 { 0525 QFETCH(QString, original); 0526 QFETCH(QString, expected); 0527 0528 const auto replaced = gdbmi::quotedString(original); 0529 0530 QCOMPARE(replaced, expected); 0531 } 0532 0533 void TestGdbmi::quoted_data() 0534 { 0535 QTest::addColumn<QString>("original"); 0536 QTest::addColumn<QString>("expected"); 0537 0538 QTest::newRow("nothing") << "nothing" 0539 << "nothing"; 0540 QTest::newRow("quotable") << "abc \"cde\"" 0541 << "abc \\\"cde\\\""; 0542 QTest::newRow("already_quoted") << "abc \\\"cde\\\"" 0543 << "abc \\\"cde\\\""; 0544 } 0545 0546 void TestGdbmi::tryRecord() 0547 { 0548 QFETCH(QString, msg); 0549 QFETCH(int, start); 0550 QFETCH(bool, empty); 0551 QFETCH(bool, error); 0552 QFETCH(int, position); 0553 QFETCH(int, category); 0554 QFETCH(QString, resultClass); 0555 QFETCH(int, token); 0556 QFETCH(QJsonObject, value); 0557 0558 const auto tok = gdbmi::tryRecord(msg.toUtf8().at(start), msg.toUtf8(), start, token); 0559 0560 QCOMPARE(tok.isEmpty(), empty); 0561 if (empty) { 0562 QCOMPARE(tok.hasError(), error); 0563 QCOMPARE(tok.position, start); 0564 } else { 0565 QCOMPARE(tok.position, position); 0566 QVERIFY(tok.value.has_value()); 0567 const auto record = tok.value.value(); 0568 QCOMPARE(category, (int)record.category); 0569 QCOMPARE(record.token.value_or(-1), token); 0570 QCOMPARE(resultClass, record.resultClass); 0571 compare(value, record.value); 0572 } 0573 } 0574 0575 void TestGdbmi::tryRecord_data() 0576 { 0577 QTest::addColumn<QString>("msg"); 0578 QTest::addColumn<int>("start"); 0579 QTest::addColumn<bool>("empty"); 0580 QTest::addColumn<bool>("error"); 0581 QTest::addColumn<int>("position"); 0582 QTest::addColumn<int>("category"); 0583 QTest::addColumn<QString>("resultClass"); 0584 QTest::addColumn<int>("token"); 0585 QTest::addColumn<QJsonObject>("value"); 0586 0587 QTest::newRow("^running") << "^running" << 0 << false << false << 8 << (int)gdbmi::Record::Result << QStringLiteral("running") << -1 << QJsonObject(); 0588 QTest::newRow("123^done") << "123^done" << 3 << false << false << 8 << (int)gdbmi::Record::Result << QStringLiteral("done") << 123 << QJsonObject(); 0589 QTest::newRow("*stopped,reason=\"exited-normally\"") 0590 << "*stopped,reason=\"exited-normally\"" << 0 << false << false << 33 << (int)gdbmi::Record::Exec << QStringLiteral("stopped") << -1 0591 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("exited-normally")}}; 0592 QTest::newRow("=thread-created,id=\"id\",group-id=\"gid\"") 0593 << "=thread-created,id=\"id\",group-id=\"gid\"" << 0 << false << false << 38 << (int)gdbmi::Record::Notify << QStringLiteral("thread-created") << -1 0594 << QJsonObject{{QStringLiteral("id"), QStringLiteral("id")}, {QStringLiteral("group-id"), QStringLiteral("gid")}}; 0595 QTest::newRow( 0596 "*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"1\",thread-id=\"0\",frame={addr=\"0x08048564\",func=\"main\",args=[{name=\"argc\",value=" 0597 "\"1\"},{name=\"argv\",value=\"0xbfc4d4d4\"}],file=\"myprog.c\",fullname=\"/home/nickrob/myprog.c\",line=\"68\",arch=\"i386:x86_64\"}") 0598 << "*stopped,reason=\"breakpoint-hit\",disp=\"keep\",bkptno=\"1\",thread-id=\"0\",frame={addr=\"0x08048564\",func=\"main\",args=[{name=\"argc\",value=" 0599 "\"1\"},{name=\"argv\",value=\"0xbfc4d4d4\"}],file=\"myprog.c\",fullname=\"/home/nickrob/myprog.c\",line=\"68\",arch=\"i386:x86_64\"}" 0600 << 0 << false << false << 250 << (int)gdbmi::Record::Exec << QStringLiteral("stopped") << -1 0601 << QJsonObject{{QStringLiteral("reason"), QStringLiteral("breakpoint-hit")}, 0602 {QStringLiteral("disp"), QStringLiteral("keep")}, 0603 {QStringLiteral("bkptno"), QStringLiteral("1")}, 0604 {QStringLiteral("thread-id"), QStringLiteral("0")}, 0605 {QStringLiteral("frame"), 0606 QJsonObject{{QStringLiteral("addr"), QStringLiteral("0x08048564")}, 0607 {QStringLiteral("func"), QStringLiteral("main")}, 0608 {QStringLiteral("args"), 0609 QJsonArray{QJsonObject{{QStringLiteral("name"), QStringLiteral("argc")}, {QStringLiteral("value"), QStringLiteral("1")}}, 0610 QJsonObject{{QStringLiteral("name"), QStringLiteral("argv")}, 0611 {QStringLiteral("value"), QStringLiteral("0xbfc4d4d4")}}}}, 0612 {QStringLiteral("file"), QStringLiteral("myprog.c")}, 0613 {QStringLiteral("fullname"), QStringLiteral("/home/nickrob/myprog.c")}, 0614 {QStringLiteral("line"), QStringLiteral("68")}, 0615 {QStringLiteral("arch"), QStringLiteral("i386:x86_64")}}}}; 0616 } 0617 0618 void TestGdbmi::parseResponse() 0619 { 0620 gdbmi::GdbmiParser parser; 0621 0622 qRegisterMetaType<gdbmi::StreamOutput>("StreamOutput"); 0623 qRegisterMetaType<gdbmi::Record>("Record"); 0624 QSignalSpy outputSpy(&parser, &gdbmi::GdbmiParser::outputProduced); 0625 QVERIFY(outputSpy.isValid()); 0626 QSignalSpy recSpy(&parser, &gdbmi::GdbmiParser::recordProduced); 0627 QVERIFY(recSpy.isValid()); 0628 0629 const QString text = QStringLiteral(R"--( 0630 ~algo 0631 =thread-created,id="id",group-id="gid" 0632 *stopped,reason="breakpoint-hit",disp="keep",bkptno="1",thread-id="0",frame={addr="0x08048564",func="main",args=[{name="argc",value="1"},{name="argv",value="0xbfc4d4d4"}],file="myprog.c",fullname="/home/nickrob/myprog.c",line="68",arch="i386:x86_64"} 0633 123^done,bkpt={number="1",type="breakpoint",disp="keep",enabled="y",addr="0x08048564",func="main",file="myprog.c",fullname="/home/nickrob/myprog.c",line="68",thread-groups=["i1"],times="0"} 0634 )--"); 0635 0636 parser.parseResponse(text.toLocal8Bit()); 0637 0638 QCOMPARE(outputSpy.size(), 1); 0639 QCOMPARE(recSpy.size(), 3); 0640 0641 QCOMPARE(QStringLiteral("algo"), qvariant_cast<gdbmi::StreamOutput>(outputSpy[0][0]).message); 0642 0643 QCOMPARE(QStringLiteral("thread-created"), qvariant_cast<gdbmi::Record>(recSpy[0][0]).resultClass); 0644 QCOMPARE(QStringLiteral("stopped"), qvariant_cast<gdbmi::Record>(recSpy[1][0]).resultClass); 0645 QCOMPARE(QStringLiteral("done"), qvariant_cast<gdbmi::Record>(recSpy[2][0]).resultClass); 0646 } 0647 0648 void TestGdbmi::parseResponse2() 0649 { 0650 gdbmi::GdbmiParser parser; 0651 0652 qRegisterMetaType<gdbmi::StreamOutput>("StreamOutput"); 0653 qRegisterMetaType<gdbmi::Record>("Record"); 0654 QSignalSpy outputSpy(&parser, &gdbmi::GdbmiParser::outputProduced); 0655 QVERIFY(outputSpy.isValid()); 0656 QSignalSpy recSpy(&parser, &gdbmi::GdbmiParser::recordProduced); 0657 QVERIFY(recSpy.isValid()); 0658 0659 const QString text = QStringLiteral(R"--( 0660 ~"Starting program: /home/nobody/pruebas/build-cpp1/cpp1 \n" 0661 =thread-group-started,id="i1",pid="5271" 0662 =thread-created,id="1",group-id="i1" 0663 =library-loaded,id="/lib64/ld-linux-x86-64.so.2",target-name="/lib64/ld-linux-x86-64.so.2",host-name="/lib64/ld-linux-x86-64.so.2",symbols-loaded="0",thread-group="i1",ranges=[{from="0x00007ffff7fc5090",to="0x00007ffff7fee335"}] 0664 ^running 0665 *running,thread-id="all" 0666 (gdb) 0667 )--"); 0668 0669 parser.parseResponse(text.toLocal8Bit()); 0670 0671 QCOMPARE(outputSpy.size(), 1); 0672 QCOMPARE(recSpy.size(), 6); 0673 0674 QCOMPARE(QStringLiteral("Starting program: /home/nobody/pruebas/build-cpp1/cpp1 \n"), qvariant_cast<gdbmi::StreamOutput>(outputSpy[0][0]).message); 0675 0676 QCOMPARE(QStringLiteral("thread-group-started"), qvariant_cast<gdbmi::Record>(recSpy[0][0]).resultClass); 0677 QCOMPARE(QStringLiteral("thread-created"), qvariant_cast<gdbmi::Record>(recSpy[1][0]).resultClass); 0678 QCOMPARE(QStringLiteral("library-loaded"), qvariant_cast<gdbmi::Record>(recSpy[2][0]).resultClass); 0679 QCOMPARE(QStringLiteral("running"), qvariant_cast<gdbmi::Record>(recSpy[3][0]).resultClass); 0680 QCOMPARE(gdbmi::Record::Result, qvariant_cast<gdbmi::Record>(recSpy[3][0]).category); 0681 QCOMPARE(QStringLiteral("running"), qvariant_cast<gdbmi::Record>(recSpy[4][0]).resultClass); 0682 QCOMPARE(gdbmi::Record::Exec, qvariant_cast<gdbmi::Record>(recSpy[4][0]).category); 0683 QCOMPARE(gdbmi::Record::Prompt, qvariant_cast<gdbmi::Record>(recSpy[5][0]).category); 0684 } 0685 0686 void TestGdbmi::parseResponse3() 0687 { 0688 gdbmi::GdbmiParser parser; 0689 0690 qRegisterMetaType<gdbmi::StreamOutput>("StreamOutput"); 0691 qRegisterMetaType<gdbmi::Record>("Record"); 0692 QSignalSpy outputSpy(&parser, &gdbmi::GdbmiParser::outputProduced); 0693 QVERIFY(outputSpy.isValid()); 0694 QSignalSpy recSpy(&parser, &gdbmi::GdbmiParser::recordProduced); 0695 QVERIFY(recSpy.isValid()); 0696 QSignalSpy errorSpy(&parser, &gdbmi::GdbmiParser::parserError); 0697 QVERIFY(errorSpy.isValid()); 0698 0699 const QString text = QStringLiteral(R"--( 0700 =breakpoint-modified,bkpt={number="1",type="breakpoint",disp="del",enabled="y",addr="0x00005555555551f5",func="main()",file="/home/hector/pruebas/cpp1/main.cpp",fullname="/home/hector/pruebas/cpp1/main.cpp",line="7",thread-groups=["i1"],times="1",original-location="main"} 0701 ~"\n" 0702 ~"Temporary breakpoint 1, main () at /home/hector/pruebas/cpp1/main.cpp:7\n" 0703 ~"7\t{\n" 0704 *stopped,reason="breakpoint-hit",disp="del",bkptno="1",frame={addr="0x00005555555551f5",func="main",args=[],file="/home/hector/pruebas/cpp1/main.cpp",fullname="/home/hector/pruebas/cpp1/main.cpp",line="7",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="1" 0705 =breakpoint-deleted,id="1" 0706 (gdb) 0707 )--"); 0708 0709 parser.parseResponse(text.toLocal8Bit()); 0710 0711 QCOMPARE(errorSpy.size(), 0); 0712 QCOMPARE(outputSpy.size(), 3); 0713 0714 QCOMPARE(QStringLiteral("\n"), qvariant_cast<gdbmi::StreamOutput>(outputSpy[0][0]).message); 0715 QCOMPARE(QStringLiteral("Temporary breakpoint 1, main () at /home/hector/pruebas/cpp1/main.cpp:7\n"), 0716 qvariant_cast<gdbmi::StreamOutput>(outputSpy[1][0]).message); 0717 QCOMPARE(QStringLiteral("7\t{\n"), qvariant_cast<gdbmi::StreamOutput>(outputSpy[2][0]).message); 0718 0719 QCOMPARE(recSpy.size(), 4); 0720 0721 QCOMPARE(QStringLiteral("breakpoint-modified"), qvariant_cast<gdbmi::Record>(recSpy[0][0]).resultClass); 0722 QCOMPARE(QStringLiteral("stopped"), qvariant_cast<gdbmi::Record>(recSpy[1][0]).resultClass); 0723 QCOMPARE(QStringLiteral("breakpoint-deleted"), qvariant_cast<gdbmi::Record>(recSpy[2][0]).resultClass); 0724 QCOMPARE(gdbmi::Record::Prompt, qvariant_cast<gdbmi::Record>(recSpy[3][0]).category); 0725 } 0726 0727 void TestGdbmi::compare(const QJsonValue &ref, const QJsonValue &result) 0728 { 0729 if (ref.isNull()) { 0730 QVERIFY(result.isNull()); 0731 } else if (ref.isUndefined()) { 0732 QVERIFY(result.isUndefined()); 0733 } else if (ref.isString()) { 0734 QVERIFY(result.isString()); 0735 QCOMPARE(ref.toString(), result.toString()); 0736 } else if (ref.isBool()) { 0737 QVERIFY(result.isBool()); 0738 QCOMPARE(ref.toBool(), result.toBool()); 0739 } else if (ref.isDouble()) { 0740 QVERIFY(result.isDouble()); 0741 QCOMPARE(ref.toDouble(), result.toDouble()); 0742 } else if (ref.isArray()) { 0743 QVERIFY(result.isArray()); 0744 compare(ref.toArray(), result.toArray()); 0745 } else if (ref.isObject()) { 0746 QVERIFY(result.isObject()); 0747 compare(ref.toObject(), result.toObject()); 0748 } 0749 } 0750 0751 void TestGdbmi::compare(const QJsonArray &ref, const QJsonArray &result) 0752 { 0753 QCOMPARE(ref.size(), result.size()); 0754 0755 for (int idx = 0; idx < ref.size(); ++idx) { 0756 compare(ref.at(idx), result.at(idx)); 0757 } 0758 } 0759 0760 void TestGdbmi::compare(const QJsonObject &ref, const QJsonObject &result) 0761 { 0762 QCOMPARE(ref.size(), result.size()); 0763 0764 for (auto it = ref.constBegin(); it != ref.constEnd(); ++it) { 0765 compare(it.value(), result[it.key()]); 0766 } 0767 } 0768 0769 #include "moc_test_gdbmi.cpp"