diff --git a/plugins/debuggercommon/tests/test_miparser.cpp b/plugins/debuggercommon/tests/test_miparser.cpp index 0261d6986b..0581da897c 100644 --- a/plugins/debuggercommon/tests/test_miparser.cpp +++ b/plugins/debuggercommon/tests/test_miparser.cpp @@ -1,221 +1,221 @@ /* This file is part of KDevelop * * Copyright 2018 Friedrich W. H. Kossebau * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU Library General Public License as * published by the Free Software Foundation; either version 2 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this program; if not, write to the * Free Software Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include "test_miparser.h" // SUT #include // Qt #include struct ResultData { QString name; QVariant value; }; struct ResultRecordData { uint32_t token; QString reason; QVector results; QVariant toVariant() { return QVariant::fromValue(*this); } }; Q_DECLARE_METATYPE(ResultRecordData) struct AsyncRecordData { int subkind; QString reason; QVector results; QVariant toVariant() { return QVariant::fromValue(*this); } }; Q_DECLARE_METATYPE(AsyncRecordData) struct StreamRecordData { int subkind; QString message; QVariant toVariant() { return QVariant::fromValue(*this); } }; Q_DECLARE_METATYPE(StreamRecordData) void TestMIParser::testParseLine_data() { QTest::addColumn("line"); QTest::addColumn("recordKind"); QTest::addColumn("recordData"); // prompt QTest::newRow("gdpprompt") << QByteArray("(gdb)") << (int)KDevMI::MI::Record::Prompt << QVariant(); // result records QTest::newRow("done") << QByteArray("^done") << (int)KDevMI::MI::Record::Result << ResultRecordData{0, "done", {}}.toVariant(); QTest::newRow("doneWToken") << QByteArray("11^done") << (int)KDevMI::MI::Record::Result << ResultRecordData{11, "done", {}}.toVariant(); QTest::newRow("runningWToken") << QByteArray("25^running") << (int)KDevMI::MI::Record::Result << ResultRecordData{25, "running", {}}.toVariant(); // Out-of-band records QTest::newRow("stopreply") << QByteArray("*stop,reason=\"stop\",address=\"0x123\",source=\"a.c:123\"") << (int)KDevMI::MI::Record::Async << AsyncRecordData{KDevMI::MI::AsyncRecord::Exec, "stop", {{"reason", "stop"}, {"address", "0x123"}, {"source", "a.c:123"}}}.toVariant(); QTest::newRow("threadgroupadded") << QByteArray("=thread-group-added,id=\"i1\"") << (int)KDevMI::MI::Record::Async << AsyncRecordData{KDevMI::MI::AsyncRecord::Notify, "thread-group-added", {{"id", "i1"}}}.toVariant(); QTest::newRow("symbolfilereply") << QByteArray("*breakpoint,nr=\"3\",address=\"0x123\",source=\"a.c:123\"") << (int)KDevMI::MI::Record::Async << AsyncRecordData{KDevMI::MI::AsyncRecord::Exec, "breakpoint", {{"nr", "3"}, {"address", "0x123"}, {"source", "a.c:123"}}}.toVariant(); // breakpoint creation records QTest::newRow("breakreply") << QByteArray("&\"break /path/to/some/file.cpp:28\\n\"") << (int)KDevMI::MI::Record::Stream << StreamRecordData{KDevMI::MI::StreamRecord::Log, "break /path/to/some/file.cpp:28\n"}.toVariant(); QTest::newRow("breakreply2") << QByteArray("~\"Breakpoint 1 at 0x400ab0: file /path/to/some/file.cpp, line 28.\\n\"") << (int)KDevMI::MI::Record::Stream << StreamRecordData{KDevMI::MI::StreamRecord::Console, "Breakpoint 1 at 0x400ab0: file /path/to/some/file.cpp, line 28.\n"}.toVariant(); QTest::newRow("breakreply3") << QByteArray("=breakpoint-created,bkpt={number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"0x0000000000400ab0\",func=\"main(int, char**)\",file=\"/path/to/some/file.cpp\",fullname=\"/path/to/some/file.cpp\",line=\"28\",thread-groups=[\"i1\"],times=\"0\",original-location=\"/path/to/some/file.cpp:28\"}") << (int)KDevMI::MI::Record::Async << AsyncRecordData{KDevMI::MI::AsyncRecord::Notify, "breakpoint-created", {{"bkpt", QVariantMap{ {"number", "1"}, {"type", "breakpoint"}, {"disp", "keep"}, {"enabled", "y"}, {"addr", "0x0000000000400ab0"}, {"func", "main(int, char**)"}, {"file", "/path/to/some/file.cpp"}, {"fullname", "/path/to/some/file.cpp"}, {"line", "28"}, {"thread-groups", QVariantList{"i1"}}, {"times", "0"}, {"original-location", "/path/to/some/file.cpp:28"}}}}}.toVariant(); } void TestMIParser::doTestResult(const KDevMI::MI::Value& actualValue, const QVariant& expectedValue) { if (expectedValue.type() == QVariant::String) { QCOMPARE((int)actualValue.kind, (int)KDevMI::MI::Value::StringLiteral); QCOMPARE(actualValue.literal(), expectedValue.toString()); } else if (expectedValue.type() == QVariant::List) { QCOMPARE(actualValue.kind, KDevMI::MI::Value::List); const auto expectedList = expectedValue.toList(); QCOMPARE(actualValue.size(), expectedList.size()); for (int i = 0; i < expectedList.size(); ++i) { doTestResult(actualValue[i], expectedList[i]); } } else if (expectedValue.type() == QVariant::Map) { QCOMPARE(actualValue.kind, KDevMI::MI::Value::Tuple); const auto expectedMap = expectedValue.toMap(); for (auto it = expectedMap.begin(), end = expectedMap.end(); it != end; ++it) { const auto& expectedMapField = it.key(); QVERIFY(actualValue.hasField(expectedMapField)); const auto& expectedMapValue = it.value(); doTestResult(actualValue[expectedMapField], expectedMapValue); } } else { QFAIL("Using unexpected QVariant type"); } } void TestMIParser::testParseLine() { QFETCH(QByteArray, line); QFETCH(int, recordKind); QFETCH(QVariant, recordData); KDevMI::MI::MIParser m_parser; KDevMI::MI::FileSymbol file; file.contents = line; std::unique_ptr record(m_parser.parse(&file)); - QVERIFY(record); + QVERIFY(record != nullptr); QCOMPARE((int)record->kind, recordKind); switch(recordKind) { case KDevMI::MI::Record::Result: { const auto& resultRecord = static_cast(*record); const auto resultData = recordData.value(); QCOMPARE(resultRecord.token, resultData.token); QCOMPARE(resultRecord.reason, resultData.reason); for (const auto& result : resultData.results) { QVERIFY(resultRecord.hasField(result.name)); doTestResult(resultRecord[result.name], result.value); } break; } case KDevMI::MI::Record::Async: { const auto& asyncRecord = static_cast(*record); const auto asyncData = recordData.value(); QCOMPARE((int)asyncRecord.subkind, asyncData.subkind); QCOMPARE(asyncRecord.reason, asyncData.reason); for (const auto& result : asyncData.results) { QVERIFY(asyncRecord.hasField(result.name)); doTestResult(asyncRecord[result.name], result.value); } break; } case KDevMI::MI::Record::Stream: { const auto& streamRecord = static_cast(*record); const auto streamData = recordData.value(); QCOMPARE((int)streamRecord.subkind, streamData.subkind); QCOMPARE(streamRecord.message, streamData.message); break; } case KDevMI::MI::Record::Prompt: break; } } QTEST_GUILESS_MAIN(TestMIParser)